01、什么是Vuex?

1.1、为什么需要状态管理?

在复杂的系统中,我们会把系统按照业务逻辑拆分为多个层次、多个模块,采用组件式的开发方式。而此时不同模块、父子模块之间的通信就成了一个问题。

为了解决这个问题,就有了状态管理,核心概念就是把大家共享的状态(数据)抽出来,放到一个全局共享的仓库里,按照一定约定统一管理,让状态的变化可预测。这就有两个关键点:

  • 统一存储:共享的状态统一存储,全局共享。
  • 可预测:共享的状态不可随意修改,需要按照约定的规则修改,才能监测状态变更、通知更新。

1.2、Vuex简介

Vuex 就是面向Vue的状态管理组件,采用集中式存储+管理应用的所有共享状态。Vuex只能在Vue中使用,深度使用了Vue的能力,如用Vue来实现state的响应式特性。

简单来说,就是Vuex有一个全局公共的store(类似Vue里的data),作为公共数据仓库,保存了大家共享的状态(数据)。这个数据仓库store实现了数据响应、自动通知更新,这样就很容易实现了各个组件间的数据通信了。

其实,对于简单的应用不一定需要Vuex,不过Vuex文件并不大(gzip压缩后10K左右)。

Vuex主要特点就是:单向数据流+单一数据源。

  • state:存储数据仓库,类似Vue的data,也是响应式的,变更后会自动通知View。
  • views:组件视图,就是使用state的Vue组件。
  • actions:更新state状态,为了规范管理,state不能直接修改,必须通过action进行提交。Vuex中分为同步Mutation、和异步Action。

02、安装使用

  • 通过<script>标签直接引用vuex.js
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3/dist/vuex.js"></script>
// 注册插件
Vue.use(Vuex);
  • 通过 vue-cli 脚手架搭建vue的开发框架,集成了vuex组件。
  • 注册插件:Vue.use(Vuex)

调试已经被集成在了Vue的调试工具Devtools中了。


03、Vuex3入门

3.1、Vuex选项&实例

Store构造器选项 描述
state Vuex store 实例的根 state 对象
mutations 注册 mutation,就是修改数据的方法,参数为state。不支持异步,通过store.commit(name)调用
actions 注册 action,参数为context,同store实例,但不是她。支持异步,通过store.dispatch(name)调用
getters 注册 getter{ [key: string]: Function },参数为state,定义、使用同计算属性
modules 子模块的对象,分割管理store,{ key(moduleName) : {state, namespaced?, mutations?, actions? ... }}
strict 是否严格模式,默认false,true=严格模式下,任何 mutation 处理函数以外修改state 都会抛出错误。
store实例属性 描述
state 数据源state根对象
getters 所有注册的getter
store 实例方法
commit(name, arg?, options?) 提交 mutation 执行申请,namemutation注册的方法名
dispatch(name, arg?, options?) 提交 action 执行申请,nameaction注册的方法名
replaceState(state: Object) 替换 store 的根状态,用于合并状态,如加载持久化的state数据。
watch(fn, callback) 响应式地侦听 fn 的返回值,当值改变时调用回调函数
subscribe(handler, option?) 订阅 store 的 mutation,每一个mutation执行完调用
subscribeAction(handler, option?) 订阅 store 的 action
registerModule(path, module) 注册一个动态模块
unregisterModule(path) 卸载一个动态模块
hasModule(path) 检查模块是否以注册
hotUpdate(newOptions: Object) 热替换新的 action 和 mutation
const store = new Vuex.Store({
strict:false,
state: { //定义数据结构-数据仓库
points: 1000,
user: { id: '001', name: 'sam' }
},
mutations: { //修改数据的方法
setUser(state, obj) {
state.user.id = obj.uid;
state.user.name = obj.uname;
},
},
actions: { //修改数据的方法-异步
set(context, obj) { context.commit('setUser', obj) }
},
getters: { //获取数据的计算属性
userExist(state) { return state.user.id != ''; }
}
})
//提交数据修改
store.commit('setUser',{uid:'007',uname:'zhangsan'});
console.log(store.state.user); //id : "007" name : "zhangsan"
console.log(store.getters.userExist); //true

3.2、Vuex核心流程

