html部分

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

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

响应式原理部分

class Vue {
  constructor(options) {
    //1.保存数据
    this.$options = options;
    this.$data = options.data;
    this.$el = options.el;

    //2.将data添加到响应式系统中
    new Observer(this.$data);

    //3.代理this.$data的数据
    Object.keys(this.$data).forEach(key => {
      this._proxy(key);
    })

    //4.处理el
    new Complier(this.$el, this);

  }

  _proxy(key) {
    Object.defineProperty(this, key, {
      configurable: true,
      enumerable: true,
      set(newValue) {
        this.$data[key] = newValue;
      },

      get() {
        return this.$data[key];
      }
    })
  }
}

class Observer {
  constructor(data) {
    this.data = data;

    Object.keys(data).forEach(key => {
      this.defineReactive(this.data, key, data[key]);
    })
  }

  defineReactive(data, key, val) {
    const dep = new Dep();
    Object.defineProperty(data, key, {
      enumerable: true,
      configurable: true,
      get() {
        if (Dep.target) {
          dep.addSub(Dep.target);
        }
        return val
      },
      set(newValue) {
        if (newValue === val) {
          return;
        }
        val = newValue;
        dep.notify();
      }
    })
  }
}

class Dep {
  constructor() {
    this.subs = [];
  }

  addSub(sub) {
    this.subs.push(sub);
  }
  notify() {
    this.subs.forEach(sub => {
      sub.update();
    })
  }
}

class Watcher {
  constructor(node, name, vm) {
    this.node = node;
    this.name = name;
    this.vm = vm;
    Dep.target = this;
    this.update();
    Dep.target = null;
  }

  update() {
    this.node.nodeValue = this.vm[this.name]
  }
}

const reg = /\{\{(.+)\}\}/

class Complier {
  constructor(el, vm) {
    this.el = document.querySelector(el);
    this.vm = vm;

    this.frag = this._createFragment();
    this.el.appendChild(this.frag);
  }

  _createFragment() {
    const frag = document.createDocumentFragment();

    let child;
    while (child = this.el.firstChild) {
      this._compile(child);
      frag.appendChild(child);
    }
    return frag;
  }

  _compile(node) {
    if (node.nodeType === 1) {
      const attrs = node.attributes;
      if (attrs.hasOwnProperty('v-model')) {
        const name = attrs['v-model'].nodeValue;
        node.addEventListener('input', e => {
          this.vm[name] = e.target.value;
        })
      }
    }
    if (node.nodeType === 3) {
      console.log(reg.test(node.nodeValue));
      if (reg.test(node.nodeValue)) {
        const name = RegExp.$1.trim();
        new Watcher(node, name, this.vm)
      }
    }
  }
}

vue实例部分

    const app = new Vue({
      el: '#app',
      data: {
        message: '你好啊',
        name:'Tom'
      }
    })
最后修改:2021 年 08 月 25 日 11 : 46 AM
如果觉得我的文章对你有用,请随意赞赏