基本列表
v-for指令:
1.用于展示列表數(shù)據(jù)
2.語法:v-for="(item,index) in xxx" :key="yyy"
3.可遍歷:數(shù)組舌仍、對象、字符串(用的很少)泰偿、指定次數(shù)(用的很少)
key的原理
面試題:react熄守、vue的key有什么作用(key的內(nèi)部原理)
1.虛擬DOM中key的作用:
key是虛擬DOM對象的標識,當狀態(tài)中的數(shù)據(jù)發(fā)生變化時耗跛,Vue會根據(jù)【新數(shù)據(jù)】生成【新的虛擬DOM】
隨后Vue進行【新虛擬DOM】與【舊虛擬DOM】的差異比較裕照,比較規(guī)則如下:
2.對比原則:
(1)舊虛擬DOM中找到了與新虛擬DOM相同的key
若虛擬DOM中內(nèi)容沒變,直接使用之前的真實DOM
若虛擬DOM中內(nèi)容變了调塌,則生成新的真實DOM晋南,隨后替換掉頁面中之前的真實DOM
(2)舊虛擬DOM中未找到與新虛擬DOM相同的key,創(chuàng)建新的真實DOM,隨后渲染到頁面
3.用index作為key可能會引發(fā)的問題:
( 1)若對數(shù)據(jù)進行:逆序添加羔砾、逆序刪除等破壞順序操作:
會產(chǎn)生沒有必要的真實DOM更新 =》界面效果沒問題负间,但效率低
(2)如果結(jié)構(gòu)中還包含輸入類的DOM:
會產(chǎn)生錯誤的DOM更新=》界面有問題
4.開發(fā)中如何選擇key
(1)最好使用每條數(shù)據(jù)的唯一標識作為key,比如ID姜凄、手機號政溃、身份證號、學號等
(2)如果不存在對數(shù)據(jù)的逆序添加檀葛、逆序刪除等破壞順序操作玩祟,僅用于渲染列表用于展示,使用index作為key是沒有問題的
<div id="root">
<!-- 遍歷數(shù)組 -->
<h2>人員列表(遍歷數(shù)組)</h2>
<ur>
<li v-for="(person,index) in persons" :key="person.id">
{{person.name}} - {{person.age}} - {{index}}
</li>
</ur>
<!-- 遍歷對象 -->
<h2>汽車信息(遍歷對象)</h2>
<ur>
<li v-for="(value,key) of car" :key="key">
{{key}} - {{value}}
</li>
</ur>
<!-- 遍歷字符串 -->
<ur>
<li v-for="(char,index) of str" :key="index">
{{index}} - {{char}}
</li>
</ur>
<!-- 遍歷指定次數(shù) -->
<ur>
<li v-for="(number,index) of 5" :key="index">
{{index}} - {{number}}
</li>
</ur>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:"#root",
data:{
persons:[
{id:'001',name:'張三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20},
],
car:{
name:'奧迪',
price:'20萬',
color:'黑色'
},
str:'hello'
},
})
</script>
列表過濾
<body>
<div id="root">
<h2>人員列表</h2>
<input type="text" placeholder="請輸入名字" v-model="keyWord">
<ur>
<li v-for="(p,index) in filPersons" :key="p.id">
{{p.name}} - {{p.age}} - {{p.sex}}
</li>
</ur>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
//watch實現(xiàn)
//#region
/*const vm = new Vue({
el:"#root",
data:{
keyWord:'',
persons:[
{id:'001',name:'馬冬梅',age:34,sex:'女'},
{id:'002',name:'周冬雨',age:29,sex:'女'},
{id:'003',name:'周杰倫',age:30,sex:'男'},
{id:'004',name:'溫兆倫',age:40,sex:'男'}
],
filPersons:[]
},
watch:{
keyWord:{
immediate:true,
handler(val){
this.filPersons = this.persons.filter((p)=>{
return p.name.indexOf(val) !== -1
})
}
}
}
})*/
// #region
//用computed實現(xiàn)
new Vue({
el:"#root",
data:{
keyWord:'',
persons:[
{id:'001',name:'馬冬梅',age:34,sex:'女'},
{id:'002',name:'周冬雨',age:29,sex:'女'},
{id:'003',name:'周杰倫',age:30,sex:'男'},
{id:'004',name:'溫兆倫',age:40,sex:'男'}
],
},
computed:{
filPersons(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
}
}
})
</script>
列表排序
<body>
<!--
-->
<div id="root">
<h2>人員列表</h2>
<input type="text" placeholder="請輸入名字" v-model="keyWord">
<button @click="sortType = 2">年齡升序</button>
<button @click="sortType = 1">年齡降序</button>
<button @click="sortType = 0">原順序</button>
<ur>
<li v-for="(p,index) in filPersons" :key="p.id">
{{p.name}} - {{p.age}} - {{p.sex}}
</li>
</ur>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
//用computed實現(xiàn)
new Vue({
el:"#root",
data:{
keyWord:'',
sortType:0,//0原順序 1:降序 2屿聋;升序
persons:[
{id:'001',name:'馬冬梅',age:34,sex:'女'},
{id:'002',name:'周冬雨',age:29,sex:'女'},
{id:'003',name:'周杰倫',age:30,sex:'男'},
{id:'004',name:'溫兆倫',age:40,sex:'男'}
],
},
computed:{
filPersons(){
const arr = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
//判斷是否需要排序
if(this.sortType){
arr.sort((p1,p2)=>{
return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
})
}
return arr
}
}
})
</script>
</body>
注意:更新數(shù)據(jù)時空扎,直接賦值無效,用splice方法有效
updateMei(){
//無效
// this.persons[0]= {id:'001',name:'馬老師',age:50,sex:'女'}
this.persons.splice(0,1,{id:'001',name:'馬老師',age:50,sex:'女'})
}