Vue 状态管理与与SSR详解
1、vuex简介
1、定义
在vue项⽬中,每个组件的数据都有其独⽴的作⽤域。当组件间需要跨层级或者同层之间频繁传递的时候,数据交互就会⾮常繁琐。vuex的主要作⽤就是集中管理所有组件的数据和状态以及规范数据修改的⽅式。
官方解释:Vuex 是⼀个专为 Vue.js 应⽤程序开发的状态管理模式。它采⽤集中式存储管理应⽤的所有组件的状态,并以相应的规则保证状态以⼀种可预测的⽅式发⽣变化。
2、使用场景
⼀般来讲,是以项⽬中的数据交互复杂程度来决定的。具体包括以下场景:
项⽬组件间数据交互不频繁,组件数量较少:不使⽤状态管理
项⽬组件间数据交互频繁,但组件数量较少:使⽤eventBus或者vue store解决
项⽬组件间数据交互频繁,组件数量较多:vuex解决
3、核心原理分析
// a.vue
<h1>{{ username }}</h1>// b.vue
<h2>{{ username }}
</h2>/**
* 如果 username 需要在每个组件都获取一次,是不是很麻烦,虽然可以通过共同的父级传入,但是不都是这种理想情况
*/
复制代码
Flux 架构主要思想是应用的状态被集中存放到一个仓库中,但是仓库中的状态不能被直接修改,必须通过特定的方式才能更新状态。
vuex基于flux思想为vue框架定制,区分同步和异步,定义两种行为,Actions 用来处理异步状态变更(内部还是调用 Mutations),Mutations 处理同步的状态变更,整个链路应该是一个闭环,单向的,完美契合 FLUX 的思想
「页面 dispatch/commit」-> 「actions/mutations」-> 「状态变更」-> 「页面更新」-> 「页面 dispatch/commit」…
2、vuex五大核心
vue使用单一状态树,单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
用一个对象(主干)就包含了全部的(分支)应用层级状态。
每个应用将仅仅包含一个 store 实例对象(主干)。
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state) 。Vuex 和单纯的全局对象有以下两点不同:
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
1、State
当前应⽤状态,可以理解为组件的data⽅法返回的Object
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)const store = new Vuex.Store({state: {count: 0}
})new Vue({store, //把store的实例注入所有的子组件,this.$store可访问render: h => h(App)
}).$mount('#app')
复制代码
2、Getters
Getter为state的计算属性,当需要重复对某个数据进⾏某种操作的时候可以封装在getter⾥⾯,当state中的数据改变了以后对应的getter也会相应的改变。
const store = new Vuex.Store({state: {date: new Date()},getters: {// Getter 接受 state 作为其第一个参数weekDate: (state) => {return moment(state.date).format('dddd'); },//Getter 还也可以接收 getters 作为第二个参数dateLength: (state, getters) => {return getters.weekDate.length;},//Getter本身为一属性,传参需返回一个函数weekDate: (state) => (fm) => {return moment(state.date).format(fm ? fm : 'dddd'); }}
})//属性访问
console.log(store.getters.weekDate)
console.log(store.getters.dateLength)
//方法访问,传参
console.log(store.getters.weekDate('MM Do YY'))
复制代码
3、Mutations
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,必须是同步函数。
Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type) 和 一个 回调函数 (handler)。
回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,第二个参数为载荷(payload)对象。
const store = new Vuex.Store({state: {count: 1},mutations: {// 事件类型 type 为 incrementincrement (state) {state.count++},// 添加第二个参数increment1 (state, payload) {state.count += payload.amount}}
})//参数调用
store.commit('increment')// 1、把载荷和type分开提交
store.commit('increment1', {amount: 10
})// 2、整个对象都作为载荷传给 mutation 函数
store.commit({type: 'increment1',amount: 10
})//----- 修改参数并使用常量,必须遵循vue规则,使用set或者对象解构 -------
// mutation-types.js
export const ADD_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import { ADD_MUTATION } from './mutation-types'
const store = new Vuex.Store({state: {student: {name: '小明',sex: '女'}},mutations: {// 使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名[ADD_MUTATION] (state) {Vue.set(state.student, 'age', 18) //添加age属性// state.student = { ...state.student, age: 18 }}}
})
//使用
import {ADD_PROPERTY} from '@/store/mutation-types'
this.$store.commit(ADD_PROPERTY)
复制代码
4、Actions
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作
Action 函数接受一个 context 参数,它与 store 实例有着相同的方法和属性,可以使用 context.commit 来提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters
const store = new Vuex.Store({state: {count: 0},mutations: {increment (state) {state.count++}},actions: {increment (context) {context.commit('increment')},//使用解构简化increment ({ commit }) {commit('increment')}}
})//分发actions
store.dispatch('increment')
// 以载荷形式分发
store.dispatch('incrementAsync', {amount: 10
})
// 以对象形式分发
store.dispatch({type: 'incrementAsync',amount: 10
})
复制代码
5、Modules
modules的主要功能是为了防⽌state过于庞⼤和冗余,所以对其进⾏模块化分隔
模块内部的 state 是局部的,只属于模块本身所有,所以外部必须通过对应的模块名进行访问
模块内部的 action、mutation 和 getter 默认可是注册在全局命名空间的,通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
//无命名空间
<script>import {mapState, mapMutations} from 'vuex';export default {computed: { //state不同...mapState({name: state => (state.moduleA.text + '和' + state.moduleB.text)}),},methods: { //mutation全局...mapMutations(['setText']),modifyNameAction() {this.setText();}},}
</script>//使用命名空间
export default {namespaced: true,// ...
}
<script>import {mapActions, mapGetters} from 'vuex';export default {computed: {...mapState({name: state => (state.moduleA.text + '和' + state.moduleB.text)}),...mapGetters({name: 'moduleA/detail'}),},methods: {...mapActions({call: 'moduleA/callAction'}),/* 另外写法 */...mapActions('moduleA', {call: 'callAction'}),...mapActions('moduleA', ['callAction']),modifyNameAction() {this.call();}},}
</script>
复制代码
3、辅助函数
1、mapStates
使用 mapState 辅助函数帮助我们生成计算属性,入参为对象
当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组
// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'export default {computed: {...mapState({// 箭头函数可使代码更简练a: state => state.a,// 传字符串参数 'b'// 等同于 `state => state.b`bAlias: 'b',// 为了能够使用 `this` 获取局部状态// 必须使用常规函数cInfo (state) {return state.c + this.info}}),...mapState([// 映射 this.a 为 store.state.a'a','b','c'])
}
复制代码
2、mapGetters
import { mapGetters } from 'vuex'export default {// ...computed: {...mapGetters(['doneTodosCount','anotherGetter',// ...]),...mapGetters({doneCount: 'doneTodosCount'})}
}
复制代码
3、mapMutaions
import { mapMutations } from 'vuex'export default {// ...methods: {...mapMutations([// 将 `this.increment()` 映射为 // `this.$store.commit('increment')`'increment', // `mapMutations` 也支持载荷:// 将 `this.incrementBy(amount)` 映射为 // `this.$store.commit('incrementBy', amount)`'incrementBy' ]),...mapMutations({// 将 `this.add()` 映射为 // `this.$store.commit('increment')`add: 'increment' })}
}
复制代码
4、mapActions
import { mapActions } from 'vuex'export default {// ...methods: {...mapActions([// 将 `this.increment()` 映射为 // `this.$store. dispatch('increment')`'increment', // `mapActions` 也支持载荷:// 将 `this.incrementBy(amount)` 映射为 // `this.$store. dispatch('incrementBy', amount)`'incrementBy' ]),...mapActions({// 将 `this.add()` 映射为 // `this.$store. dispatch('increment')`add: 'increment' })}
}
复制代码
4、源码解析
1、思路
flux思想
问题:在开发中面临最多的场景是状态重复但是不集中,在不同的组件中依赖了同样的状态,重复就会导致不对等的风险。
思想:基于 FLUX 的思想,我们设计的状态管理将是中心化的工具,也就是集中式存储管理应用的所有组件的状态,将所有的状态放在一个全局的 Tree 结构中,集中放在一起的好处是可以有效避免重复的问题,也更好的管理,将状态和视图层解耦。
解决:使用全局的store对象管理状态和数据,单一状态树
状态流转
单一流转
同步和异步分层:mutations负责同步状态管理、actions负责异步事件(内部通过mutations改变状态)
与vue集成
通过插件将 vue 集成在一起,通过 mixin 将 $store 这样的快速访问 store 的快捷属性注入到每一个 vue 实例中
响应式
利用vue的data响应式实现
扩展
辅助函数
模块化
插件支持
2、源码解析
1、store注册
/**
* store.js - store 注册
*/
let Vue// vue 插件必须要这个 install 函数
export function install(_Vue) {Vue = _Vue // 拿到 Vue 的构造器,存起来// 通过 mixin 注入到每一个vue实例
Vue 状态管理与与SSR详解相关推荐
- Vue状态管理vuex
转: https://www.cnblogs.com/xiaohuochai/p/7554127.html 前面的话 由于多个状态分散的跨越在许多组件和交互间各个角落,大型应用复杂度也经常逐渐增长.为 ...
- redis cluster管理工具redis-trib.rb详解
redis cluster管理工具redis-trib.rb详解 redis-trib.rb是redis官方推出的管理redis集群的工具,集成在redis的源码src目录下,是基于redis提供的集 ...
- 微信h5登录php,vue实现微信授权登录步骤详解
这次给大家带来vue实现微信授权登录步骤详解,vue实现微信授权登录的注意事项有哪些,下面就是实战案例,一起来看一下. 背景 vue前后端分离开发微信授权 场景 app将商品分享到微信朋友圈或者分享给 ...
- 【Vue路由(router)进一步详解】
Vue路由(router)进一步详解 query属性 具体实例代码如下: params属性 具体实例代码如下: props属性 replace属性 编程式路由导航 路由缓存 具体代码: 总结 本篇文章 ...
- vue动画过渡 javascript钩子函数详解
vue动画过渡js钩子函数详解 前言 js钩子函数运行时间 js钩子函数的过渡或动画 总结 结语 前言 转载请注明出处并附上链接. 本文中,enter(leave)过程指的是beforeEnter.e ...
- python的编程模式-Python设计模式之状态模式原理与用法详解
本文实例讲述了Python设计模式之状态模式原理与用法.分享给大家供大家参考,具体如下: 状态模式(State Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类 ...
- mysql切换用户sql语句,MySQL用户管理及SQL语句详解
[(none)]>select user,host frommysql.user; #查询用户和主机+---------------+-----------+ | user | host | + ...
- 第二篇supervisor集群管理工具cesi安装详解-如何安装supervisor-cesiwebUI
第二篇supervisor集群管理工具cesi安装详解-如何安装supervisor-cesiwebUI 介绍 安装 解压 安装依赖 修改配置 注册为系统服务 启动 登录一下,发现报错了 解决方法 介 ...
- 第一篇supervisor集群管理工具cesi安装详解-如何安装supervisor
第一篇supervisor集群管理工具cesi安装详解-如何安装supervisor 环境 准备 安装python3.7.4 问题 解决方法 安装supervisor 配置supervisor服务 启 ...
最新文章
- 2018.09.01 poj3071Football(概率dp+二进制找规律)
- java concat和 的区别,RxJava2 merge和concat 区别
- 开发日记-20190531 关键词 读书笔记《鸟哥的Linux私房菜-基础学习篇》
- ecshop分类页调用分类名称
- 万字长文搞定C语言指针
- java.sql.SQLException: ORA-01438: 值大于此列指定的允许精确度
- oracle date引入哪个包,oracle 索引字段包含date类型,使用spring jdbc更新时不走索引,而是走table access full的问题...
- 数学建模:评价模型——聚类分析 K-Means python实现
- ASIHTTPRequest类库简介
- 洛谷——P2524 Uim的情人节礼物·其之弐
- 什么是排他思想算法?(源码解析)
- ChartControl柱状图指定每一个柱子的颜色
- 石油化工行业的MES系统解决方案
- vs2005 无法启动调试 绑定句柄无效的解决
- DXGI 方式采集流程
- android studio开始暂停按钮
- Codeforces894A QAQ
- 互联网吞噬世界,“大数据”吞噬互联网!
- GBase 8c查看数据
- python之freshman00
热门文章