1赠法、key的作用
作為一個(gè)DOM節(jié)點(diǎn)的標(biāo)識(shí)值秒啦,結(jié)合Diff算法可以實(shí)現(xiàn)節(jié)點(diǎn)的復(fù)用陶舞。(key相同的節(jié)點(diǎn)會(huì)被復(fù)用)
只有當(dāng)key(或其他導(dǎo)致isSameNode判斷為false)發(fā)生改變時(shí)捡多,才會(huì)觸發(fā)節(jié)點(diǎn)的重新渲染。否則Vue將會(huì)復(fù)用之前的節(jié)點(diǎn)筐眷,通過(guò)改變節(jié)點(diǎn)的屬性來(lái)實(shí)現(xiàn)節(jié)點(diǎn)的更新黎烈。
<button @click="addEmployee">添加員工</button>
<ul>
<!-- 列表渲染時(shí),key值最好是對(duì)象的唯一屬性值,比如:學(xué)號(hào)照棋,工號(hào)资溃,身份證號(hào),手機(jī)號(hào)等待
目的是:當(dāng)列表更新時(shí)烈炭,提高后期的渲染性能溶锭。
因?yàn)関ue在渲染數(shù)據(jù)時(shí),先將數(shù)據(jù)生存一份虛擬DOM符隙,再將虛擬DOM生成對(duì)應(yīng)的真實(shí)DOM掛載到頁(yè)面中
當(dāng)vue中的數(shù)據(jù)修改后趴捅,會(huì)重新生成一份虛擬DOM,并跟之前的虛擬DOM進(jìn)行匹配霹疫,
如果兩份虛擬DOM中的key和key對(duì)應(yīng)的值完全相同拱绑,不會(huì)重新生成對(duì)應(yīng)的真實(shí)DOM
只有key和key對(duì)應(yīng)的值不同的虛擬DOM,才會(huì)生成新的真實(shí)DOM并掛載的頁(yè)面中丽蝎。-->
<li v-for="(item) in employees" :key="item.id">{{item}}</li>
</ul>
export default {
name: 'Home',
data() {
return {
//定義一個(gè)工程師數(shù)組
employees:[
{
id:1001,
name:'劉德華',
age:20,
sex:'男'
},
{
id:1002,
name:'張學(xué)友',
age:22,
sex:'男'
}
]
}
},
}
methods: {
//添加員工的方法
addEmployee(){
let emp = {
id:Date.now(),
name:'蔡依林',
sex:'女',
age:26
}
this.employees.unshift(emp)
}
},
2猎拨、key使用id與index區(qū)別
不推薦使用index作為key,因?yàn)檫@種做法會(huì)導(dǎo)致某些節(jié)點(diǎn)被錯(cuò)誤的原地復(fù)用征峦,具體如下:
性能損耗:列表渲染時(shí)會(huì)導(dǎo)致變動(dòng)項(xiàng)往后的所有列表節(jié)點(diǎn)(內(nèi)容)的更新(相當(dāng)于key沒(méi)有發(fā)揮作用)
出現(xiàn)錯(cuò)誤:某些節(jié)點(diǎn)在錯(cuò)誤的位置被復(fù)用迟几。(例如列表項(xiàng)中使用到復(fù)選框時(shí))
3消请、 Vue.nextTick()方法
定義:在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)栏笆。在修改數(shù)據(jù)之后立即使用這個(gè)方法,獲取更新后的 DOM臊泰。
所以就衍生出了這個(gè)獲取更新后的DOM的Vue方法蛉加。所以放在Vue.nextTick()回調(diào)函數(shù)中的執(zhí)行的應(yīng)該是會(huì)對(duì)DOM進(jìn)行操作的 js代碼;
理解:nextTick()缸逃,是將回調(diào)函數(shù)延遲在下一次dom更新數(shù)據(jù)后調(diào)用针饥,簡(jiǎn)單的理解是:當(dāng)數(shù)據(jù)更新了,在dom中渲染后需频,自動(dòng)執(zhí)行該函數(shù)丁眼,
<div class="one">
<input type="text" v-model="carName" />
<button @click="addCar">添加汽車(chē)</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 {
//汽車(chē)名稱(chēng)
carName: "",
//汽車(chē)數(shù)組
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方法,需要傳一個(gè)回調(diào)函數(shù)昭殉,
// 回調(diào)函數(shù)里面的代碼在DOM更新完成后執(zhí)行苞七。
this.$nextTick(() => {
// 讓最后一個(gè)li元素里面的input元素獲取焦點(diǎn)
this.$refs.list.lastChild.lastChild.focus();
});
},
addSex(){
// this.$set(this.employee,'sex','男')
// 直接添加的屬性,不具備響應(yīng)式
this.employee.sex='男'
// $forceUpdate()方法挪丢,迫使 Vue 實(shí)例重新渲染
this.$forceUpdate()
}
注意:Vue實(shí)現(xiàn)響應(yīng)式并不是數(shù)據(jù)發(fā)生變化之后DOM立即變化蹂风,而是按照一定的策略進(jìn)行DOM的更新。
nextTick惠啄,則可以再回調(diào)中獲取更新后的DOM。
4、自定義指令
<div v-red>好好學(xué)習(xí)</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>保時(shí)捷卡宴真好看</h2>'
}
},
//定義局部指令撵渡,所有的指令背后都是在操作DOM融柬,我們將這種功能稱(chēng)之為:造輪子。
directives:{
//自定義一個(gè)指令趋距,指令名稱(chēng)是myhtml丹鸿,
//自定義指令就是一個(gè)方法,該方法有兩個(gè)參數(shù):返回指令所在的dom元素棚品,綁定的一份數(shù)據(jù)
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靠欢、自定義插件
定義一個(gè)插件,插件就是將給Vue添加的全局成員铜跑,歸類(lèi)到一起去门怪,這樣做利于后期維護(hù)。
在src新建一個(gè)plugins文件夾锅纺,在新建一個(gè)index.js
// 插件本質(zhì)上就是一個(gè)對(duì)象
export default {
// 該對(duì)象中必須包含一個(gè)install()方法
// install()方法的第一個(gè)參數(shù)是Vue掷空,第二個(gè)參數(shù)是配置對(duì)象
// install()方式,會(huì)在use的時(shí)時(shí)候執(zhí)行囤锉,
// Vue.use(插件)坦弟,這里的Vue會(huì)作為install方法的第一個(gè)參數(shù)
install:function(Vue,options){
// 可以直接給Vue添加成員
Vue.sayHi = function(){
console.log('大家好!我是Vue');
},
Vue.msg = "歡迎是插件",
// 可以在Vue的原型上擴(kuò)展成員
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);
}
},
}),
// 注冊(cè)全局組件
Vue.component('b-box', {
// 在腳手架環(huán)境中酿傍,只能通過(guò)渲染函數(shù)定義全局組件
render(h) {
return h('div',this.$slots.default)
},
}),
// 注冊(cè)全局指令
Vue.directive('bgcolor', function(el,bind){
el.style.backgroundColor = bind.value
})
}
}