javascript实现数据的双向绑定(手动绑定)

2,041 阅读3分钟

今天来讲一下Javascript是如何实现数据的双向绑定,因为是第一次写文章所以是借鉴了一下别人的文章。根据别人的文章来谈一些自己的理解,废话不多说直接开始讲解。

首先数据双向绑定大家一定都不陌生(如angular,vue等),那么它的结构大致如下

<input q-value="value" type="text" id="input">
<div q-text="value" id="el"></div>

这跟vue的写法很像这是比较老的实现方式,有点像观察者编程模式,主要思路是通过在数据对象上定义get和set方法(当然还有其它方法),调用时手动调用get或set数据,改变数据后出发UI层的渲染操作;以视图驱动数据变化的场景主要应用与input、select、textarea等元素,当UI层变化时,通过监听dom的change,keypress,keyup等事件来出发事件改变数据层的数据。整个过程均通过函数调用完成。 先上一段代码

var elems = [document.getElementById('el'), document.getElementById('input')];

整体思路是先取到标签,然后把取到的标签放到一个数组里

var data = {
    value: 'hello!'
};

之后定义一个初始化的值数组data里面value的值为hello

var command = {
        text: function(str){
            this.innerHTML = str;
        },
        value: function(str){
            this.setAttribute('value', str);
        }
};

text定义文本得内容 value输入的内容之后通过setAttribute() 方法给输入框添加指定的文本内容 定义完之后基础的部分也就做好了之后是需要进行逻辑的编写

var scan = function(){
        /**
         * 扫描带指令的节点属性
         */
        for(var i = 0, len = elems.length; i < len; i++){
            var elem = elems[i];
            elem.command = [];
            for(var j = 0, len1 = elem.attributes.length; j < len1; j++){
                var attr = elem.attributes[j];
                if(attr.nodeName.indexOf('q-') >= 0){
                    /**
                     * 调用属性指令,这里可以使用数据改变检测
                     */
                    command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
                    elem.command.push(attr.nodeName.slice(2));
                }
            }
        }
    }

首先需要循环节点首先定义一个空数组elem.command = []用来存取改变的值, 之后需要循环获取指定字符首次出现的位置elem.attributes.length就是这个东西然后做判断调用指令,这里可以使用数据改变检测

 command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
 elem.command.push(attr.nodeName.slice(2));

之后可以设置扫描执行来改变视图的显示

function mvSet(key, value){
       data[key] = value;
       scan();
}

然后通过数据绑定监听来实现数据的绑定效果

elems[1].addEventListener('keyup', function(e){
       mvSet('value', e.target.value);
}, false);

addEventListener方法用于向指定元素添加事件句柄

target可返回事件目标节点(触发该事件的节点),如生成事件的元素、文档或窗口。

最后一步就是设置时间来更新视图的显示

 setTimeout(function(){
        mvSet('value', data.value)
},1000)

这里绑定了刚才上面设置的数组的值

下面帖一下整体的代码

<input q-value="value" type="text" id="input">
<div q-text="value" id="el"></div>
<script>
    var elems = [document.getElementById('el'), document.getElementById('input')];

    var data = {
        value: 'hello!'
    };

    var command = {
        text: function(str){
            this.innerHTML = str;
        },
        value: function(str){
            this.setAttribute('value', str);
        }
    };

    var scan = function(){
        /**
         * 扫描带指令的节点属性
         */
        for(var i = 0, len = elems.length; i < len; i++){
            var elem = elems[i];
            elem.command = [];
            for(var j = 0, len1 = elem.attributes.length; j < len1; j++){
                var attr = elem.attributes[j];
                if(attr.nodeName.indexOf('q-') >= 0){
                    /**
                     * 调用属性指令,这里可以使用数据改变检测
                     */
                    command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
                    elem.command.push(attr.nodeName.slice(2));
                }
            }
        }
    }

    /**
     * 设置数据后扫描
     */
    function mvSet(key, value){
        data[key] = value;
        scan();
    }
    /**
     * 数据绑定监听
     */
    elems[1].addEventListener('keyup', function(e){
        mvSet('value', e.target.value);
    }, false);

    scan();

    /**
     * 改变数据更新视图
     */
    setTimeout(function(){
        mvSet('value', 'fuck');
    },1000)

</script>

这样就做到了javascript的双向数据绑定,测试了一下绑定的数据还是不能改变的只能做到视图层的改变,之后我会进一步的研究双向绑定数据是如何改变的原理。

参考文章转自http://www.jb51.net/article/107917.html

如有解释上的错误还望各位提出来我会一一改正

经过3天的研究成果就是这么多因为本人是第一次发文章心里还是有点小紧张的希望各位多多包涵,谢谢。