1.首先新建一个html在建立一个Kvue.js
<div id="app">
{{ message }}
<p>{{message}}</p>
<input type="text" k-model="name">{{name}}
<textarea k-model="age" name="" id="" cols="30" rows="10"></textarea>{{age}}
</div>
<script>
let vm = new Kvue({
el:'#app',
data:{
message: '数据展现',
name: '李四',
age: 20
}
})
</script>
复制代码
2.而后在Kvue.js新建一个class类
class Kvue {
constructor(options){
this.$options = options;
this._data = options.data;
this.observer(this._data)
this.compile(options.el)
}
observer (data){
Object.keys(data).forEach(key=>{
let value = data[key];
let dep = new Dep();
Object.defineProperty(data,key,{
enumerable: true,
configurable: true,
get (){
if (Dep.target){
dep.addSub(Dep.target);
}
return value
},
set (newValue){
if (newValue !== value)
value = newValue
dep.notify(newValue);
}
})
})
}
compile (el){
let element = document.querySelector(el);
this.compileNdoe(element)
}
compileNdoe(element){
let node = element.childNodes;
Array.from(node).forEach(node=>{
if (node.nodeType == 3){
// 处理文本
let nodeContext = node.textContent;
let reg = /\{\{\s*(\S*)\s*\}\}/;
if (reg.test(nodeContext)){
node.textContent = this._data[RegExp.$1];
new Watcher(this,RegExp.$1,newValue=>{
// 视图更新
node.textContent = newValue;
});
}
} else if (node.nodeType == 1){
let attrs = node.attributes;
Array.from(attrs).forEach(attr=>{
let attrName = attr.name;
let attrValue = attr.value;
if (attrName.indexOf('k-') == 0){
attrName = attrName.substr(2);
if (attrName == 'model'){
node.value = this._data[attrValue]
console.log(node.value)
}
node.addEventListener('input',e=>{
this._data[attrValue] = e.target.value;
})
new Watcher(this,attrValue,newValue =>{
node.value = newValue;
})
}
})
// 处理标签
}
if (node.childNodes.length > 0){
this.compileNdoe(node);
}
})
}
}
// 发布者
class Dep {
constructor(){
this.subs = []
}
addSub(sub){
this.subs.push(sub)
}
notify(newValue){
this.subs.forEach(v=>{
v.update(newValue);
})
}
}
//订阅者
class Watcher {
constructor(vm,exp,cb){
Dep.target = this;
vm._data[exp];
this.cb = cb;
Dep.target = null;
}
update(newValue){
this.cb(newValue);
}
}
复制代码
3.经过Object.defineProperty来监听数据变化,经过获取dom元素来实现数据绑定,最后经过发布者和订阅者来驱动视图更新。