Vue之MVVM数据代理

Posted 爱上口袋的天空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue之MVVM数据代理相关的知识,希望对你有一定的参考价值。

目录

一、MVVM模型

二、数据代理

2.1、Object.defineProperty

2.2、什么是数据代理

2.3、Vue中的数据代理


一、MVVM模型

  • M:模型(Model) :对应 data 中的数据
  • V:视图(View) :模板
  • VM:视图模型(ViewModel) : Vue 实例对象

 

  • 图的右下角是一个model它指的是一个一般的JS对象。整个绿色的部分讲就是Vue所缔造的实例对象。
  • 我们可以先看到向左指的箭头,他代表的意思是:存在JS一般对象里的数据经过Vue示例进行数据绑定,就把数据摆在了页面中想要的位置(页面就是把模板进行解析)
  • 再看向右指的箭头,他的大致意思是:页面上的改变,能映射回数据里的改变。完整过程:DOM监听器通过监听视图的数据变化来动态的改变JS对象里存储的数据。

我们还可以通过代码来理解:

说白了ViewModel就是把一堆乱七八糟的数据和DOM结构在中间进行了一次链接(相当于一个桥梁纽带)。前端领域中的一些主流框架都是运用到了这个思想:把数据放在要求的地方,然后写出模板代码,模板里面具体怎么插入值,就是框架的核心。

以后拿变量去接收Vue对象的时候,一般统一用vm 

注意:

  • 在data中的属性,我们在vm对象中也可以找得到
  • vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。

二、数据代理

2.1、Object.defineProperty

首先我们要了解Object.defineProperty这个方法,在Vue的底层很多地方都使用到了这个方法(比如:数据劫持、数据代理,计算属性等)。

这个方法用来给对象添加属性,其中要传入三个参数

  • 给哪个对象添加属性
  • 添加的属性叫什么名字
  • 配置对象(比如属性值value,控制遍历enumerable,控制修改的writable,控制删除的configurable等)

其中控制遍历enumerable,控制修改的writable,控制删除的configurable的默认值都是false。

 

那么这个方法有什么特别之处?直接添加不是更加简单嘛?

  • 用此方法添加的属性是不能被枚举的,也就是说不参加遍历。同时他还是不可以改变的,不可以删除的。(当然这些都可以通过配置对象进行修改)
  • 配置对象中还能添加一些高级配置。例如我们现在提一个需求:我们将一个对象的属性值设为一个变量,我们想让这个属性值随着变量的变化而变化。
  • 我们知道按照一般情况来说,这个是不能实现的,因为这个属性值他只会等于最初的那个变量值,其后变量发生改变,属性值也不会再发生变化。究其原因是因为代码从前往后执行,执行过了的代码不会再回头又去执行。
  • 不过我们可以通过一个高级配置项get()方法来解决这一个问题,这个方法在有人读取对应属性的时候(也就是你defineProperty()中指定的属性)会自动执行。并且这个方法的返回值作为对应属性的值
  • 同理还有一个高级配置项set()方法,这个方法会在有人修改对应的属性时调用,且会收到修改的具体值。

我们将上面涉及到的知识点形成代码:

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

 属性名为get,值是一个方法,把它们放在一起我们一般不叫get函数,而是叫做getter


2.2、什么是数据代理

数据代理通过一个对象代理对另一个对象中属性的操作(读 / 写)

比如说我们有一个对象叫obj,他有一个属性x,还有一个对象叫obj2。我们想让obj2也能访问到x,并且能修改x。这个过程就类似于数据代理。通过代码来理解:

   <body>
		<!-- 数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)-->
		<script type="text/javascript" >
			let obj = x:100
			let obj2 = y:200

			Object.defineProperty(obj2,'x',
				get()
					return obj.x
				,
				set(value)
					obj.x = value
				
			)
		</script>
	</body>

2.3、Vue中的数据代理

  • Vue中的数据代理

        通过vm对象来代理data对象中属性的操作(读/写)

  • Vue中数据代理的好处

        更加方便的操作data中的数据

  • 基本原理

        通过Object.defineProperty()把data对象中所有属性添加到vm上。为每一个添加到vm上的属性,都指定一个getter/setter。在getter/setter内部去操作(读/写)data中对应的属性。

我们先给出代码,来看看它的具体代理过程:

    <body>
 		<!-- 准备好一个容器-->
		<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>

 

我们将两个白色箭头从左到右依次称为第一步和第二步

我们首先解释第一步:
在创建完Vue实例对象vm之后,Vue会为这个对象准备一系列的属性方法。直到准备到_data,其中_data中的数据完全来源于data。注意这个过程没有使用代理,是直接赋值过来的。

(如果Vue单纯只做到这一步我们的代码也是可以书写的,只不过会非常的麻烦,我们写什么都要带上一个_data前缀)

 

 为了避免繁琐的前缀,所以说Vue会继续为vm对象创建name、address属性,也就是第二步。这个name的值是通过getter去读取到data里面的name。当有人修改vm上的name时,会通过setter映射到data里面的name进行修改。address同理也是如此。 图中的紫色、橙色两条箭头代表的就是数据代理,他们都是使用Object.defineProperty来办到的。

 

以上是关于Vue之MVVM数据代理的主要内容,如果未能解决你的问题,请参考以下文章

MVVM源码解析之数据代理篇

MVVM源码解析之数据代理篇

Vue基础系列MVVM模型-属性操作Object.defineProperty-数据代理

vue之mvvm的理解

前端MVVM框架之“Vue.js入门篇”

Vue学习——第四弹