{ // ... props: { title: String, likes: Number, isPublished: Boolean, commentIds: Array, author: Object } //... }
对于须要默认值的prop,建议指定其默认值javascript
这是在ubuntu系统中遇到的,全局安装后能够css
npm install -g vue-cli
跨层级的组件间通信可使用 eventbus
可是要注意两点:
event 会注册到全局,要注意模块化
注意销毁,否则会使用两次
一、在vue中子组件为什么不能够修改父组件传递的Prop, 若是修改了,二、Vue是如何监控到属性的修改并给出警告的
每当父组件属性值修改时, 该值都将被覆盖。
——> 引伸出一个问题:html
若是在子组件须要修改prop呢?
- 经过事件修改父组件状态 - 或者子组件把prop赋给data()或者comuted,
封装Vue组件的一些技巧
vue 最先是双向数据流,子组件能够改变 props ,以后由于引起不少问题而改为单向数据流。如今在子组件内触发修改会致使报错。
以函数透传的形式实现控制子组件修改父组件状态不是一个好办法。vue
传统实现仍是 v-modeljava
可是,v-model 里子组件不能直接改变父组件状态,而是要经过事件,本质上依然是单向数据流。react
https://vuejs-templates.githu...webpack
webpack 中提供了 require.ensure()来实现按需加载。之前引入路由是经过 import 这样的方式引入,改成 const 定义的方式进行引入。git
import home from '../../common/home.vue'
const home = r => require.ensure( [], () => r (require('../../common/home.vue')))
https://blog.csdn.net/qq_2762...
slot 在ui库中有普遍的应用
<slot></slot>
标签,简单来讲就是占位符,它会帮你占好位置,等你须要的时候直接将html传入,它会帮你显示出来。<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <script type="text/javascript" src="vue.min.js"></script> </head> <body> <div id="app"> <h1>我是父组件的标题</h1> <my-component> <p>这是一些初始内容</p> <p>这是更多的初始内容</p> </my-component> </div> <script type="text/javascript"> Vue.component('my-component', { // 有效,由于是在正确的做用域内 template: '<div>\ <h2>我是子组件的标题</h2>\ <slot>只有在没有要分发的内容时才会显示。</slot>\ </div>', data: function () { return { } } }); new Vue({ el:'#app', data:{ msg:'你好啊' } }) </script> </body> </html>
组件中的模板中写入slot标签,在父级调用子组件的时候传入html便可。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <script type="text/javascript" src="vue.min.js"></script> </head> <body> <div id="app"> <my-component> <h1 slot="header">这里多是一个页面标题</h1> <p>主要内容的一个段落。</p> <p>另外一个主要段落。</p> <p slot="footer">这里有一些联系信息</p> </my-component> </div> <script type="text/javascript"> Vue.component('my-component', { // 有效,由于是在正确的做用域内 template: '<div class="container">\ <header>\ <slot name="header"></slot>\ </header>\ <main>\ <slot></slot>\ </main>\ <footer>\ <slot name="footer"></slot>\ </footer>\ </div>', data: function () { return { } } }); new Vue({ el:'#app', data:{ msg:'你好啊' } }) </script> </body> </html>
具名插槽,顾名思义当有多个slot标签时,你须要给他们起个本身的名字,在父组件调用时须要slot="内部的对应名字",当存在没有命名的slot标签时,父级组件传入的默认html代码将所有输出在无名的slot标签中。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <script type="text/javascript" src="vue.min.js"></script> </head> <body> <div id="app"> <!-- 在父级中,具备特殊特性 slot-scope 的 <template> 元素必须存在,表示它是做用域插槽的模板。slot-scope 的值将被用做一个临时变量名,此变量接收从子组件传递过来的 prop 对象: --> <child> <template scope="props"> <span>hello from parent</span><br> <span>{{ props.text }}</span> </template> </child> </div> <script type="text/javascript"> // 在子组件中,只需将数据传递到插槽,就像你将 prop 传递给组件同样: Vue.component('child',{ template:'<ul>' + '<slot text="hello from child"></slot>' + '</ul>', data:function(){ return { } }, }); new Vue({ el:'#app', data:{ msg:'你好啊' } }) </script> </body> </html>
https://codepen.io/AlexZ33/pe...
做用域插槽是一种特殊类型的插槽,用做一个 (能被传递数据的) 可重用模板,来代替已经渲染好的元素。
其实就是至关于,在父组件中能够获取到子组件传递出来的props对象,从而渲染到父组件上。
Vue开发——watch监听数组、对象、变量
这里要注意的是对数组的watch
v-if
初始渲染
初始值为 false 组件不会渲染,生命周期钩子不会执行,v-if 的渲染是惰性的。
初始值为 true 时,组件会进行渲染,并依次执行 beforeCreate,created,beforeMount,mounted 钩子。
切换
false => true
依次执行 beforeCreate,created,beforeMount,mounted 钩子。
true => false
依次执行 beforeDestroy,destroyed 钩子。
v-show
渲染
不管初始状态,组件都会渲染,依次执行 beforeCreate,created,beforeMount,mounted 钩子,v-show 的渲染是非惰性的。
切换
对生命周期钩子无影响,切换时组件始终保持在 mounted 钩子。
vue v-cloak 解决页面加载时闪烁出现vue标签或者指令的问题
// chart/WaterMark.js export default class WaterMark { constructor (userNm, userCd) { this.userNm = userNm this.userCd = userCd } draw () { let canvas = document.createElement('canvas') let ctx = canvas.getContext('2d') canvas.width = 250 canvas.height = 130 ctx.translate(canvas.width / 2, canvas.height / 2 - 35) ctx.rotate(-Math.PI / 12) ctx.font = '700 12px/Mircosoft Yahei' ctx.textAlign = 'center' ctx.textBaseline = 'middle' ctx.fillStyle = '#eaf0f5' // ctx.fillStyle = '#f00' ctx.fillText(`镜心的小树屋 ${this.userNm} ${this.userCd}`, 0, 0) return canvas.toDataURL('image/png') } }
// rule.js /** * 用户信息相关 */ exports.useInfor = { data: { name: '', userCd: '', userNm: '' }, clear: function () { this.data = { name: '', userCd: '', userNm: '', flag: false } } }
// directives/WaterMark.js import WaterMark from '../chart/WaterMark.js' import { useInfor } from '../rule' export default { inserted (el, binding) { let timer = setInterval(() => { if (useInfor.data.userNm && useInfor.data.userCd) { let wMark = new WaterMark(useInfor.data.userNm, useInfor.data.userCd) let imageSrc = wMark.draw() if (binding.value && binding.value === false) return el.style.background = `#fff url(${imageSrc}) repeat top left` clearInterval(timer) } }, 50) } }
// https://cn.vuejs.org/v2/guide/custom-directive.html#%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0 // 注册一个全局自定义指令 'v-focus' export default { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() } }
router.push('index')
最近遇到一个需求,须要刷新当前页面来更新数据
vue 无痕刷新
【BUG】iview多选框插件默认选中有问题,局部刷新后会取消选中状态?
https://www.cnblogs.com/sifo/...
在使用vue框架iview是常常须要在组件里面修改某一个样式,为了防止组件之间的样式污染,咱们须要使用scoped来限制在当前组件内生效,但每每样式会没法生效。我以前的解决方案是在当前这个组件的父级加一个只有当前组件才有的class而后早style没有scoped中去写样式,这样既能够改变iview自带的样式,也能够人为去限制组件之间的样式污染,这也是当时没有办法下本身想到的惟一的办法。最近又发现一个新的解决方案/deep/深度选择器
->戳这里
.reset-sub-modal /deep/ .ivu-modal-footer padding-bottom: 25px
https://www.cnblogs.com/golov...
观察到数据变化,vue开启一个队列,并缓冲同一事件循环的全部数据变化;
若是同一个watcher被屡次触发,只会被推入队列中一次;(去重,避免没必要要计算和DOM操做)
在下一个事件循环tick中,vue刷新队列并执行已去重的工做;
所以,改数据(eg vm.someData = ’88’)时,组件不会立刻更新,而是在vue下一个tick刷新队列时更新;
为了在数据变化后,要在vue的dom状态更新后作什么,可在数据变化后调用vue.nextTick(callback),则dom更新完成后会调用回调函数;
Vue生命周期的created()钩子函数进行的DOM操做必定要放在Vue.nextTick()的回调函数中;
在数据变化后要执行的某个操做,而这个操做须要使用随数据改变而改变的DOM结构的时候,这个操做都应该放进Vue.nextTick()的回调函数中;
更多原理和示例戳这里
文档
简单示例: https://jsfiddle.net/chrisvfr...
正常项目中:

对于VUE的初学者来说,确定会感受prop的写法很麻烦,很讨厌!你确定想若是prop也能够实现双向绑定那怎是一个爽字了得!不过现实是残酷的,若是子组件能够任意修改父组件的内容,那势必会带来数据的混乱,从而形成维护的困扰!毕竟父组件也是有尊严的!
https://www.jianshu.com/p/d42...
使用 Vue.js 怎么调用其余组件的方法
中央事件总线eventbus
/** * 中央事件总线 * 这个插件能够在能够在全部的组件之间随意使用 * 经常使用于兄弟组件间通讯 * 注意: * $bus.on应该在 created钩子内使用,若是在mounted使用,它可能接受不到其余组件来自created钩子发出的事件 * 第二点是使用了$bus.on,在beforeDestroy钩子里应该使用$bus.off解除,由于组件销毁后,就不必把监听的句柄储存在vue-bus里了 * @param {*} Vue 传入的Vue class */ const install = function (Vue) { const Bus = new Vue ({ methods: { emit (event, ...args) { this.$emit(event, ...args) }, on (event, callback) { this.$on(event, callback) }, off (event, callback) { this.$off(event, callback) } } }) Vue.prototype.$bus = Bus } export default install
屡次触发问题-> issue
资料集合
multiselect
在 vue-multiselect 基础上建立 ImageSelect 组件
https://github.com/vuejs/awes...
.label-required display: inline-block height: 33px line-height: 28px &:before content: '*' display: inline-block margin-right: 4px line-height: 1 font-family: SimSun font-size: 12px color: #ed3f14
$parent 也能够用来访问父组件的数据。
并且子组件能够经过$parent 来直接修改父组件的数据,不会报错!
可使用props的时候,尽可能使用props显式地传递数据(能够很清楚很快速地看出子组件引用了父组件的哪些数据)。
另外在一方面,直接在子组件中修改父组件的数据是很糟糕的作法,props单向数据流就没有这种顾虑了。
非大厂隔离环境的话可用ssh( 大厂生产环境是隔离的 要经过跳板机 代码不可能经过ssh直接发到生产的):
Vue-CLI 3.x 自动部署项目至服务器
为何组件中的 data 必须是一个函数,而后 return 一个对象,而 new Vue 实例里,data 能够直接是一个对象?
由于组件是用来复用的,JS 里对象是引用关系,这样做用域没有隔离;而 new Vue 的实例,是不会被复用的,所以不存在引用对象的问题。
从最初学习Vue就知道v-model能够实现双数据绑定,但它能实现绑定的原理究竟是什么呢?经过查看官方文档和各类博客资料,如下是个人理解。根据官方文档介绍,v-model本质上就是语法糖,即利用v-model绑定数据后,其实就是既绑定了数据,又添加了一个input事件监听,以下:
https://www.cnblogs.com/attac...
这个问题几乎是面试必问的,回答也是有深有浅。基本上要知道核心的 API 是经过 Object.defineProperty() 来劫持各个属性的setter / getter,在数据变更时发布消息给订阅者,触发相应的监听回调,这也是为何 Vue.js 2.x 不支持 IE8 的缘由(IE 8 不支持此 API,且没法经过 polyfill 实现)
https://cn.vuejs.org/v2/guide...
vue.js 是采用数据劫持结合发布者-订阅者模式的方式,经过 Object.defineProperty()来劫持各个属性的 setter,getter,在数据变更时发布消息给订阅者,触发相应的监听回调。
具体步骤:
第一步:须要 observe 的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter 这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化
第二步:compile 解析模板指令,将模板中的变量替换成数据,而后初始化渲染页面视图,并将每一个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变更,收到通知,更新视图
第三步:Watcher 订阅者是 Observer 和 Compile 之间通讯的桥梁,主要作的事情是:
第四步:MVVM 做为数据绑定的入口,整合 Observer、Compile 和 Watcher 三者,经过 Observer 来监听本身的 model 数据变化,经过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的通讯桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据 model 变动的双向绑定效果。
vue组件中各方法执行顺序是怎么样的
Props -》 Methods -》 Data -》Computed -》 Watch
咱们应该都知道vue会经过object.defineProperty对数据进行劫持,来实现视图响应数据的变化,然而有些时候咱们的组件就是纯粹的数据展现,不会有任何改变,咱们就不须要vue来劫持咱们的数据,在大量数据展现的状况下,这可以很明显的减小组件初始化的时间,那如何禁止vue劫持咱们的数据呢?能够经过object.freeze方法来冻结一个对象,一旦被冻结的对象就不再能被修改了。
export default { data: () => ({ users: {} }), async created() { const users = await axios.get("/api/users"); this.users = Object.freeze(users); } };
另外须要说明的是,这里只是冻结了users的值,引用不会被冻结,当咱们须要reactive数据的时候,咱们能够从新给users赋值。
export default { data: () => ({ users: [] }), async created() { const users = await axios.get("/api/users"); this.users = Object.freeze(users); }, methods:{ // 改变值不会触发视图响应 this.users[0] = newValue // 改变引用依然会触发视图响应 this.users = newArray } };
vue-router 有哪几种导航钩子?
import NProgress from 'nprogress' // http://ricostacruz.com/nprogress/
若是请求来的数据不是要被其余组件公用,仅仅在请求的组件内使用,就不须要放入 vuex 的 state 里
若是被其余地方复用,请将请求放入 action 里,方便复用,并包装成 promise 返回
组件要考虑的三个基本内容:
组件须要提供修改样式的能力, 修改内容的能力,和基本的交互反馈能力。
而一个可复用的组件,须要开放控制粒度。一般来讲,控制粒度约高的组件,开发者使用起来就越方便,可是维护起来也越困难。肯定本身的组件控制开放到什么程度是重要的内容。
另外,也存在只提供基本的控制开放的组件。各我的会有其偏向性。而反馈组件的状态决定了组件是否易用。程序须要知道用户作了什么。
恰当的反馈,加上合适的控制,才能写出易用的组件。
vue中的css做用域、vue中的scoped坑点
css loader 深度做用选择器
vue nextTick深刻理解-vue性能优化、DOM更新时机、事件循环机制
Vue.js 技术揭秘
Vue技术内幕
深度剖析:如何实现一个 Virtual DOM 算法
Vue使用中的小技巧
Vue问得最多的面试题
让vue-cli3.0 配置简单起来(vue.config.js编结)
Creating Vue.js Component Instances Programmatically
Vue项目经验
「Vue实践」武装你的前端项目
7个有用的Vue开发技巧
基于vue的进阶散点干货