<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="name" placeholder="name">
<input type="text" v-model="age" placeholder="age">
<input type="text" v-model="email" placeholder="email">
<input type="text" v-model="tel" placeholder="tel">
<br>
<p>姓名:<span>{{ name }}</span></p>
<p>年龄:<span>{{ age }}</span></p>
<p>邮箱:<span>{{ email }}</span></p>
<p>电话:<span>{{ tel }}</span></p>
</div>
<script>
class MVVM {
constructor(el, data) {
this.el = document.querySelector(el)
this._data = data
this.domPool = {}
this.init()
}
init() {
this.initData()
this.initDom()
}
initDom() {
this.bindDom(this.el)
this.bindInput(this.el)
}
initData() {
this.data = {}
const _this = this
for (const key in this._data) {
Object.defineProperty(this.data, key, {
get() {
return _this._data[key]
},
set(newVal) {
_this.domPool[key].innerHTML = newVal
_this._data[key] = newVal
}
})
}
}
bindInput(el) {
const nodeList = document.querySelectorAll('input')
nodeList.forEach(item => {
const _VModel = item.getAttribute('v-model')
if (!_VModel) return
item.addEventListener('keyup', this.handleInput.bind(this, _VModel, item), false)
})
}
handleInput(key, el) {
const value = el.value
this.data[key] = value
}
bindDom(el) {
const childs = el.childNodes
childs.forEach(item => {
if (item.nodeType === 3) {
const _value = item.nodeValue
if (_value.trim().length) {
let isValid = /\{\{(.+?)\}\}/.test(_value)
if (isValid) {
const _key = _value.match(/\{\{(.+?)\}\}/)[1].trim()
this.domPool[_key] = item.parentNode
item.parentNode.innerText = this._data[_key] || undefined
}
}
}
item.childNodes && this.bindDom(item)
})
}
}
</script>
<script>
new MVVM('#app', {
name: '1',
age: '1',
email: '1',
tel: '1'
})
</script>
</body>
</html>```
手搓V-model双向绑定实现原理-基于defineProperty
最新推荐文章于 2024-04-03 16:05:44 发布