vuex 的使用以及如何结合axios进行使用
vuex的源码分析以及他是如何运作的呢?
掘金 的vuex的源码分析 https://juejin.im/post/59f66bd7f265da432d275d30
vuex 认识描述的问题 http://whutzkj.space/2017/10/24/vuex/#more
vuex的官网的文档 https://vuex.vuejs.org/zh-cn/
主线为=== 是什么== 为什么=== 怎么做?
一. vuex的知识
更新的版本的问题
vuex的定义: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
vuex 的产生以及是如何运作的呢? 原理基本的思想=== 通过分析一个数字的不断累加然后实现====思路=== 单向数据流(state:驱动应用的数据源;view:以声明方式将state映射到试图上;actions: 响应在view上用户输入导致的状态变化;)====== 当多个组件共享状态的时候,单向的数据流就很容易北破坏,我们会有一下的疑问:a: 多个视图依赖同一状态; b:来自不同的行为需求变更同一状态 以上的两个问题是我们需要考虑的那么如何解决呢? 解决思路: 把组件的共享状态抽离出来,以一个全局的单例模式进行管理, 例子: 树的结构,这时候不管在树的那个位置,任何组件都能够获取状态或者触发行为,隔离开也有助于我们代码的维护。
Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。 (针对我这种英文不好的人的注释:backend API: 后端接口,同vuex 中的action,异步处理异步获取的数据,建立起前后台之间的联系;vuex具体分为actions,这里不再解释,之后会写链接 以方便大家查看文档; 通过commit 交付给 Mutations(突变和变化):这里可以使用调试工具进行检测变化;再通过mutate交付给State:当状态发生改变的时候,组件也会跟着render,同时组件也可以dispatch(分发,派发)来触发actions发送请求等等;形成一个闭环;接着就是无限循环。)
任何事物都是一把双刃剑;vuex给我们带来方便的同时也带来了一些麻烦,给我们带来了更多的概念和框架;这个就需要我们对短期和长期的效益进行均衡。如何不是大型的单页面应用,可能会显得繁琐;简单的可以使用一个global event 就可以了, 中大型的分析好之后vuex就会成为很好的选择。
如何您能看到这里,是不是已经有了简单的认识,那么请跟着我这已经慢了很多的脚步接着拨开vuex这个洋葱吧,哈哈。
store: 每一个vuex应用的核心就是store(仓库),其实就是一个容器,它包含你的应用中的大部分的状态state,这里vuex和单纯的全局变量与以下两点不同,1. vuex的状态存储是响应式的,你变我也变。2. 你不能直接改变store中的状态,改变store中的状态的唯一途径就是显式的提交(commit)mutations,这样做的好处是可以方便我们跟踪每一个状态的变化,从而能够让我们实现一些工具帮助我们更好的了解我们的应用。
最简单的store实例: // 如果在模块化构建系统中,请确保在开头调用了 Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } } }) ;现在我们可与使用store.state来获取状态对象,以及通过store.commit方法触发状态变更。store.commit(‘increment’) console.log(store.state.count) // -> 1 这样做的意图更加明显,更容易理解应用内部的状态变化。
简单的例子过后,接下来我们来看看一些核心的概念。
state: 单一状态树, 包含了所有的应用的层级状态,每一个应用仅仅有一个store的实例,单一状态树和模块化不冲突; 问题是===需要频繁的引入,于是有了下面的处理从根组件注入到所有的子组件中vue.use(vuex),子组件通过 this.$store来进行状态的获取。
问题: 当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性。 mapState 辅助函数, 更为简单的方法是对象展开运算符,computed: { 使用对象展开运算符将此对象混入到外部对象中 …mapState({ // … }) }
值得数注意的是组件仍然保有局部状态,如何与有些状态严格属于单个组件最好还是作为组件的局部状态,这里需要根据需求来定。
另一个问题是: 有时候我们需要从 store 中的 state 中派生出一些状态,如果有多个组件需要用到此属性,我们要么复制这个函数,或者抽取到一个共享函数然后在多处导入它,上面的方式是传统的方式,在vuex我们有更好的处理方式,定义getter(可以认为是store的计算属性),特点为getter的返回值会根据他的依赖缓存起来,并且只有当他的依赖值发生改变的时候才会重新计算。getter接受state作为第一个参数 ;Getter 会暴露为 store.getters 对象, getter可以接受第二个参数 getter ; 方便使用mapGetters辅助函数 import { mapGetters } from ‘vuex’ export default { // … computed: { // 使用对象展开运算符将 getter 混入 computed 对象中 …mapGetters([ ‘doneTodosCount’, ‘anotherGetter’, // … ]) } }
mutation : 更新vuex中store中的状态的唯一方法就是提交mutation, 每一个mutation都有一个字符串的事件类型type和一个回调函数handle, 触发是需要使用commit; 第一个参数是store 也可以提交载荷 payload, 你可以向store.commit传入额外的参数即mutation的载荷
应该遵循一定vue 的规则: 1. 最好提前在你的store中初始化所有的所需属性 2. 当需要在对象上添加属性时候你应该 使用
使用 Vue.set(obj, ‘newProp’, 123), 或者
以新对象替换老对象。例如,利用 stage-3 的对象展开运算符我们可以这样写:
state.obj = { …state.obj, newProp: 123 } 对象的复制
1. 使用常量代替mutation的事件类型 此时需要放在一个的单独的文件里面 mutation-types.js 使用不使用常量自己来决定
注意: mutation 必须是同步函数 然而,在上面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用——实质上任何在回调函数中进行的的状态的改变都是不可追踪的。
也可以在组件中提交mutation 那么如何处理异步操作呢? 进而引入了 action;
1. action 的定义 ,====类似于mutation,不同点为提交的是mutation而不是直接变更状态;可以包含任意异步操作;
参数解构,来简化代码,特别是需要调用commit很多次的时候,actions: { increment ({ commit }) { commit(‘increment’) } }
分发action ====actions: { checkout ({ commit, state }, products) { // 把当前购物车的物品备份起来 const savedCartItems = […state.cart.added] // 发出结账请求,然后乐观地清空购物车 commit(types.CHECKOUT_REQUEST) // 购物 API 接受一个成功回调和一个失败回调 shop.buyProducts( products, // 成功操作 () => commit(types.CHECKOUT_SUCCESS), // 失败操作 () => commit(types.CHECKOUT_FAILURE, savedCartItems) ) } }
在组件中分发action dispatch 或者使用mapActions辅助函数
组合action promise 注要使用es6的语法进行执行的先后顺序
一、 module ==== 当使用单一的状态树,应用的所有对象集中到一个比较大的对象,当应用变得复杂的时候,store对象就有可能变得臃肿====如何解决?vuex允许我们将store分割成模块module,每个模块拥有自己的state,mutation,action,getter,甚至是 嵌套子模块,从上到下 进行通用的方式的分割;
当然不同模块拥有自己的作用域,称为,模块的局部状态,对于模块内部的的mutation,getter,接受的参数是模块的局部状态对象;
对于模块内部的action,和getter 通过context.rootState: 根节点暴露出来。
命名的空间, namespaced: true
辅助函数的使用 可以使用createNamespacedHelpers 来创建某个命名空间辅助函数
如何各位大神有能力开发插件的话 ,请注意命名空间
模块的动态注册的问题
为了实现模块的重用,可以使用函数来声明模块的状态;
至此vuex 就已经介绍完了,那么在实际的项目中应该如何使用呢?》
项目的目录 :├── index.html
├── main.js
├── api │ └── … # 抽取出API请求
├── components
│ ├── App.vue
│ └── …
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块
上面的例子可以查看购物车的示例 : https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart
二、 插件
1 . 在插件内提交mutation 例如websocket
生成state快照 此时需要对状态对象进行省拷贝 一般是在 开发的时候的时候使用
严格模式
表单处理
测试
热重载
api的文档