手寫簡單的雙向數據綁定

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();
        });
    }
複製代碼

這樣結合上面的雙向數據綁定解釋

相關文章
相關標籤/搜索