https://www.jb51.net/article/172633.htm
function Vue(options){
this.$data = options.data
this.$el = document.querySelector(options.el)
this.derevtive = {}
this.Observer(this.$data)
this.Compile(this.$el)
}
Vue.prototype.Observer = function(data){
for(let key in data){
this.derevtive[key] = []
let direct = this.derevtive[key]
let oldVal = data[key]
Object.defineProperty(this.$data, key, {
get(){
return oldVal
},
set(newVal){
if(newVal !== oldVal){
oldVal = newVal
direct.forEach(item=>{
item.updata()
})
}
}
})
}
}
Vue.prototype.Compile = function(node){
let nodes = node.children
for(let i=0,len=nodes.length;i<len;i++){
let nodeChild = nodes[i]
if(nodeChild.children.length){
this.Compile(nodeChild)
}
if(nodeChild.hasAttribute('v-text')){
let attr = nodeChild.getAttribute('v-text')
this.derevtive[attr].push(new Watcher({
nodeChild,
type: 'innerText',
vm: this,
attr
}))
}
if(nodeChild.hasAttribute('v-model')){
let attr = nodeChild.getAttribute('v-model')
this.derevtive[attr].push(new Watcher({
nodeChild,
type: 'value',
vm: this,
attr
}))
nodeChild.addEventListener('input', ()=>{
this.$data[attr] = nodeChild.value
})
}
}
}
function Watcher(options){
this.nodeChild = options.nodeChild
this.type = options.type
this.vm = options.vm
this.attr = options.attr
this.updata()
}
Watcher.prototype.updata = function(){
this.nodeChild[this.type] = this.vm.$data[this.attr]
}
https://zhuanlan.zhihu.com/p/282763032
class Vue {
constructor(options){
this.$data = options.data
this.$el = document.querySelector(options.el)
this.derevtive = {}
this.Observer(this.$data)
this.Compile(this.$el)
}
// 数据劫持,代理所有的数据
Observer(data){
for(let key in data){
this.derevtive[key] = []
let direct = this.derevtive[key]
let oldVal = data[key]
Object.defineProperty(this.$data, key, {
get(){
return oldVal
},
set(newVal){
if(newVal !== oldVal){
oldVal = newVal
// 这里数据更新了,发布消息通知视图更新,
// this.derevtive里面存储了所有的数据的全部watcher实例,在解析指令的过程中创建
direct.forEach(item=>{
item.updata()
})
}
}
})
}
}
// 指令解析
Compile(node){
let nodes = node.children
for(let i=0,len=nodes.length;i<len;i++){
let nodeChild = nodes[i]
if(nodeChild.children.length){
this.Compile(nodeChild)
}
if(nodeChild.hasAttribute('v-text')){
let attr = nodeChild.getAttribute('v-text')
this.derevtive[attr].push(new Watcher({
nodeChild,
type: 'innerText',
vm: this,
attr: attr
}))
}
if(nodeChild.hasAttribute('v-model')){
let attr = nodeChild.getAttribute('v-model')
this.derevtive[attr].push(new Watcher({
nodeChild,
type: 'value',
vm: this,
attr: attr
}))
nodeChild.addEventListener('input', ()=>{
this.$data[attr] = nodeChild.value
})
}
}
}
}
class Watcher {
constructor(options){
this.nodeChild = options.nodeChild
this.type = options.type
this.vm = options.vm
this.attr = options.attr
this.updata()
}
updata(){
this.nodeChild[this.type] = this.vm.$data[this.attr]
}
}