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, 数组使用重写数组的方法 :::
