Vue的响应式和生命周期

目录

响应式:

Vue的响应式如何实现的?

数组的响应式:

Vue的生命周期


响应式:

修改data后,页面自动改变/刷新。这就是响应式。就像我们在使用excel的时候,修改一个单元格中的数据,其它单元格的数据会联动更新,这也是响应式。

Vue的响应式如何实现的?

数据劫持:Vue底层使用了Object.defineProperty,将data中的数据放到了_data中,在_data中配置了setter方法,当去修改属性值时,setter方法则被自动调用,setter方法中不仅修改了属性值,而且还做了其他的事情,例如:重新渲染页面。setter方法就像半路劫持一样,所以称为数据劫持。

Vue会给data中**除$、_**以外命名的所有的属性,以及属性中的属性,都会添加响应式

后期添加响应式:

Vue.set(目标对象, '属性名', 值)

vm.$set(目标对象, '属性名', 值)

数组的响应式:

调用Vue提供的7个API:

push() 在数组 尾部逐个添加 元素,返回结果数组的长度,能接收任意数量参数,push() 修改了原数组。

pop() 移除数组最后一项,返回的是被移除项。修改原数组

reverse() 可将数组进行倒序,此方法会改变原数组。

splice() 通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。

shift() 删除数组的第一项元素,返回被删除的元素, 修改原数组

unshift() 向数组的头部添加元素,返回的是结果数组的长度,修改原数组

sort() 可将数组项灵活地进行升序或降序排列,此方法会改变原数组。

或者使用:

Vue.set(数组对象, 'index', 值)

vm.$set(数组对象, 'index', 值)

javascript 复制代码
  vm.$set(数组对象, 下标, 值)  vm.$set(vm.users,0,'杰克')
  Vue.set(数组对象, 下标, 值)  vm.set(vm.users,0,'杰克')

Vue的生命周期

Vue的生命周期指的是:vm对象从创建到最终销毁的整个过程。

Vue的生命周期可以被划分为4个阶段:初始阶段、挂载阶段、更新阶段、销毁阶段。

每个阶段会调用两个钩子函数。两个钩子函数名的特点:beforeXxx()、xxxed()。

8个生命周期钩子函数分别是:

(1) 初始阶段

① beforeCreate() 创建前

② created() 创建后

(2) 挂载阶段

① beforeMount() 挂载前

② mounted() 挂载后

(3) 更新阶段

① beforeUpdate() 更新前

② updated() 更新后

(4) 销毁阶段

① beforeDestroy() 销毁前

② destroyed() 销毁后

8个钩子函数写在哪里?直接写在Vue构造函数的options对象当中。


初始阶段做了什么事儿

做了这么几件事:

(1) 创建Vue实例vm(此时Vue实例已经完成了创建,这是生命的起点)

(2) 初始化事件对象和生命周期(接产大夫正在给他洗澡)

(3) 调用beforeCreate()钩子函数(此时还无法通过vm去访问data对象的属性)

(4) 初始化数据代理和数据监测

(5) 调用created()钩子函数(此时数据代理和数据监测创建完毕,已经可以通过vm访问data对象的属性)

(6) 编译模板语句生成虚拟DOM(此时虚拟DOM已经生成,但页面上还没有渲染)

该阶段适合做什么?

beforeCreate:可以在此时加一些loading效果,自定义一些属性放到this身上,好比全局事件总线

created:结束loading效果。也可以在此时发送一些网络请求,获取数据。也可以在这里添加定时器。

挂载阶段做了什么事儿

做了这么几件事:

(1) 调用beforeMount()钩子函数(此时页面还未渲染,真实DOM还未生成,此时操作数据,不会最终显示在页面中)

(2) 给vm追加el属性,用它来代替"el",el代表了真实的DOM元素(此时真实DOM生成,页面渲染完成)

(3) 调用mounted()钩子函数

该阶段适合做什么?

mounted:可以操作页面的DOM元素了。也有人喜欢在这个阶段请求数据

面试题:请求数据是在哪个钩子里,原因是什么?

请求数据可以在created,mounted中,但最好在created中,因为mounted已经挂载完毕,数据回来后,需要重新渲染,可能会出现闪屏的情况

更新阶段做了什么事儿

(1) data发生变化(这是该阶段开始的标志)

(2) 调用beforeUpdate()钩子函数(此时只是内存中的数据发生变化,页面还未更新)

(3) 虚拟DOM重新渲染和修补

(4) 调用updated()钩子函数(此时页面已更新)

该阶段适合做什么?

beforeUpdate:适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