Vuex核心概念

  • Store 单一状态树:一个应用程序中只有一个Store实例(单例模式),Store包含了stateactionsmutationsgettermodules。一般会在根Vue注册store实例,这样组件内所有地方都可以 this.$store 访问了。
  • State 数据源:实现了响应式监听,可用mapState辅助函数包装为计算属性访问。
  • Getter 访问属性:返回对state状态数据进行加工后的结果,类似Vue中的计算属性、过滤器,区别就是这是全局共享的。
  • Mutation 修改数据:Vuex中用于修改状态数据的主要方式,是唯一修改state数据的合理途径了。通过store.commit() 调用mutation。(mutation /mjuːˈteɪʃ(ə)n/ 改变)
  • Action 异步操作:类似Vue的methods,支持异步操作。通过store.dispatch()调用,实际修改数据也是要调用mutation的。Action 可用来发起异步ajax请求获取处理 state的数据,这是和mutation最大的不同了。
  • Module 模块:当Store很复杂时,用Module拆分为多个模块管理,每个模块里有自己的stateactionsmutationsgettermodules

基本流程

定义数据 state,和data一样,预先定义好数据结构,以及数据更新的mutation方法。

使用数据 state

  • 在根组件注入store实例,组件内所有地方(包括后代组件)都可以 this.$store 访问了。
  • 通过计算属性computed包装所需的 state数据。如果state数据需要双向绑定到表单元素,则需要用计算属性实现get、set来代理实现。
  • 通过方法methods包装数据的更新store.mutation
  • View上绑定使用,可以绑定包装后的计算属性、方法,也可以直接绑定注入的$store

❸ 触发更新,根据业务需要更新state数据。

  • store.commit(name, arg?, options?)
  • store.dispatch(name, arg?, options?)

❹ 正式修改state数据,并触发 View 自动更新。

<div id="app">
<button @click="login">登录</button>
<p>用户:{{$store.state.user.name}}({{$store.state.user.id}})</p>
<p v-text="`用户:${$store.state.user.name}(${$store.state.user.id})`"></p>
</div>
<script>
// 注册插件
Vue.use(Vuex);
//申明全局store
const store = new Vuex.Store({
state: { user: { id: '', name: '' } },
mutations: { setUser(state, obj) { state.user.id = obj.uid; state.user.name = obj.uname; }, },
getters: { userExist(state) { return state.user.id != ''; } }
})
//根Vue
let app = new Vue({
el: '#app',
data: {},
store: store,  //在根组件注入store实例,组件内所有地方都可以 this.$store 通过访问了
methods: {
login() { this.$store.commit('setUser',{ uid: '007', uname: 'zhangsan' }) }
}
})
</script>

3.3、创建Vuex()-购物车案例

  1. 注册插件:Vue.use(Vuex)
  2. 创建全局共享的Store实例,并配置数据、方法。
  3. 注入store,在根Vue组件上注入store实例。
  4. 愉快的使用了。
<script>
// 注册插件
Vue.use(Vuex);
//申明全局store
const store = new Vuex.Store({
state: { cart: ['汽车01', '苹果', '梨子'] },
mutations: {
add(state, item) { state.cart.push(item); },
delete(state, index) { state.cart.splice(index,1) }
},
actions: { add(context, item) { context.commit('add', item) } },
getters: { cartTotal(state) { return state.cart.length; } }
})
</script> <div id="app1">
<p>购物车({{this.$store.getters.cartTotal}})(直接绑定)</p>
<p>购物车({{cartTotal}}) <button @click="add">添加商品</button></p>
<cart-box></cart-box>
</div>
<template id="cardBoxTemplate"> <!--购物列表模板-->
<ul>
<li v-for="(item,index) in cartList">{{item}} <button v-on:click="deleteItem(index)">删除</button></li>
</ul>
</template>
<script>
let app1 = new Vue({
el: "#app1",
data: {},
store: store, //在根组件注入store实例,组件内所有地方都可以 this.$store 访问了
computed: {
cartTotal: function () { return this.$store.getters.cartTotal; }
},
methods: { add: function (item) { this.$store.dispatch('add', "西瓜") } },
components: { //购物车组件
'cart-box': {
computed: { cartList() { return this.$store.state.cart; } },
template: '#cardBoxTemplate',
methods: { deleteItem: function (index) { this.$store.commit("delete", index); } }
}
}
})
</script>

3.4、...mapState语法糖

mpaStatestate的一种Vuex提供的 “语法糖”,主要作用是简化代码。比如当state有多个状态属性,在组件中都要用就得一个一个包装,代码冗余。这时,mapState就可以简化这个重复、无聊的代码了。

