这里的代码只是说明最好用this
const myData = {
n:0
}
const vm = new Vue({
data(){
return {
n:0
}
},
template:`
<div>{{n}}<button @click="add">+10</button></div>
`,
methods:{
add(){
this.n += 10 //最好用this.n,因为一般data数据都写在opitons中了
//myData.n += 10
}
}
}).$mount("#app")
setTimeout(()=>{
myData.n +=10
console.log(myData) //本节课精髓
})
什么是数据响应式
如果修改Vue的实例vm.n的值,UI就会自动响应。
先插入一些知识点
先讲一下ES6的新语法,getter和setter
getter
let obj2 = {
姓:"高",
名:"圆圆",
//get表示后面只是一个属性,只是以函数形式来定义而已,是计算属性
get 姓名(){
return this.姓 + this.名;
},
age:18
}
//调用不需要加括号
obj2.姓名
setter
let obj3 = {
姓:"高",
名:"圆圆",
set 姓名(xxx){
this.姓 = xxx[0]
this.名 = xxx.slice(1)
},
age = 18
}
//给姓名设置值
obj3.姓名 = "刘诗诗"
虽然可以对”姓名”进行读和写,但并不存在一个真正的姓名属性,只存在”get 姓名”和”set 姓名”
再学习一下Object.defineProperty
给obj3添加一个属性
var _xxx = 0 //这个声明,是用来放xxx的值的
//注意,这里的xxx是不存在的属性
Object.defineProperty(obj3,"xxx",{
get(){
return _xxx
},
set(value){
_xxx = value
}
})
几个实验
需求一,用Object.defineProperty定义
let data0 = {
n:0
}
//需求一,用Object.defineProperty定义
let data1 = {}
Object.defineProperty(data1,"n",{
value: 0
})
console.log(`需求一:${data1.n}`)
//总结:这傻逼语法把事情搞复杂了?非也,继续看
需求二,不能小于0,即data2.n = -1应该无效,但data2.n = 1有效
let data2 = {}
data2._n = 0 //_n 用来偷偷存储n的值
Object.defineProperty(data2,'n',{
get(){
return this._n
},
set(value){
if(value < 0) return
this._n = value
}
})
console.log(`需求二:${data2.n}`)
需求三,使用代理
let data3 = proxy({data:{n:0}}) //括号里是匿名对象,无法访问
function proxy({data}){ //解构赋值
const obj = {}
//这里的n,写死了,理论上应该遍历data的所有key,这里做了简化
//因为我怕你们看不懂
Object.defineProperty(obj,'n',{
get(){
return data.n
},
set(value){
if(value < 0) return
data.n = value
}
})
return obj
}
console.log(`需求三:${data3.n}`)
data3.n = -1
console.log(`需求三:${data3.n},设置为-1失败`)
data3.n = 1
console.log(`需求三:${data3.n},设置为1成功`)
需求四,绕过代理仍然能改
let myData = {n:0}
let data4 = proxy({data:myData})
console.log(`杠精:${data4.n}`)
myData.n = -1
console.log(`杠精:${data4.n},设置为-1失效了吗?`)
//现在还不是可以改myData
需求五,就算用户擅自修改myData,也要拦截他
let myData5 = {n:0}
let data5 = proxy2({data.myData5})
function proxy2(data){
let value = data.n //保存最开始的n
Object.defineProperty(data,'n',{ //这里声明的n是虚拟属性,放到了data上,会覆盖初始的n
get(){
return value
},
set(newValue){
if(newValue<0) return
value = newValue
}
})
//就加了上面几句,这几句话会监听data,是监听的逻辑
const obj = {}
Object.defineProperty(obj,'n',{
get(){
return data.n
},
set(value){
if(value < 0) return
data.n = value
}
})
//这几句是代理的逻辑
return obj //obj就是代理
}
console.log(`需求五:${data5.n}`)
myData5.n = -1
console.log(`需求五:${data5.n},设置为-1失效了`)
myData5.n = 1
console.log(`需求五:${data5.n},设置为1成功了`)
以上是任何时候都能监听数据的修改,原理等同于vue的内部源码。
小结:
Object.defineProperty
可以给对象添加属性value
可以给对象添加getter/setter
getter/setter用于对属性的读写进行监控
啥是代理(设计模式)
对myData对象的属性读写,全权由另一个对象vm负责
那么vm就是myData的代理(类似房东租房)
比如myData.n不用,偏要用vm.n来操作myData.n
vm=new Vue({data:myData})
一、会让vm成为myData的代理(proxy)
二、会对myData的所有属性进行监控
为什么要监控,为了放置myData的属性变了,vm不知道
vm知道了又如何?知道了属性变了就可以调用render(data)呀!
UI=render(data)
资料来源:饥人谷