Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。下面记录一下个人对Vuex的一些学习笔记。
一、说白了就是vue的状态管理,你只需要每次动态的改变这些状态就行,数据就会自动渲染。
1、安装vue项目
vue init webpack projectName
2、进入项目目录
cd projectName
3、安装vuex
npm i vuex --save
4、项目启动
npm run dev
二、vuex的引入
项目安装成功以后,初始的文件目录格式都是一样的,下图是VueX测试目录。
然后我们简单的使用,在main.js中引入vuex
//main.js
import Vue from 'vue'
import store from './store'
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
//其中store文件下的index.js文件负责设置Vuex
import Vue from 'vue'
import Vuex from 'vuex'
import settings from './modules/settings'
import heade from './modules/heade'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
settings,
heade
},
})
export default store
以下内容参考https://segmentfault.com/a/1190000020912384?utm_source=tag-newest,并加入自己个人实操的一些方式。
三、在main.js中加入
var store = new vuex.Store({//store对象
state:{
count:0
}
})
四、把刚才的store对象实例化到Vue中
new Vue({
el: '#app',
router,
store,//加入store对象
template: '<App/>',
components: { App }
})
完成这一步我们就可以使用了,一个简单的vuex的state就可以了,怎么用呢
<div id="hello">
<p>{{this.$store.state.count}}</p>
</div>
五、很明显,刚才只是简单的一例子,如果你需要做大型的项目,不可能把store对象写在main.js里,这样是非常不方便管理的,所以我们需要在src下新建一个文件夹store专门存放store对象,然后我们新建一个文件index.js
//index.js
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);
export default new vuex.Store({
state:{
count:0
}
})
相应的main,js就需要做修改了
import store from './store/index'
new Vue({
el: '#app',
router,
store,//这个store是刚才创建的index文件引入的
template: '<App/>',
components: { App }
})
这样做就是为了把store对象分离出去,方便管理,但是你会发现这个store对象是全局的所有组件都可以使用,如果我们的组件多了,数据多了,全部堆放在一起,是不是特别臃肿,所以现在我们就该使用modules
首页我们新建一个js文件存放一个组件可能用到的store对象,比如我新建heade.js,在这里我们不需要引用vuex了,只需要默认export default就行了
//heade.js
export default {
state: {
count: 0
}
}
然后我们把在index.js中使用modules
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);
import HeadeStore from './heade';//引入刚才的heade.js export default new vuex.Store({
modules: {
Heade: HeadeStore
}
})
现在我们管理起来就方便多了,比如还有其他的呢我们放在modules下就可以了,比如,我们除了heade.js里管理的是一个组件的store对象,我们还有一个content.js来管理另外一个组件的store对象,那么我们在store文件夹下载新建一个content.js,和heade.js一样,只需要默认输出就可以了
//content.js
export default {
state: {
cont: '这是content内容'
}
}
然后我们在index.js中引入挂在modules下就可以啦
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);
import HeadeStore './heade';//引入刚才的heade.js
import ContentStore from './content' //引入content.js
export default new vuex.Store({
modules: {
Heade: HeadeStore,
Content: ContentStore
}
})
这样是不是方便多了,但是怎么用呢,很简单,现在需要通过modules去找他,之前的方法:$store.state.count改成$store.state.Heade.count就行了,很明显这是找到了heade.js下的count值,那么找content.js下cont的值呢?一样的,换一下modules的名就行$store.state.Content.cont
//heade组件<p>{{$store.state.Heade.count}}</p>//content组件<p>{{$store.state.Content.cont}}</p>
输出结果分贝为:0,这是content内容
六、那么接下来你觉得问题解决了吗,难道你们的项目组件所有的状态都用这一个,那如果我需要动态的改变他的状态呢,怎么办?没事,这不mutations来了吗,问题就好多了,怎么用呢,这是干嘛的呢,说白了就是动态的改变state的值完成页面的同步渲染,看看用法吧,直接在state对象后面加就行了
//heade.js
export default {
state: {
count: 0
},
mutations: {
Count (state) {
state.count =1
}
}
}
解释一下,mutations对象是函数,默认传值是state,也就是上面的state,所以可以直接操作state.count
怎么用呢,很简单,比如页面有一个按钮,点击改变state的count
<a href="javascript:;" @click="$store.commit('Count ')">click</a>
此时页面渲染为1
commit('Count ')调用mutations的固定方法,参数为mutations的方法名,当然commit不止传一个参数,也可以传很多,比如:
<a href="javascript:;" @click="$store.commit('Count',10)">click</a>
可以在heade.js的mutations下Count方法接收它
//heade.js
export default {
state: {
count: 0
},
mutations: {
Count (state,n) {
state.count =state.count+n
}
}
}
此时输出结果为10
需要注意的是另一种引入方式,如以下代码settings.js:
此时使用在界面中调用this.$store.commit('count')来调用会出现报错。
解决方案参考https://blog.csdn.net/qq_44979541/article/details/108144777
//新增settings.js
const state = {
count: 0,
}
const mutations = {
count (state) {
state.count =1
},
}
export default {
namespaced: true,
state,
mutations,
}
以这种方式定义的JS模块,在调用mutations中的count方法时,有区别于上面的heade.js的调用方式,需要如上图设置namespaced: true,在通过this.$store.commit('settings/count')方式来调用。
官方文档给的解释:默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
<div class="app-container">
{{this.$store.state.settings.count}}
<div @click="aa">
修改值
</div>
</div>
methods: {
aa(){
this.$store.commit('settings/count')
}
},
};
这样调用报错就解决了。
到这一步为止,我们已经可以正常的动态的修改state来渲染在页面了,你会发现,mutations是同步的,只要你在一个组件执行mutations的方法了,那所有的组件只要用到mutations的方法都会同步进行改变,这并不是我们想要的结果,所以,actions来解决问题了,写法一样
//heade.js
export default {
state: {
count: 0
},
mutations: {
Count (state,n) {
state.count =state.count+n
}
},
actions: {
Acount (context) {
context.commit('Count ')
}
}
}
接着解释,actions和mutations的写法一样,都是函数,但是actions的默认参数是context,context.commit('Count ')的意思是触发mutations下的Count函数,那么怎么触发actions的函数呢,方法就是
<a href="javascript:;" @click="$store.dispatch('Acount')">click</a>
dispatch方法是官方固定触发actions下函数的方法
官方推荐 , 将异步操作放在 action 中
还有一个属性我觉得也没有必要说了,getters,解释一下它的作用
getters 和 vue 中的 computed 类似 , 都是用来计算 state 然后生成新的数据 ( 状态 ) 的。比如我们heade.js的state有一个值show:false getters就是计算与false相反的,但是它计算的值是不能直接修改的, 需要对应的 state 发生变化才能修改。
//heade.js
export default {
state: {
count: 0,
show: false
},
mutations: {
Count (state,n) {
state.count =state.count+n
}
},
actions: {
Acount (context) {
context.commit('Count ')
}
},
getters:{
not_show(state){
return !state.show;
}
}
}
它也是默认接受state
最后一点就是为了方便操作开发,一般情况$store.state.Heade.show,$store.state.show写起来不是很方便,那么vuex的辅助函数mapState、mapGetters、mapActions就可以解决这个问题,办stroe对象那个映射到this
<template>
<div class="Heade">
<p>{{msg}}</P>
</div>
</template>
<script>
import {mapState} from 'vuex';
export default {
name: 'Heade',
data () {
return {
msg: ''
}
},
computed:{ //这里的三点叫做 : 扩展运算符
...mapState([
count:state=>state.Heade.count
]),
},
created () {
this.msg = this.count
}
}
</script>
现在我们就直接可以用this.count去找到state下count的值了,created方法是页面刚载入加载完事执行的方法,完后动态的赋值给msg,mapState一般放在computed计算属性中,mapActions一般放在methods下