---
title: Vue 教程
sidebar_position: 3
---

import Alert from '@site/src/components/Alert'
import UseTaroState from '@vue-demo/useState/index.vue'
import UseTaroEffect from '@vue-demo/useEffect/index.vue'
import UseTaroRef from '@vue-demo/useRef/index.vue'
import UseTaroReducer from '@vue-demo/useReducer/index.vue'
import UseTaroContext from '@vue-demo/useContext/index.vue'

:::caution

下面的内容都建立在拥有足够的**Vue3** 和 **React-hooks** 的基础上. 若还对前面叙述的不清楚的可以先了解一下

:::

## 概述

**taro-hooks** 支持 **Vue3** 的方式为插件化. 使用插件模拟对应的常用 **React-hooks**. 当然, 如果你不想使用 **taro-hooks**. 但想要在 **Vue3** 中体验 **React-hooks**. 可以使用下面的插件.

## 配置

### 安装 **taro-hooks**

```bash
# npm
$ npm i taro-hooks
# yarn
$ yarn add taro-hooks
# pnpm
$ pnpm add taro-hooks
```

### 安装插件

首先需要下载 **@taro-hooks/plugin-vue** 插件

```bash
# npm
$ npm i @taro-hooks/plugin-vue
# yarn
$ yarn add @taro-hooks/plugin-vue
# pnpm
$ pnpm add @taro-hooks/plugin-vue
```

> 建议您同时下载 **@taro-hooks/shared** 插件用于转换一些等同状态的 **state**

```bash
# npm
$ npm i @taro-hooks/shared
# yarn
$ yarn add @taro-hooks/shared
# pnpm
$ pnpm add @taro-hooks/shared
```

### 项目配置

```js title="config/index.js"
const config = {
  // ...
  plugins: ['@taro-hooks/plugin-vue'],
  // ...
};
```

> 我们也配套提供了适配 `unplugin-auto-import` 的插件 [`@taro-hooks/plugin-auto-import`](/docs/quick/auto-import)

> 注意: 插件内部会检测当前项目的框架和依赖状态, 若您的项目不是 **Vue3** 的项目, 那么很可能无法正常启动.

## **Hooks**

所有的 **Hooks** 均在运行时注入到了 **@taro-hooks/core** 内部, 并使用了和 **React** 中一致的名称.

```html title="example/index.vue" showLineNumbers
<script>
  import {
    useState,
    useEffect,
    useRef,
    useReducer,
    useCallback,
    useMemo,
    useLayoutEffect,
    useContext,
    useWatchEffect,
    createContext,
  } from '@taro-hooks/core';

  export default {
    setup() {
      // use hooks in setup
    },
  };
</script>
```

:::tip

下面的 **Hook** 使用示例尽可能的和 **React** 教程保持了一致. 方便 **React** 开发的同学阅读

:::

### **useState**

**useState** 帮助您快速创建一个响应式数据和更改它的方法
但这里需要注意的是, 它内部使用的是 **Ref**. 在 **template** 内会被自动解包. 但在 **setup** 内使用依然需要显式的使用 **state.value** 来获取值. 当然我们也提供了一个工具来抹平差异. 在下面的示例中有体现

<UseTaroState />

:::caution

注意: **useEffect** 、 **useWatchEffect** 、 **useRef**、 **useCallback**、 **useMemo** 内部均使用 **watchEffect** 收集依赖变化. 它满足 [**与watch共享的行为**](https://v3.cn.vuejs.org/guide/reactivity-computed-watchers.html#%E4%B8%8E-watcheffect-%E5%85%B1%E4%BA%AB%E7%9A%84%E8%A1%8C%E4%B8%BA). 应尽量避免在 **hooks** 外单独处理依赖清除
:::

### **useEffect**

**useEffect** 帮助您给函数组件增加操作副作用的能力. 它和 **componentDidMount|DidUpdate|WillUnmount** 具有相同的用途.

<UseTaroEffect />

### **useRef**

**useRef** 帮助您创建一个不会触发重新渲染的引用. 它和 **React.createRef** 具有相同的用途.

<UseTaroRef />

<Alert type="warning">
注意<strong>useRef</strong>内部是默认使用<strong>reactive</strong>来生成. 若需要在视图内保活, 请不要解构.
</Alert>

### **useReducer**

**useReducer** 帮助您创建一个 **reducer** (**eventBus**) 在组件中使用.

<UseTaroReducer />

### **useCallback**

**useCallback** 返回一个 [**memoized**](https://en.wikipedia.org/wiki/Memoization) 回调函数

```js showLineNumbers title="/useCallback/index.vue"
const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);
```

### **useMemo**

**useMemo** 返回一个 [**memoized**](https://en.wikipedia.org/wiki/Memoization) 回调函数

```js showLineNumbers title="/useMemo/index.vue"
const memoizedValue = useMemo(
  () => computeExpensiveValue(a, b),
  [a, b]
);
```

<Alert type="warning">
你可以把 useMemo 作为性能优化的手段，但不要把它当成语义上的保证
</Alert>

### **useLayoutEffect**

**useLayoutEffect** 函数签名和 **useEffect** 相同. 但它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染

<Alert type="danger">
请尽可能的减少使用此 hook 的次数，因为它会导致额外的性能开销
</Alert>

### **useContext**

**useContext** 帮助您读取和订阅组件的上下文.

<UseTaroContext />

<Alert type="danger">
注意: <strong>context</strong> 必须设置为对象的形式. 为了达到多层继承的目的. 继承的动作由 <code>createContext</code> 来完成. 内部实则走的是扩展合并.
</Alert>
