vuex优点
存缓存的话容易修改和暴露,vuex的话就没那么容易了
存缓存的话刷新浏览器缓存不会被重置,vuex会被重置
vuex用于组件之间的传值,localstorage,sessionstorage则主要用于不同页面之间的传值。
但是当两个组件共用一个数据源(对象或数组)时,如果其中一个组件改变了该数据源,希望另一个组件响应该变化时,localstorage,sessionstorage无法做到
新建store/index.js
npm install vuex --save
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex)
const Store = new Vuex.Store({
state:{
count:1
}
})
export default Store;
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/index.js' //新增
new Vue({
el: '#app',
router,
store,//新增
components: { App },
template: '<App/>'
})
子组件引用
{{this.$store.state.count}} //1
容易混淆
mutation是同步的 即不进行axios或者promise之类的异步请求操作
actions是异步的 即进行axios或者promise之类的异步请求操作 但本质上也是通过commit改变state的值
使用vuex修改state时,有两种方式:
可以直接使用 this.$store.state.变量 = xxx;
this.$store.dispatch(actionType, payload)
或者:this.$store.commit(commitType, payload)
使用dispatch 和 commit的区别在于,前者是异步操作,后者是同步操作,所以 一般情况下,推荐直接使用commit,
即 this.$store.commit(commitType, payload),以防异步操作会带来的延迟问题。
异同点
共同点: 能够修改state里的变量,并且是响应式的(能触发视图更新)
不同点:
若将vue创建 store 的时候传入 strict: true, 开启严格模式,那么任何修改state的操作,只要不经过
mutation的函数,vue就会 throw error : [vuex] Do not mutate vuex store state outside mutation handlers。
使用commit提交到mutation修改state的优点:
vuex能够记录每一次state的变化记录,保存状态快照,实现时间漫游/回滚之类的操作。
(实际本人未用到,暂时未遇到使用该特性的需求)
结论: 官方推荐最好设置严格模式,并且每次都要commit来修改state,而不能直接修改state,以便于调试等。
getters
getters 可以减少代码量,如果其他组件需要,
getters 在通过方法访问时,每次都会去进行调用,而不会缓存结果
和计算属性一样,getter 的返回值会根据它的依赖被缓存起来
且只有当它的依赖值发生了改变才会被重新计算。
store 对象注入到根实例后,在所有的子组件中,就可以用this.$store 来指向store 对象,获取state。在子组件中,computed 属性是根据它的依赖自动更新的。所以只要store中的state发生变化,它就会自动变化。
getters: {
//得到状态值
getCountAdd:state=>{
state.count = state.count+999;
},
},
//and
computed: {
fn() {
return this.$store.getters.getCountAdd
}
}
子组件引用
this.$store.getters.getCountAdd // 1+999
mutations(同步操作)
actions是异步操作(本身也是操作mutation)
改变state唯一方法是提交 mutation即commit
如果直接调用mutation方法跟直接改变store.state是一样,这样vuex跟踪不到数据的变化,无法做到响应式了
commit是响应式的
你可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload) 传参数
store/index.js
// 不建议在mutations修改 建议在action修改
mutations:{
add(state,n){
state.count = state.count+n;
}
},
子组件
clickAdd:function(){
this.$store.commit("add",1)
},
分发actions(异步操作)
Action 提交的是 mutation,而不是直接变更状态。
Action 通过 store.dispatch 方法触发
mutations:{
add(state,n){
state.count = state.count+n.count;
}
},
actions:{
addFun:function(context,n){
context.commit("add",n.count)
},
}
子组件引用
this.$store.dispatch("addFun",{
count:1
})//actions
es6 解构赋值
{ commit } 的 commit= context.commit
在action中调用其他action(用处不大)
module
引用: this.$store.state.moduleA.name
moduleA.js
const moduleA = {
state:{
count:1
},
getters: {},
// 不建议在mutations修改 建议在action修改
mutations:{
addModule(state,n){
// state.count = state.count+n.count;
console.log("module 分组件引用")
}
},
actions:{
addModuleFun:function(context,n){
context.commit("addModule",n)
}
}
}
export default moduleA;
store/index.js
import Vue from "vue";
import Vuex from "vuex";
import moduleA from "./moduleA.js";
Vue.use(Vuex)
const Store = new Vuex.Store({
state:{},
getters: {},
// 不建议在mutations修改 建议在action修改
mutations:{},
actions:{},
modules:{
moduleA:moduleA
}
})
export default Store;
子组件引用
console.log(this.$store.dispatch("addModuleFun",2))//actions
//打印 'module 分组件引用'
但是引用modules里面的state要用: this.$store.state.login.useName
其他getters mutations actions 都可以通过全局引用 在其引用的函数里默认参数却不是全局的,都是局部的比如state引用全局需引用rootState
rootState.job 就是全局里面的state里面的job等于 'web' 字符串
const actions = {
// actions 中的context参数对象多了 rootState 参数
changeName ({commit, rootState},anotherName) {
if(rootState.job =="web") {
commit("change_name", anotherName)
}
}
};
如果想局部使用commit之类的得用namespaced:true限定到模块的命名空间
// namespaced 属性,限定命名空间
export default {
namespaced:true,
state,
mutations,
actions,
getters
}
例子
methods: {
changeName() {
this.$store.dispatch("login/changeName", "Jason")
},
alertName() {
this.$store.dispatch("login/alertName")
}
辅助函数
mapState 与 mapGetters 要放在计算属性computed中。
(computed只能使用属性)this.state or this.gettters
mapMutations与mapActions要放在methods中。
(methods只能使用方法)this.mutations() or this.action() or this.gettters()
//正常
computed: {
orderList(){
return this.$store.state.orderList;
},
login(){
return this.$store.state.login;
}
}
//mapState
computed: {
...mapState([
'orderList',
'login'
]),
}
切记:mapState的属性的时候,一定要和state的属性值相对应,也就是说 state中定义的属性值叫add,那么mapState就叫add,如果我们改成add2的话,就获取不到add的值了,并且add2的值也是 undefined
computed: {
...mapState({
add: state => state.add,
counts: state => state.counts
})
},
mounted() {
console.log(this.add); // 打印出 0
console.log(this.counts); // 打印 0
}
this.incrementStep
import { mapGetters } from 'vuex'
//数组形式
//...mapGetters([
//'getCountAdd',
//'getCountAdd2'
//]),
//对象形式
...mapGetters({
getCountAdd:"getCountAdd",
getCountAdd2:"getCountAdd2"
})
//相当于 => this.$store.getters("getCountAdd") this.$store.getters("getCountAdd2")
...mapState同理
...mapState({
counts: state => console.log( "mapStateL:"+state.count)
}),
...mapMutations同理
...mapActions同理
test() {
// 调用
Promise.all([this.commonActionGet(['getPower', {}])]).then((res) => {
});
},
// mapActions 使用方法一 将 this.commonActionGet() 映射为 this.$store.dispatch('commonActionGet')
...mapActions(['commonActionGet', 'commonActionGetJSON', 'commonActionPost', 'commonActionPostJSON'])
/*
// 第二种方式
...mapActions({
'commonActionGet': 'commonActionGet',
'commonActionGetJSON': 'commonActionGetJSON',
'commonActionPost': 'commonActionPost',
'commonActionPostJSON': 'commonActionPostJSON'
})
*/
}
事件名字和action一样的时候
...mapActions({
'increment'
})
事件名字和action不一样的时候
...mapActions({
add: 'increment'
})
<button @click="addFun({count:123})">add</button>
//store/index.js
import Vue from "vue";
import Vuex from "vuex";
import moduleA from "./moduleA.js";
Vue.use(Vuex)
const Store = new Vuex.Store({
state:{
count:1
},
getters: {},
// 不建议在mutations修改 建议在action修改
mutations:{
add(state,n){
state.count = state.count+n.count;
}
},
actions:{
addFun:function(context,n){
context.commit("add",n)
// context.commit("add",{count:1})
}
},
modules:{
moduleA:moduleA
}
})
export default Store;
子组件
methods:{
...mapActions({
addFun:"addFun",
}),
//this.$store.dispatch("addFun",{count:123})
}
如果需要传值就用 事件绑定@的方式 或者this.$store.dispatch("addFun",{count:1})
//较完整的例子
import Vue from "vue";
import Vuex from "vuex";
import moduleA from "./moduleA.js";
import moduleB from "./moduleB.js";
Vue.use(Vuex)
const Store = new Vuex.Store({
state:{
count:1
},
getters: {
//得到状态值 只能通过 mutations 改变 state 的值
getCountAdd:(state)=>{
state.count = state.count+999;
console.log(state.count )
},
getCountAdd2:(state)=>{
state.count = state.count+1000;
console.log(state.count )
},
},
// 不建议在mutations修改 建议在action修改
mutations:{
add(state,n){
state.count = state.count+n.count;
},
remove(state,n){
state.count = state.count-n;
}
},
actions:{
addFun:function(context,n){
context.commit("add",{count:1})
context.commit("add",{count:1})
},
removeFun:function(context,n){
context.commit("remove",n)
}
},
modules:{
moduleA:moduleA,
moduleB
}
})
export default Store;
vuex辅助函数简单实用demo
//Mutations
const increment = (state) => {
state.count++
}
const decrement = (state) => {
state.count--
}
// action处理一些异步操作 Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象
let incrementAsync = (content) => {
setTimeout(() => {
content.commit('increment')
}, 1000)
}
let decrementAsync = (content) => {
setTimeout(() => {
content.commit('decrement')
}, 1000)
}
export {increment ,decrement ,incrementAsync, decrementAsync}
<template>
<div>
<button @click="decrementAsync">-</button>
<span>{{count}}</span>
<button @click="incrementAsync">+</button>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
/*
mapState辅助函数和你要调用的this.data的参数一样 必须在computed里
普通写法:this.$store.state.count
mapMutations, mapActions辅助函数的名字必须和事件的名字一样 必须在methods里
普通写法:this.$store.commit("increment ")//this.$store.commit("increment",2)
普通写法:this.$store.dispatch("incrementAsync")//this.$store.dispatch("incrementAsync",2)
*/
export default {
computed: {
...mapState(['count'])
},
methods: {
...mapMutations(['increment', 'decrement']),
...mapActions(['incrementAsync', 'decrementAsync']) //这里用了辅助函数
}
}
</script>
<style>
</style>
this.$store.dispatch() 与 this.$store.commit()方法的区别
this.store.dispatch( ) 与this. store.dispatch() 与 this.store.dispatch()与this.store.commit()方法的区别总的来说他们只是存取方式的不同,两个方法都是传值给vuex的mutation改变state
this.store.dispatch() : 含 有 异 步 操 作 , 例 如 向 后 台 提 交 数 据 ,写 法:this. store.dispatch() :含有异步操作,例如向后台提交数据,写法:this.store.dispatch():含有异步操作,例如向后台提交数据,写法:this.store.dispatch(‘action方法名’,值)
this.store.commit( ) : 同 步 操 作 , 写 法 : this. store.commit():同步操作,,写法:this.store.commit():同步操作,,写法:this.store.commit(‘mutations方法名’,值)
commit: 同步操作
存储 this.$store.commit('changeValue',name)
取值 this.$store.state.changeValue
dispatch: 异步操作
存储 this.$store.dispatch('getlists',name)
取值 this.$store.getters.getlists