<script>
let app1 = new Vue({
el: "#app1",
data: {},
store: store, computed: { //做一个简单包装,使用时更方便
card() { return $store.state.card; },
user() { return $store.state.user; }
},
computed: Vuex.mapState(['card', 'user']), //直接赋值,效果同上,简化了包装代理代码
computed: {
cartTotal: function () { return this.$store.getters.cartTotal; },
//展开运算符展开
...Vuex.mapState({
'cart': 'cart', //计算属性名称:state状态名称
currentUserId: 'user',
}),
...Vuex.mapState(['cart', 'user']) //更简洁的写法
},
})
</script>
  • mpaState() 是Vuex提供一个辅助函数,帮助生成计算属性。返回的是一个对象(结构同计算属性computed)。

mapState(namespace?: string, map: Array<string> | Object<string | function>): Object

  • ...mapState,三个点...是ES6的展开运算符,把对象展开混入当前环境。

其他还有 mapGetters、mapActions、mapMutations 都是类似作用和用法。

3.5、Module模块化

当共享的数据和操作太多时,就需要分模块管理了,如下模块示例。

const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
} const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
} const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
}) store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

每个模块 module 都包含完整的store结构。

module定义结构{ key(moduleName) : {state, namespaced?, mutations?, actions?, getters? modules? }}

  • key:就是模块的名称,也是模块的命名空间。
  • value,就是一个和store结构相同的对象,存放模块的store信息。模块里方法的参数statecontext都是命名空间内的局部对象。

模块化的项目结构:

├── index.html
├── main.js
├── api
│ └── ... # 抽取出API请求
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块

04、Vuex4区别

几乎所有的 Vuex 4 API 都与 Vuex 3 保持不变,有少量差异。

  • 创建方式不同,Vuex4 使用 createStore({}) 函数创建store对象,之前的方式依然支持。
  • 安装方式,app.use(store),已经注入了store实例,不用再注册store实例了。
  • 打包产物已经与 Vue 3 配套。
  • 新特性:useStore组合式函数。//TODO

05、一些问题

Vuex的持久化?

如果用户刷新页面,导致页面的各种实例重新初始化,之前的全局状态就会丢失。解决方法就是把state数据仓库存起来,当刷新页面的时候读取出来,如果关闭页面就不用管了。

  1. 持久化state:在页面刷新时的 beforeunload事件中保存statesessionStorage里。sessionStorage刷新页面不会丢失,关闭才清除。
  2. 加载state:Vue create中加载持久化的state,并清除持久化的state数据。
created: function () {
window.addEventListener('beforeunload', () => {
sessionStorage.setItem('vstore', JSON.stringify(this.$store.state));
});
try {
const vstore = sessionStorage.getItem('vstore')
if (vstore)
this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(vstore)));
}
catch (ex) { console.log(ex) }
sessionStorage.removeItem('vstore');
}

️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀

Vuex极速入门的更多相关文章

  1. [转]Nginx基本功能极速入门

    原文链接:Nginx基本功能极速入门 | 叉叉哥的BLOG 本文主要介绍一些Nginx的最基本功能以及简单配置,但不包括Nginx的安装部署以及实现原理.废话不多,直接开始. 1.静态HTTP服务器 ...

  2. 《Python黑客编程之极速入门》正式开课

    玄魂 玄魂工作室 今天 之前开启了一个<Python黑客编程>的系列,后来中断了,内容当时设置的比较宽,不太适合入门.现在将其拆分成两个系列<Python黑客编程之极速入门>和 ...

  3. 1 小时 SQL 极速入门(三)——分析函数

    1 小时 SQL 极速入门 前面两篇我们从 SQL 的最基础语法讲起,到表联结多表查询. 大家可以点击链接查看 1 小时 SQL 极速入门(一) 1 小时 SQL 极速入门(二) 今天我们讲一些在做报 ...

  4. Go 语言极速入门

    本系列文章主要是记录<Go 语言实战>和<Google 资深工程师深度讲解 Go 语言>的学习笔记. Go 语言极速入门1 - 环境搭建与最简姿势Go 语言极速入门2 - 基础 ...

  5. Vuex 2 入门与提高。

    从计数器开始 让我们从一个简单的计数器,开始进入Vuex 的世界: 计数器应用的数据模型很简单:使用一个counter属性来表示计数器的 当前值就够了. 在Vue实例的created钩子 中,应用启动 ...

  6. Vuex的入门教程

    前言 在 Vue.js 的项目中,如果项目结构简单, 父子组件之间的数据传递可以使用  props 或者 $emit 等方式,详细点击这篇文章查看. 但是如果是大型项目,很多时候都需要在子组件之间传递 ...

  7. 多本Python极速入门最佳书籍,不可错过的Python学习资料!

    Python作为现在很热门的一门编程语言,介于Python的友好,许多的初学者都将其作为首选,为了帮助大家更好的学习Python,我筛选了2年内优秀的python书籍,个别经典的书籍扩展到5年内.   ...

  8. vuex 基本入门和使用(三)-关于 mutation

    vuex 基本入门和使用(三)-关于 mutation vuex 版本为^2.3.1,按照我自己的理解来整理vuex. 关于 mutation 这里应该很好理解. 更改 Vuex 的 store 中的 ...

  9. Knative 初体验:CICD 极速入门

    Knative 社区很早就在讨论用 Tekton 替换 Build 模块的相关事宜.Knative Build 官方已经正式说明不再建议使用 Knative Build 了. 如果你知道 Knativ ...

  10. 60 分钟极速入门 PyTorch

    2017 年初,Facebook 在机器学习和科学计算工具 Torch 的基础上,针对 Python 语言发布了一个全新的机器学习工具包 PyTorch. 因其在灵活性.易用性.速度方面的优秀表现,经 ...

