## 入门

### 介绍

Vue 是一套用于构建用户界面的渐进式框架

- Vue 3.x 官方文档 (cn.vuejs.org)
- Vue Router 4.x 官方文档 (router.vuejs.org)
- Vue 2 备忘清单

注意：Vue 3.x 版本对应 Vue Router 4.x 路由版本

### 创建应用

已安装 `16.0` 或更高版本的 Node.js

    $ npm init vue@latest

指令将会安装并执行 create-vue，它是 Vue 官方的项目脚手架工具

    ✔ Project name: … <your-project-name>
    ✔ Add TypeScript? … No/Yes
    ✔ Add JSX Support? … No/Yes
    ✔ Add Vue Router for Single Page Application development? … No/Yes
    ✔ Add Pinia for state management? … No/Yes
    ✔ Add Vitest for Unit testing? … No/Yes
    ✔ Add Cypress for both Unit and End-to-End testing? … No/Yes
    ✔ Add ESLint for code quality? … No/Yes
    ✔ Add Prettier for code formatting? … No/Yes

    Scaffolding project in ./<your-project-name>...
    Done.

安装依赖并启动开发服务器

    $ cd <your-project-name>
    $ npm install
    $ npm run dev

当你准备将应用发布到生产环境时，请运行：

    $ npm run build

此命令会在 `./dist` 文件夹中为你的应用创建一个生产环境的构建版本

### 应用实例

    import { createApp } from 'vue'

    const app = createApp({
      data() {
        return { count: 0 }
      }
    })
    app.mount('#app')

挂载应用

    <div id="app">
      <button @click="count++">
        {{ count }}
      </button>
    </div>

### 通过 CDN 使用 Vue

    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <div id="app">{{ message }}</div>
    <script>
      const { createApp } = Vue
      createApp({
        data() {
          return {
            message: 'Hello Vue!'
          }
        }
      }).mount('#app')
    </script>

### 使用 ES 模块构建版本

    <div id="app">{{ message }}</div>
    <script type="module">
      import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
      createApp({
        data() {
          return {
            message: 'Hello Vue!'
          }
        }
      }).mount('#app')
    </script>

## 模板语法

### 文本插值

    <span>Message: {{ msg }}</span>

使用的是 `Mustache` 语法 (即双大括号)，每次 `msg` 属性更改时它也会同步更新

### 原始 HTML

    <p>Using text interpolation: {{ rawHtml }}</p>
    <p>Using v-html directive: <span v-html="rawHtml"></span></p>

双大括号`{{}}`会将数据解释为纯文本，使用 `v-html` 指令，将插入 HTML

### Attribute 绑定

    <div v-bind:id="dynamicId"></div>

简写

    <div :id="dynamicId"></div>

### 布尔型 Attribute

    <button :disabled="isButtonDisabled">
      Button
    </button>

### 动态绑定多个值

    data() {
      return {
        objectOfAttrs: {
          id: 'container',
          class: 'wrapper'
        }
      }
    }

通过不带参数的 `v-bind`，你可以将它们绑定到单个元素上

    <div v-bind="objectOfAttrs"></div>

### 使用 JavaScript 表达式

    {{ number + 1 }}
    {{ ok ? 'YES' : 'NO' }}
    {{ message.split('').reverse().join('') }}

    <div :id="`list-${id}`"></div>

### 仅支持表达式(例子都是无效)

    <!-- 这是一个语句，而非表达式 -->
    {{ var a = 1 }}
    <!-- 条件控制也不支持，请使用三元表达式 -->
    {{ if (ok) { return message } }}

### 调用函数

    <span :title="toTitleDate(date)">
      {{ formatDate(date) }}
    </span>

### 指令 Directives

    <p v-if="seen">Now you see me</p>

### 参数 Arguments

    <a v-bind:href="url"> ... </a>
    <!-- 简写 -->
    <a :href="url"> ... </a>

### 绑定事件

    <a v-on:click="doSomething"> ... </a>
    <!-- 简写 -->
    <a @click="doSomething"> ... </a>

### 动态参数

    <a v-bind:[attributeName]="url"> ... </a>
    <!-- 简写 -->
    <a :[attributeName]="url"> ... </a>

