天天看點

12.清單渲染

清單渲染

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>
           
vue