数据代理,数据劫持,key原理,vue监视数据变化视图响应式更新

目录

数据代理

数据劫持 

key作用与原理

Vue检索数据  this.$set( target, key, value )

数据代理

  1. 了解Object.defineproperty方法
           // Object.defineproperty 的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性

           // Object.defineproperty可以接收三个参数

           // Object.defineproperty(obj, prop, desc)

           // obj :  第一个参数就是要在哪个对象身上添加或者修改属性

           // prop : 第二个参数就是添加或修改的属性名

           // desc : 配置项,一般是一个对象

            let number = 18
			let person = {
				name:'张三',
				sex:'男',
			}
			Object.defineProperty(person,'age',{
				// value:18,
				// enumerable:true, //控制属性是否可以枚举,默认值是false
				// writable:true, //控制属性是否可以被修改,默认值是false
				// configurable:true //控制属性是否可以被删除,默认值是false
				
               //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
				get(){
					console.log('有人读取age属性了')
					return number
				},
				
                //当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
				set(value){
					console.log('有人修改了age属性,且值是',value)
					number = value
				}
			})
         

2. 拓展:关于Object.keys()和Object.values()的使用

// 关于Object.keys():查看一个对象本身的所有属性,返回一个数组,成员是参数对象自身的(不含继承的)//所有可遍历(enumerable)属性的键名 (取对象属性名转成数组)

let person ={ name:'张三',age:24,address:'杭州' }
Object.keys(person) // ['name', 'age', 'address']
Object.keys(person).forEach(key => {
  console.log(key)  //name, age, address
  console.log(person[key])  //张三, 24, 杭州
})


//关于Object.values() 
//Object.values()和Object.keys()是相反的操作,把一个对象的值转换为数组 (取对象属性值转成数组)
let person = { name: '张三', age: 24, address: '杭州', getName: function () {} }
console.log(Object.keys(person)) // ['name', 'age', 'address', 'getName']
Object.keys(person).map((key) => {
    console.log(person[key], '属性值') //获取到属性对应的值,根据需求做一些处理
})

3. 数据代理的定义:通过一个对象代理对另一个对象中属性的操作(读|写)

            let obj = {x:100}
			let obj2 = {y:200}

			Object.defineProperty(obj2,'x',{
                //当有人读取obj2的x属性时,get函数(getter)就会被调用,且返回值就是x的值
				get(){
					return obj.x
				},
                //当有人修改obj2的x属性时,set函数(setter)就会被调用,且会收到修改的具体值
				set(value){
					obj.x = value
				}
			})

4. vue中的数据代理

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>Vue中的数据代理</title>
		<!-- 引入Vue -->
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
		<!-- 
			    vm:vue实例对象   vc:组件实例对象
				1.Vue中的数据代理:
							通过vm对象来代理data对象中属性的操作(读/写)
				2.Vue中数据代理的好处:
							更加方便的操作data中的数据
				3.基本原理:
							通过Object.defineProperty()把data对象中所有属性添加到vm上。
							为每一个添加到vm上的属性,都指定一个getter/setter。
							在getter/setter内部去操作(读/写)data中对应的属性。
		 -->
		<!-- 准备好一个容器-->
		<div id="root">
			<h2>学校名称:{{name}}</h2>
			<h2>学校地址:{{address}}</h2>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
		
		const vm = new Vue({
			el:'#root',
			data:{
				name:'张三',
				address:'杭州'
			}
		})
	</script>
</html>

数据劫持 

key作用与原理

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>key的原理</title>
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
		<!-- 
				面试题: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是没有问题的。
		-->
		<!-- 准备好一个容器-->
		<div id="root">
			<!-- 遍历数组 -->
			<h2>人员列表(遍历数组)</h2>
			<button @click.once="add">添加一个测试</button>
			<ul>
				<li v-for="(item,index) of persons" :key="index">
					{{item.name}}-{{item.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>

Vue检索数据  this.$set( target, key, value )

Vue中this.$set的用法
1.  Vue.set( target, propertyName/index, value )

     数组:第一个参数是要修改的数组, 第二个值是修改的下标或字段,第三个是要修改成什么值。

2. this.$set(this._data,”key”,value')
      对象:第一个参数是要修改的对象, 第二个值是修改属性字段,第三个是要修改成什么值。

      target: 要更改的数据源(可以是一个对象或者数组) key 要更改的具体数据 (索引) value 重新赋的值。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>总结vue数据监视</title>
		<style>
			button{
				margin-top: 10px;
			}
		</style>
		<!-- 引入Vue -->
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
		<!--
			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的根数据对象(vm._data) 添加属性!!!
		-->
		<!-- 准备好一个容器-->
		<div id="root">
			<h1>学生信息</h1>
			<button @click="addSex">添加性别属性,默认值:女</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:'mary',
					age:18,
					hobby:['唱歌','跳舞','跑步'],
					friends:[
						{name:'jerry',age:25},
						{name:'tony',age:16}
					]
				}
			},
			methods: {
				addSex(){
					// Vue.set(this.student,'sex','女')
					this.$set(this.student,'sex','女')
				},
				addFriend(){
					this.student.friends.unshift({name:'jack',age:50})
				},
				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>


 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值