<script>
//发布者
class Vue {
constructor(options) {
this.options = options
this.$data = options.data
this.$el = document.querySelector(options.el)
this._directives = {} //存放订阅了对应数据的(什么东西)
//{myText:[订阅者1,订阅者2],mybox:[订阅者1]}
this.Observer(this.$data)
this.Compile(this.$el)
}
//劫持数据
Observer(data) {
//更新视图
for (let key in data) {
this._directives[key] = []
let _this = this._directives[key]
let val = data[key] //当前值
Object.defineProperty(this.$data, key, {
get: function () {
return val
},
set: function (newVal) {
if (newVal !== val) {
val = newVal
//[订阅者1,订阅者2]
_this.forEach(watch => {
watch.update()
});
}
}
})
}
}
//解析指令
Compile(el) {
let nodes = el.children //获取根节点下的子元素
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i] //当前元素
if (node.children.length) {//如果还有子节点
this.Compile(node)
}
if (node.hasAttribute("v-text")) { //查找v-text
let attrVal = node.getAttribute("v-text")
this._directives[attrVal].push(new Watch(node, attrVal, this, 'innerHTML'))
}
if (node.hasAttribute("v-model")) { //查找vmodel
let attrVal = node.getAttribute("v-model")
this._directives[attrVal].push(new Watch(node, attrVal, this, 'value'))
let _this = this
node.addEventListener("input", (function () {
return function () {
//更新视图到模型
_this.$data[attrVal] = node.value
}
})())
}
}
}
}
//订阅者
class Watch {
constructor(el, vm, mySelf, attr) {
this.el = el
this.vm = vm
this.mySelf = mySelf
this.attr = attr
this.update()
}
update() {
this.el[this.attr] = this.mySelf.$data[this.vm]
//div对象[innerHTML]=vue对象.data["myText"]
}
}
</script>
<body>
<div id="app">
<h1>数据响应式</h1>
<div>
<div v-text="myText"></div>
<input type="text" v-model="myText">
</div>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
myText: '大吉大利,今晚吃鸡'
}
})
</script>
vue双向绑定原理
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 关于Vue实现数据双向绑定的原理,请点击:Vue实现数据双向绑定的原理原文链接:JavaScript设计模式之观察...