Vue核心②(MVVM、数据代理)

导读:本篇文章讲解 Vue核心②(MVVM、数据代理),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

也许你感觉自己的努力总是徒劳无功,但不必怀疑,你每天都离顶点更进一步。今天的你离顶点还遥遥无期。但你通过今天的努力,积蓄了明天勇攀高峰的力量。加油!

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模板中都可以直接使用

数据代理

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

什么是数据代理

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

比如说我们有一个对象叫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>

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来办到的

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/122137.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!