版权声明:【原创】GitHub:https://github.com/susuGirl,微信公众号:fuxiaodexing,博客:https://blog.csdn.net/weixin_41845146 https://blog.csdn.net/weixin_41845146/article/details/84872298
<!DOCTYPE html>
<html>
<head>
<title>myVue</title>
<style>
#app{
text-align: center;
}
</style>
</head>
<body>
<div id="app">
<form>
<input type="text" v-model="number" />
<button type="button" v-click="increment">增加</button>
</form>
<h3 v-bind="number"></h3>
</div>
</body>
<script>
function myVue(option) {
this._init(option)
}
myVue.prototype._init = function (options) { // 传了一个配置对象
this.$options = options
this.$el = document.querySelector(options.el)
this.$data = options.data
this.$methods = options.methods
this._binding = {}
this._obsever(this.$data)
this._compile(this.$el)
}
myVue.prototype._obsever = function (obj) {
let _this = this
Object.keys(obj).forEach((key) => {
if (obj.hasOwnProperty(key)) {
_this._binding[key] = {
directives: []
}
}
let value = obj[key]
if (typeof value === 'Object') {
_this._obsever(value)
}
let binding = _this._binding[key]
Object.defineProperty(_this.$data, key, {
enumerable: true,
configurable: true,
get: () => {
return value
},
set: (newVal) => {
if (value !== newVal) {
value = newVal
binding.directives.forEach((item) => {
item.update()
})
}
}
})
})
}
myVue.prototype._compile = function (root) {
let _this = this
let nodes = root.children
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i]
if (node.children.length > 0) {
_this._compile(node)
}
if (node.hasAttribute('v-click')) {
let attrVal = node.getAttribute('v-click')
node.onclick = _this.$methods[attrVal].bind(_this.$data)
}
if (node.hasAttribute('v-model') && (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA')) {
let attrVal = node.getAttribute('v-model')
_this._binding[attrVal].directives.push(new Watcher(
'input',
node,
_this,
attrVal,
'value'
))
node.addEventListener('input', () => {
_this.$data[attrVal] = node.value
})
}
if (node.hasAttribute('v-bind')) {
let attrVal = node.getAttribute('v-bind')
_this._binding[attrVal].directives.push(new Watcher(
'text',
node,
_this,
attrVal,
'innerHTML'
))
}
}
}
function Watcher(name, el, vm, exp, attr) {
this.name = name
this.el = el
this.vm = vm
this.exp = exp
this.attr = attr
this.update()
}
Watcher.prototype.update = function () {
this.el[this.attr] = this.vm.$data[this.exp]
}
window.onload = () => { // 当文档内容完全加载完成会触发该事件,避免获取不到对象的情况
new myVue({
el: '#app',
data: {
number: 0,
count: 0
},
methods: {
increment() {
this.number++
},
incre() {
this.count++
}
}
})
}
</script>
</html>