天天看点

vue双向绑定原来

1 实现最简单的双向绑定

我们知道,通过Object.defineProperty()可以实现数据劫持

Vue双向绑定原理

2 讲解vue如何实现

2.1 obsever–对data的所有属性,循环利用1中的方法实现数据劫持,然后通知订阅者,订阅者触发它的update方法,对视图进行更新。

obsever的实现如下;

function()

总结:最后demo如下:

{{text00}} {{text}} {{text}} {{text}} {{text02}}

// function nodeToFragment(node, vm) {

// var fragment = document.createDocumentFragment();

// var child;

// while (child = node.firstChild) {

// compile(child, vm);

// fragment.appendChild(child);

// }

// return fragment

// }

function nodeToFragment(node, vm) {

var frag = document.createDocumentFragment()

fragFoo(node, frag, vm)

return frag

}

function fragFoo(node, frag, vm) {

let nodes= node.childNodes

let length = nodes.length

for(let i=0; i<length; i++){

let child = nodes[0]

compile(child, vm)

frag.appendChild(child)

if(child.childNodes && child.childNodes.length) {

fragFoo(child, frag.lastChild, vm)

}

}

}

// Vue构造函数

// 观察data中的所有属性值,注意增添了observe

function Vue(options) {

this.data = options.data;

observe(this.data, this)

var id = options.el;

var dom = nodeToFragment(document.getElementById(id), this)

//处理完所有节点后,重新把内容添加回去

document.getElementById(id).appendChild(dom)

}

// 实现一个响应式监听属性的函数。一旦有赋新值就发生变化

function defineReactive(obj, key, val) {

var dep = new Dep();

Object.defineProperty(obj, key, {

get: function () {

if (Dep.target) {

dep.addSub(Dep.target)

}

return val

},

set: function (newVal) {

if (newVal === val) {

return

}

val = newVal;

console.log(‘新值’ + val);

//一旦更新立马通知

dep.notify();

}

})

}

// 实现一个观察者,对于一个实例 每一个属性值都进行观察。

function observe(obj, vm) {

for (let key of Object.keys(obj)) {

defineReactive(vm, key, obj[key]);

}

}

// Watcher监听者

function Watcher(vm, node, name) {

Dep.target = this;

this.vm = vm;

this.node = node;

this.name = name;

this.update();

Dep.target = null;

}

Watcher.prototype = {

update() {

this.node.nodeValue = this.vm[this.name] //更改节点内容,同时触发相应的get

}

}

// dep构造函数

function Dep() {

this.subs = []

}

Dep.prototype = {

addSub(sub) {

this.subs.push(sub)

},

notify() {

this.subs.forEach(function (sub) {

sub.update();

})

}

}

var vm = new Vue({

el: ‘app’,

data: {

text00: ‘hello’,

text: ‘nihao’,

text02: ‘hhh’

}

})

继续阅读