• web前端面试高频考点——Vue3.x新增API(生命周期,ref、toRef 和 toRefs 的理解和最佳使用方式)


    系列文章目录



    一、Vue3 比 Vue2 有什么优势?

    • 性能更好
    • 体积更小
    • 更好的 ts 支持
    • 更好的代码组织
    • 更好的逻辑抽离
    • 更多新功能

    二、Vue2 和 Vue3 生命周期区别

    App.vue 父组件:

    <template>
      <div>
        <life-cycles :msg="msg" v-if="flag" />
        <button @click="changeHandler">change msg</button>
        <button @click="changeFlagHandler">change flag</button>
      </div>
    </template>
    
    <script>
    import LifeCycles from "./components/LifeCycles.vue";
    export default {
      data() {
        return {
          msg: "hello vue3",
          flag: true,
        };
      },
      methods: {
        changeHandler() {
          this.msg = "hello vue3" + Date.now();
        },
        changeFlagHandler() {
          this.flag = !this.flag;
        },
      },
      components: { LifeCycles },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    1、Options API 生命周期

    LiftCycles.vue 子组件:

    • Vue2.x 的形式
    • 点击按钮进行 组件更新组件销毁(查看控制台输出内容)
    <template>
      <p>生命周期 {{ msg }}</p>
    </template>
      
    <script>
    export default {
      name: "LiftCycles",
      props: {
        msg: String,
      },
      beforeCreate() {
        console.log("beforeCreate");
      },
      created() {
        console.log("created");
      },
      beforeMount() {
        console.log("beforeMount");
      },
      mounted() {
        console.log("mounted");
      },
      beforeUpdate() {
        console.log("beforeUpdate");
      },
      updated() {
        console.log("updated");
      },
      beforeUnmount() {
        console.log("beforeUnmount");
      },
      unmounted() {
        console.log("unmounted");
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在这里插入图片描述


    在这里插入图片描述


    在这里插入图片描述


    2、Composition API 生命周期

    • beforeDestroy 改为 beforeUnmount
    • destroyed 改为 unmounted
    • 其他沿用 Vue2 的生命周期
    <template>
      <p>生命周期 {{ msg }}</p>
    </template>
      
    <script>
    import {
      onBeforeMount,
      onMounted,
      onBeforeUpdate,
      onUpdated,
      onBeforeUnmount,
      onUnmounted,
    } from "vue";
    
    export default {
      name: "LiftCycles",
      props: {
        msg: String,
      },
      // 等于 beforeCreate 和 created
      setup() {
        console.log("setup");
    
        onBeforeMount(() => {
          console.log("onBeforeMounted");
        });
        onMounted(() => {
          console.log("onMounted");
        });
        onBeforeUpdate(() => {
          console.log("onBeforeUpdate");
        });
        onUpdated(() => {
          console.log("onUpdated");
        });
        onBeforeUnmount(() => {
          console.log("onBeforeUnmount");
        });
        onUnmounted(() => {
          console.log("onUnmounted");
        });
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    在这里插入图片描述


    在这里插入图片描述


    在这里插入图片描述


    三、如何理解 Composition API 和 Options API

    Options API 对比 Composition API:

    请添加图片描述

    1、Composition API 带来了什么

    • 更好的代码组织
    • 更好的逻辑复用
    • 更好的类型推导

    2、Composition API 和 Options API 如何选择?

    • 不建议共用,容易引起代码混乱
    • Composition API 用于复杂的业务情况
    • Options API 用于简单的业务情况

    3、如何选择

    • 不建议乱用,会引起混乱
    • 小型项目、业务逻辑简单,用 Options API
    • 中大型项目、逻辑复杂,用 Composition API

    4、别误解 Composition API

    • Composition API 属于高阶技巧,不是基础必会
    • Composition API 是为解决复杂业务逻辑而设计
    • Composition API 就像 Hooks 在 React 中的地位

    四、如何理解 ref、toRef 和 toRefs

    1、ref

    • 生成值类型的响应式数据
    • 可以用于 reactive,也可以用于模板(不需要 .value)
    • 用 .value 去修改值
    • 所有的 ref 变量,尽量使用 xxxRef 的格式命名,便于区分

    Ref.vue 组件

    • ref 用来定义响应式的值类型
    • reactive 用来定义响应式的引用类型
    • ref 定义的值类型可在 reactive 和 模板中直接使用(不需要 .value
    • 修改值的时候要使用 .value
    <template>
      <p>ref demo {{ ageRef }} {{ state.name }}</p>
    </template>
      
    <script>
    import { ref, reactive } from "vue";
    export default {
      name: "Ref",
      setup() {
        const ageRef = ref(21); // 值类型 响应式
        const nameRef = ref("杂货铺");
    
        const state = reactive({
          name: nameRef,
        });
    
        setTimeout(() => {
          console.log("ageRef", ageRef.value);
    
          ageRef.value = 18; // .value 修改值
          nameRef.value = "前端杂货铺";
        }, 1000);
    
        return {
          ageRef,
          state,
        };
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述


    在这里插入图片描述


    2、ref 扩展(获取模板的dom元素)

    RefTemplate.vue 组件

    • ref 本身的意思就是一个引用,给它传什么,它就是指向什么
    • 传一个 DOM 当然就指向 DOM 了
    <template>
      <p ref="elemRef">我是一行文字</p>
    </template>
    
    <script>
    import { ref, onMounted } from "vue";
    export default {
      name: "RefTemplate",
      setup() {
        const elemRef = ref(null);
    
        onMounted(() => {
            console.log('ref template', elemRef.value.innerHTML, elemRef.value);
        })
    
        return {
          elemRef,
        };
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述


    3、toRef

    • 针对一个响应式对象(reactive)的 prop(属性)
    • 创建一个 ref,具有响应式
    • 两者保持引用关系

    toRef.vue 组件

    • toRef(对象, "属性") 修改响应式对象的属性
    • 改变 ageRef 时, state.age 也会改变
    • 改变 state.age 时,ageRef 也会改变
    <template>
      <p>toRef demo - {{ ageRef }} - {{ state.name }} - {{ state.age }}</p>
    </template>
    
    <script>
    import { reactive, toRef } from "@vue/reactivity";
    
    export default {
      name: "ToRef",
      setup() {
        const state = reactive({
          age: 20,
          name: "杂货铺",
        });
    
        // toRef 如果用于普通对象(非响应式对象),产出的结果不具备响应式
        // const state = {
        //     age: 20,
        //     name: '杂货铺'
        // }
    
    	// 修改响应式对象(reactive)的一个属性(age)
        const ageRef = toRef(state, "age");
    
        setTimeout(() => {
          state.age = 25;
        }, 1000);
    
        setTimeout(() => {
          ageRef.value = 30; // 用 .value 修改值
        }, 2000);
    
        return {
          state,
          ageRef,
        };
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    在这里插入图片描述


    在这里插入图片描述


    在这里插入图片描述

    4、toRefs

    • 将响应式对象(reactive 封装)转换为普通对象
    • 对象的每个 prop 都是对应的 ref
    • 两者保持引用关系

    toRefs 组件

    • toRefs,将响应式对象变为普通对象(仍然具有响应式)
    • 对象的每个属性都是对应的 ref
    <template>
      <p>toRefs demo {{ ageRef }} {{ nameRef }}</p>
    </template>
    
    <script>
    import { toRefs, reactive } from "vue";
    export default {
      name: "ToRefs",
      setup() {
        const state = reactive({
          age: 20,
          name: "杂货铺",
        });
    
        // 将响应式对象,变为普通对象
        const stateAsRefs = toRefs(state); 
    
        // 每个属性,都是 ref 对象
        const { age: ageRef, name: nameRef } = stateAsRefs; 
    
        setTimeout(() => {
          state.age = 25
        }, 1000)
    
        return {
          ageRef,
          nameRef,
        };
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在这里插入图片描述

    或者这么写(推荐):

    • 直接返回这个普通对象
    • 注意此时模板内容也发生了变化,直接写对象里面的属性
    <template>
      <p>toRefs demo {{ name }} {{ age }}</p>
    </template>
    
    <script>
    import { toRefs, reactive } from "vue";
    export default {
      name: "ToRefs",
      setup() {
        const state = reactive({
          age: 20,
          name: "杂货铺",
        });
    
        // 将响应式对象,变为普通对象
        const stateAsRefs = toRefs(state); 
    
    	setTimeout(() => {
          state.age = 25
        }, 1000)
        
        return stateAsRefs
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述

    在这里插入图片描述

    五、ref、toRef 和 toRefs 的最佳使用方式

    • 用 reactive 做对象的响应式,用 ref 做值类型的响应式
    • setup 中返回 toRefs(state),或者 toRefs(state, ‘xxx’)
    • ref 的变量命名都用 xxxRef
    • 合成函数返回响应式对象时,使用 toRefs

    xxx.js 文件

    • 定义函数和响应式对象
    • 返回时转为 ref
    import { toRefs, reactive } from "vue"
    
    function useFeatureX() {
        const state = reactive({
          x: 1,
          y: 2
        })
      
        // 逻辑运行状态,省略 N 行
          
        // 返回时转换为 ref
        return toRefs(state)
    }
    
    export default useFeatureX
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    xxx.vue 组件

    • 使用时直接写对象的属性就可以
    export default {
      setup() {
        // 可以在不是去响应式的情况下破坏结构
        const { x, y } = useFeatureX()
    
        return {
          x,
          y
        }
      } 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    不积跬步无以至千里 不积小流无以成江海

    这篇文章如果对你有些许帮助,还请铁铁 三连 + 关注 支持一波,优质好文,正在产出…

  • 相关阅读:
    基础化学试题A卷
    nginx 添加lua 支持 之安装
    2022年智慧城市与智能电网国际会议(CSCSG 2022)
    第十五章《网络编程》第4节:基于UDP协议的网络编程
    字符串转数字, 数字转字符串
    x265 帧间预测
    VS Code配置
    Filter&Listener&Ajax的介绍
    Linux故障排查思路
    【大数据平台】从Hadoop到Spark安装配置教程
  • 原文地址:https://blog.csdn.net/qq_45902692/article/details/126630532