1. vue2响应式原理
1.1 添加属性
<template>
<div id="app">
<h1>姓名:{{person.name}}</h1>
<h1>年龄:{{person.age}}</h1>
<h1 v-show='person.sex'>性别:{{person.sex}}</h1>
<button @click="addSex">添加一个sex属性</button>
<button @click="deleteName">删除name属性</button>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
person:{
name: 'IRIC',
age: 20,
}
}
},
methods: {
addSex() {
/**
* 下面的不会生效, 数据变了, 但是页面不会渲染
* 因为这样添加Object.defainePropoty监测不到, 所以页面不会渲染
*/
// this.person.sex = 'girl'
this.$set(this.person,'sex','女')
},
deleteName() {
},
},
}
添加属性如果直接使用this.person.sex = ‘girl’, 则页面不会显示改属性。 此时数据已经加上了, 但是页面不会渲染。 因为Object.defainePropoty监测不到。
1.2 第二种方法
this.$set(this.person,’sex’,’女’)
<template>
<div id="app">
<h1>姓名:{{person.name}}</h1>
<h1>年龄:{{person.age}}</h1>
<h1 v-show='person.sex'>性别:{{person.sex}}</h1>
<button @click="addSex">添加一个sex属性</button>
<button @click="deleteName">删除name属性</button>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
person:{
name: 'IRIC',
age: 20,
}
}
},
methods: {
addSex() {
this.$set(this.person,'sex','女')
},
deleteName() {
},
},
}
</script>
1.3 添加属性
:::success
import Vue from ‘vue’
Vue.set(this.person, ‘sex’,’女’)
:::
<template>
<div id="app">
<h1>姓名:{{person.name}}</h1>
<h1>年龄:{{person.age}}</h1>
<h1 v-show='person.sex'>性别:{{person.sex}}</h1>
<button @click="addSex">添加一个sex属性</button>
<button @click="deleteName">删除name属性</button>
</div>
</template>
<script>
import Vue from 'vue'
export default {
name: 'App',
data() {
return {
person:{
name: 'IRIC',
age: 20,
}
}
},
methods: {
addSex() {
Vue.set(this.person, 'sex','女')
},
deleteName() {
},
},
}
1.4删除属性
删除对象的属性:
<template>
<div id="app">
<h1 v-show='person.name'>姓名:{{person.name}}</h1>
<h1>年龄:{{person.age}}</h1>
<h1 v-show='person.sex'>性别:{{person.sex}}</h1>
<button @click="addSex">添加一个sex属性</button>
<button @click="deleteName">删除name属性</button>
</div>
</template>
<script>
import Vue from 'vue'
export default {
name: 'App',
data() {
return {
person:{
name: 'IRIC',
age: 20,
}
}
},
methods: {
addSex() {
Vue.set(this.person, 'sex','女')
},
deleteName() {
//直接删除不会生效
// delete this.person.name
// Vue.delete(this.person,'name')
this.$delete(this.person, 'name')
},
},
}
</script>
更新数组:
<template>
<div id="app">
<h1 v-show='person.name'>姓名:{{person.name}}</h1>
<h1>年龄:{{person.age}}</h1>
<h1 v-show='person.sex'>性别:{{person.sex}}</h1>
<button @click="addSex">添加一个sex属性</button>
<button @click="deleteName">删除name属性</button>
<ul>
<li v-for="(item, index) in hobby" :key="index">
{{ item }}
</li>
</ul>
<button @click='addHobby'>添加hobby</button>
<button @click='updateHobby'>修改hobby</button>
</div>
</template>
<script>
import Vue from 'vue'
export default {
name: 'App',
data() {
return {
person:{
name: 'IRIC',
age: 20,
},
hobby:['画画','游泳']
}
},
methods: {
addSex() {
Vue.set(this.person, 'sex','女')
},
deleteName() {
//直接删除不会生效
// delete this.person.name
// Vue.delete(this.person,'name')
this.$delete(this.person, 'name')
},
addHobby(){
this.hobby.push('跑步')
},
updateHobby(){
//不会生效, 只是数据改了, 但是页面不会变化, 因为无法检测到改操作
// this.hobby[0] = '钓鱼'
console.log(this.hobby) //[钓鱼', '游泳', '跑步',]
// Vue.set(this.hobby,0,'逛街')
this.$set(this.hobby,0,'跳舞')
this.hobby.splice(0,1,'唱歌')
}
},
}
</script>
2. 总结:
vue2.x的响应式
实现原理:
- 对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。
- 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
Object.defineProperty(data, 'count', {
get () {},
set () {}
})
存在问题: :::success
新增属性、删除属性, 界面不会更新。
- 直接通过下标修改数组, 界面不会自动更新。
- 解决方案
- 使用Vue.set、Vue.delete或者vm.$set、vm.$delete这些API, 数组使用重写数组的方法 :::