Vue(Vue数据代理)

138 阅读3分钟

数据代理

Vue框架的特性,主要是体现在如下两方面

  • 数据驱动视图
  • 双向数据绑定

数据驱动视图

  • 好处:当页面数据发生变化时,页面会自动重新渲染!
  • 注意:数据驱动视图是单向的数据绑定

双向数据绑定

在网页中,form表单负责**采集数据**,Ajax负责提交数据。

表单负责采集数据,作者在不操作DOM的前题下,vue自动把用户输入的信息取到更新到js数据中

好处:开发者不再需要手动操作DOM元素,来获取表单元素最新的值!

vue的特点

采用主键化模式,提高代码复用率、让代码更好维护 声明式编码,让编码人员无需直接操作dom元素

MVVM模型

  1. M:模型(Model) : data中的数据
  2. V:视图(View) :模板代码
  3. VM:视图模型(ViewModel): Vue实例 观察发现:
  4. data中所有的属性,最后都出现在vm身上
  5. vm身是的所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用

image.png

image.png

Object。defineproperty方法 (数据劫持,数据代理,计算属性)

Object.keys()将对象里的所有属性名提取出来形成数组

Object.defineProperty

  1. // 参数1:传添加属性的对象
  2. // 参数2:传对象中新增的键
  3. // 参数3:传配置项

枚举

可以枚举就是形容能遍历,不能枚举就是不能遍历,在我们使用Object.defineProperty进行添加对象里的键值时,添加的不能枚举

Object.defineProperty中的配置参数

enumerable

enumerable 控制Object.defineProperty创建的键值能否枚举,控制属性是否可以枚举,默认值是false

writerable

writerable 控制Object.defineProperty创建的键值能否修改,控制属性是否可以被修改,默认值是false

configurable

configurable 控制Object.defineProperty创建的属性是否能删除,控制属性是否可以删除,默认值为false

get()

当有人读取obj中age属性时,get函数(getter)就会被调用,且返回值就是age的值

注意:当我们写get()时上面的配置需要注释,否则↓

image.png

set()

当有人修改obj中age属性时,set函数(getter)就会被调用,且会收到修改的具体值

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        let number = 20
        let obj = {
            name: '靓仔',
            gander: "男",
        }
        // Object.defineProperty 
        // 参数1:传添加属性的对象
        // 参数2:传对象中新增的键
        // 参数3:传配置项
        Object.defineProperty(obj, "age", {
            /*      value: 18,//在对象创建的键的值
                 enumerable: true,//控制属性是否可以枚举,默认值是false
                 writable: true, //控制属性是否可以被修改,默认值是false
                 configurable: true, //控制属性是否可以删除,默认值为false */
            // 当有人读取obj中age属性时,get函数(getter)就会被调用,且返回值就是age的值
            get() {
                console.log('有人读取age属性了')
                return number
            },
            // 当有人修改obj中age属性时,set函数(getter)就会被调用,且会收到修改的具体值
            set(value) {
                console.log('有人修改了age')
                number = value
            }
        })
        // 不能枚举是什么呢?就是不能遍历
        /*  for (let key in obj) {
             console.log(obj[key] + "========" + key);
         }
         console.log(Object.keys(obj)) */
    </script>
</body>

</html>

数据代理

let obj1 = { x: 100 }
        let obj2 = { y: 200 }
        Object.defineProperty(obj2, 'x', {
            get() {
                console.log("obj2.x被读取将obj.x的值赋值给obj2.x")
                return obj1.x
            },
            set(value) {
                console.log("obj2.x被修改导致obj1.x的值为obj2.x被修改的值");
                obj1.x = value
            }
        })

Vue中的数据代理

image.png

image.png

Vue中的数据代理是怎么样的呢?

在我们创建Vue实例化对象vm时存储在Vue中配置项的data中的数据是存储在vm实例化对象中的_data中

image.png

但我们看到在vm实例化对象中也存在

image.png

那是为什么呢?

那是为了方便我们引用vm实例化对象中data的数据,因为我们当前的root盒子被vm实例化对象接管了,root盒子中的插值中如果要访问vm实例化对象中的data中的值我们需要_data.name,才能访问到会比较麻烦,所有我们可以看到vm实例化对象中还出现了

image.png 由此我们可以看出vm中的name和age被数据代理了,那他们代理的数据是哪里的呢?

很明显代理的肯定是vm实例化对象中_data的数据,vm实例化对象中 _dataVue配置项中的data数据是等价的。但我们_data中数据打开与我们预想的不一样

image.png 这是为什么呢?

因为_data中的数据进行了数据拦截,对于数据拦截我就是与视图相关联数据变化就渲染到视图

image.png 只要Vue配置项data中的数据变化视图就会变化

image.png

image.png

<!-- 
        1.Vue中的数据代理:
            通过vm对象来代理data对象中属性的操作(读/写)
        2.Vue中数据代理的好处:
            更加方便的操作data中的数据
        3.基本原理
            通过Object.DefineProperty()把data对象中所有属性添加到vm上
            为每一个添加到vm上的属性,都指定一个getter/setter。
            在getter/setter内部去操作(读/写)data中对应的属性
     -->
    <div id="root">
        <div>{{name}}</div>
        <div>{{age}}</div>
    </div>
    <script src="../../vue.js"></script>
    <script>
        Vue.config.productionTip = false
        let vm = new Vue({
            el: '#root',
            data: {
                name: "小黑",
                age: 21
            }
        })
    </script>