• Vue3从零开始——掌握setup、ref和reactive函数的奥秘



    在这里插入图片描述

    一、Vue 3 组合式 API 概述

    下载 (14)

    在 Vue 3 中,引入了组合式 API(Composition API) ,这使得开发者可以更灵活地组织代码逻辑,并提升了组件的复用性和可维护性。相比于 Vue 2 中的选项式 API,组合式 API 提供了一种更具功能性的方式来构建应用。

    主要优点:

    • 逻辑复用和组织:通过组合函数可以更清晰地组织代码逻辑,避免在生命周期函数中写大量逻辑。
    • 更好的 TypeScript 支持:组合式 API 天然地支持 TypeScript,这使得类型推断和类型检查变得更加轻松。
    • 性能优化:组合式 API 的实现方式在某些场景下可以带来性能上的提升。

    二、setup​ 函数的基本使用

    setup​ 函数是 Vue 3 组件中使用组合式 API 的起点,它是一个新增加的组件选项,所有的组合式 API 的逻辑都需要在这个函数中书写。

    2.1 setup​ 函数的特点

    • 从组件生命周期来看,在beforeCreate​之前调用,因此它没有 this​ 绑定。
    • 函数中 this​ 不是组件实例,是 undefined​。
    • 返回一个对象,该对象将被合并到组件的 data​ 中,可以在模板中直接使用。

    2.2 setup​ 函数的基本结构

    <template>
      <div>
        
      div>
    template>
    
    <script>
    import { ref, reactive } from 'vue';
    
    export default {
      setup() {
        // 在这里定义响应式变量和方法
    
        return {
          // 返回需要在模板中使用的变量和方法
        };
      },
    };
    script>
    
    <style scoped>
    /* 样式部分 */
    style>
    

    2.3 实现一个简单的小demo

    <template>
        <div>
            <p @click="show()">{{ msg }}p>
        div>
    template>
    
    <script>
    
    export default {
        setup() {
            console.log("setup 函数执行了");
    
            let msg = 'Hello World';
    
            function show(){
                console.log("show 函数执行了");
            }
    
            // 返回定义的变量和函数
            return {
                msg,
                show
            };
        },
        beforeCreate() {
            console.log("beforeCreate 函数执行了");
        },
    };
    script>
    
    <style scoped>
    button {
        margin: 5px;
        padding: 10px 20px;
        background-color: #4caf50;
        color: white;
        border: none;
        border-radius: 5px;
        cursor: pointer;
    }
    
    button:hover {
        background-color: #45a049;
    }
    
    
    p {
        font-size: 18px;
    }
    style>
    

    image

    三、ref​ 函数的功能和应用

    3.1 ref​函数介绍

    ref​ 函数用于创建一个持有单个值的响应式引用。它适用于基本数据类型(如字符串、数字、布尔值)和不需要深度响应的数据结构。通过 ref​ 函数,我们可以在 Vue 组件中创建简单的响应式数据。

    主要特点:

    • 基本类型响应性:为基本数据类型创建响应式状态。
    • 引用式访问:通过 .value​ 属性访问和修改值。
    • 适用于 DOM 引用:可以用于 DOM 元素的引用。

    3.2 基本使用

    3.2.1 定义ref​数据
    import { ref } from 'vue';
    
    export default {
      setup() {
    	// 创建响应式数据
    	const count = ref(0); 
        const message = ref('Hello, Vue 3!');
        const isVisible = ref(true);
      
        return {
    	  count,
          message,
          isVisible,
        };
      },
    };
    
    3.2.2 修改响应式变量

    要修改 ref​ 创建的响应式变量,需要使用 .value​ 属性:

    count.value++; // 增加 count
    count.value = 10; // 设置 count 的值
    

    注意:当在Vue的模板(template​)中使用时,ref​ 的值可以直接使用,无需显式调用 .value​:

    <template>
      <div>
        <p>{{ count }}p>
        <button @click="count++">增加button>
      div>
    template>
    

    3.3 使用ref​函数实现计数器

    应用需求:

    • 显示当前计数。
    • 提供按钮增加计数。
    • 提供按钮重置计数。
    <template>
        <div>
            <p>当前计数:{{ count }}p>
            <button @click="increment">增加button>
            <button @click="reset">重置button>
        div>
    template>
    
    <script>
    import { ref } from 'vue';
    
    export default {
        setup() {
            console.log("setup 函数执行了");
    
            // 创建一个响应式对象
            const count = ref(0);
    
            // 增加计数
            function increment() {
                count.value++;
                console.log("count = " + count.value);
              
            }
    
            // 重置计数
            function reset() {
                count.value = 0;
            }
    
            return {
                count,
                increment,
                reset,
            };
        },
        beforeCreate() {
            console.log("beforeCreate 函数执行了");
        },
    };
    script>
    
    <style scoped>
    button {
        margin: 5px;
        padding: 10px 20px;
        background-color: #4caf50;
        color: white;
        border: none;
        border-radius: 5px;
        cursor: pointer;
    }
    
    button:hover {
        background-color: #45a049;
    }
    
    
    p {
        font-size: 18px;
    }
    style>
    

    代码解读:

    1. 创建响应式变量
      • 使用 ref 创建一个响应式变量 count实现记录数字。ref(0) 表示将初始值设置为 0
    2. 定义方法
      • increment 方法:用于增加计数值。在函数内部,通过 count.value++ 来递增计数器,并在控制台中输出新的计数值。
      • reset 方法:用于重置计数值。将 count.value 设为 0 来重置计数器。
    3. 组件返回
      • return:返回 count 和方法 incrementreset,使其在模板中可以直接访问,这一步非常重要!!
    4. 模板绑定
      • {{ count }}:在模板中使用双花括号语法绑定 count,动态显示当前计数值。
      • @click :绑定 button 元素的点击事件到 incrementreset 函数上,实现按钮点击后对计数值的增加和重置。
    5. 生命周期钩子
      • beforeCreate:输出消息以便于理解setup函数的执行顺序。

    image

    四、reactive​ 函数的功能和应用

    4.1 reactive​ 函数介绍

    reactive​ 是 Vue 3 提供的一个 API,用于创建深度响应式对象。与 ref​ 不同,ref​ 适用于基本数据类型,而 reactive​ 更适用于对象、数组等复杂数据结构。

    主要特点:

    • 创建深度响应式的数据对象。
    • 自动跟踪依赖变化并更新视图。
    • 可以结合 toRefs​ 解构成多个响应式引用。

    4.2 基本使用

    import { reactive } from 'vue';
    
    export default {
      setup() {
        // 创建响应式对象
        const state = reactive({
          count: 0,
          message: 'Hello, Vue 3!',
        });
    
        // 方法示例
        function increment() {
          state.count++;
        }
    
        return {
          state,
          increment,
        };
      },
    };
    

    在上面的代码中,我们使用 reactive​ 创建了一个响应式对象 state​,其中包含了两个属性:count​ 和 message​。increment​ 函数可以用来增加 count​ 的值。

    4.3 使用reactive​函数实现计数器

    应用需求:

    • 显示当前计数。
    • 提供按钮增加计数。
    • 提供按钮重置计数。
    <template>
      <div>
        <h1>{{ state.title }}h1>
        <p>当前计数:{{ state.count }}p>
        <button @click="increment">增加button>
        <button @click="reset">重置button>
      div>
    template>
    
    <script>
    import { reactive } from 'vue';
    
    export default {
      setup() {
        // 创建一个响应式对象
        const state = reactive({
          count: 0,
          title: '计数器应用',
        });
    
        // 增加计数
        function increment() {
          state.count++;
        }
    
        // 重置计数
        function reset() {
          state.count = 0;
        }
    	// 暴露定义的数据和函数
        return {
          state,
          increment,
          reset,
        };
      },
    };
    script>
    
    <style scoped>
    button {
      margin: 5px;
      padding: 10px 20px;
      background-color: #4caf50;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
    }
    
    button:hover {
      background-color: #45a049;
    }
    
    h1 {
      color: #333;
    }
    
    p {
      font-size: 18px;
    }
    style>
    

    代码解读:

    跟前面的其实差不多,只不过用法上有一点区别,其他其实差别并不大。

    1. 创建响应式变量:使用 ref 创建两个响应式变量 counttitle
    2. 定义方法:定义 incrementdecrement 函数,用于增加和减少计数。
    3. 模板绑定:在模板中使用 {{ }} 绑定响应式变量,并通过 @click 指令绑定事件处理函数。

    image

    4.4 reactive​函数的的局限性

    参考自:https://cn.vuejs.org/guide/essentials/reactivity-fundamentals.html#reactive

    reactive()​ API 有一些局限性:

    1. 有限的值类型:它只能用于对象类型 (对象、数组和如 Map​、Set​ 这样的集合类型)。它不能持有如 string​、number​ 或 boolean​ 这样的原始类型

    2. 不能替换整个对象:由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用。这意味着我们不能轻易地“替换”响应式对象,因为这样的话与第一个引用的响应性连接将丢失:
      js

      let state = reactive({ count: 0 })
      
      // 上面的 ({ count: 0 }) 引用将不再被追踪
      // (响应性连接已丢失!)
      state = reactive({ count: 1 })
      
    3. 对解构操作不友好:当我们将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接:
      js

      const state = reactive({ count: 0 })
      
      // 当解构时,count 已经与 state.count 断开连接
      let { count } = state
      // 不会影响原始的 state
      count++
      
      // 该函数接收到的是一个普通的数字
      // 并且无法追踪 state.count 的变化
      // 我们必须传入整个对象以保持响应性
      callSomeFunction(state.count)
      

    由于这些限制,我们建议使用 ref()​ 作为声明响应式状态的主要 API。

    五、ref​ 与 reactive​ 的区别

    Vue 3 提供了两种创建响应式数据的方式:ref​ 和 reactive​。它们在功能上有一些不同,适用于不同的场景。

    5.1 主要区别

    特性refreactive
    用途创建持有基本类型值的响应式引用创建深度响应式对象,适合复杂数据结构
    访问方式通过.value​访问和修改直接访问和修改对象的属性
    响应性基本类型响应性深度响应性,自动追踪对象属性的变化
    适用场景适用于简单的状态和需要 DOM 引用的场景适用于多属性对象、数组、复杂数据结构
    数据类型支持
    对任意类型有效只对 object 类型有效
    使用方式