updated:页面更新后,如果想对数据做统一处理,可以在这里完成。

销毁阶段做了什么事儿

做了这么几件事:

(1) vm.$destroy()方法被调用(这是该阶段开始的标志)

(2) 调用beforeDestroy()钩子函数(此时Vue实例还在。虽然vm上的监视器、vm上的子组件、vm上的自定义事件监听器还在,但是它们都已经不能用了。此时修改data也不会重新渲染页面了)

(3) 卸载子组件和监视器、解绑自定义事件监听器

(4) 调用destroyed()钩子函数(虽然destroyed翻译为已销毁,但此时Vue实例还在,空间并没有释放,只不过马上要释放了,这里的已销毁指的是vm对象上所有的东西都已经解绑完成了)

该阶段适合做什么?

beforeDestroy:适合做销毁前的准备工作,和人临终前写遗嘱类似。例如:可以在这里清除定时器,解绑自定义事件,解除watch监听等

案例
javascript 复制代码
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue的生命周期</title>
    <script src="./js/vue.js"></script>
  </head>
<!-- 
el,template,data,methods,computed,watch,directives,filters,8个钩子  
-->
  <body>
    <div id="app">
      <h1>{{msg}}</h1>
      <h3>计数器:{{counter}}</h3>
      <button @click="add">点我加1</button>
      <h3 v-text="counter"></h3>
      <button @click="$destroy()">点我销毁</button>
    </div>
    <script>
      const vm = new Vue({
        el: "#app",
        data() {
          return {
            msg: "Vue生命周期",
            counter: 1,
          };
        },
        methods: {
          add() {
            this.counter++;
          },
        },
        // 初始阶段
        // 创建前
        beforeCreate() {
          console.log("添加等待读取data数据的loading效果");
          console.log("添加一些自定义的属性:全局事件总线");
          console.log("beforeCreate");
        },
        // 创建后
        created() {
          console.log("结束等待拿到data数据的loading效果");
          console.log(
            "这里是最早可以拿到data数据,更新data数据的地方。例如发送ajax请求,更新数据",
          );

          console.log("created");
        },
        // 挂载阶段
        // 挂载前
        beforeMount() {
          console.log("此时虚拟dom已经创建好,等待着放到页面,成为真实dom");
          console.log("beforeMount");
        },

        // 挂载后
        mounted() {
          console.log("发送请求,更新数据");

          console.log(
            "此时真实dom已经渲染完毕, 这里是最早可以拿到页面节点的地方",
          );

          console.log("mounted");
        },

        // 更新阶段
        // 更新前
        beforeUpdate() {
          console.log("此时数据已更新,但页面没更新");
          // console.log(this);
          console.log("beforeUpdate");
        },

        // 更新后
        updated() {
          console.log("页面更新完毕");
          console.log("updated");
        },
        // 销毁阶段
        // 销毁前
        beforeDestroy() {
          console.log("结束监听");
          console.log("清除定时器");
          console.log("解绑自定义事件");
          console.log(
            "做一些收尾工作,但切记此时你再去改数据,页面也没有响应式",
          );
          // this.msg = "hello123";
          // console.log(this);
          console.log("beforeDestroy");
        },

        // 销毁后
        destroyed() {
          console.log("这个阶段,一般我们不做什么");
          console.log("destroyed");
        },
      });
    </script>
  </body>
</html>
相关推荐
灵感__idea5 小时前
Hello 算法:贪心的世界
前端·javascript·算法
GreenTea7 小时前
一文搞懂Harness Engineering与Meta-Harness
前端·人工智能·后端
killerbasd8 小时前
牧苏苏传 我不装了 4/7
前端·javascript·vue.js
吴声子夜歌9 小时前
ES6——二进制数组详解
前端·ecmascript·es6
码事漫谈9 小时前
手把手带你部署本地模型,让你Token自由(小白专属)
前端·后端
ZC跨境爬虫9 小时前
【爬虫实战对比】Requests vs Scrapy 笔趣阁小说爬虫,从单线程到高效并发的全方位升级
前端·爬虫·scrapy·html
爱上好庆祝9 小时前
svg图片
前端·css·学习·html·css3
橘子编程9 小时前
JavaScript与TypeScript终极指南
javascript·ubuntu·typescript
王夏奇10 小时前
python中的__all__ 具体用法
java·前端·python
叫我一声阿雷吧10 小时前
JS 入门通关手册(45):浏览器渲染原理与重绘重排(性能优化核心,面试必考
javascript·前端面试·前端性能优化·浏览器渲染·浏览器渲染原理,重排重绘·reflow·repaint