Vue更新原理

159 阅读1分钟

Vue更新原理

一、模拟数据监测

let data = {
  name: 'aaa',
  address: 'bbb'
}

function Observer(obj) {
  const keys = Object.keys(obj);
  
  // 创建一个监视的实例对象,用于监视data中属性的变化
  const obs = new Observer(data);
  
  // 准备一个vm实例
  let vm = {};
  vm._data = data = obs;
  
  
  keys.forEach(key => {
    Object.defineProperty(this, key, {
      get() {
        return obj[key];
      },
      set(newValue) {
        console.log(`${key}被修改了,此时应该解析模板,生成虚拟DOM,进行diff算法比较,。。。`);
        obj[key] = newValue;
      }
    })
  });
}

二、VUE中响应式方法练习

<div id="root">
  <button @click="student.age++">年龄+1岁</button><br>
  <button @click="addSex">添加性别属性,默认值: 男</button><br>
  <button @click="addFriend">在列表首位添加一个朋友</button><br>
  <button @click="editFriend">修改第一个朋友的名字为:张三</button><br>
  <button @click="addHobby">添加一个爱好</button><br>
  <button @click="editHobby">修改第一个爱好为: 开车</button><br>

  <h2>学生姓名: {{ student.name }}</h2>
  <h2>学生年龄: {{ student.age }}</h2>
  <h2 v-if="student.sex">学生性别: {{ student.sex }}</h2>
  <h2>爱好:</h2>
  <ul>
    <li v-for="(h, index) in student.hobbies" :key="index">
      {{ h }}
    </li>
  </ul>
  <h2>朋友们</h2>
  <ul>
    <li v-for="(f, index) in student.friends" :key="index">
      {{ f.name }} -- {{ f.age }}
    </li>
  </ul>
</div>

<script>
  const vm = new Vue({
    el: '#root',
    data() {
      return {
        student: {
          name: 'tom',
          age: 18,
          friends: [
            { name: 'jerry', age: 35 },
            { name: 'tonyt', age: 36 }
          ],
          hobbies: ['抽烟', '喝酒', '烫头']
        }
      }
    },
    methods: {
      addSex() {
        this.$set(this.student, 'sex', '男');
      },
      addFriend() {
        this.student.friends.unshift({
          name: 'xz',
          age: 10
        });
      },
      editFriend() {
        this.student.friends[0].name = '张三';
      },
      addHobby() {
        this.student.hobbies.push('蹦迪');
      },
      editHobby() {
        this.student.hobbies.splice(0, 1, '开车');
      }
    },
  });
</script>

三、VUE监视数据原理总结

  • Vue会监视data中所有层次的数据

  • 如何监测对象中的数据?

    • 通过setter实现监视,且要在new Vue时就要传入监测的数据

    • 对象中后追加的属性,Vue默认不做响应式处理

    • 如需给后添加的属性做响应式,可以使用如下API

      Vue.set(target, propertyName/index, value)或者

      vm.$set(target, propertyName/index, value)

  • 如何监测数据中的数据?

    • 通过包裹数据更新元素的方法实现,本质上就是做了两件事:

      1、调用原生对应的方法对数据进行更新

      2、重新解析模板,进而更新页面

  • 在Vue修改数组中的某个元素可以使用如下方法

    • push
    • pop
    • shift
    • unshift
    • splice
    • reserve
    • sort
    • Vue.set()或者vm.$set()
  • 特别注意:Vue.set()和vm.$set()不能给vm,或vm的跟数据对象添加属性