Vue源码分析之双向数据绑定

  • 双向数据绑定建立在单向数据绑定(model-view)的基础之上
  • 实现流程:
  1. 解析v-model指令时给当前元素添加input监听
  2. 当input的value发生改变时,将最新的值赋给当前表达式所对应的data属性
Compile.prototype = {
    compile: function (node) {
        var attrs = node.attributes,
        me = this;
        [].slice.call(attrs).forEach(function (attr) { 
            var attrName = attr.name
            if (me.isDrection(attrName)) {
                var exp = attrName.value,
                dir = attrName.slice(2);
                if (me.isEventDirection(dir)) {
                    eventHandler(node, me.$vm, dir, exp)
                } else {
                    compileUtil[dir] && compileUtil[dir](node, me.$vm, exp)  // 解析普通指令
                }
                node.removeAttribute(attrName)
            }
        })
    },
}

var compileUtil = {
    // 解析v-model
    model: function (node, vm, exp) {
        // 实现数据的初始化显示和创建对应的watcher
        this.bind(node, vm, exp, 'model')
        var value = this.getVMVal(vm, exp),
        me = this;
        // 给节点绑定input事件监听(输入改变时)
        node.addEventListener('input', function () {
            var newValue = e.target.value
            if (newValue === value) {
                return
            }
            // 将最新的value保存给表达式所对应的属性
            me.setVMVal(vm, exp, newValue)
            val = newValue
        })
    },
    bind: function (node, vm, exp, dir) {
        var updateFn = updater[dir+'Updater']
        updateFn && updateFn(node, this.getVMVal(vm, exp))
        
        // 为表达式创建一个对应的watcher,实现节点的更新
        new Watcher(vm, exp, function (value, oldValue) {//当表达式对应的一个属性值变化时回调
            // 更新界面中的指定节点
            updateFn && updateFn(node, value, oldValue)
        })
    },

    updateFn: function (node, val) {
        node.textContent = typeof val === 'undefined' ? '' : val
    },

    setVMVal: function (vm, exp, value) {
        var val = vm
        exp = exp.split('.')
        exp.forEach(function (k, i) {
            if (i < exp.length - 1) {
                val = val[k]
            } else {
                val[k] = value
            }
        })
        return val
    },
}

var updater = {
    modelUpdater: function (node, val) {
        node.value = typeof val === 'undefined' ? '' : val;
    },
}

 

你可能感兴趣的:(vue)