vue中的数据代理

vue数据代理

Vue实现数据代理的核心----Object.defineProperty();

数据代理

数据代理的定义是:一个对象操作(读\写)另一个对象中的属性和方法。

  //  数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)
      let obj = { x: 100 }
      let obj2 = { y: 200 }
      Object.defineProperty(obj2, 'x', {
        get() {
          return obj.x
        },
        set(value) {
          obj.x = value
        },
      })
// 当访问obj2上的x属性时,就会调用get方法读取obj的属性,当我们修改了obj2上x属性时,就会调用set方法,并且传入修改的值value值,将obj的x属性改为value
Vue中的数据代理
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./vue.min.js"></script>
</head>
<body>
<!-- 1.Vue中的数据代理:
	 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 在启动时生成生产提示。
  let data = {
    name: 'xizhutao',
    address: '中国',
  }
  const vm = new Vue({
    el: '#root',
    data
  })
  console.log("vm",vm);
</script>
</html>

对于上面的案例,vm实例上有data中的数据,访问方式为:vm.name vm.address

image-20230715125639941

但不能通过vm.data.name 或 vm.data.address进行访。因为实例中的data被编译后在vm中就不是data,而是vm._data;即:vm._data == data ;

image-20230715130800272

image-20230715125852120

vue实例中的数据到通过vm.name进行访问,就是object.defineProperty() 所做的工作。

详细分析一波

打印一下vm实例,看看里面有那些东西:

image-20230715124027539

其中vm.name 以及 vm.address 属性是直接暴露在vue实例上的,这里的实例指的就是vm。借助官网的解释:

使用选项式 API,我们可以用包含多个选项的对象来描述组件的逻辑,例如 datamethodsmounted。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例。

是的,这里的API风格就是选项式API。

那么,data中的数据是如何暴露在其对应的实例中的呢?该工作就是由 数据代理的核心:object.defineProperty() 做的

首先,实例中的data会被实例编译为 vm中的 _data,然后object.defineProperty() 把 _data中的数据代理为 vm 下的name 和 address,也就实现了暴露在vm实例上。如图所示:

image-20230715111608718

我们操作的是vm.name 和 vm.address

访问vm.name ,object.defineProperty()就会通过其内置的get方法,把_data中的数据获取到并展示出来。

修改vm.name,object.defineProperty()就会通过其内置的set方法,等同于在_data中修改name;因为_data中的数据发生了改变,即是vm 实例中的 data 发生了改变,所以,页面上也会同步的更新。

object.defineProperty() 详解

Object.defineproperty方法需要传递3个参数;Object.defineproperty(obj, prop, desc )

参数

  • 参数1:obj 需要定义属性的当前对象
  • 参数2:prop 当前需要定义的属性名
  • 参数3:desc 描述符 一般是一个对象

一般通过为对象的属性赋值的情况下,对象的属性可以修改也可以删除,但是通过Object.defineProperty()定义属性,通过描述符的设置可以进行更精准的控制对象属性。

属性

注意:当使用了getter或setter方法,不允许使用writable和value这两个属性(如果使用,会直接报错)

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>Object.defineproperty方法</title>
	</head>
	<body>
		<script type="text/javascript" >
			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
				}
			})
 
			// console.log(Object.keys(person))
 
			console.log(person)
		</script>
	</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值