1、key的作用
作为一个DOM节点的标识值,结合Diff算法可以实现节点的复用。(key相同的节点会被复用)
只有当key(或其他导致isSameNode判断为false)发生改变时,才会触发节点的重新渲染。否则Vue将会复用之前的节点,通过改变节点的属性来实现节点的更新。
<button @click="addEmployee">添加员工</button>
<ul>
<!-- 列表渲染时,key值最好是对象的唯一属性值,比如:学号,工号,身份证号,手机号等待
目的是:当列表更新时,提高后期的渲染性能。
因为vue在渲染数据时,先将数据生存一份虚拟DOM,再将虚拟DOM生成对应的真实DOM挂载到页面中
当vue中的数据修改后,会重新生成一份虚拟DOM,并跟之前的虚拟DOM进行匹配,
如果两份虚拟DOM中的key和key对应的值完全相同,不会重新生成对应的真实DOM
只有key和key对应的值不同的虚拟DOM,才会生成新的真实DOM并挂载的页面中。-->
<li v-for="(item) in employees" :key="item.id">{{item}}</li>
</ul>
export default {
name: 'Home',
data() {
return {
//定义一个工程师数组
employees:[
{
id:1001,
name:'刘德华',
age:20,
sex:'男'
},
{
id:1002,
name:'张学友',
age:22,
sex:'男'
}
]
}
},
}
methods: {
//添加员工的方法
addEmployee(){
let emp = {
id:Date.now(),
name:'蔡依林',
sex:'女',
age:26
}
this.employees.unshift(emp)
}
},
2、key使用id与index区别
不推荐使用index作为key,因为这种做法会导致某些节点被错误的原地复用,具体如下:
性能损耗:列表渲染时会导致变动项往后的所有列表节点(内容)的更新(相当于key没有发挥作用)
出现错误:某些节点在错误的位置被复用。(例如列表项中使用到复选框时)
3、 Vue.nextTick()方法
定义:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
所以就衍生出了这个获取更新后的DOM的Vue方法。所以放在Vue.nextTick()回调函数中的执行的应该是会对DOM进行操作的 js代码;
理解:nextTick(),是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数,
<div class="one">
<input type="text" v-model="carName" />
<button @click="addCar">添加汽车</button>
<ul ref="list">
<li v-for="item in cars" :key="item.id">
<input :value="item.name" />
</li>
</ul>
<hr>
<button @click="employee.name='蔡依林'">修改姓名</button>
<button @click="addSex">添加性别</button>
<div>{{employee}}</div>
</div>
data() {
return {
//汽车名称
carName: "",
//汽车数组
cars: [
{
id: 1001,
name: "玛莎拉蒂",
},
{
id: 1002,
name: "帕拉梅拉",
},
],
employee:{
name:'周杰伦',
age:20
}
};
},
methods: {
addCar() {
let car = {
id: Date.now(),
name: this.carName,
};
this.cars.push(car);
this.carName = "";
// $nextTick方法,需要传一个回调函数,
// 回调函数里面的代码在DOM更新完成后执行。
this.$nextTick(() => {
// 让最后一个li元素里面的input元素获取焦点
this.$refs.list.lastChild.lastChild.focus();
});
},
addSex(){
// this.$set(this.employee,'sex','男')
// 直接添加的属性,不具备响应式
this.employee.sex='男'
// $forceUpdate()方法,迫使 Vue 实例重新渲染
this.$forceUpdate()
}
注意:Vue实现响应式并不是数据发生变化之后DOM立即变化,而是按照一定的策略进行DOM的更新。nextTick,则可以再回调中获取更新后的DOM。
4、自定义指令
<div v-red>好好学习</div>
<p v-red>天天向上</p>
<div v-html="car" v-color="'red'"></div>
<div v-myhtml="car" v-color="'green'"></div>
data() {
return {
car:'<h2>保时捷卡宴真好看</h2>'
}
},
//定义局部指令,所有的指令背后都是在操作DOM,我们将这种功能称之为:造轮子。
directives:{
//自定义一个指令,指令名称是myhtml,
//自定义指令就是一个方法,该方法有两个参数:返回指令所在的dom元素,绑定的一份数据
myhtml:function(el,binding){
el.innerHTML = binding.value
},
red:function(el){
el.style.color = 'red'
},
color:function(el,binding){
el.style.color = binding.value
}
}
5、自定义插件
定义一个插件,插件就是将给Vue添加的全局成员,归类到一起去,这样做利于后期维护。
在src新建一个plugins文件夹,在新建一个index.js
// 插件本质上就是一个对象
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)
},
}),
// 注册全局指令
Vue.directive('bgcolor', function(el,bind){
el.style.backgroundColor = bind.value
})
}
}