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 用于创建响应式数据,incrementdecrement 方法分别用于增加和减少计数器的值。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
    };
  }
};
相关推荐
豆豆5 分钟前
为什么用PageAdmin CMS建设网站?
服务器·开发语言·前端·php·软件构建
计算机学姐20 分钟前
基于SpringBoot+Vue的在线投票系统
java·vue.js·spring boot·后端·学习·intellij-idea·mybatis
JUNAI_Strive_ving35 分钟前
番茄小说逆向爬取
javascript·python
看到请催我学习44 分钟前
如何实现两个标签页之间的通信
javascript·css·typescript·node.js·html5
twins35201 小时前
解决Vue应用中遇到路由刷新后出现 404 错误
前端·javascript·vue.js
qiyi.sky1 小时前
JavaWeb——Vue组件库Element(3/6):常见组件:Dialog对话框、Form表单(介绍、使用、实际效果)
前端·javascript·vue.js
煸橙干儿~~1 小时前
分析JS Crash(进程崩溃)
java·前端·javascript
哪 吒1 小时前
华为OD机试 - 几何平均值最大子数(Python/JS/C/C++ 2024 E卷 200分)
javascript·python·华为od
安冬的码畜日常2 小时前
【D3.js in Action 3 精译_027】3.4 让 D3 数据适应屏幕(下)—— D3 分段比例尺的用法
前端·javascript·信息可视化·数据可视化·d3.js·d3比例尺·分段比例尺
杨荧2 小时前
【JAVA开源】基于Vue和SpringBoot的洗衣店订单管理系统
java·开发语言·vue.js·spring boot·spring cloud·开源