直接上代码呗!
<!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>双向数据绑定</title>
</head>
<body>
<div id="app">
<input type="text" v-model="name">
{{ name }}
</div>
<script src="./index.js"></script>
<script>
var vm = new Vue({
el: '#app',
data() {
return {
name: 'hello, lyq'
}
}
})
</script>
</body>
</html>
class Vue {
constructor(options) {
let { el, data } = options;
this.el = document.querySelector(el)
this._data = data()
this.domPool = {}
this.init()
}
init() {
this.initData()
this.initDom(this.el)
}
// 数据劫持
initData() {
let _this = this;
_this.data = {}
for (let key in _this._data) {
Object.defineProperty(_this.data, key, {
get() {
return _this._data[key]
},
set(newValue) {
_this._data[key] = newValue;
_this.domPool[key].nodeValue = newValue
}
})
}
}
initDom(el) {
this.bindDom(el)
this.bindInput(el)
}
// text处理
bindDom(el) {
let _childNodes = el.childNodes;
_childNodes.forEach(node => {
if (node.nodeType === 3) {
let reg = /\{\{(.*?)\}\}/g;
let _value = node.nodeValue;
let _isValid = reg.test(_value);
if (_isValid) {
let _name = RegExp.$1.trim();
node.nodeValue = this._data[_name]
this.domPool[_name] = node;
}
}
node.childNodes && this.bindDom(node)
})
}
// input 处理
bindInput(el) {
const _allInputs = el.querySelectorAll('input');
_allInputs.forEach(input => {
let vModel = input.getAttribute('v-model');
if (vModel) {
input.value = this.data[vModel];
input.addEventListener('input',
this.handleInput.bind(this, input, vModel),
false
)
}
})
}
handleInput(dom, key) {
this.data[key] = dom.value
}
}