vue的双向数据绑定

原理:

VUE实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。
它接收三个参数,要操作的对象,要定义或修改的对象属性名,属性描述符。重点就是最后的属性描述符。
属性描述符是一个对象,主要有两种形式:数据描述符和存取描述符。这两种对象只能选择一种使用,不能混合两种描述符的属性同时使用。上面说的get和set就是属于存取描述符对象的属性。

在面试中如何应对?
面试官:说一下VUE双向绑定的原理?
答:VUE实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。代码演示:defineProperty的用法var obj = { };var name;//第一个参数:定义属性的对象。//第二个参数:要定义或修改的属性的名称。//第三个参数:将被定义或修改的属性描述符。
Object.defineProperty(obj, “data”,
{//获取值get: function () {return name;},
//设置值set: function (val) {name = val;console.log(val)}})
//赋值调用 setobj.data = ‘aaa’;
//取值调用 getconsole.log(obj.data);

什么是数据双向绑定?

vue是一个mvvm框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。这也算是vue的精髓之处了。值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定。 单向数据绑定是使用状态管理工具(如redux)的前提。如果我们使用vuex,那么数据流也是单项的,这时就会和双向数据绑定有冲突,我们可以这么解决。

为什么要实现数据的双向绑定?

在vue中,如果使用vuex,实际上数据还是单向的,之所以说是数据双向绑定,这是用的UI控件来说,对于我们处理表单,vue的双向数据绑定用起来就特别舒服了。

即两者并不互斥, 在全局性数据流使用单项,方便跟踪; 局部性数据流使用双向,简单易操作。
   一、访问器属性
  Object.defineProperty()函数可以定义对象的属性相关描述符, 其中的set和get函数对于完成数据双向绑定起到了至关重要的作用,下面,我们看看这个函数的基本使用方式。

var obj = {
  foo: 'foo'
}

Object.defineProperty(obj, 'foo', {
  get: function () {
    console.log('将要读取obj.foo属性');
  }, 
  set: function (newVal) {
    console.log('当前值为', newVal);
  }
});

obj.foo; // 将要读取obj.foo属性
obj.foo = 'name'; // 当前值为 name

可以看到,get即为我们访问属性时调用,set为我们设置属性值时调用。
二、简单的数据双向绑定实现方法

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>forvue</title>
</head>
<body>
<input type="text" id="textInput">
输入:<span id="textSpan"></span>
<script>
var obj = {},
    textInput = document.querySelector('#textInput'),
    textSpan = document.querySelector('#textSpan');

Object.defineProperty(obj, 'foo', {
  set: function (newValue) {
    textInput.value = newValue;
    textSpan.innerHTML = newValue;
  }
});

textInput.addEventListener('keyup', function (e) {
    obj.foo = e.target.value;
});

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

最终效果图:
在这里插入图片描述
可以看到,实现一个简单的数据双向绑定还是不难的: 使用Object.defineProperty()来定义属性的set函数,属性被赋值的时候,修改Input的value值以及span中的innerHTML;然后监听input的keyup事件,修改对象的属性值,即可实现这样的一个简单的数据双向绑定。

三、 实现任务的思路
  上面我们只是实现了一个最简单的数据双向绑定,而我们真正希望实现的时下面这种方式:

<div id="app">
        <input type="text" v-model="text">
        {{ text }}
</div>  

    <script>
        var vm = new Vue({
            el: '#app', 
            data: {
                text: 'hello world'
            }
        });
    </script>

即和vue一样的方式来实现数据的双向绑定。那么,我们可以把整个实现过程分为下面几步:

输入框以及文本节点与 data 中的数据绑定
输入框内容变化时,data 中的数据同步变化。即 view => model 的变化。
data 中的数据变化时,文本节点的内容同步变化。即 model => view 的变化。

四、DocumentFragment
  如果希望实现任务一,我们还需要使用到 DocumentFragment 文档片段,可以把它看做一个容器,如下所示:

<div id="app">
        
    </div>
    <script>
        var flag = document.createDocumentFragment(),
            span = document.createElement('span'),
            textNode = document.createTextNode('hello world');
        span.appendChild(textNode);
        flag.appendChild(span);
        document.querySelector('#app').appendChild(flag)
    </script>

这样,我们就可以得到下面的DOM树:
 在这里插入图片描述
 使用文档片段的好处在于:在文档片段上进行操作DOM,而不会影响到真实的DOM,操作完成之后,我们就可以添加到真实DOM上,这样的效率比直接在正式DOM上修改要高很多 。

vue进行编译时,就是将挂载目标的所有子节点劫持到DocumentFragment中,经过一番处理之后,再将DocumentFragment整体返回插入挂载目标。

如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>forvue</title>
</head>
<body>
    <div id="app">
        <input type="text" id="a">
        <span id="b"></span>
    </div>

    <script>
        var dom = nodeToFragment(document.getElementById('app'));
        console.log(dom);

        function nodeToFragment(node) {
            var flag = document.createDocumentFragment();
            var child;
            while (child = node.firstChild) {
                flag.appendChild(child);
            }
            return flag;
        }

        document.getElementById('app').appendChild(dom);
    </script>

</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值