模仿vue的mvvm实现方式,实现数据渲、改变data以及v-model
源码地址vue
script src="Tvue.js"></script>
<body>
<div id="app">
{{message}}
<p>{{message}}</p>
</div>
</body>
<script>
let vm = new Tvue({
el: "#app",
data: {
message: '测试'
}
})
</script>
复制代码
先实现数据替换功能node
class Tvue {
constructor(options) { // new Tvue里的值
this.$options = options
this._data = options.data // 参考源码,避免与data重名
this.compile(options.el) // 查找替换
}
compile(el) {
// 做用域 范围内查找
let element = document.querySelector(el) // 获取<div id="app"></div>
let childNodes = element.childNodes // 获取子节点
Array.from(childNodes).forEach((node) => {
// console.log(node, 'nodeType 属性可用来区分不一样类型的节点,好比 元素, 文本 和 注释。')
if (node.nodeType === 3) {
// 文本替换
let nodeContent = node.textContent
let reg = /\{\{\s*(\S*)\s*\}\}/ // 考虑插值表达式的先后空格
if (reg.test(nodeContent)) {
node.textContent = this._data[RegExp.$1]
}
} else {
}
})
}
}
复制代码
打开浏览器mvvm模式已经实现,有个问题是git
{{message}}github
尚未被替换,还须要使用递归实现多层嵌套查找替换compileNode(element) { // 递归实现多层嵌套查找替换
let childNodes = element.childNodes // 获取子节点
Array.from(childNodes).forEach((node) => {
// console.log(node, 'nodeType 属性可用来区分不一样类型的节点,好比 元素, 文本 和 注释。')
if (node.nodeType === 3) {
// 文本替换
let nodeContent = node.textContent
let reg = /\{\{\s*(\S*)\s*\}\}/ // 考虑插值表达式的先后空格
if (reg.test(nodeContent)) {
node.textContent = this._data[RegExp.$1]
}
} else if (node.nodeType === 1) { // 处理标签
}
if (node.childNodes.length > 0) {
this.compileNode(node)
}
})
}
复制代码
OK,截止目前能够实现多层数据嵌套vuex
let attrs = node.attributes;
Array.from(attrs).forEach(attr => {
let attrName = attr.name;
let attrValue = attr.value;
if (attrName.indexOf("t-") == 0) {
attrName = attrName.substr(2);
if (attrName == "model") {
node.value = this._data[attrValue];
}
node.addEventListener("input", e => {
this._data[attrValue] = e.target.value;
})
new Watcher(this, attrValue, newValue => {
node.value = newValue;
});
}
})
复制代码