Vue的数据响应式

136 阅读2分钟

&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp数据响应式,即响应式的数据,数据一旦发生改变,视图就会做出相对应的变化。

&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp说到数据响应式,首先要知道ES6的getter/setter。

&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbspvue的数据打印出来正是个有get和set属性的对象,vue的data不是直接获取数值,而是get/set方法,来对数据进行读写操作。

let obj={
   fistName:'张',
   secondName:'三',
   get fullName(){
      return this.firstName+this.secondName;
   },
   set fullName(name){
      this.firstName=name[0]
      this.secondName=name.substring(1)
   }
}

//可以直接以属性方式调用,不加括号
obj.fullName
obj.fullName='李四'

&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp对于已经声明好的对象,我们不能直接去写入get/set,于是需要使用Object.defineProperty()来添加

let data={}
data._n=0
Object.defineProperty(data,'n',{
  get(){
      return this._n
  },
  set(value){
      if(value<0)return
      this._n=value
  }
})

&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp但是这样可以直接偷偷篡改data._n来使data.n的值发生变化,不会去走set的逻辑,为了避免原数据直接被篡改,试着使用代理

let data=proxy({data:{n:0}})//传入无法访问的匿名对象

function proxy({data}){
  const obj={}
  Object.defineProperty(obj,'n',{
     get(){
        return data.n
     },
     set(value){
        if(value<0)return
        data.n=value
     }
  })
  return obj
  //obj就是data的代理
}

但是如果需要采用

let data1={n:0}
let data2=proxy({data:data1})

&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp这种形式,n的值依然可以通过data1偷偷被改,依然是为了避免数据在不知情的情况下被修改,需要能够获取到“原数据”的修改过程

let myData={n:0}
let data=proxy2({data:myData})

function proxy2({data}){
  //监听逻辑
  let value=data.n
  //拷贝原数据后删除,再添加一个n,可以不加这句,因为定义了相同属性名,会直接覆盖
  delete data.n
  Object.defineProperty(data,'n',{
     get(){
       return value
     },
     set(newValue){
       if(newValue<0)return
       value=newValue
     }
  })
  //代理逻辑
  const obj={}
  Object.defineProperty(obj,'n',{
    get(){
      return data.n
    },
    set(value){
      if(value<0)return
      data.n=value
    }
  })
  return obj
}
myData.n=-1
console.log(data.n)//结果依然是0

类似于vm=new Vue({data:myData})

这会让vm成为myData的代理

会对myData的所有属性进行监控

防止myData的属性变了,vm不知道。vm监听了myData的属性变化就可以在每次数据被修改时直接调用render(data),实现响应式的数据变化。