# Vue

## 介绍下 Vue

Vue.js 是一个前端框架，用来构建交互式的单页应用。

它用了 MVVM 架构：

1. M，Model，模型，对应代码里的数据对象
2. V，View，视图，对应 Vue 模板。我们可以在模板中使用文本插值 `{{ msg }}`、各种指令 `v-`、模板引用 `ref`，这种声明式的渲染模型帮我们抽象了对 DOM 的直接操作
3. VM，ViewModel，视图模型，对应 Vue 的响应式数据绑定。Vue.js 通过使用双向数据绑定来实现数据与视图间的同步。这意味着当数据发生变化时，视图会自动更新，反之亦然。这大大简化了开发过程，无需手动操作 DOM 元素。

此外：

1. Vue 实现了自己的组件模型，让代码更加模块化，易于理解和维护。也可以嵌套组件，形成组件树
   1. 全局注册和局部注册、同步组件和异步组件
   2. 生命周期钩子：允许开发者在组件的不同生命周期阶段执行自定义逻辑
   3. 组件通信
2. Vue Router 实现了单页应用的导航和路由管理，能将不同的组件与 URL 路径相关联
3. 状态管理：Vuex 库 → Pinia 库、RxJS 库，用来管理应用程序的状态

此外：

1. 使用 Vue CLI 来快速搭建 Vue.js 项目
2. 丰富的第三方插件和库
3. 文档齐全、社区活跃

关于 Vue 指令：

1. Vue.js 提供了一些指令，用来处理 DOM 元素。比如
   * `v-bind` 用于绑定属性，`v-model` 用于实现表单元素与数据的双向绑定
   * `v-if` 用于条件渲染、`v-for` 用于循环渲染
   * `v-on` 指令来监听 DOM 元素上事件并触发一个函数
2. 一个指令的任务：是在其表达式的值变化时，响应式地更新 DOM

## 响应式数据绑定

Vue 的响应式数据绑定是基于数据的 getter 和 setter 机制，以及虚拟 DOM 的比较和局部更新。

1. 侦听属性：Vue 在组件实例化时会递归遍历数据对象 data，将每个属性转化为 getter 和 setter。这意味着当访问一个属性时，Vue 会记录该属性的依赖关系，并为属性的变化设置一个监听器。
   1. 依赖追踪：在模板中，当一个属性被用于渲染视图时，Vue 会建立一个依赖关系。这意味着模板中的元素依赖于数据属性，当属性发生变化时，Vue 知道哪些视图需要被更新。
   2. 派发更新：当数据属性发生变化时，setter 会被触发。这时，Vue 会通知依赖于该属性的视图进行更新。Vue 会进行批处理以提高性能，确保只在合适的时候进行DOM更新，而不是立即更新。
2. 虚拟 DOM：差异比较、批量异步更新、局部更新
   1. 虚拟 DOM 的差异比较：Vue 会将虚拟 DOM 与之前的虚拟 DOM 进行比较，找出实际变化的部分（目的是为了减少 DOM 操作的数量，提高性能）
   2. 批量异步更新：在数据发生变化后，Vue 不会立即执行 DOM 更新操作，而是将其放入事件队列中，等到下一个事件循环时才进行更新。这允许 Vue 在同一事件循环内收集多个数据变化，并批量处理它们，以进一步提高性能
   3. 局部更新：根据虚拟 DOM 的差异，Vue 只更新实际变化的DOM元素，而不是整个页面。这使得更新过程更加高效。
   4. 跨平台兼容性：虚拟 DOM 不仅可以在浏览器中使用，还可以在其他环境中使用，例如服务器端渲染（SSR）。这为构建通用应用程序提供了便利。
3. 反应式循环：如果在更新过程中数据再次改变，Vue 会再次触发更新过程，以确保视图与数据保持同步，直到不再有更新发生

> DOM 的更新并不是同步的，Vue 会缓冲它们直到更新周期的“下个时机”，以确保无论我们进行了多少次声明更改，每个组件都只需要更新一次。全局 API `nextTick()` 可确保等待一个状态改变后的 DOM 更新完成。

## 组件间的通信方式

1. 直接父子组件
   1. props：单向数据流，只能从父到子
   2. 自定义事件：子通过 `$emit()` 触发自定义事件，父来监听（只能直接子，没有冒泡）
   3. 透传 attributes（从父到子，一层一层）
2. 若要在兄弟组件或跨越多层嵌套的组件间通信
   1. EventBus：是一个空的 Vue 实例，用来在任意两个组件之间进行通信 `$on`, `$emit`
   2. 全局状态管理：Vuex 库 → Pinia 库
      * 每个 Vue 组件实例都在“管理”它自己的响应式状态了：State, Actions, View
      * 当有多个组件共享一个共同的状态时
   3. 依赖注入（可跨多层）：上层组件提供 `provide()`，下层组件获取 `inject()`

> 补充：若要在有多个组件共享一个共同的状态，其它可选的办法：
>
> 1. props 层层传下来：将共享状态“提升”到共同的祖先组件上去，再通过 props 传递下来
> 2. 用响应式 API 做简单状态管理（手动）：抽取出组件间的共享状态，放在一个全局单例中来管理

其它：

* Suspense API

## Vue 中的设计原则和设计模式

以下仅供参考：

1. 开发人员会用到的
   1. 生命周期钩子函数，模板方法
   2. computed 属性，代理模式
   3. 事件，发布-订阅：引入一个中介者（event bus）来协调生产者和消费者之间的通信
   4. Veux 状态管理模式，单例模式：全局 Store 来存储应用的所有状态
   5. 组件的依赖注入，依赖注入模式
2. Vue 本身的
   1. 组件嵌套的结构，组合模式
   2. 响应式数据绑定，观察者模式：通过 getter 方法收集依赖，通过 setter 方法派发
   3. 插件机制，适配器模式
   4. mixins，装饰器模式


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://anjia1.gitbook.io/web/framework/qa/vue.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
