Vue 数据绑定
Vue2
vue.js
function vue(){
this.$data ={
a:1
};
this.el = document.getElementById("app");
this._html = "";
this.observe(this.$data)
this.render()
}
vue.prototype.observe = function(obj){
var value;
var self = this;
for(var key in obj){
value = obj[key];
if(typeof value === "object"){
this.observe(value);
}else{
Object.defineProperty(this.$data, key, {
get:function(){
// 会有依赖收集 deep()
return value;
},
set:function(newvalue){
// notify更新 监听组件语法树ast observe('AST)
value=newvalue;
self.render()
}
})
}
}
}
vue.prototype.render = function(){
this._html="i am" + this.$data.a;
this.el.innerHTML = this._html;
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
<script src="vue.js"></script>
<script>
var vm=new vue()
setTimeout(function(){
console.log('change')
console.log(vm.$data)
vm.$data.a=4
},3000) // 3秒视图更新
</script>
</body>
</html>
单一对象可以,但是数组是如何让他监听从而更新视图的呢
var arraypro = Array.prototype;
var arrayob = Object.create(arraypro);
var arr=["push","pop","shift"]
// arr里的方法,既能保持原有的方法,又能触发更新 装饰着模式
arr.forEach(function(method,index){
arryob[method] = function(){
var ret = arraypro[method].apply(this,arguments);
console.log('检测数组变动,触发更新')
// self.render()
return ret
}
})
var arr =[];
arr.__proto__=arrayob;
arr.push(1)
Vue3
function vue(){
this.$data ={
a:1
};
this.el = document.getElementById("app");
this._html = "";
this.observe(this.$data)
this.render()
}
vue.prototype.observe = function(obj){
var self = this;
this.$data=new Proxy(this.$data,{
get:function(target, key) {
return target[key]
},
set: function(target, key, newvalue){
target[key] = newvalue
self.render()
}
})
}
vue.prototype.render = function(){
this._html="i am" + this.$data.a;
this.el.innerHTML = this._html;
}
也可以看我之前的 vue3数据绑定 链接 地址
两种比较
defineProperty只能监听某个属性,不能全局对象监听,而proxy就可以,所以省去for-in;
defineProperty get中没有值;
,提高效率,可以监听数组,不需要再去单独对数组做操作
Proxy 做校验拦截
function createValidator(target,validator){
return new Proxy(target,{
_validator:validator,
set(target,key,value,proxy){
if(target.hasOwnProperty(key)){
var validator = this._validator[key];
if(validator(value)){
return Reflect.set(target,key,value,proxy)
}else{
throw Error('type,error')
}
}
}
})
}
var personValidator = {
name(val){
return typeof val === "string"
},
age(val){
return typeof val === "number"&&age>18
}
}
class Person{
constructor(name,age){
this.name = name;
this.age = age;
return createValidator(this,personValidator)
}
}
var tss = new Person('YP',18)
// tss.name