VUE实现原理v-model双向数据绑定原理学习分析

 

1、view视图层

实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数

2、mode数据层

实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者

实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,

执行指令绑定的相应回调函数,从而更新视图

de479adc706cc21c6dc12810d523195000f.jpg

具体代码实现原理

/**
 * 初始化vue对象,把定义的组件的vue对象初始
 * 获取lue对象的data数据,实行data属性的数据双向绑定
 *
 */
class Lue {
    constructor(options) {
        // 参数私有化
        this.data = options.data
        var data = this.data
        var id = options.el
        // 1、对数据模型的监听,对数据层的管理
        observe(data, this)
        // 2、对视图层的监听,实现视图层的同步
        var dom = nodeToFragment(document.getElementById(id), this)
        document.getElementById(id).appendChild(dom)

    }
}
//mode
function observe(obj, vm) {
    // 这里特别注意,我们以前直接返回data为json格式对象,现在为函数对象
    // 取出所有属性遍历
    let dataJson=""
    if (!obj || typeof obj !== 'function') {
         dataJson = obj
    }else{
         dataJson = obj.apply()
    }
    Object.keys(dataJson).forEach((objkey) => {
        defineRecActive(vm, objkey, dataJson[objkey])
    })
}
// 数据热反应堆
function defineRecActive(vm, key, value) {
    // observe(value,vm); // 监听子属性
    var dep = new Dep()
    Object.defineProperty(vm, key, {
        set: function (val) {
            if (val === value) {
                retutn
            }
            value = val
            dep.notiy()

        },
        get: function () {
            if (Dep.target) {
                dep.addSubs(Dep.target)
            }
            return value;
        }
    })

}

class Watcher {
    constructor(vm, node, name) {
        Dep.target = this;
        this.vm = vm;
        this.node = node;
        this.name = name;
        this.update();
        Dep.target = null;
    }
    update() {
        this.get()
        this.node.nodeValue = this.value
    }
    get() {
        this.value = this.vm[this.name]
    }
}
class Dep {
    constructor() {
        this.subs = [] // 创建wahcher仓库
    }
    addSubs(sub) {
        this.subs.push(sub)
    }
    notiy() {
        this.subs.forEach((sub) => {
            sub.update()
        })
    }
}
// dom 模版引擎整理-------------------------------视图层整理---------------------------------------
function nodeToFragment(node, vm) {
    //整理现有最新的dom对象
    var flag = document.createDocumentFragment(); //这个是创建一个文档片段
    var child;
    // 把node的信息全部移动到flag中
    while (child = node.firstChild) {
        Compile(child, vm)
        flag.append(child)
    }
    return flag
}

function Compile(node, vm) {
    // 我们对标签节点进行过滤
    if (node.nodeType === 1) {
        if (node.hasAttribute("v-model")) {
            var name = node.getAttribute("v-model");
            console.log("name: " + name)
            node.addEventListener('input', e => {
                vm[name] = e.target.value
                console.log(vm)
            })
        }
        node.value = vm[name]
        node.removeAttribute("v-model")


    }
    let reg = /\{\{(.*)\}\}/
    if (node.nodeType === 3) {
        if (reg.test(node.nodeValue)) {
            var name = RegExp.$1
            name = name.trim()
            console.log(name)

            node.nodeValue = vm[name]
        }
    }
    new Watcher(vm, node, name) // 进行➡监听
}
// dom 模版引擎整理-------------------------------视图层整理---------------------------------------

转载于:https://my.oschina.net/liuxinzhou/blog/2244630

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值