<commit_before>
# 状态管理Vuex 

## 介绍


### Vuex 是什么？

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态，并以相应的规则保证状态以一种可预测的方式发生变化。

uni-app 内置了 [Vuex](https://vuex.vuejs.org/zh/) 。



### 什么是“状态管理模式”？

让我们从一个简单的 Vue 计数应用开始：


```html
<!-- view 视图-->
<template>
	<view>
		{{count}}
	</view>
</template>
<script>
	export default {
		// state 数据源
		data() {
			return {
				count: 0
			}
		},
		// actions 控制状态变化
		methods: {
			increment() {
				this.count++
			}
		}
	}
</script>
```


这个状态自管理应用包含以下几个部分：

- state，驱动应用的数据源；
- view，以声明方式将 state 映射到视图；
- actions，响应在 view 上的用户输入导致的状态变化。

以下是一个表示“单向数据流”理念的简单示意：


<img width="300px" src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-dc-site/b0ed6b40-45ec-11eb-bf0a-894cbc80c40a.png" />



但是，当我们的应用遇到**多个组件共享状态**时，单向数据流的简洁性很容易被破坏：

- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。

因此，我们把组件的共享状态抽取出来，以一个全局单例模式管理。在这种模式下，我们的组件树构成了一个巨大的“视图”，不管在树的哪个位置，任何组件都能获取状态或者触发行为！这就是vuex的产生。

通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性，我们的代码将会变得更结构化且易维护。这就是 Vuex 背后的基本思想。


Vuex 是专门为 Vue.js 设计的状态管理库，以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。


<img width="300px" src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-dc-site/b1ba7f40-45ec-11eb-8a36-ebb87efcf8c0.png" />


如果你想交互式地学习 Vuex，可以看这个 [Scrimba 上的 Vuex 课程](https://scrimba.com/learn/vuex)，它将录屏和代码试验场混合在了一起，你可以随时暂停并尝试。




## 优势与使用场景

- Vuex的状态存储是响应式的，可跟踪每一个状态变化，一旦它改变，所有关联组件都会自动更新相对应的数据。
- 共享数据，解决了非父子组件的消息传递（将数据存放在state中）。
- 统一状态管理，减少了请求次数，有些情景可以直接从内存中的state获取数据。



### Vuex与全局变量区别


|vuex	|全局变量|
|--	|--	|
|不能直接改变store里面的变量，由统一的方法修改数据	|可以任意修改	|
|每个组件可以根据自己vuex的变量名引用不受影响	|全局变量可能操作命名污染	|
|解决了多组件之间通信的问题	|跨页面数据共享	|
|适用于多模块、业务关系复杂的中大型项目	|适用于demo或者小型项目	|



### 什么时候需要用vuex？

- 当一个组件需要多次派发事件时。例如购物车数量加减。
- 跨组件共享数据、跨页面共享数据。例如订单状态更新。
- 需要持久化的数据。例如登录后用户的信息。
- 当您需要开发中大型应用，适合复杂的多模块多页面的数据交互，考虑如何更好地在组件外部管理状态时。




## 项目结构


使用 Vuex 需要遵守的规则：

- 应用层级的状态应该集中到单个 `store` 对象中。

- 提交 `mutation` 是更改状态的唯一方法，并且这个过程是同步的。

- 异步逻辑都应该封装到 `action` 里面。

只要你遵守以上规则，如何组织代码随你便。如果你的 `store` 文件太大，只需将 `action` 、`mutation` 和 `getter` 分割到单独的文件。

对于大型应用，我们会希望把 `Vuex` 相关代码分割到模块中。下面是项目结构示例：


```html
├── pages
├── static
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules           # 模块文件夹
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块
├── App.vue
├── main.js
├── manifest.json
├── pages.json
└── uni.scss
```




## 核心概念


每一个 `Vuex` 应用的核心就是 `store`（仓库），它包含着你的应用中大部分的状态 (`state`)。

状态管理有5个核心：`state`、`getter`、`mutation`、`action`、`module`。



### State

单一状态树，定义应用状态的默认初始值，页面显示所需的数据从该对象中进行读取。


- `Vuex` 使用单一状态树，用一个对象就包含了全部的应用层级状态。它便作为一个“唯一数据源”而存在。这也意味着，每个应用将仅仅包含一个 store 实例。
- 单一状态树让我们能够直接地定位任一特定的状态片段，在调试的过程中也能轻易地取得整个当前应用状态的快照。
- 不可直接对 `state` 进行更改，需要通过 `Mutation` 方法来更改。


由于 `Vuex` 的状态存储是响应式的，从 `store` 实例中读取状态最简单的方法就是在计算属性中返回某个状态：

```js
// 创建一个 Counter 组件
const Counter = {
	computed: {
		count () {
			return store.state.count
		}
	}
}
```


每当 `store.state.count` 变化的时候, 都会重新求取计算属性，并且触发更新相关联的 DOM。

然而，这种模式导致组件依赖全局状态单例。在模块化的构建系统中，在每个需要使用 `state` 的组件中需要频繁地导入，并且在测试组件时需要模拟状态。



Vuex 通过 store 选项，提供了一种机制将状态从根组件“注入”到每一个子组件中（需调用 Vue.use(Vuex)）：


1.在 `uni-app` 项目根目录下，新建 `store` 目录，在此目录下新建 `index.js` 文件。在 `index.js` 文件配置如下：

```js
<!-- 页面路径：store/index.js -->
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);//vue的插件机制

//Vuex.Store 构造器选项
const store = new Vuex.Store({
	state:{//存放状态
		"username":"foo"
		"age":18
	}
})
export default store
```


2.在 `main.js` 中导入文件。

```js
<!-- 页面路径：main.js -->
import Vue from 'vue'
import App from './App'
import store from './store'

Vue.prototype.$store = store<commit_msg>update docs/vue-vuex.md.<commit_after>
# 状态管理Vuex 

## 介绍


### Vuex 是什么？

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态，并以相应的规则保证状态以一种可预测的方式发生变化。

uni-app 内置了 [Vuex](https://vuex.vuejs.org/zh/) 。



### 什么是“状态管理模式”？

让我们从一个简单的 Vue 计数应用开始：


```html
<!-- view 视图-->
<template>
	<view>
		{{count}}
	</view>
</template>
<script>
	export default {
		// state 数据源
		data() {
			return {
				count: 0
			}
		},
		// actions 控制状态变化
		methods: {
			increment() {
				this.count++
			}
		}
	}
</script>
```


这个状态自管理应用包含以下几个部分：

- state，驱动应用的数据源；
- view，以声明方式将 state 映射到视图；
- actions，响应在 view 上的用户输入导致的状态变化。

以下是一个表示“单向数据流”理念的简单示意：


<img width="300px" src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-dc-site/b0ed6b40-45ec-11eb-bf0a-894cbc80c40a.png" />



但是，当我们的应用遇到**多个组件共享状态**时，单向数据流的简洁性很容易被破坏：

- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。

因此，我们把组件的共享状态抽取出来，以一个全局单例模式管理。在这种模式下，我们的组件树构成了一个巨大的“视图”，不管在树的哪个位置，任何组件都能获取状态或者触发行为！这就是vuex的产生。

通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性，我们的代码将会变得更结构化且易维护。这就是 Vuex 背后的基本思想。


Vuex 是专门为 Vue.js 设计的状态管理库，以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。


<img width="300px" src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-dc-site/b1ba7f40-45ec-11eb-8a36-ebb87efcf8c0.png" />


如果你想交互式地学习 Vuex，可以看这个 [Scrimba 上的 Vuex 课程](https://scrimba.com/learn/vuex)，它将录屏和代码试验场混合在了一起，你可以随时暂停并尝试。




## 优势与使用场景

- Vuex的状态存储是响应式的，可跟踪每一个状态变化，一旦它改变，所有关联组件都会自动更新相对应的数据。
- 共享数据，解决了非父子组件的消息传递（将数据存放在state中）。
- 统一状态管理，减少了请求次数，有些情景可以直接从内存中的state获取数据。



### Vuex与全局变量区别


|vuex	|全局变量|
|--	|--	|
|不能直接改变store里面的变量，由统一的方法修改数据	|可以任意修改	|
|每个组件可以根据自己vuex的变量名引用不受影响	|全局变量可能操作命名污染	|
|解决了多组件之间通信的问题	|跨页面数据共享	|
|适用于多模块、业务关系复杂的中大型项目	|适用于demo或者小型项目	|



### 什么时候需要用vuex？

- 当一个组件需要多次派发事件时。例如购物车数量加减。
- 跨组件共享数据、跨页面共享数据。例如订单状态更新。
- 需要持久化的数据。例如登录后用户的信息。
- 当您需要开发中大型应用，适合复杂的多模块多页面的数据交互，考虑如何更好地在组件外部管理状态时。




## 项目结构


使用 Vuex 需要遵守的规则：

- 应用层级的状态应该集中到单个 `store` 对象中。

- 提交 `mutation` 是更改状态的唯一方法，并且这个过程是同步的。

- 异步逻辑都应该封装到 `action` 里面。

只要你遵守以上规则，如何组织代码随你便。如果你的 `store` 文件太大，只需将 `action` 、`mutation` 和 `getter` 分割到单独的文件。

对于大型应用，我们会希望把 `Vuex` 相关代码分割到模块中。下面是项目结构示例：


```html
├── pages
├── static
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules           # 模块文件夹
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块
├── App.vue
├── main.js
├── manifest.json
├── pages.json
└── uni.scss
```




## 核心概念


每一个 `Vuex` 应用的核心就是 `store`（仓库），它包含着你的应用中大部分的状态 (`state`)。

状态管理有5个核心：`state`、`getter`、`mutation`、`action`、`module`。



### State

单一状态树，定义应用状态的默认初始值，页面显示所需的数据从该对象中进行读取。


- `Vuex` 使用单一状态树，用一个对象就包含了全部的应用层级状态。它便作为一个“唯一数据源”而存在。这也意味着，每个应用将仅仅包含一个 store 实例。
- 单一状态树让我们能够直接地定位任一特定的状态片段，在调试的过程中也能轻易地取得整个当前应用状态的快照。
- 不可直接对 `state` 进行更改，需要通过 `Mutation` 方法来更改。


由于 `Vuex` 的状态存储是响应式的，从 `store` 实例中读取状态最简单的方法就是在计算属性中返回某个状态：

```js
// 创建一个 Counter 组件
const Counter = {
	computed: {
		count () {
			return store.state.count
		}
	}
}
```


每当 `store.state.count` 变化的时候, 都会重新求取计算属性，并且触发更新相关联的 DOM。

然而，这种模式导致组件依赖全局状态单例。在模块化的构建系统中，在每个需要使用 `state` 的组件中需要频繁地导入，并且在测试组件时需要模拟状态。



Vuex 通过 store 选项，提供了一种机制将状态从根组件“注入”到每一个子组件中（需调用 Vue.use(Vuex)）：


1.在 `uni-app` 项目根目录下，新建 `store` 目录，在此目录下新建 `index.js` 文件。在 `index.js` 文件配置如下：

```js
<!-- 页面路径：store/index.js -->
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);//vue的插件机制

//Vuex.Store 构造器选项
const store = new Vuex.Store({
	state:{//存放状态
		"username":"foo",
		"age":18
	}
})
export default store
```


2.在 `main.js` 中导入文件。

```js
<!-- 页面路径：main.js -->
import Vue from 'vue'
import App from './App'
import store from './store'

Vue.prototype.$store = store
{'fraction_non_alphanumeric': 0.15471540178571427, 'fraction_numerical': 0.011997767857142858, 'mean_word_length': 4.318249258160237, 'pattern_counts': {'":': 4, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 8, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '867058', 'n_tokens_mistral': 5166, 'n_tokens_neox': 5646, 'n_words': 510}