美文网首页
Object.defineProperty实现视图数据绑定dem

Object.defineProperty实现视图数据绑定dem

作者: Allan要做活神仙 | 来源:发表于2017-04-26 14:50 被阅读465次

    vue.js 最核心的功能有两个,一个是响应式数据绑定,二是组件系统。
    今天讲讲双向数据绑定的实现
    vue.js和avalon.js是通过Object.defineProperty实现双向数据绑定的

    1、简单用法如下

        var a= {}
        Object.defineProperty(a,"b",{
            value:123
        })
        console.log(a.b);//123
    

    2、具体参数看下面代码、其中有比较关键的setget

    var obj = {}; // Creates a new object 创造对象
    Object.defineProperty(obj, "hello", {
             get: function () {return sth},
             set: function (val) {/* do sth */}
    })
    obj.hello // 可以像普通属性一样读取访问器属性
    访问器属性的"值"比较特殊,读取或设置访问器属性的值,实际上是调用其内部特性:get和set函数。
    obj.hello // 读取属性,就是调用get函数并返回get函数的返回值
    obj.hello = "abc" // 为属性赋值,就是调用set函数,赋值其实是传参
    

    好了现在简单讲下如何实现数据视图绑定

    极简双向绑定的实现一

        <input type="text" id="test">
        <p id="test2"></p>
    
    <script type="text/javascript">
        var obj = {};
        Object.defineProperty(obj, "test", {
            set: function (newVal){
                document.getElementById("test2").innerHTML = newVal;
            }
        })
    
        document.addEventListener('keyup', function(e) {
            obj.test = e.target.value;    // input输入的值作为obj的“动态属性值”,赋值给p
        })
    </script>
    

    此例实现的效果是:随文本框输入文字的变化,span 中会同步显示相同的文字内容;在js或控制台显式的修改 obj.hello 的值,视图会相应更新。这样就实现了 model => view 以及 view => model 的双向绑定。

    ![vue实现双向绑定的原理]554AJ.png](https://img.haomeiwen.com/i1627906/f6bd2f7554a1e143.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    极简双向绑定的实现二

    HTML
        <div>
            <p>你好,<span id='nickName'></span></p>
            <div id="introduce"></div>
        </div>
        <button id="btn">点击</button>
    
    JS
    var userInfo = {};
    Object.defineProperty(userInfo, "nickName", {
        get: function(){
            return document.getElementById('nickName').innerHTML;
        },
        set: function(nick){
            document.getElementById('nickName').innerHTML = nick;
        }
    });
    Object.defineProperty(userInfo, "introduce", {
        get: function(){
            return document.getElementById('introduce').innerHTML;
        },
        set: function(introduce){
            document.getElementById('introduce').innerHTML = introduce;
        }
    })
    
    document.getElementById('btn').onclick = function(){
        userInfo.nickName = "xxx";
        userInfo.introduce = "我是xxx,我来自杭州,..."
    }
    
    0 1

    三、分解任务
    上述示例仅仅是为了说明原理。我们最终要实现的是:


    0
    1

    首先将该任务分成几个子任务:
       1、输入框以及文本节点与 data 中的数据绑定
       2、输入框内容变化时,data 中的数据同步变化。即 view => model 的变化。
       3、data 中的数据变化时,文本节点的内容同步变化。即 model => view 的变化。
    要实现任务一,需要对 DOM 进行编译,这里有一个知识点:DocumentFragment

    DocumentFragment

    DocumentFragment(文档片段)可以看作节点容器,它可以包含多个子节点,当我们将它插入到 DOM 中时,只有它的子节点会插入目标节点,所以把它看作一组节点的容器。使用 DocumentFragment 处理节点,速度和性能远远优于直接操作 DOM。Vue 进行编译时,就是将挂载目标的所有子节点劫持(真的是劫持,通过 append 方法,DOM 中的节点会被自动删除)到 DocumentFragment 中,经过一番处理后,再将 DocumentFragment 整体返回插入挂载目标。

    相关文章

      网友评论

          本文标题:Object.defineProperty实现视图数据绑定dem

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