Vue监视数据的原理

334 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

列表过滤

在这里插入图片描述

列表过滤用watch或computed实现在输入框中输入关键字,从而使得下方列表留下包含关键字的几项,如下图:

在这里插入图片描述

实现代码:

<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">
	//用watch实现
	/* 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先执行一次保证开始就显示一个完整列表
				handler(val){
					this.filPerons = this.persons.filter((p)=>{
						return p.name.indexOf(val) !== -1
						//p.name.indexOf('马')值为0,'abcde'.indexOf('a')值为0.
					})
				}
			}
		}
	}) */
	
	//用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>

列表排序

通过点击按钮可以使列表变为相应的排序。

在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 </title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/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 filPersons" :key="p.id">
        		{{p.name}}-{{p.age}}-{{p.sex}}
        	</li>
        </ul>
    </div>
    <script type="text/javascript">
			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:{
					filPersons(){
						const arr = this.persons.filter((p)=>{
							return p.name.indexOf(this.keyWord) !== -1
						})
						//判断一下是否需要排序
						if(this.sortType){//!=0
							arr.sort((p1,p2)=>{
								return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
							})
						}
						return arr
					}
				}
			})
    </script>

</body>
</html>

Vue监视数据的原理

  • vue会监视data中所有层次的数据。

  • 如何监测对象中的数据? 通过setter实现监视,且要在new Vue时就传入要监测的数据。 (1).对象中后追加的属性,Vue默认不做响应式处理 (2).如需给后添加的属性做响应式,请使用如下API: Vue.set(target,propertyName/index,value) 或 vm.$set(target,propertyName/index,value)

  • 如何监测数组中的数据? 通过包裹数组更新元素的方法实现,本质就是做了两件事: (1).调用原生对应的方法对数组进行更新。 (2).重新解析模板,进而更新页面。

  • 在Vue修改数组中的某个元素一定要用如下方法: 1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse() 2.Vue.set() 或 vm.$set()

  • 特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象(vm._data) 添加属性!!!

  • 不能直接给数组中的某个元素赋值e.g.:this.student.friends[0] = {name:'tony',age:36},因为它==没有setter和getter==;但是this.student.friends[0].name = '张三'却是可以的,因为可看作 对象.属性='张三'。

<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">
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','男')//或vm.$set
		},
		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>