Vue初识三

86 阅读2分钟

一、看以下代码

import Vue from "vue/dist/vue.js";
Vue.config.productionTip = false;

const myData = {
  n: 0
};
console.log(myData)
const vm = new Vue({
  data: myData,
  template: `<div>{{n}} 
    <button @click="add">+10</button></div>
   `,
  methods: {
    add() {
      // this.n+=10
      myData.n += 10;
    }
  }
}).$mount("#app");
setTimeout(() => {
  myData.n += 10;
  console.log(myData);
  console.log(vm);
}, 3000);
console.log(myData)

显示结果为

image.png

log得出的myData值为

image.png 可以看到n{n:0}变成n:(...) 为什么???

二、getter

1.如何不用()获得姓名

看第一段代码

let obj1={
  姓:"高",
  名:"圆圆",
  姓名(){
    return this.姓+this.名;
  },
  age:18
}
console.log(obj1.姓名());//这里需要()
//输出:高圆圆

2.看第二段代码

let obj2={
  姓:"高",
  名:"圆圆",
  get 姓名(){    //这里给了get
    return this.姓+this.名;
  },
  age:18
}
console.log(obj2.姓名);//这里不需要()
//同样输出:高圆圆

总结:getter是不加括号的函数,获得某个值

三、setter

setter设置值

let obj2={
  姓:"高",
  名:"圆圆",
  get 姓名(){    //这里给了get
    return this.姓+this.名;
  },
  set 姓名(xxx){
    this.姓=xxx[0]
    this.名=xxx.slice(1)
  }
}
obj.姓名="赵丽颖"
console.log(`姓${obj.姓},名${obj.名}`);//这里不需要()
//输出:姓赵,名丽颖

打印出obj console.log(obj)

image.png

可以看到,obj有姓名:(...),姓名并不是我们自己设置的,这里说明的是我们可以对姓名进行读写,但是并不存在一个属性是姓名。同理,n也是如此

四、Object.defineProperty

直接在一个对象上定义一个新属性

Object.defineProperty(对象,定义的一个属性,{get(){},set(){}}

Object.defineProperty(obj,'xxx'}{
    get(){
    return _xxx
    }
    set(value){
    _xxx=value 
}}

五、代理和监听

1.代码一

let data1={}
 Object.defineProperty(data1,'n',{
 value:0
}
console.log(`${data1.n}`)
//输出:0

2.代码2:n不能小于0

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}`)
  data2.n=-1
  console.log(`${data2.n}设置为-1失败`)
  data2.n=1
  console.log(`${data2.n}设置为1成功`)
  //输出:0
         0设置为-1失败
         1设置为1成功

但是如果data._n被改变了怎么办?

3.代理

let data3=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就是代理
}
console.log(`${data3.n}`)
data3.n=-1
console.log(`${data3.n},设置-1失败`)
data3.n=1
console.log(`${data3.n},设置1成功`)
//输出:0
         0设置为-1失败
         1设置为1成功

通过改obj的值来改data的值,obj就是代理 但是如果直接操控myData的值也可以使n<0,看一下代码

let myData={n:0}
let data4=proxy({data:myData})//括号里是匿名对象,无法访问

console.log(`${data4.n}`)
myData.n=-1
console.log(`${data4.n},设置成功了吗`)
//输出:0
        -1,设置成功了吗

从输出结果可以看到,可以直接通过myData使n<0 接下来,拦截用户直接修改myData的值

let myData5={n:0}
let data5=proxy2({data:myData5})

function proxy2({data}){
    let value=data.n  //保存最开始的n
    delete data.n //这句话可以不写,因为n的值在下面会被覆盖
    Object.defineProperty(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
 }  
   //现在修改myDaya的值看看还能不能成功
   console.log(`${data5.n}`)
   myData5.n=-1
   console.log(`${data5.n},设置为-1失败了`)
   myData5.n=1
   console.log(`${data5.n},设置为1成功了`)
   //输出结果:0
              0,设置为-1失败了
              1,设置为1成功了
   

总结

Object.defineProperty

• 可以给对象添加属性value

• 可以给对象添加getter/setter

• getter/setter用于对属性的读写进行监控

代理

• 对myData对象的属性进行读写,但是全权由另一个对象来vm操控

• 所以vm就是myData的代理

let vm = new Vue({data:myData})

• 会让vm成为myData的代理

• 会对myData的属性进行监控

  1. 为什么要监控,为了防止myData属性发生了改变,但是vm不知道
  2. 知道了,就可以调用render(data)
  3. 所以,vue会对里面的data加监听,同时,新生成的对象会变成Vue的代理