Vuex原理
Vuex的原理
Vuex是专门为Vue.js应用程序设计的状态管理工具。相当于数据库mongoDB,MySQL等,任何组件都可以存取仓库中的数据。其中vuex类似的 还是有Redux,Redux大多用于React,针对Redux后续在做补充
Vuex运行机制
(1)Vuex的状态存储是响应式的
(2)当vue组件从store中读取时,若store中状态发生改变,响应的组件也会更新状态
(3)不能直接改变state,必须通过显示的提交(commit)mutations来追踪每个状态的变化
Vuex有什么好处?及使用场景
好处:可以做状态管理、采用localstorage保存信息、数据一直存储在用户的客户端中
使用场景:(1)登录信息、(2)购物车、(3)复杂的组件通信
vue的使用步骤
1、安装vuex
npm install vuex --save/-dev
2、引用vuex,创建仓库store。 创建 store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//数据
const state={
count:10
}
//action 执行异步操作,不可以修改state数据
const actions={
getParamSync (context,Object) {
//处理异步操作
setTimeout(()=>{
//3.通过commit提交一个名为getParam的mutation
//action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation
context.commit('increment',Object)
},3000)
}
}
//mutation 可直接修改state数据
const mutations={
increment(state,value){
state.count += value;
},
decrement(state,value){
state.count -=value;
}
}
//getter
const getters = {
newCount:state => state.count * 3
}
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
3 . 在 main.js中注册到根组件中
import store from './store/store.js'
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
vuex的属性以及使用
-
state - - - state是存储的单一状态,是存储的基本数据。
-
getters - - - getters是store的计算属性,相当于组件中的computed的属性,getters返回的值会根据它的依赖被缓存起来,且只有当它的依赖值发生改变才会被重新计算,在组件中使用$store.getters.fun()
-
mutations - - - 修改状态,并且是同步的。在组件中使用$store.commit(’’,params)
-
actions - - - 异步操作 在组件中使用 $store.dispatch("")
-
module - - -
Module是store分割的模块,每个模块拥有自己的state、getters、mutations、actions
异步是怎么修改数据的
异步更改action,action中通过commit触发mutations进行数据更改
如图所示:
vue和vuex的关系
vuex同样能和vue一样实现响应式
在vuex中
state相当于组件中的data
getters相当于computed
mutations相当于methods
** 分享大家一下方式,将vuex每个部分拆分
运用vuex语法糖mapMutations**
motations.js
const mutations = {
SET_NEWS(state, val) {
state.news = val
}
}
export default mutations
1、存储数据 ( a.vue文件 )
import { mapMutations } from "vuex"; // 引入mapMutations
export default {
methods: {
...mapMutations({
// 将changeNews与mutations中的SET_NEWS关联
changeNews: "SET_NEWS"
}),
submit(){
// 提交一个名为changeNews的mutation,并传入参数val
let val = 'test news';
this.changeNews(val);// 相当于this.$store.commit("changeNews", val);
}
}
}
2、获取数据( b.vue文件 )
import { mapGetters } from "vuex"; // 引入mapGetters
export default {
computed: {
// 用vuex读取数据(读取的是getters.js中的数据)
// 相当于this.$store.getters.news(vuex语法糖)
...mapGetters(["news"])
},
created() {
// 获取getters中news数据
console.log(this.news);
}
}
3、index.js
import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import state from './state'
import mutations from './mutations'
//每次修改state都会在控制台打印log
import createLogger from 'vuex/dist/logger'
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production'
export default new Vuex.Store({
actions,
getters,
state,
mutations,
strict: debug, // 当debug=true时开启严格模式(性能有损耗)
plugins: debug ? [createLogger()] : []
})
state.js
const state = {
news: {}
}
export default state
mutations.js:
const mutations = {
SET_NEWS(state, val) {
state.news= val
}
}
export default mutations
getters.js:
// 通常通过getters取数据 (this.$store.getters.news;)
export const news = state => state.news // 不做其他处理 直接映射出去
actions.js
//异步处理
...
4.使用store
在main.js中引用
import store from './store' //vuex存储文件
...
...
new Vue({
el: '#app',
router,
store,
components: {
App
},
template: '<App/>'
})
module综合用法
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const test1 = {
namespaced: true,
state: {
name: 'moduleA',
type: 'module A'
},
mutations: {
updateNameByMutation(state, appendStr){
state.name = state.name + " append Str: " + appendStr
}
},
actions: {
udpateNameByAction({commit}, appendStr) {
commit("updateNameByMutation", appendStr)
}
},
getters: {
getNameA(state){
return state.name
}
}
}
const test2 = {
// 当namespaced=true 时, vuex, 将会自动给各自module 添加访问路径名。 方便区分moduel
namespaced: true,
state:{
name: 'moduleB',
type: 'module B'
},
mutations: {
updateNameByMutation(state, appendStr){
state.name = state.name + " append Str: " + appendStr
}
},
actions: {
// 如果不使用命名空间, 那么view 指向actions 的该方法时,会执行所有与指定action名相同的函数(即:这里module A,B 中该action都会执行)
udpateNameByAction({commit}, appendStr){
commit("updateNameByMutation", appendStr)
}
},
getters: {
getNameB(state){
return state.name
}
}
}
const storeInstall = new Vuex.Store({
state: {
name: 'i am root state name'
},
modules:{
// 这里的路径名: test1, test2, 在view 中 通过 mapActions('test1', [actionName]) 使用并区分需要使用的module
test1,
test2
}
})
export default storeInstall
store.js 几个简单的vuex 使用场景模拟。 我们有多个模块,分别为: test1, test2… 。
我们发现开发中可能会存在相同的stateName/ actionName/ mutaionName /。 (实际开发中,getterName 如果有重名编译会提示 getter 重名....)
我们使用vuex 需要实例化一个Vuex的Store构造函数。 这里storeInstall 中第一个state, 我们可以理解为根 state, 它全局可访问。 modules 中则是我们自定义注册的module. 每个module 中都有自己独立的state, action, mutation, getter...
需要注意的是,这里通过给每个module 对象添加namespaced: true, 来达到命名空间来区分Module的效果。也是通过它来区分更新/调用 对应的vuex 方法来隔离未知数据更新等数据相关问题
vue组件
<template>
<div>
<div>
<h2>Page Test1</h2>
</div>
<div>
<a href="javascript:" @click="changeName">udpate: 名称Name</a>
<a href="javascript:" @click="showName">显示更新后的Name</a>
</div>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
data(){
return {}
},
computed: {
...mapState('test1', {
state: state => state
})
},
methods: {
// test1 模块路径名
...mapActions('test1', [
'udpateNameByAction'
]),
changeName(){
this["udpateNameByAction"]('ha ha test1 udpate !!')
},
showName(){
console.log(this.$store.state)
},
},
mounted() {
console.log("store name: ", this.$store)
console.log("namespace test1 state: ", this.state)
}
}
</script>
关于vuex module 这里只是个基本讲解。 总结下来就是module 给了我们一种隔离vuex store 各个 state及相关api 的方法,让数据相关操作在复杂的项目场景可以更清晰,易追踪。
上一篇: python实现rsa加密实例详解