class Vue {
constructor(options) {
if (typeof options.beforeCreate === 'function') {
options.beforeCreate.bind(this)()
}
this.$data = options.data()
this.dataReact()
this.thisData(this.$data)
if (typeof options.created === 'function') {
options.created.bind(this)()
}
if (typeof options.beforeMount === 'function') {
options.beforeMount.bind(this)()
}
this.$el = document.querySelector(options.el)
this.methods = options.methods
if (typeof options.mounted === 'function') {
options.mounted.bind(this)()
}
this.compliedNode(this.$el)
}
thisData(data) {
for (let key in data) {
this[key] = data[key]
}
}
dataReact() {
Object.keys(this.$data).forEach(key => {
Observe.bind(this)(this.$data, key, this.$data[key])
})
function Observe(data, key, value, that = this) {
Object.defineProperty(data, key, {
get() {
return value
},
set(newVal) {
value = newVal
that[key] = newVal
that.Dep.trigger(key)
}
})
}
}
Dep = {
map: {},
collect(eventName, fn) {
if (!this.map[eventName]) {
this.map[eventName] = []
}
this.map[eventName].push(fn)
},
trigger(eventName) {
this.map[eventName].forEach(fn => fn())
}
}
compliedNode(node) {
let childNodes = node.childNodes
let tagNodes = Array.from(childNodes).filter(item => {
return item.nodeType === 1
})
this.recursiveNode(tagNodes)
}
recursiveNode(nodeParent) {
nodeParent.forEach(node => {
if (node.childNodes.length > 0) {
this.recursiveNode(node.childNodes)
}
if (node.nodeType === 1) {
let attrs = node.attributes
Array.from(attrs).forEach((item) => {
if (item.nodeName === '@click') {
node.addEventListener('click', this.methods[item.nodeValue].bind(this))
}
if (item.nodeName === 'v-model') {
node.value = this.$data[item.nodeValue]
this.Dep.collect(item.nodeValue, () => node.value = this.$data[item.nodeValue])
node.addEventListener('input', (e) => {
node.value = this.$data[item.nodeValue] = e.target.value
})
}
})
if (node.innerHTML.includes('{{')) {
let reg = /{{(.*?)}}/g
let match = node.innerHTML.match(reg)
match.forEach((item) => {
let key = item.slice(2, -2).trim()
if (this.$data[key]) {
node.innerHTML = node.innerHTML.replace(item, this.$data[key])
let lastValue = JSON.parse(JSON.stringify(this.$data[key]))
this.Dep.collect(key, () => {
if (lastValue !== this.$data[key]) {
node.innerHTML = node.innerHTML.replace(lastValue, this.$data[key])
lastValue = JSON.parse(JSON.stringify(this.$data[key]))
}
})
}
})
}
}
})
}
}