美文网首页
从0开始探究vue-双向绑定原理

从0开始探究vue-双向绑定原理

作者: IT_梅 | 来源:发表于2020-02-26 10:06 被阅读0次

    理解

    vue是一个非常优秀的框架,其优秀的双向绑定原理,mvvm模型,组件,路由解析器等,非常的灵活方便,也使开发者能够着重于数据处理,让开发者更清晰的设计自己的业务。

    双向绑定,就是数据变化的时候,自动触发视图的变化。

    实践

    我们都理解,vue2.0中,双向绑定的核心为Object.defineProperty(obj, prop, descriptor),方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象

    参数obj要在其上定义属性的对象。

    参数prop要定义或修改的属性的名称。

    参数descriptor将被定义或修改的属性描述符。

    返回被传递给函数的对象。

    尝试Object.defineProperty拦截用户对变量的设置

    我们可以新建一个项目,用来模拟及学习vue双向绑定的相关内容

    
    +   vue相关
    
    +       |- 双向绑定原理
    
    +           |- js
    
    +               |- myVue.js
    
    +           |- index.html
    
    

    修改index.html中的内容,引入自己创建的myVue.js。

    
    +   <!DOCTYPE html>
    
    +   <html lang="en">
    
    +   <head>
    
    +       <meta charset="UTF-8">
    
    +       <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    +       <title>Document</title>
    
    +   </head>
    
    +   <body>
    
    +
    
    +      <script src="./js/myVue.js"></script>
    
    +   </body>
    
    +   </html>
    
    

    编辑myVue.js的内容,来尝试一下Object.defineProperty(obj, prop, descriptor)这个API

    
    +   var data = {
    
    +       a: 1
    
    +   }
    
    +   Object.defineProperty(data, 'a', {// 为data中的a进行拦截,读取a的时候返回自己新建的_a的值,设置a的值的时候,设置到_a上。这样,开发者对a的操作,都会映射到我们新建的虚拟的_a变量上
    
    +       configurable: true, //  是否允许删除属性,默认true
    
    +       enumerable: true, //  是否允许遍历,默认true
    
    +       get: function () {
    
    +           console.log('我被读取了,返回了_a的值', this._a)
    
    +           return this._a
    
    +       },
    
    +       set(value) {
    
    +           // this.a = value;
    
    +           this._a = value;
    
    +           console.log('我被设置了,被设置的值为', this._a, '并放进了a的对象中')
    
    +       }
    
    +   })
    
    

    在浏览器中,打开页面,并查看控制台,对data.a进行操作

    
    data.a                                                              myVue.js:8 
    
    我被读取了,返回了_a的值 undefined
    
    undefined
    
    ——————————————————————————————————————————————————————————————————————————————
    
    data.a = 10                                                         myVue.js:14 
    
    我被设置了,被设置的值为 10 并放进了a的对象中
    
    10
    
    ——————————————————————————————————————————————————————————————————————————————
    
    data.a                                                              myVue.js:8
    
    我被读取了,返回了_a的值 10
    
    10
    
    

    可以看到,我们对data.a进行的操作,实际改变的变量是我们已经拦截的_a变量。

    目前出现的问题是,第一次读取的时候,这个值没有被设置上,在下面来模拟解决方案

    私有变量

    声明概念_开头的变量一版为私有变量,外部无法访问,但是我们现在在控制台中输入并修改私有变量data._a

    
    data._a
    
    10
    
    ——————————————————————————————————————————————————————————————————————————————
    
    data._a = 20
    
    20
    
    ——————————————————————————————————————————————————————————————————————————————
    
    data._a
    
    20
    
    ——————————————————————————————————————————————————————————————————————————————
    
    data.a                                                              myVue.js:8 
    
    我被读取了,返回了_a的值 20
    
    20
    
    

    却可以拿到私有变量中的_a的值,也可以进行无拦截的修改,这显然是我们所不希望的

    所以我们可以为Object.defineProperty(obj, prop, descriptor)来进行封装一次,把我们理解的_a变成一个私有变量

    修改myVue.js的内容为如下内容,

    
    var data = {
    
        a: 1
    
    }
    
    myDefineProperty(data, 'a')
    
    function myDefineProperty(obj,key){//对Object.defineProperty进行一次拦截,使外界无法访问私有变量value
    
        var value = obj[key];
    
        Object.defineProperty(obj,key,{// 为data增加
    
            configurable: true, //  是否允许删除属性,默认true
    
            enumerable: true, //  是否允许遍历,默认true
    
            get: function () {
    
                console.log('我被读取了,返回了value的值', value)
    
                return value
    
            },
    
            set(newValue) {
    
                value = newValue;
    
                console.log('我被设置了,被设置的值为', newValue, '并放进了value的对象中')
    
            }
    
        })
    
    }
    
    

    然后再查看控制台

    
    data._a
    
    undefined
    
    ——————————————————————————————————————————————————————————————————————————————
    
    data.value
    
    undefined
    
    ——————————————————————————————————————————————————————————————————————————————
    
    data.a                                                             myVue.js:12
    
    我被读取了,返回了value的值 1
    
    1
    
    ——————————————————————————————————————————————————————————————————————————————
    
    

    开发者就无法自行操作我们设计的私有变量value的内容了

    自此,我们解决了,对一个对象属性的拦截,并且阻止了用户对我们设计的私有变量进行操作

    双向绑定实践

    我们知道了拦截属性之后,那么就进一步来实现,一个简单的双向绑定

    我们修改一下index.html中的内容

    
        <!DOCTYPE html>
    
        <html lang="en">
    
        <head>
    
            <meta charset="UTF-8">
    
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
            <title>Document</title>
    
    +       <input type="text" @change='changeIpt'>
    
    +       <p id='changeValue'></p>
    
        </head>
    
        <body>
    
    
    
            <script src="./js/myVue.js"></script>
    
        </body>
    
        </html>
    
    

    并在myVue.js中,在set中添加双向绑定的操作

    
        var data = {
    
            a: 1
    
        }
    
        myDefineProperty(data, 'a')
    
    +   var ipt = document.getElementById('ipt');
    
    +   ipt.oninput =  function(e){
    
    +       data.a = e.target.value
    
    +   }
    
        function myDefineProperty(obj,key){
    
            var value = obj[key];
    
            Object.defineProperty(obj,key,{// 为data增加
    
                configurable: true, //  是否允许删除属性,默认true
    
                enumerable: true, //  是否允许遍历,默认true
    
                get: function () {
    
                    console.log('我被读取了,返回了value的值', value)
    
                    return value
    
                },
    
                set(newValue) {
    
                    value = newValue;
    
    +               document.getElementById('iptValue').innerText = newValue;
    
    +               ipt.value = newValue;
    
                    console.log('我被设置了,被设置的值为', newValue, '并放进了value的对象中')
    
                }
    
            })
    
        }
    
    

    然后我们在input框里输入内容,便表现出了双向绑定的能力。

    点击查看demo

    记得打开控制台哦!~

    下方为录制的屏幕,可能无法正常显示,可以点击上方demo来查看

    <video id="video" controls="" preload="none" poster="http://www.meixiaohan.com/file/myBlog/useFile/mvvm-video.mp4">

    <source id="mp4" src="http://www.meixiaohan.com/file/myBlog/useFile/mvvm-video.mp4" type="video/mp4">
    

    </video>

    觉得好的话,可以给我的 github点个star

    <iframe
    style="margin-left: 2px; margin-bottom:-5px;"
    frameborder="0" scrolling="0" width="100px" height="20px"
    src="https://ghbtns.com/github-btn.html?user=mr-xiao-han&repo=myBlog&type=star&count=true" >
    </iframe>

    相关文章

      网友评论

          本文标题:从0开始探究vue-双向绑定原理

          本文链接:https://www.haomeiwen.com/subject/gtzpchtx.html