这里的 `attributeName` 会作为一个 JS 表达式被动态执行

### 动态的事件名称

    <a v-on:[eventName]="doSomething"> ... </a>
    <!-- 简写 -->
    <a @[eventName]="doSomething">

### 修饰符 Modifiers

    <form @submit.prevent="onSubmit">
      ...
    </form>

`.prevent` 修饰符会告知 `v-on` 指令对触发的事件调用 `event.preventDefault()`

### 指令语法

    v-on:submit.prevent="onSubmit"
    ──┬─ ─┬──── ─┬─────  ─┬──────
      ┆   ┆      ┆        ╰─ Value 解释为JS表达式
      ┆   ┆      ╰─ Modifiers 由前导点表示
      ┆   ╰─ Argument 跟随冒号或速记符号
      ╰─ Name 以 v- 开头使用速记时可以省略

## 响应式基础

### 声明状态

    <div>{{ count }}</div>

    export default {
      data() {
        return {
          count: 0
        }
      },
    }

### 声明方法

    <button @click="increment">
      {{ count }}
    </button>

    export default {
      data() {
        return {
          count: 0
        }
      },
      methods: {
        increment() {
          this.count++
        }
      }
    }

### 有状态方法

    import { debounce } from 'lodash-es'
    export default {
      created() {
        // 每个实例都有了自己的预置防抖的处理函数
        this.debouncedClick = debounce(this.click, 500)
      },
      unmounted() {
        // 最好是在组件卸载时
        // 清除掉防抖计时器
        this.debouncedClick.cancel()
      },
      methods: {
        click() {
          // ... 对点击的响应 ...
        }
      }
    }

## API 参考

### 全局 API - 应用实例

:- | :-
--- | ---
`createApp()` | #
`createSSRApp()` | #
`app.mount()` | #
`app.unmount()` | #
`app.provide()` | #
`app.component()` | #
`app.directive()` | #
`app.use()` | #
`app.mixin()` | #
`app.version` | #
`app.config` | #
`app.config.errorHandler` | #
`app.config.warnHandler` | #
`app.config.performance` | #
`app.config.compilerOptions` | #
`app.config.globalProperties` | #
`app.config.optionMergeStrategies` | #

### 全局 API - 通用

:- | :-
--- | ---
`version` | #
`nextTick()` | #
`defineComponent()` | #
`defineAsyncComponent()` | #
`defineCustomElement()` | #

### 组合式 API - setup()

:- | :-
--- | ---
`基本使用` | #
`访问 Props` | #
`Setup 上下文` | #
`与渲染函数一起使用` | #

### 组合式 API - 响应式: 工具

:- | :-
--- | ---
`isRef()` | #
`unref()` | #
`toRef()` | #
`toRefs()` | #
`isProxy()` | #
`isReactive()` | #
`isReadonly()` | #

### 组合式 API - 生命周期钩子

:- | :-
--- | ---
`onMounted()` | 组件挂载完成后执行 #
`onUpdated()` | 状态变更而更新其 DOM 树之后调用 #
`onUnmounted()` | 组件实例被卸载之后调用 #
`onBeforeMount()` | 组件被挂载之前被调用 #
`onBeforeUpdate()` | 状态变更而更新其 DOM 树之前调用 #
`onBeforeUnmount()` | 组件实例被卸载之前调用 #
`onErrorCaptured()` | 捕获了后代组件传递的错误时调用 #
`onRenderTracked()` | 组件渲染过程中追踪到响应式依赖时调用 #
`onRenderTriggered()` | 响应式依赖的变更触发了组件渲染时调用 #
`onActivated()` | 若组件实例是 <KeepAlive> 缓存树的一部分，当组件被插入到 DOM 中时调用 #
`onDeactivated()` | 若组件实例是 <KeepAlive> 缓存树的一部分，当组件从 DOM 中被移除时调用 #
`onServerPrefetch()` | 组件实例在服务器上被渲染之前调用 #

### 组合式 API - 依赖注入

:- | :-
--- | ---
`provide()` | #
`inject()` | #

### 组合式 API - 响应式: 核心

:- | :-
--- | ---
`ref()` | #
`computed ()` | #
`reactive()` | #
`readonly()` | #
`watchEffect()` | #
`watchPostEffect()` | #
`watchSyncEffect()` | #
`watch()` | #

