一、key
列表渲染时,key值最好是对象的唯一属性值,比如:学号,工号,身份证号,手机号等等。
目的是:当列表更新时,提高后期的渲染性能。
因为vue在渲染数据时,先将数据生存一份虚拟DOM,再将虚拟DOM生成对应的真实DOM挂载到页面中
当vue中的数据修改后,会重新生成一份虚拟DOM,并跟之前的虚拟DOM进行匹配,
如果两份虚拟DOM中的key和key对应的值完全相同,不会重新生成对应的真实DOM
只有key和key对应的值不同的虚拟DOM,才会生成新的真实DOM并挂载的页面中。
(1)key最好是对象的唯一属性
在循环列表时,如果key为index下标,后续要修改数据时候,和该数据相关的下标都会进行重新渲染,这样很损耗性能
<li v-for="(item) in employees" :key="index">{{item}}</li>
(2)key最好是对象的唯一属性值
<li v-for="(item) in employees" :key="item.id">{{item}}</li>
二、$nextTick()
操作数据后,会重新渲染页面。如果此时要获取最后一次元素,直接获取可能会页面还没渲染完成。此时可以使用$nextTick()延后执行
$nextTick方法,需要传一个回调函数,
回调函数里面的代码在DOM更新完成后执行。
addCar() {
let car = {
id: Date.now(),
name: this.carName,
};
this.cars.push(car);
添加完后清空文本框,文本框绑定的值是carName,所以只需要设置这个值为空,文本框就为空
this.carName = "";
this.$nextTick(() => {
让最后一个li元素里面的input元素获取焦点
this.$refs.list.lastChild.lastChild.focus();
});
},
三、$set
vue数据是响应式的,只要数据发生变化页面就会更新,重新渲染DOM,后加的数据没有响应式
Vue.$set(target,key,value):可以动态的给数组、对象添加和修改数据,并更新视图中数据的显示。
$set 这个方法只能用于data 里面的子数组对象,而不能直接用于data (这个根数据)
使用Vue.set(object, key, value)方法将响应属性添加到嵌套的对象上。Vue.set(this.form, 'showFlag', true)
还可以使用vm.$set实例方法,这也是全局Vue.set方法的别名:this.$set(this.form, 'showFlag', true)
(1)通过$set添加响应式数据
addsex(){
this.$set(this.employee,'sex','男')
}
四、$forceUpdate()
直接给对象添加属性和值,页面不会重新渲染。可以使用$forceUpdate()迫使页面更新
addSex(){
这种方式添加不具备响应式,就不会更新页面
this.employee.sex='男'
this.$forceUpdate()
}
五、自定义指令
vue自带了很多指令如:v-for、v-if、v-show、v-bind、v-on等
我们也可以通过directives定义指令,指令就是一个方法:
方法的第一个参数传递的是指令所在的DOM元素。
第二个参数的bind是给指令绑定的值(指令也可不传值),返回是对象。这个对象的vlue属性就是当前元素的内容。expression是给指令绑定的值。name是指令的名称。rawName是指令全名。
定义局部指令,所有的指令背后都是在操作DOM,我们将这种功能称之为:造轮子。
(1)局部自定义指令&v-html实现原理
<div v-red>好好学习</div>
<p v-red>天天向上</p>
<div v-html="car"></div>
<div v-myhtml="car"></div>
directives:{
//指令就是一个方法,方法的第一个参数传递的是指令所在的DOM元素
red:function(el){
el.style.color="red"
},
//指令方法的第二个参数是给指令绑定的值
myhtml(el,bind){
el.innerHTML = bind.value
}
},
(2)创建全局自定义指令
新建文件src->directive->index.js
然后在mian.js中注册全局指令import './directive'
mian.js
import './direcktive'
directive中先引入vue
import Vue from 'vue'
Vue.directive('color',function(el,bind){
el.style.color=bind.value
})
组件中使用
<p v-html="car" v-color="'pink'"></p>
<p v-myhtml="car" v-color="'green'"></p>
六、自定义插件
新建文件src->plugins->index.js,然后在main.js中导入和use使用.
vue-router是一个插件,插件必须要use后才能使用。Vue.use(VueRouter)
插件通常用来为Vue添加全局功能,插件的功能范围没有严格的限制——一般有下面几种:
1.添加全局方法或prototype。如:vue-custom-element
2.添加全局资源:指令/过滤器/过渡等。如vue-touch
3.通过全局混入来添加一些组件选项。如vue-router
4.添加vue实例方法,通过把他们添加到vue.prototype上实现。
5.一个库,提供自己的API,同时提供上面提到的一个或多个功能,如vue-router
1.main.js中导入自定义插件
// 导入自己插件
import myPlugin from './plugins'
// 注意:一定要use
Vue.use(myPlugin)
2.plugins
// 插件本质上就是一个对象
export default {
// 该对象中必须包含一个install()方法
// install()方法的第一个参数是Vue,第二个参数是配置对象
// install()方式,会在use的时时候执行,
// Vue.use(插件),这里的Vue会作为install方法的第一个参数
install:function(Vue,options){
// 可以直接给Vue添加成员,这种方法添加实例获取不了
Vue.sayHi = function(){
console.log('大家好!我是Vue');
},
Vue.msg = "欢迎是插件",
// 可以在Vue的原型上扩展成员
Vue.prototype.sayHello = function(){
console.log('哈哈!我是Vue原型上的方法');
},
// 给Vue混入成员
Vue.mixin({
data() {
return {
plane:{
name:'奔驰',
price:'100W'
}
}
},
methods: {
showPlane(){
console.log(this.plane.name,this.plane.price);
}
},
}),
// 注册全局组件
Vue.component('b-box', {
// 在脚手架环境中,只能通过渲染函数定义全局组件,不能使用模板
render(h) {
return h('div',this.$slots.default)
渲染指定h函数,返回 h函数,实参是(‘div’,这个插槽预留位置除了具名插槽)
$slots是一个插槽用来预留位置,default则是指除了具名插槽以外的所有内容。
为了便于理解,可以将this.$slots.default理解成<slot></slot>,将this.$slots.footer理解成<slot name="footer"></slot>,
然后放置插槽的位置就和template一样的思路即可。
例如想要在p标签放置默认插槽,则将this.$slots.default当做p标签的子元素即可。具名插槽和作用域插槽类似。
},
}),
// 注册全局指令
Vue.directive('bgcolor', function(el,bind){
el.style.backgroundColor = bind.value
})
}
}
3.组件
vue原型上的方法可以直接调
<button @click="sayHello">sayHello</button>
<button @click="showPlane">showPlane</button>
<div v-bgcolor="'lightblue'">我是淡蓝色</div>
<b-box>
哈哈
</b-box>