前提是对Vue有一定的了解
<!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>属性定义器</title>
<script type="text/javascript" src='vue.js'></script>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript">
var model = {
title:'test title'
};
var val = model.title;
Object.defineProperty(model,"title",{
get:function(){
console.log("调用了getter");
return val;
},
set:function(nval){
console.log("调用了setter");
val=nval;
}
})
window.setTimeout(function(){
model.title="一个人的朝圣之路";
console.log(model.title);
},1000);
</script>
</body>
</html>
那Vue是怎么实现
<!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>属性定义器</title>
<script type="text/javascript" src='vue.js'></script>
</head>
<body>
<div id="app">
<h1>{{title}}</h1>
<ul>
<li v-for ="item in users">{{item.name}}</li>
</ul>
<input type="text" v-model="name">
<button @click = "addUser">添加</button>
</div>
<script type="text/javascript">
var model = {
name:'新用户',
title:'Vue 项目',
users:[{name:'刘备'},{name:'关羽'},{name:'张飞'}]
};
var vue = new Vue({
el:'#app',
data:model,
methods:{
addUser:function(){
this.users.push({name:this.name});
this.name="";
}
}
})
</script>
<!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>属性定义器</title>
<script type="text/javascript" src='vue.js'></script>
</head>
<body>
<div id="app">
<h1>{{title}}</h1>
<ul>
<li v-for ="item in users">{{item.name}}</li>
</ul>
<input type="text" v-model="name">
<button @click = "addUser">添加</button>
</div>
<script type="text/javascript">
var model = {
title:'test title'
};
// Object.defineProperty(model,"title",{
// get:function(){
// console.log("调用了getter");
// return val;
// },
// set:function(nval){
// console.log("调用了setter");
// val=nval;
// }
// })
reactiveMVVM(model,"title");
function reactiveMVVM(obj,key){
var property = Object.getOwnPropertyDescriptor(obj, key);
console.log(property)
}
</script>
</body>
</html>
虽然报错,但是可以推断出以前哪怕只是简单的赋值,都会有默认的定义器配置,比如上方图片截图,什么都没做处理,但是类型值都是true;在以下代码中设置默认定义器配置false,如下:
<!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>属性定义器</title>
<script type="text/javascript" src='vue.js'></script>
</head>
<body>
<div id="app">
<h1>{{title}}</h1>
<ul>
<li v-for ="item in users">{{item.name}}</li>
</ul>
<input type="text" v-model="name">
<button @click = "addUser">添加</button>
</div>
<script type="text/javascript">
var model = {
title:'test title'
};
Object.defineProperty(model,"title",{
configurable: false,
enumerable: false,
writable: false
})
reactiveMVVM(model,"title");
function reactiveMVVM(obj,key){
var property = Object.getOwnPropertyDescriptor(obj, key);
console.log(property)
}
</script>
</body>
</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>属性定义器</title>
<script type="text/javascript" src='vue.js'></script>
</head>
<body>
<div id="app">
<h1 id="title">{{title}}</h1>
</div>
<script type="text/javascript">
var view = title;
var model = {
title:'test title'
};
reactiveMVVM(model,"title",model.title);
function reactiveMVVM(obj,key,val,customSetter){
var property = Object.getOwnPropertyDescriptor(obj, key);
// console.log(property)
if (property && property.configurable === false) { //false就不能监听
return
}
var getter = property && property.get; //原生
var setter = property && property.set; //原生
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
var value = getter ? getter.call(obj) : val;
// if (Dep.target) {
// dep.depend();
// if (childOb) {
// childOb.dep.depend();
// if (Array.isArray(value)) {
// dependArray(value);
// }
// }
// } //深度监测
return value
},
set: function reactiveSetter (newVal) {
var value = getter ? getter.call(obj) : val;
/* eslint-disable no-self-compare */
// 如果值相等,return 不做视图改变
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
/* eslint-enable no-self-compare */
if (customSetter) {
customSetter();
}
// #7981: for accessor properties without setter
if (getter && !setter) { return }
if (setter) {
setter.call(obj, newVal);
} else {
val = newVal;
}
// childOb = !shallow && observe(newVal); //watcher
// dep.notify();//通知
view.innerText = val;
}
}
)
}
</script>
</body>
</html>