用原生js实现Vue单向数据绑定

94 阅读1分钟

何为数据的单向绑定?

传统开发模式下,如使用jQuery开发,我们想将一个变量显示到html中,首先要定义一个变量name,然后通过jq代码操作dom将变量放到HTML中,如果name发生修改,还要再次通过jq代码操作dom将新的变量值放到HTML中。这就是传统的MVC框架,其中的Model和View是我们通过代码联系在一起的。

在MVVM框架中,我们不再过多的关注数据与视图间的操作,而是使用一种新的机制,数据的单/双向绑定。

Vue单向数据绑定

Vue单向数据绑定,数据只能从data流向页面,即数据改变,页面元素也会跟着改变;而页面元素改变时,数据并不会跟着变。主要有两种形式:

1.插值形式

    <template>
    <div id="vm">
        <p>Hello, {{name}}!</p>
        <p>You are {{age}} years old!</p>
    </div>
    </template>
    <script>
    export default {
      data(){
        return{
          name:'951',
          age:28
        }
      }
    }
<script>

2.v-bind形式

    <template>
    <div id="vm">
      <p v-bind:class="classed">Hello, {{name}}!</p>
    </div>
    </template>
    <script>
    export default {
      data(){
        return{
          name:'951',
          classed:'red'
        }
      }
    }

    <script>
    <style>
        .red {
            background: red;
        }
    
    
        .blue {
            background: blue;
        }
    </style>

单向数据流过程:

简单的单向数据流(unidirectional data flow)是指用户访问View,View发出用户交互的Action,在Action里对state进行相应更新。state更新后会触发View更新页面的过程。这样数据总是清晰的单向进行流动,便于维护并且可以预测

原生js实如何现数据单向绑定?

首先会用到Object.defineProperty(),这个方法直接在对象上定义一个新属性,或修改对象上的现有属性,并返回该对象。

Object.defineProperty(obj, prop, descriptor)

参数

 obj 定义属性的对象。
 prop 要定义或修改的属性的名称。
 descriptor 定义或修改属性的描述符。
 返回值 传递给函数的对象。

注意:数据描述符和访问器描述符,不能同时存在(value,writable 和 get,set)

  get:函数return将被用作属性的值。

  set:该函数将仅接收参数赋值给该属性的新值。(在属性改变时调用)

看下边示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<input type="text" id="model"/>
<span id="spanCont">{{hello}}</span>
<script>
    // 双向数据绑定的原理:属性拦截
    // 属性拦截实现方式 : 使用Object.defineProperty()将对象的属性变成访问器属性。

    var obj = {};
    var model = document.querySelector("#model")
    var spanCont = document.querySelector("#spanCont")
    // obj 定义属性的对象。
     //prop 要定义或修改的属性的名称。
     //descriptor 定义或修改属性的描述符。
    Object.defineProperty(obj, 'hello', {
        get: function () {
            return model.value;
        },
        set: function (val) {
           spanCont.innerHTML = obj.hello;
        }
    });

    document.getElementById('model').onkeyup = function () {
        obj.hello = this.value;
    };

    obj.hello = ""; //属性名必须设置为空,否则在使用插值表达式的时候直接会把插值表达式显示出来
</script>
</body>
</html>