美文网首页@IT·互联网Web大前端架构专题
Vue 3.x全面升级指南:Composition API深度探

Vue 3.x全面升级指南:Composition API深度探

作者: 天涯学馆 | 来源:发表于2024-05-15 16:27 被阅读0次

    Vue 3.x 的全面升级引入了 Composition API,这是对 Vue 2.x 传统 Options API 的一个重大改进,它提供了更加灵活和模块化的代码组织方式.

    Composition API的核心概念和函数

    setup()函数:

    Vue 3 中的核心入口,用于设置组件的状态和逻辑,它在 beforeCreate 钩子之后,create 钩子之前执行。代替了原本在 data、methods 等选项中定义的内容。

    import { ref, computed } from 'vue';
    
    export default {
      setup() {
        // 响应式数据
        const count = ref(0);
    
        // 计算属性
        const doubleCount = computed(() => count.value * 2);
    
        // 方法
        function increment() {
          count.value++;
        }
    
        // 返回需要在模板中使用的数据和方法
        return {
          count,
          doubleCount,
          increment
        };
      }
    };
    

    ref 和 reactive:

    用于创建响应式数据,ref用于创建基本类型的响应式数据,reactive 用于对象和数组的响应式代理。

    import { ref, reactive } from 'vue';
    
    export default {
      setup() {
        // 使用ref创建响应式基本类型
        const count = ref(0);
    
        // 使用reactive创建响应式对象
        const user = reactive({
          name: 'Alice',
          age: 30
        });
    
        // 修改响应式数据
        count.value++;
        user.age++;
    
        return { count, user };
      }
    };
    

    计算属性与侦听器:

    computed 用于创建计算属性,只有当依赖发生变化时才会重新计算。

    import { ref, computed } from 'vue';
    
    export default {
      setup() {
        const firstName = ref('John');
        const lastName = ref('Doe');
    
        // 计算全名
        const fullName = computed(() => `${firstName.value} ${lastName.value}`);
    
        return { firstName, lastName, fullName };
      }
    };
    

    watch 用于观察响应式数据的变化,并在变化时执行回调。

    import { ref, watch } from 'vue';
    
    export default {
      setup() {
        const count = ref(0);
    
        // 观察count变化
        watch(count, (newVal, oldVal) => {
          console.log(`count changed from ${oldVal} to ${newVal}`);
        });
    
        function increment() {
          count.value++;
        }
    
        return { count, increment };
      }
    };
    

    组合函数

    Composition API鼓励创建可复用的组合函数。

    // useCounter.js
    export function useCounter(initialValue = 0) {
      const count = ref(initialValue);
      function increment() {
        count.value++;
      }
      return { count, increment };
    }
    
    // 在组件中使用
    import { useCounter } from './useCounter';
    
    export default {
      setup() {
        const { count, increment } = useCounter(10);
        return { count, increment };
      }
    };
    

    生命周期钩子:

    Vue 3 中的生命周期钩子不再直接在 setup() 内部使用,而是通过 onBeforeMount、onMounted 等新的生命周期钩子函数。

    1. onBeforeMount: 此钩子在组件挂载到DOM之前被调用。这类似于Vue 2.x中的 beforeMount 生命周期钩子。

       import { onBeforeMount } from 'vue';
       
       export default {
         setup() {
           onBeforeMount(() => {
             console.log('组件即将挂载');
           });
         }
       };
    

    2. onMounted: 当组件被挂载到DOM上后立即调用。相当于Vue 2.x的 mounted

       import { onMounted } from 'vue';
       
       export default {
         setup() {
           onMounted(() => {
             console.log('组件已挂载');
           });
         }
       };
    

    3. onBeforeUpdate: 在组件数据变化导致的更新之前调用,但还未开始DOM更新。类似于Vue 2.x的 beforeUpdate

       import { onBeforeUpdate } from 'vue';
       
       export default {
         setup() {
           let previousData;
           onBeforeUpdate(() => {
             console.log('数据更新前:', previousData);
           });
           
           return { data };
         }
       };
    

    4. onUpdated: 组件数据变化导致的DOM更新完成后调用。相当于Vue 2.x的 updated。

       import { onUpdated } from 'vue';
       
       export default {
         setup() {
           onUpdated(() => {
             console.log('组件更新完成');
           });
         }
       };
    

    5. onBeforeUnmount: 组件卸载之前调用。类似于Vue 2.x的 beforeDestroy。

       import { onBeforeUnmount } from 'vue';
       
       export default {
         setup() {
           onBeforeUnmount(() => {
             console.log('组件即将卸载');
           });
         }
       };
    

    6. onUnmounted: 组件已经被卸载后调用。相当于Vue 2.x的 destroyed。

       import { onUnmounted } from 'vue';
       
       export default {
         setup() {
           onUnmounted(() => {
             console.log('组件已卸载');
           });
         }
       };
    

    7. onActivated: 仅在使用 <keep-alive> 包裹的组件激活时调用。

       import { onActivated } from 'vue';
       
       export default {
         setup() {
           onActivated(() => {
             console.log('组件被激活');
           });
         }
       };
    

    8. onDeactivated: 仅在使用 <keep-alive> 包裹的组件停用时调用。

       import { onDeactivated } from 'vue';
       
       export default {
         setup() {
           onDeactivated(() => {
             console.log('组件被停用');
           });
         }
       };
    

    Composition API编写组件

    • 创建响应式数据:使用 ref 和 reactive 创建响应式变量。
    • 计算属性:使用 computed 函数创建计算属性。
    • 响应式函数:使用 toRefs() 和 toRef() 转换对象属性为响应式。
    • 监听器:使用 watch 或 watchEffect 监听数据变化。
    import { ref, reactive, computed, toRefs, watch } from 'vue';
    import axios from 'axios';
    
    export default {
      setup() {
        // 创建响应式数据
        const state = reactive({
          cityInput: '',
          city: '',
          weather: null
        });
    
        // 计算属性,直接返回输入的城市名称
        const currentCity = computed(() => state.cityInput);
    
        // 将state对象的属性转化为响应式引用
        const { cityInput } = toRefs(state);
    
        // 响应式函数,用于处理API请求
        const fetchWeather = async () => {
          if (!cityInput.value.trim()) return;
    
          try {
            const response = await axios.get(`https://api.weatherapi.com/v1/current.json?key=YOUR_API_KEY&q=${cityInput.value}`);
            state.city = response.data.location.name;
            state.weather = { temp: response.data.current.temp_c };
          } catch (error) {
            console.error('获取天气信息失败', error);
          }
        };
    
        // 监听器,监听城市输入变化,清空天气信息
        watch(cityInput, () => {
          state.weather = null;
        });
    
        // 返回暴露给模板的变量和方法
        return {
          cityInput,
          currentCity,
          fetchWeather
        };
      }
    };
    
    • 创建响应式数据:使用reactive创建了一个包含cityInputcityweather的响应式对象。ref也可以用于基本类型的响应式数据,但在这个场景下,reactive更适合管理多个状态。

    • 计算属性: currentCity计算属性直接返回state.cityInput的值,虽然在这个例子中直接使用v-model="cityInput"可能更直观,但展示了如何定义计算属性。

    • 响应式函数: 使用toRefsstate对象的属性转化为独立的响应式引用,便于在模板中直接绑定。这里主要展示了响应式数据的使用,而不是转换函数本身,因为直接使用解构赋值(如const { cityInput } = state;)在模板中已经足够。

    • 监听器: 使用watch监听cityInput的变化,每次输入变化时清除weather状态,以便于下次查询。

    从Options API迁移到Composition API

    组件结构

    将状态、方法和逻辑分离到单独的函数中。在Options API中,我们通常在组件选项中定义data、methods、computed等。而在Composition API中,这些逻辑被分离到单独的函数中。例如:

    Options API:

    export default {
      data() {
        return {
          message: 'Hello, Vue!'
        };
      },
      methods: {
        greet() {
          console.log(this.message);
        }
      },
      computed: {
        reversedMessage() {
          return this.message.split('').reverse().join('');
        }
      }
    };
    

    Composition API:

    import { ref, computed } from 'vue';
    
    export default {
      setup() {
        const message = ref('Hello, Vue!');
        
        function greet() {
          console.log(message.value);
        }
        
        const reversedMessage = computed(() => message.value.split('').reverse().join(''));
    
        return {
          message,
          greet,
          reversedMessage
        };
      }
    };
    

    依赖注入

    使用 provide 和 inject。在Options API中,我们使用provide和inject来传递数据。在Composition API中,这个过程保持不变:

    Options API:

    // 父组件
    export default {
      provide() {
        return {
          parentValue: '父组件的值'
        };
      }
    };
    
    // 子组件
    export default {
      inject: ['parentValue'],
      mounted() {
        console.log(this.parentValue); // 输出 "父组件的值"
      }
    };
    

    Composition API:

    // 父组件
    export default {
      setup() {
        provide('parentValue', '父组件的值');
      }
    };
    
    // 子组件
    export default {
      setup(_, { inject }) {
        const parentValue = inject('parentValue');
        onMounted(() => {
          console.log(parentValue); // 输出 "父组件的值"
        });
      }
    };
    

    模板重构

    将绑定的属性和方法从 this 转换为直接引用。

    相关文章

      网友评论

        本文标题:Vue 3.x全面升级指南:Composition API深度探

        本文链接:https://www.haomeiwen.com/subject/qxavfjtx.html