Vue 3 Composition API与Hooks模式

Vue 3 的 Composition API 引入了 Hook 函数的概念,这是一种更加模块化和可重用的状态管理和逻辑组织方式。

自定义Hook

首先,我们创建一个自定义 Hook,例如 useCounter,它封装了计数器的逻辑:

javascript 复制代码
// useCounter.js
import { ref } from 'vue';

export function useCounter() {
  const count = ref(0);

  function increment() {
    count.value++;
  }

  function decrement() {
    count.value--;
  }

  return {
    count,
    increment,
    decrement
  };
}

在上面的代码中,ref 用于创建响应式数据,increment 和 decrement 方法分别用于增加和减少计数器的值。return 语句暴露了可以被组件直接使用的数据和方法。

然后,在组件中,我们可以导入并使用这个 Hook:

javascript 复制代码
<template>
  <div>
    <h1>Count: {{ count }}</h1>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>

<script>
import { defineComponent } from 'vue';
import { useCounter } from './useCounter';

export default defineComponent({
  setup() {
    const { count, increment, decrement } = useCounter();

    return {
      count,
      increment,
      decrement
    };
  }
});
</script>

在组件的 setup 函数中,我们调用了 useCounter Hook 并将返回的对象解构赋值给局部变量。这些变量可以直接在模板中使用,因为它们都是响应式的。

这种模式的好处在于:

  1. 逻辑分离:Hook 可以封装特定的业务逻辑,使得组件代码更清晰,更容易维护。
  2. 复用性:Hook 可以在多个组件之间共享,减少代码重复。
  3. 类型安全:在 TypeScript 中,自定义 Hook 可以提供类型定义,提高代码的可读性和可预测性。
  4. 响应式系统:通过 ref 或 reactive 创建的响应式数据,可以确保状态变化时视图的自动更新。

Vue 3 的 Composition API 结合 Hook 模式,使得开发者能够更灵活地组织和重用代码,提高了代码的可维护性和开发效率。

内置Hook

除了自定义 Hook,Vue 3 的 Composition API 还提供了许多内置 Hook,如 watch, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, toRefs, computed, watchEffect 等。

1. onMounted: 当组件挂载完成后执行的钩子。

javascript 复制代码
import { onMounted } from 'vue';

export default {
  setup() {
    let element;

    onMounted(() => {
      element = document.querySelector('#someElement');
      // 在这里可以执行依赖于DOM的初始化操作
    });

    return {};
  }
};

2. computed: 计算属性,类似于 Vue 2 中的计算属性。

javascript 复制代码
import { ref, computed } from 'vue';

export default {
  setup() {
    const base = ref(10);
    const multiplier = ref(2);

    const result = computed(() => {
      return base.value * multiplier.value;
    });

    return {
      base,
      multiplier,
      result
    };
  }
};

3. watch: 监听响应式数据的变化。

javascript 复制代码
import { ref, watch } from 'vue';

export default {
  setup() {
    const base = ref(10);
    const multiplier = ref(2);

    watch(base, (newBase, oldBase) => {
      console.log(`Base changed from ${oldBase} to ${newBase}`);
    });

    return {
      base,
      multiplier
    };
  }
};

4. watchEffect: 在任何依赖改变时运行的副作用函数。

javascript 复制代码
import { ref, watchEffect } from 'vue';

export default {
  setup() {
    const base = ref(10);
    const multiplier = ref(2);

    watchEffect(() => {
      console.log(`Result: ${base.value * multiplier.value}`);
    });

    return {
      base,
      multiplier
    };
  }
};

5. toRefs: 将对象的属性转换为响应式引用,以便直接在模板中使用。

javascript 复制代码
import { ref, toRefs } from 'vue';

export default {
  props: {
    user: {
      type: Object,
      required: true
    }
  },
  setup(props) {
    const { name, age } = toRefs(props.user);

    return {
      name,
      age
    };
  }
};

6. reactive: 创建一个响应式对象,允许深度监听对象的属性变化。

javascript 复制代码
import { reactive } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0,
      user: {
        name: 'John Doe',
        age: 30
      }
    });

    function increment() {
      state.count++;
    }

    return {
      state,
      increment
    };
  }
};

7. provide/inject: 提供和注入依赖,类似于 Vue 2 中的非响应式版本,但Vue 3中可以提供响应式数据。

javascript 复制代码
// 父组件
import { provide } from 'vue';

export default {
  setup() {
    const theme = ref('light');

    provide('theme', theme);

    return {};
  }
};
javascript 复制代码
// 子组件
import { inject } from 'vue';

export default {
  setup() {
    const theme = inject('theme');

    return {
      theme
    };
  }
};

8. watch with options:

提供更细粒度的控制,如深度监听、异步处理和仅在初始值更改时触发。

javascript 复制代码
import { ref, watch } from 'vue';

export default {
  setup() {
    const base = ref(10);
    const multiplier = ref(2);

    watch(
      [base, multiplier],
      ([newBase, newMultiplier], [oldBase, oldMultiplier]) => {
        if (newBase !== oldBase || newMultiplier !== oldMultiplier) {
          console.log(`Result: ${newBase * newMultiplier}`);
        }
      },
      {
        deep: true, // 深度监听
        immediate: true // 初始值更改时立即触发回调
      }
    );

    return {
      base,
      multiplier
    };
  }
};

9. effectScope: 用于在特定作用域内运行副作用,便于清理和管理。

javascript 复制代码
import { effectScope, ref } from 'vue';

export default {
  setup() {
    const scope = effectScope();
    const count = ref(0);

    const stopEffect = scope.run(() => {
      console.log('Effect running');
      scope.watch(count, () => {
        console.log(`Count is now: ${count.value}`);
      });
    });

    return {
      count,
      stopEffect
    };
  }
};
相关推荐
IT_陈寒几秒前
React实战技巧总结
前端·人工智能·后端
陈随易7 小时前
Postman 被曝自动往 Claude Code 和 Codex 装插件
前端·后端·程序员
Dream-Y.ocean9 小时前
鸿蒙PC平台宅匠 3D 室内设计适配实战:基于 Electron 壳方案的 Three.js 双渲染引擎与参数化户型编辑器开发
javascript·3d·harmonyos
Csvn10 小时前
性能监控
前端
Highcharts.js10 小时前
Highcharts Gantt使用符号的自定义数据标签开发甘特图示例
javascript·甘特图·highcharts·图表开发·实战代码·响应式图表
Csvn11 小时前
构建工具
前端
FRing0311 小时前
vue2干货总结3(computed计算属性、watch监听器)
开发语言·前端·vue.js·vue2
Java小卷12 小时前
JuanForm vs FormCreate!Vue3 表单引擎联动配置 PK!
vue.js·低代码
kyriewen14 小时前
Skills 榜前 10 我全装了:只有 3 个能直接用
前端·javascript·程序员
IT_陈寒14 小时前
当Java的hashCode遇上Lombok,我的缓存被全清了
前端·人工智能·后端