清單渲染
1. 基本清單
條件渲染:
1.v-if
寫法:
(1).v-if="表達式"
(2).v-else-if="表達式"
(3).v-else="表達式"
适用于:切換頻率較低的場景。
特點:不展示的DOM元素直接被移除。
注意:v-if可以和:v-else-if、v-else一起使用,但要求結構不能被“打斷”。
2.v-show
寫法:v-show="表達式"
适用于:切換頻率較高的場景。
特點:不展示的DOM元素未被移除,僅僅是使用樣式隐藏掉
3.備注:使用v-if的時,元素可能無法擷取到,而使用v-show一定可以擷取到
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>條件渲染</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 準備好一個容器-->
<div id="root">
<h2>目前的n值是:{{n}}</h2>
<button @click="n++">點我n+1</button>
<!-- 使用v-show做條件渲染 -->
<!-- <h2 v-show="false">歡迎來到{{name}}</h2>
<h2 v-show="1 === 1">歡迎來到{{name}}</h2> -->
<!-- 使用v-if做條件渲染 -->
<h2 v-if="false">歡迎來到{{name}}</h2>
<h2 v-if="1 === 1">歡迎來到{{name}}</h2>
<!-- v-else和v-else-if -->
<div v-if="n === 1">Angular</div>
<div v-else-if="n === 2">React</div>
<div v-else-if="n === 3">Vue</div>
<div v-else>哈哈</div>
<!-- v-if與template的配合使用 -->
<!-- template 模闆 -->
<template v-if="n === 1">
<h2>你好</h2>
<h2>尚矽谷</h2>
<h2>北京</h2>
</template>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'尚矽谷',
n:0
}
})
</script>
</html>
2. key的原理
面試題:react、vue中的key有什麼作用?(key的内部原理)
1. 虛拟DOM中key的作用:
key是虛拟DOM對象的辨別,當資料發生變化時,Vue會根據【新資料】生成【新的虛拟DOM】,
随後Vue進行【新虛拟DOM】與【舊虛拟DOM】的差異比較,比較規則如下:
2.對比規則:
(1).舊虛拟DOM中找到了與新虛拟DOM相同的key:
①.若虛拟DOM中内容沒變, 直接使用之前的真實DOM!
②.若虛拟DOM中内容變了, 則生成新的真實DOM,随後替換掉頁面中之前的真實DOM。
(2).舊虛拟DOM中未找到與新虛拟DOM相同的key
建立新的真實DOM,随後渲染到到頁面。
3. 用index作為key可能會引發的問題:
1. 若對資料進行:逆序添加、逆序删除等破壞順序操作:
會産生沒有必要的真實DOM更新 ==> 界面效果沒問題, 但效率低。
2. 如果結構中還包含輸入類的DOM:
會産生錯誤DOM更新 ==> 界面有問題。
4. 開發中如何選擇key?:
1.最好使用每條資料的唯一辨別作為key, 比如id、手機号、身份證号、學号等唯一值。
2.如果不存在對資料的逆序添加、逆序删除等破壞順序操作,僅用于渲染清單用于展示,
使用index作為key是沒有問題的。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>key的原理</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 準備好一個容器-->
<div id="root">
<!-- 周遊數組 -->
<h2>人員清單(周遊數組)</h2>
<button @click.once="add">添加一個老劉</button>
<ul>
<li v-for="(p,index) of persons" :key="index">
{{p.name}}-{{p.age}}
<input type="text">
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'張三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20}
]
},
methods: {
add(){
const p = {id:'004',name:'老劉',age:40}
this.persons.unshift(p)
}
},
})
</script>
</html>
3. 清單過濾
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>清單過濾</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 準備好一個容器-->
<div id="root">
<h2>人員清單</h2>
<input type="text" placeholder="請輸入名字" v-model="keyWord">
<ul>
<li v-for="(p,index) of filPerons" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
//用watch實作
//#region
/* new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'馬冬梅',age:19,sex:'女'},
{id:'002',name:'周冬雨',age:20,sex:'女'},
{id:'003',name:'周傑倫',age:21,sex:'男'},
{id:'004',name:'溫兆倫',age:22,sex:'男'}
],
filPerons:[]
},
watch:{
keyWord:{
immediate:true,
handler(val){
this.filPerons = this.persons.filter((p)=>{
return p.name.indexOf(val) !== -1
})
}
}
}
}) */
//#endregion
//用computed實作
new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'馬冬梅',age:19,sex:'女'},
{id:'002',name:'周冬雨',age:20,sex:'女'},
{id:'003',name:'周傑倫',age:21,sex:'男'},
{id:'004',name:'溫兆倫',age:22,sex:'男'}
]
},
computed:{
filPerons(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
}
}
})
</script>
</html>
4. 清單排序
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>清單排序</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<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>
<ul>
<li v-for="(p,index) of filPerons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
<input type="text">
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
keyWord:'',
sortType:0, //0原順序 1降序 2升序
persons:[
{id:'001',name:'馬冬梅',age:30,sex:'女'},
{id:'002',name:'周冬雨',age:31,sex:'女'},
{id:'003',name:'周傑倫',age:18,sex:'男'},
{id:'004',name:'溫兆倫',age:19,sex:'男'}
]
},
computed:{
filPerons(){
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>
</html>
5. vue資料監測原理
Vue監視資料的原理:
1. vue會監視data中所有層次的資料。
2. 如何監測對象中的資料?
通過setter實作監視,且要在new Vue時就傳入要監測的資料。
(1).對象中後追加的屬性,Vue預設不做響應式處理
(2).如需給後添加的屬性做響應式,請使用如下API:
Vue.set(target,propertyName/index,value) 或
vm.$set(target,propertyName/index,value)
3. 如何監測數組中的資料?
通過包裹數組更新元素的方法實作,本質就是做了兩件事:
(1).調用原生對應的方法對數組進行更新。
(2).重新解析模闆,進而更新頁面。
4.在Vue修改數組中的某個元素一定要用如下方法:
1.使用這些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
2.Vue.set() 或 vm.$set()
特别注意:Vue.set() 和 vm.$set() 不能給vm 或 vm的根資料對象 添加屬性!!!
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>總結資料監視</title>
<style>
button{
margin-top: 10px;
}
</style>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 準備好一個容器-->
<div id="root">
<h1>學生資訊</h1>
<button @click="student.age++">年齡+1歲</button> <br/>
<button @click="addSex">添加性别屬性,預設值:男</button> <br/>
<button @click="student.sex = '女' ">修改性别</button> <br/>
<button @click="addFriend">在清單首位添加一個朋友</button> <br/>
<button @click="updateFirstFriendName">修改第一個朋友的名字為:張三</button> <br/>
<button @click="addHobby">添加一個愛好</button> <br/>
<button @click="updateHobby">修改第一個愛好為:開車</button> <br/>
<button @click="removeSmoke">過濾掉愛好中的抽煙</button> <br/>
<h3>姓名:{{student.name}}</h3>
<h3>年齡:{{student.age}}</h3>
<h3 v-if="student.sex">性别:{{student.sex}}</h3>
<h3>愛好:</h3>
<ul>
<li v-for="(h,index) in student.hobby" :key="index">
{{h}}
</li>
</ul>
<h3>朋友們:</h3>
<ul>
<li v-for="(f,index) in student.friends" :key="index">
{{f.name}}--{{f.age}}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在啟動時生成生産提示。
const vm = new Vue({
el:'#root',
data:{
student:{
name:'tom',
age:18,
hobby:['抽煙','喝酒','燙頭'],
friends:[
{name:'jerry',age:35},
{name:'tony',age:36}
]
}
},
methods: {
addSex(){
// Vue.set(this.student,'sex','男')
this.$set(this.student,'sex','男')
},
addFriend(){
this.student.friends.unshift({name:'jack',age:70})
},
updateFirstFriendName(){
this.student.friends[0].name = '張三'
},
addHobby(){
this.student.hobby.push('學習')
},
updateHobby(){
// this.student.hobby.splice(0,1,'開車')
// Vue.set(this.student.hobby,0,'開車')
this.$set(this.student.hobby,0,'開車')
},
removeSmoke(){
this.student.hobby = this.student.hobby.filter((h)=>{
return h !== '抽煙'
})
}
}
})
</script>
</html>