### 选项式 API - 状态选项

:- | :-
--- | ---
`data` | #
`props` | #
`computed` | #
`methods` | #
`watch` | #
`emits` | #
`expose` | #

### 选项式 API - 生命周期选项

:- | :-
--- | ---
`beforeCreate` | #
`created` | #
`beforeMount` | #
`mounted` | #
`beforeUpdate` | #
`updated` | #
`beforeUnmount` | #
`unmounted` | #
`errorCaptured` | #
`renderTracked` | #
`renderTriggered` | #
`activated` | #
`deactivated` | #
`serverPrefetch` | #

### 选项式 API - 其他杂项

:- | :-
--- | ---
`name` | 显式声明组件展示时的名称 #
`inheritAttrs` | 默认的组件 `attribute` 透传行为 #
`components` | #
`directives` | #

### 选项式 API - 渲染选项

:- | :-
--- | ---
`template` | #
`render` | #
`compilerOptions` | #

### 选项式 API - 组件实例

:- | :-
--- | ---
`$data` | #
`$props` | #
`$el` | #
`$options` | #
`$parent` | #
`$root` | #
`$slots` | #
`$refs` | #
`$attrs` | #
`$watch()` | #
`$emit()` | #
`$forceUpdate()` | #
`$nextTick()` | #

### 选项式 API - 组合选项

:- | :-
--- | ---
`provide` | #
`inject` | #
`mixins` | #
`extends` | #

### 内置内容 - 指令

:- | :-
--- | ---
`v-text` | #
`v-html` | #
`v-show` | #
`v-if` | #
`v-else` | #
`v-else-if` | #
`v-for` | #
`v-on` | #
`v-bind` | #
`v-model` | #
`v-slot` | #
`v-pre` | #
`v-once` | #
`v-memo` | #
`v-cloak` | #

### 内置内容 - 组件

:- | :-
--- | ---
`<Transition>` | #
`<TransitionGroup>` | #
`<KeepAlive>` | #
`<Teleport>` | #
`<Suspense>` | #

### 内置内容 - 特殊 Attributes

:- | :-
--- | ---
`key` | #
`ref` | #
`is` | #

### 内置内容 - 特殊元素

:- | :-
--- | ---
`<component>` | #
`<slot>` | #

### 单文件组件 - 语法定义

:- | :-
--- | ---
`总览` | #
`相应语言块` | #
`自动名称推导` | #
`预处理器` | #
`Src 导入` | #
`注释` | #

### 单文件组件 - <script setup>

:- | :-
--- | ---
`基本语法` | #
`响应式` | #
`使用组件` | #
`使用自定义指令` | #
`defineProps() 和 defineEmits()` | #
`defineExpose` | #
`useSlots() 和 useAttrs()` | #
`与普通的 &lt;script&gt; 一起使用` | #
`顶层 await` | #
`针对 TypeScript 的功能` | #
`限制` | #

### 单文件组件 - CSS 功能

:- | :-
--- | ---
`组件作用域 CSS` | #
`CSS Modules` | #
`CSS 中的 v-bind()` | #

### 进阶 API - 渲染函数

:- | :-
--- | ---
`h()` | #
`mergeProps()` | #
`cloneVNode()` | #
`isVNode()` | #
`resolveComponent()` | #
`resolveDirective()` | #
`withDirectives()` | #
`withModifiers()` | #

### 进阶 API - 服务端渲染

:- | :-
--- | ---
`renderToString()` | #
`renderToNodeStream()` | #
`pipeToNodeWritable()` | #
`renderToWebStream()` | #
`pipeToWebWritable()` | #
`renderToSimpleStream()` | #
`useSSRContext()` | #

### 进阶 API - TypeScript 工具类型

:- | :-
--- | ---
`PropType<T>` | #
`ComponentCustomProperties` | #
`ComponentCustomOptions` | #
`ComponentCustomProps` | #
`CSSProperties` | #

### 进阶 API - 自定义渲染

:- | :-
--- | ---
`createRenderer()` | #

## 另见

- Vue 3.x 官方文档
- Vue Router 4.x 官方文档