Vue--如何自己实现双向数据绑定v-model ?

1. Vue v-model实现原理

VUE实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。

2. Object.defineProperty() 简单应用

  1. 简化版
var obj = {
      }
var name
//第一个参数:定义属性的对象。
//第二个参数:要定义或修改的属性的名称。
//第三个参数:将被定义或修改的属性描述符。
Object.defineProperty(obj, "data", {
     
  //获取值
  get: function () {
     
    return name
  },
  //设置值
  set: function (val) {
     
    name = val
    console.log(val)
  }
})
//赋值调用set
obj.data = 'aaa'
//取值调用get
console.log(obj.data)
  1. 详细版
// 详细版
 myVue.prototype._obverse = function (obj) {
      // obj = {number: 0}
    var value;
    for (key in obj) {
       //遍历obj对象
      if (obj.hasOwnProperty(key)) {
     
        value = obj[key];
        if (typeof value === 'object') {
       //如果值是对象,则递归处理
          this._obverse(value);
        }
        Object.defineProperty(this.$data, key, {
       //关键
          enumerable: true,
          configurable: true,
          get: function () {
     
            console.log(`获取${
       value}`);
            return value;
          },
          set: function (newVal) {
     
            console.log(`更新${
       newVal}`);
            if (value !== newVal) {
     
              value = newVal;
            }
          }
        })
      }
    }
  }

3. 如何实现v-model 双向绑定?

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>双向绑定</title>
</head>
<body>
  手写一个简单双向绑定<br/>
  <input type="text" id="model"><br/>
  <div id="modelText"></div>
</body>
<script>
  var model = document.querySelector("#model");
  var modelText = document.querySelector("#modelText");
  var defaultName = "defaultName";
  var userInfo = {
     }
  model.value = defaultName;
  Object.defineProperty(userInfo, "name", {
     
    get: function () {
     
      return defaultName;
    },
    set: function (value) {
     
      defaultName = value;
      model.value = value;
      console.log("-----value");
      console.log(value);
      modelText.textContent = value;
    }
  })
 
  userInfo.name = "new value";
  var isEnd = true;
 
  model.addEventListener("keyup", function () {
     
    if (isEnd) {
     
      userInfo.name = this.value;
    }
  }, false)
  //加入监听中文输入事件
  model.addEventListener("compositionstart", function () {
     
    console.log("开始输入中文");
    isEnd = false;
  })
  model.addEventListener("compositionend", function () {
     
    isEnd = true;
    console.log("结束输入中文");
  })
</script>
</html>

你可能感兴趣的:(Vue,vue.js,前端)