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

理解

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>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,612评论 5 471
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,345评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,625评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,022评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,974评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,227评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,688评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,358评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,490评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,402评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,446评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,721评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,802评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,013评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,504评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,080评论 2 341