1.key值
列表渲染时,key值最好是对象的唯一属性值,比如:学号,工号,身份证号,手机号等等,
目的是:当列表更新时,提高后期渲染的性能。
当key值时唯一属性值时,二次渲染时,之前的内容不会更新,而是更新后添加或者更改的内容。
如下图,当我们在更改原始对象数据时,vue在底层创建了一个虚拟的dom,根据这个key的值来判断,哪些值修改了,哪些值增加了或者删除了,然后在真实的dom中根据修改了或者添加删除了key值的内容进行重新渲染,而并非对整个dom进行重新渲染,这样就大大的节省了性能。
因为vue在渲染数据时,先将数据生成一份虚拟DOM,再将虚拟DOM生成对应的真实DOM挂载到页面中,
当vue中的数据修改后,会重新生成一份虚拟DOM,并跟之前的虚拟DOM进行匹配,
如果两份虚拟DOM中的key和key对应的值完全相同,不会重新生成对应的真实DOM,
只有key和key对应的值不同的虚拟DOM,才会生成新的真实DOM并挂载到页面中。
代码体现:
<template>
<div class="home">
<button @click="addEmp">添加员工</button>
<ul>
<!-- 如果key是索引index,当位置发生变化时,所有数据都会重新渲染 -->
<!-- <li v-for="(item, index) in list" :key="index">{{ item }}</li> -->
<!-- 如果key是唯一值id,当位置发生变化时,只会渲染更新的数据 -->
<li v-for="(item,index) in employees" :key="item.id">{{ item }}</li>
</ul>
</div>
</template>
<script>
export default {
name: "Home",
data() {
return {
// 定义一个工程师数组
employees: [
{
id: 1001,
name: "刘德华",
age: 20,
sex: "男",
},
{
id: 1002,
name: "张学友",
age: 21,
sex: "男",
},
{
id: 1003,
name: "黎明",
age: 23,
sex: "男",
},
{
id: 1004,
name: "郭富城",
age: 24,
sex: "男",
},
],
};
},
methods: {
// 添加员工的方法
addEmp() {
let emp={
id:Date.now(), // 返回当前时间的时间戳 确保id唯一
name:'蔡依林',
age:22,
sex:'女'
}
// this.employees.push(emp)
this.employees.unshift(emp)
},
},
};
</script>
2.$nextTick() 方法
见官方-文档-API
$nextTick( )方法,需要传一个回调函数,回调函数里面的代码在DOM更新完成后执行。如下所示,当页面的数据更新后,让添加的内容获取焦点。如果不使用则是给添加内容前的最后一个元素让其获取焦点。
代码体现:
<template>
<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>
</div>
</template>
export default {
name: "One",
data() {
return {
carName: "",
// 汽车数组
cars: [
{
id: 1001,
name: "玛莎拉蒂",
},
{
id: 1002,
name: "布加迪威龙",
},
]
};
},
methods: {
addcar() {
let car = {
id: Date.now(),
name: this.carName,
};
this.cars.push(car);
this.carName = "";
// $nextTick方法,需要传一个回调函数,回调函数里面的代码,在DOM更新完成后执行。
this.$nextTick(() => {
// 让最后一个li元素获取焦点, focus()方法用于为元素设置焦点。
this.$refs.list.lastChild.lastChild.focus();
});
},
},
};
3.$forceUpdate() 方法
见官方-文档-API
$forceUpdate(),进行强制更新。调用这个方法会更新视图和数据,触发updated生命周期。
该方法,迫使vue实例强制更新。如下,当给一个对象,使用下图的方式添加一个属性时,如果单单使用该方法,不是响应式的,dom页面无法渲染,但如果添加this.$forceUpdate( ) 方法的话,则页面会强制更新,但是依然不会响应式的。
<template>
<div class="one">
<button @click="employee.name='蔡依林'">修改姓名</button>
<button @click="addSex">添加性别</button>
<div>{{employee}}</div>
</div>
</template>
export default {
name: "One",
data() {
return {
employee: {
name: "周杰伦",
age: 20,
}
};
},
methods: {
addSex() {
// this.employee.sex='男'
// console.log(this.employee);
// 这时候打印,后台已经有性别男,这个数据了,但是页面没有更新到它
// 因为VUe在初始化的时候,会把data里的所有属性做一个响应式,而后加的就没有。
// 如果想要后加的,也具备响应式,就要
// this.$set(this.employee,'sex','男')
// 直接添加的属性,不具备响应式
this.employee.sex = "男";
// $forceUpdate()方法,迫使Vue实例重新渲染
this.$forceUpdate();
},
},
};
4.自定义指令(directives)
4.1 定义局部指令
局部就 直接在某组件内,搞一个 directives:{ }
因此,v-html背后的原理就是如下:
<div v-red>好好学习</div>
<p v-red>天天向上</p>
<div v-html="car"></div>
<div v-myhtml="car"></div>
export default {
name: "Two",
data() {
return {
car:'<h2>保时捷卡宴是真滴好看</h2>'
}
},
directives: {
// 指令就是一个方法,方法的第一个参数el,传递的是指令所在的DOM元素
// 注册一个局部自定义指令 'v-red',设置字体颜色为红色
red: function (el) {
el.style.color = "red";
},
// 指令方法的第二个参数bind,是给指令绑定的值
// 注册一个局部自定义指令 'v-myhtml',渲染html标签数据
myhtml(el,bind){
el.innerHTML = bind.value
}
},
};
因此,定义局部指令,所有的指令背后都是在操作DOM,我们将这种功能称之为:造轮子。
4.2 全局自定义指令
在src文件夹下新建一个directive文件夹,在其中创建index.js,
引入vue,然后创建全局自定义指令,
在全局入口文件main.js中导入该文件。
// 定义全局自定义指令
import Vue from 'vue'
Vue.directive('mycolor',function(el,bind){
el.style.color = bind.value
})
// 导入全局自定义指令
import './directives'
此时在任何页中均可以使用。
<div v-html="car" v-color="'skyblue'"></div>
<div v-myhtml="car" v-color="'pink'"></div>
5.自定义插件(plugins)
插件的本质上就是一个对象,该对象中必须包含一个install( ) 方法,方法的第一个参数是Vue,第二个参数是配置对象。install方法,会在use的时候执行,Vue.use(插件名),这里的vue会作为install方法的第一个参数。
在src文件夹下新建一个plugins文件夹,在其中创建index.js,
在全局入口文件main.js中导入并use插件,
使用插件。
export default {
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
})
}
}
// 导入自定义插件
import myPlugin from './plugins'
// 注意:一定要use
Vue.use(myPlugin)
<!-- 调用插件中定义的vue原型上的方法 -->
<button @click="sayHello">sayHello</button>
<!-- 调用插件中定义的vue方法 -->
<button @click="sayHi">sayHello</button>
<!-- 调用插件中定义的混入成员 -->
<button @click="showplane">showplane</button>
<div v-bgcolor="'lightblue'">我是淡蓝色</div>
<b-box>哈哈</b-box>
网友评论