Vue之MVVM数据代理
Posted 爱上口袋的天空
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue之MVVM数据代理相关的知识,希望对你有一定的参考价值。
目录
一、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数据代理的主要内容,如果未能解决你的问题,请参考以下文章