JSFiddle - React, Tailwind, and code Playground

by ruirui

HTML

vue 动态数据绑定(五)
<div id="app">
  <p>姓名:<span>{{user.name}}</span></p>
  <p>年龄:<span>{{user.age}}</span></p>
</div>
<input type="text" id="input">

JavaScript

function Vue(obj) {
  this.el = obj.el;
  this.data = obj.data;
  new Observer(this.data);
  new Compile(this.el, this);
}

/*-----------------------Observer--------------------*/
function Observer(data) {
  this.data = data;
  if(Array.isArray(data)){
    // 暂不考虑数组
  }else{
    this.makeObserver(data);
  }
}

Observer.prototype.makeObserver = function(data) {
  var self = this;
  for (var i in data) {
    if (data.hasOwnProperty(i)) {
      if (typeof data[i] === 'object') {
        new Observer(data[i]);
      } else {
        this.getset(i, data[i]);
      }
    }
  }
}

Observer.prototype.getset = function (i, value) {
  let val = value;
  let self = this;
  var dep = new Dep();
  Object.defineProperty(this.data, i, {
    configurable: true,
    enumerable: true,
    get: function () {
      console.log('你访问了' + i);
      if(Dep.target){   // 注意:这里进行收集依赖
        dep.addSub(Dep.target);
      }
      return val;
    },
    set: function (newval) {
      console.log('你设置了' + i + ',新的值为' + newval);
      if(val === newval) {
        return
      }
      val = newval;
      if(typeof newval === 'object') {
        new Observer(val);
      }
      dep.notify();
    }
  })
}


/*-----------------------Dep--------------------*/

function Dep () {
  this.subs = []; // 观察者合集
}
Dep.target = null; // 全局唯一的 Watcher,看是谁在进行依赖收集

// 向subs数组添加依赖
Dep.prototype.addSub = function (sub) {
  this.subs.push(sub);
};

Dep.prototype.notify = function () {
  // 通知所有订阅者更新
  this.subs.forEach((item) => {
    item.update();
  })
};



/*-----------------------Watcher--------------------*/
function Watcher(vm, exp, cb) {
  Dep.target = this; // Watcher 初始化的时候,将Dep.target指向全局唯一的 Watcher
  this.vm = vm;
  this.cb = cb;
  this.exp = exp;
  this.get();
  Dep.target = null;
}
Watcher.prototype.get = function() {
  return CompileUtil.parse(this.exp)(this.vm.data); // 获取值得时候会触发属性的getter添加监听,这样就将观察者加入了订阅器中,然后清空Dep.target。
}
Watcher.prototype.update = function() {
  // 获得新值
  this.newVal =...