vue2_5、MVVM模型、数据代理

1、MWM模型

mvvm模型:就是把数据和dom通过一个中间对象进行连接。
image

  • M:模型Model, data中的数据,把它当作一个单独的模块,不属于VM,因为VM对象里会将它复制一份在里面作为数据代理。data里的数据改变vue会重新解析模板。

  • V:视图View,模板代码

  • VM:视图模型ViewModel, Vue实例

观察发现

  • data中所有的属性,最后都出现在了vm身上
  • vm身上所有的属性及Vue原型身上所有的属性,在Vue模板中都可以直接使用
<!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>初始vue</title>
    <!-- 引入vue-->
    <script src="/vueBaseJs/vue.js"></script>
</head>
<body>

    <div id="root">
        <h1>学校名:{{name}}</h1>
        <h1>学校地址:{{address}}</h1>
        <h1>{{$options}}</h1>
    </div>

    <script>

        Vue.config.productionTip=false;//阻止vue启动时生成生产提示

        const vm=new Vue({
            el:"#root",
            data:function(){
                return {
                    name:"李四",
                    address:"南充"
                }
            }
        });

        console.log(vm);

    </script>
    
</body>
</html>

数据交换:
image

或者这样
image

大概流程:dom加载后执行js,然后vue就去获取容器里的dom,将里面的用vue写法的内容给替换为对应的数据(向model拿),然后再把修改后的dom返回给容器。不然浏览器会把{{name}}原格式输出。正因为有了vue的一番操作,将{{name}}替换为对应的数据。
image



2、数据代理

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

        const obj1={x:100};

        const obj2={y:200};

        //让obj2成为obj1的数据代理(也就是让obj2能访问和操作obj1的属性)
        Object.defineProperty(obj2,"x",{
            get:function(){
                return obj1.x;
            },
            set:function(value){
                obj1.x=value;
            }            
        });

        //这样在读obj2的x属性就等于是在间接操作obj1的x属性。

在控制台输出obj2对象可以看到,当鼠标悬停在obj2的x属性上时,就会有一个getter标识,就代表这个x属性是会调用get函数来读取值。
image

obj2的x属性在逻辑上就如下图一下连接着obj1的x属性。
image


vue中的数据代理

  1. Vue中的数据代理通过Vue的实例vm对象来代理data对象中属性的操作(读/写)。

  2. Vue中数据代理的好处:更加方便的操作data中的数据。

  3. 基本原理:
    a.通过object.defineProperty()data对象中所有属性添加到vm
    b.为每一个添加到vm上的属性,都指定一个gettersetter
    c.在gettersetter内部去操作(读/写)data中对应的属性。

image

Vuedata中的数据拷贝了一份到_data属性中,又将_data里面的属性提到Vue实例中(如name) ,通过defineProperty实现数据代理,这样通过geter/setter操作name,进而操作_data中的name。而_data又对data进行数据劫持,实现响应式。一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新。也就是改变_data里的数据,模型data也会受影响,而data数据改变,就会影响到页面上的值,因为vue会监听data模块。

vue的实例vm身上的_data是实例化时代码里的data的关系:就是实例身上的_data是data的数据代理,改实例身上的_data实际上是间接改data的属性。data就是MVVM里的Model,它在逻辑上是不属于vue的实例vm的。而是单独存在的。实例vm身上根本不可能有data属性,在实例化vue的实例vm的时候传进去的配置对象里的data在逻辑上本身就是单独的一个模块。实例vm确实会拷贝一个data存在自己身上,只不过这个属性名叫_data

实际上,vue的实例vm身上的_data通过vue底层实现了更改_data里的数据data里也会跟着改变,这就是上面说的它们存在着某种类似数据代理的关系。实际上,vue也为了方便我们开发,把_data里的属性给添加到了vm实例身上,这也是通过数据代理实现的,只是为了我们开发,比如:页面里可以用name直接访问到_data里的name,实际上也可以通过_data.name访问,但是这样比较麻烦,所以vue才做了_data的数据代理。

<!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>初始vue</title>
    <!-- 引入vue-->
    <script src="/vueBaseJs/vue.js"></script>
</head>
<body>

    <div id="root">
        <h1>学校名称:{{name}}</h1><br/>
        <h1>地址:{{address}}</h1>
    </div>

    <script>

        Vue.config.productionTip=false;//阻止vue启动时生成生产提示


        const obj={
                    name:"南职",
                    address:"南充"
                };

        const vm=new Vue({
            el:"#root",
            data:function(){
                return obj;
            }
        });

    </script>
    
</body>
</html>
posted @ 2022-04-01 12:44  青仙  阅读(96)  评论(0编辑  收藏  举报