随机推荐

  1. 7.prometheus监控多个MySQL实例

    mysqld_exporter集中部署 集中部署,就是说我们将所有的mysqld_exporter部署在同一台服务器上,在这台服务器上对mysqld_exporter进行统一的管理,下面介绍一下集中部 ...

  2. 跟我学Python图像处理丨带你掌握傅里叶变换原理及实现

    摘要:傅里叶变换主要是将时间域上的信号转变为频率域上的信号,用来进行图像除噪.图像增强等处理. 本文分享自华为云社区<[Python图像处理] 二十二.Python图像傅里叶变换原理及实现> ...

  3. [基础] BS/CS 区别 Http/Https 区别 中间件请求

    BS和CS的区别:   1.BS结构:Browser-Server-从浏览器到服务器,浏览器打开的所有内容都属于BS(三大主流浏览器Safari.Chrome和Firefo)   2.CS结构:Cli ...

  4. 报时机器人的rasa shell执行流程分析

      本文以报时机器人为载体,介绍了报时机器人的对话能力范围.配置文件功能和训练和运行命令,重点介绍了rasa shell命令启动后的程序执行过程. 一.报时机器人项目结构 1.对话能力范围 (1)能够 ...

  5. POJ2686 Traveling by Stagecoach (状压DP)

    将车票的使用情况用二进制表示状态,对其进行转移即可. 但是我一开始写的代码是错误的(注释部分),看似思路是正确的,但是暗藏很大的问题. 枚举S,我们要求解的是dp[S][v],这个是从u转移过来的,不 ...

  6. 修改-Python函数-2

    一.导入 $$f ( x , y ) = 2 x + 3 y$$ 上面括号里面的就是数学公式里的自变量,自变量就相当于函数里的参数. 二.为什么要有参数 如果一个大楼里有两种尺寸不一的窗户,显然在没有 ...

  7. jsp页面中怎么利用a标签的href进行传递参数以及需要注意的地方

    jsp页面中: <a href="${pageContext.request.contextPath }/infoController/getProductInfo?productId ...

  8. linux下rsync的同步

    rsync是linux系统下的数据镜像备份工具.使用快速增量备份工具Remote Sync可以远程同步,支持本地复制,或者与其他SSH.rsync****主机同步 文件下载地址: 链接:https:/ ...

  9. 使用工厂方法模式设计能够实现包含加法(+)、减法(-)、乘法(*)、除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果。要求使用相关的工具绘制UML类图并严格按照类图的设计编写程序实

    2.使用工厂方法模式设计能够实现包含加法(+).减法(-).乘法(*).除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果.要求使用相关的工具绘制UML类图并严格按照类图的设计编写程 ...

  10. 你应该知道的数仓安全:都是同名Schema惹的祸

    摘要:我是管理员账号,怎么还没有权限?当小伙伴询问的时候,我第一时间就会想到都是用户同名Schema惹的祸 本文分享自华为云社区<你应该知道的数仓安全--都是同名Schema惹的祸>,作者 ...