Vue数据响应式

80 阅读2分钟

理解new Vue({options.data})

样例

const myData = {n:0}
const vm = new Vue({
    data:myData
})

如上例,我们将myData传给vm{n:0}立马变成了{n:(…)}
此时,通过Obect.defineProperty会让vm成为myData代理``proxy;并且会让vmmyData的所有属性进行监控,可以对属性进行读写,进而就可以调用render进行渲染。

代理(设计模式)

对样例中myData对象的属性读写,对myData对象的属性读写,全权由另一个对象vm负责。那么vm就是myData的代理(中介就是房东租房的代理)。比如用vm.n代替操作myData.n

Object.defineProperty

  1. 可以给对象添加属性value
  2. 可以给对象添加getter/setter
  3. getter/setter用于对属性的读写进行监控

Object.defineProperty

let data1 = {}
Object.defineProperty(data1, 'n', { //给data1创建一个虚拟属性n,属性值为0
    value: 0
})
console.log(`需求一:${data1.n}`)

getter

let obj1 = {
姓: "张",
名: "小明",
姓名() {
return this.姓 + this.名;
},
age: 18
};
console.log("需求一:" + obj1.姓名());

let obj2 = {
姓: "张",
名: "小明",
get 姓名() {              //getter
return this.姓 + this.名;
},
age: 18
};
console.log("需求二:" + obj2.姓名);//getter作用,调用的时候不用加括号

setter

let obj3 = {
姓: "张",
名: "小明",
get 姓名() {
return this.姓 + this.名;
},
set 姓名(xxx){         //setter
this.姓 = xxx[0]
this.名 = xxx.slice(1)
},
age: 18
};
obj3.姓名 = '张小红'  //setter 用法
console.log(`需求三:姓 ${obj3.姓},名 ${obj3.名}`)

Object.defineProperty 的问题

必须要有一个'n',才能监听并代理data.n

但是如果没有给出n怎么办?以下有两种情况:

new Vue({
    data: {},
    template: `
    <div>{{n}}</div>
`
}).$mount("#app");

此时Vue会给出一个警告:
image.png

new Vue({
    data: {
    obj: {
    a: 0 // obj.a 会被 Vue 监听 & 代理
    }
   },
    template: `
    <div>
        {{obj.b}}
        <button @click="setB">set b</button>
    </div>
`,

methods: {
    setB() {
    this.obj.b = 1; //此时,页面中不会显示1
    }
  }
}).$mount("#app");

data中没有b属性,因此Vue无法监听和代理bVue只会检查第一层属性。
image.png

解决办法

  1. 一开始就设置好data的所有key,就是属性。
  2. 使用Vue.set或者this.$set

Vue.set 和 this.$set

new Vue({
    data: {
    obj: {
    a: 0 // obj.a 会被 Vue 监听 & 代理
    }
   },
    template: `
    <div>
        {{obj.b}}
        <button @click="setB">set b</button>
    </div>
`,
methods: {
    setB() {
    Vue.set(this.obj,'b',100)//在obj对象里新建属性bb的value是100
    }
  }
}).$mount("#app");

image.png

data中的数据是数组怎么办?

set新增key,会更新UI,但不会创建监听和代理。 不过尤玉溪篡改了7个API方便你对数组进行增删 这7个API不会更新UI,但不会自动处理监听和代理 this.array[n] = xxx,即不会更新 UI,也不会自动处理监听和代理 结论:数组新增key最好通过7个API

数据响应式

定义

如果一个物体能够对外界刺激做出反应,那么它就是响应式的。

Vue的data是响应式

const vm = new Vue({data: {n: 0}}) 我如果修改vm.n,那么UI中的n就会响应我。Vue2通过Object.defineProperty来实现数据响应式

响应式网页

用户改变网页窗口大小,网页内容会做出响应,那么就是响应式网页
比如:www.smashingmagazine.com/