1. vue2响应式原理

1.1 添加属性

  1. <template>
  2. <div id="app">
  3. <h1>姓名:{{person.name}}</h1>
  4. <h1>年龄:{{person.age}}</h1>
  5. <h1 v-show='person.sex'>性别:{{person.sex}}</h1>
  6. <button @click="addSex">添加一个sex属性</button>
  7. <button @click="deleteName">删除name属性</button>
  8. </div>
  9. </template>
  10. <script>
  11. export default {
  12. name: 'App',
  13. data() {
  14. return {
  15. person:{
  16. name: 'IRIC',
  17. age: 20,
  18. }
  19. }
  20. },
  21. methods: {
  22. addSex() {
  23. /**
  24. * 下面的不会生效, 数据变了, 但是页面不会渲染
  25. * 因为这样添加Object.defainePropoty监测不到, 所以页面不会渲染
  26. */
  27. // this.person.sex = 'girl'
  28. this.$set(this.person,'sex','女')
  29. },
  30. deleteName() {
  31. },
  32. },
  33. }

添加属性如果直接使用this.person.sex = ‘girl’, 则页面不会显示改属性。 此时数据已经加上了, 但是页面不会渲染。 因为Object.defainePropoty监测不到。

1.2 第二种方法

this.$set(this.person,’sex’,’女’)

  1. <template>
  2. <div id="app">
  3. <h1>姓名:{{person.name}}</h1>
  4. <h1>年龄:{{person.age}}</h1>
  5. <h1 v-show='person.sex'>性别:{{person.sex}}</h1>
  6. <button @click="addSex">添加一个sex属性</button>
  7. <button @click="deleteName">删除name属性</button>
  8. </div>
  9. </template>
  10. <script>
  11. export default {
  12. name: 'App',
  13. data() {
  14. return {
  15. person:{
  16. name: 'IRIC',
  17. age: 20,
  18. }
  19. }
  20. },
  21. methods: {
  22. addSex() {
  23. this.$set(this.person,'sex','女')
  24. },
  25. deleteName() {
  26. },
  27. },
  28. }
  29. </script>

1.3 添加属性

:::success import Vue from ‘vue’
Vue.set(this.person, ‘sex’,’女’) :::

  1. <template>
  2. <div id="app">
  3. <h1>姓名:{{person.name}}</h1>
  4. <h1>年龄:{{person.age}}</h1>
  5. <h1 v-show='person.sex'>性别:{{person.sex}}</h1>
  6. <button @click="addSex">添加一个sex属性</button>
  7. <button @click="deleteName">删除name属性</button>
  8. </div>
  9. </template>
  10. <script>
  11. import Vue from 'vue'
  12. export default {
  13. name: 'App',
  14. data() {
  15. return {
  16. person:{
  17. name: 'IRIC',
  18. age: 20,
  19. }
  20. }
  21. },
  22. methods: {
  23. addSex() {
  24. Vue.set(this.person, 'sex','女')
  25. },
  26. deleteName() {
  27. },
  28. },
  29. }

1.4删除属性

删除对象的属性:

  1. <template>
  2. <div id="app">
  3. <h1 v-show='person.name'>姓名:{{person.name}}</h1>
  4. <h1>年龄:{{person.age}}</h1>
  5. <h1 v-show='person.sex'>性别:{{person.sex}}</h1>
  6. <button @click="addSex">添加一个sex属性</button>
  7. <button @click="deleteName">删除name属性</button>
  8. </div>
  9. </template>
  10. <script>
  11. import Vue from 'vue'
  12. export default {
  13. name: 'App',
  14. data() {
  15. return {
  16. person:{
  17. name: 'IRIC',
  18. age: 20,
  19. }
  20. }
  21. },
  22. methods: {
  23. addSex() {
  24. Vue.set(this.person, 'sex','女')
  25. },
  26. deleteName() {
  27. //直接删除不会生效
  28. // delete this.person.name
  29. // Vue.delete(this.person,'name')
  30. this.$delete(this.person, 'name')
  31. },
  32. },
  33. }
  34. </script>

更新数组:

  1. <template>
  2. <div id="app">
  3. <h1 v-show='person.name'>姓名:{{person.name}}</h1>
  4. <h1>年龄:{{person.age}}</h1>
  5. <h1 v-show='person.sex'>性别:{{person.sex}}</h1>
  6. <button @click="addSex">添加一个sex属性</button>
  7. <button @click="deleteName">删除name属性</button>
  8. <ul>
  9. <li v-for="(item, index) in hobby" :key="index">
  10. {{ item }}
  11. </li>
  12. </ul>
  13. <button @click='addHobby'>添加hobby</button>
  14. <button @click='updateHobby'>修改hobby</button>
  15. </div>
  16. </template>
  17. <script>
  18. import Vue from 'vue'
  19. export default {
  20. name: 'App',
  21. data() {
  22. return {
  23. person:{
  24. name: 'IRIC',
  25. age: 20,
  26. },
  27. hobby:['画画','游泳']
  28. }
  29. },
  30. methods: {
  31. addSex() {
  32. Vue.set(this.person, 'sex','女')
  33. },
  34. deleteName() {
  35. //直接删除不会生效
  36. // delete this.person.name
  37. // Vue.delete(this.person,'name')
  38. this.$delete(this.person, 'name')
  39. },
  40. addHobby(){
  41. this.hobby.push('跑步')
  42. },
  43. updateHobby(){
  44. //不会生效, 只是数据改了, 但是页面不会变化, 因为无法检测到改操作
  45. // this.hobby[0] = '钓鱼'
  46. console.log(this.hobby) //[钓鱼', '游泳', '跑步',]
  47. // Vue.set(this.hobby,0,'逛街')
  48. this.$set(this.hobby,0,'跳舞')
  49. this.hobby.splice(0,1,'唱歌')
  50. }
  51. },
  52. }
  53. </script>

2. 总结:

vue2.x的响应式

  • 实现原理:

    • 对象类型:通过Object.defineProperty()对属性的读取改进行拦截数据劫持)。
    • 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
      1. Object.defineProperty(data, 'count', {
      2. get () {},
      3. set () {}
      4. })
  • 存在问题: :::success

  • 新增属性、删除属性, 界面不会更新。

  • 直接通过下标修改数组, 界面不会自动更新。
  • 解决方案
    • 使用Vue.set、Vue.delete或者vm.$set、vm.$delete这些API, 数组使用重写数组的方法 :::