手写简单的双向数据绑定

github.com/logictuLuoq…javascript

简单介绍一下MVVM

MVVM是Model-View-ViewModel的简写 MVVM 就是将其中的View 的状态和行为抽象化,让咱们将视图 UI 和业务逻辑分开。固然这些事 ViewModel 已经帮咱们作了html

仍是听不懂 简单一点

你控制 Model(数据)
写vue 全在控制数据
View(模板)
你就理解成 你写的templeat
ViewModel这东西叫vuevue

手写双向数据绑定是什么东西

咱们还记得react是这么操做的吗java

setData()累吧node

vue采用的是双向数据绑定 是什么呢 this.data简单吧react

咱们看里面的原理

我写完了双向数据绑定 应为中文名的缘由取名为mvvmgit

跑起来项目

git clone https://github.com/logictuLuoqi/Practice
    cd MVVM
    npm install serve
    serve .
复制代码

就跑起来了 为何要用 serve 是这样的本次代码采用 ES6的模块化github

我写代码的过程

首先写调用

<div id="app">
        <input type="text" id="a" v-model="text">
        {{ text }}
    </div>
复制代码

以后能够参照文章的 type ES6模块化

去写 MVVM的jsnpm

new Vue({
        el: 'app',
        data: {
            text: 'Hello Vue!'
        }
    })
复制代码

入口看完后咱们来看方法

observer(data, this);
    const dom = new Compile(document.querySelector(`#${el}`), this);
复制代码

针对于这两个点作一下解释bash

observer

我去这个名字也知道作什么了 双向数据绑定 这里采用 defineProperty

github.com/logictuLuoq…

帮助理解observer中的defineProperty

get() {
        if (Dep.target) {
            dep.addSub(Dep.target);
        }
        return val;
    },
    set(newVal) {
        if (newVal === val) return;
        val = newVal;
        dep.notify();
    },
复制代码

这里的 Dep.target后续介绍

dep.notify();后续解释

Compile

我在这里写的是createDocumentFragment 来代替虚拟dom这东西后面介绍虚拟dom

const frag = document.createDocumentFragment()
    return frag;
复制代码

写正则 匹配 {{里面的所有}}

const reg = /\{\{(.*)\}\}/;
复制代码

来查找到DOM节点上有这个属性的

if(node.nodeType === 3){
    if(reg.test(node.nodeValue)){
      let name = RegExp.$1;
      name = name.trim();
      new Watcher(vm, node, name, 'nodeValue');
    }
  }
复制代码

寻找input

for(let i = 0; i < attributes.length; i++){
        if(attributes[i].nodeName == 'v-model'){
            const { nodeValue } = attributes[i];
            node.addEventListener('input', function(e){
            vm[nodeValue] = e.target.value;
            })
            new Watcher(vm, node, nodeValue, 'value');
        }
    }
复制代码

Watcher

export default function Warcher(vm, node, name, type) {
        Dep.target = this;
        this.name = name;
        this.node = node;
        this.vm = vm;
        this.type = type;
        this.update();
        Dep.target = null;
    }
复制代码

Dep.target 大家发现了什么

往下看

Warcher.prototype.update = function () {
        this.get();
        const batcher = new Batcher();
        batcher.push(this)
    };

    Warcher.prototype.cb = function () {
        this.node[this.type] = this.vm.text;
    };

    Warcher.prototype.get = function () {
        this.node[this.type] = this.vm[this.name];
    };
复制代码

是否是丢失的都找到了呀

Dep.target

update()

那么Dep是什么鬼

Dep

export default function Dep(){
        this.subs = [];
    }

    Dep.prototype.addSub = function (sub) {
        this.subs.push(sub);
    }

    Dep.prototype.notify = function () {
        this.subs.forEach((sub) => {
           sub.update();
        });
    }

复制代码

就是这么说 把

export default function Dep(){
        this.subs = [Dep.target,Dep.target,Dep.target];
    }
复制代码
Dep.prototype.notify = function () {
        this.subs.forEach((sub) => {
           sub.update(); ==== Dep.target.update();
        });
    }
复制代码

这样结合上面的双向数据绑定解释

相关文章
相关标签/搜索