这是我参与「第四届青训营 」笔记创作活动的第28天,大项目已经进入到尾声,本篇将讲述大项目里用到的vuex知识。
状态管理应用
状态:驱动应用的数据源 | 视图:以声明的方式将状态映射到视图 | 操作:响应在视图上的用户输入导致状态变化
vuex
对于同个数据源共享到多个文件,数据变化对应多个页面改变,vuex主要用于

vuex适用于中大型单页应用
安装:npm i vuex@next --save
开始
vuex应用核心就是store,store基本上就是一个容器,包含着应用中大部分的状态
- vuex的存储状态是响应式的,当vue组件从store中读取状态时,store状态发生变化,相应的组件也会得到高效的更新
- 不能直接改变store中的状态,改变store状态的唯一途径就是显示地提交
最简单的store
main.js可以配置,但是入口文件尽量简洁 main.js:
import store from './store'
app.use(store)
state - 单一状态数
存储的单一状态,是存储的基本数据
src/store/index.js:
import {createStore} from 'vuex'
//创建store实例
const store = createStore({
//存放共享状态
state(){ //存储的单一状态,是存储的基本数据
return{
count: 0
}
}
})
export default store
使用:
<h2>{{$store.state.count}}</h2>
操作1:
<button @click="$store.state.count++">count++</button>
点击button可以改变store里值,但项目中不建议更改store中的数据(vuex跟踪不到数据变化)
mutations -
对象,里面存放方法 —— 用于操作store数据
mutations: {
increase(state, num){ //state表示上面返回的对象,num表传过来的参数
state.count++;
}
}
methods:{
addCount(num){
this.$store.commit('increase', num)//使用commit提交,提交调用increase方法
}
}
对象风格的提交方式
$store.commit({
type: 'increase',
num: 5
})
- mutations必须是一个同步函数
getter
store中派生出的一些状态,例如对列表进行过滤并奇数(可以理解为仓库里的计算属性)
getters:{
reverseMsg: function(state, getters){
return state.msg.split('').reverse().join('')
}
}
<h2>{{$store.getters.reverseMsg}}</h2>
第二个参数getters,用于拿到getters计算属性后的值(getters表示当前store中getters对象)
reverseMsgLength: function(state, getters){
return getters.reverseMsg.length;
}
action
action类似于mutation,而不是直接变更状态 action可以包含任何异步操作
分发Action store.dispatch方法触发
actions:{
getHot: function(context){
axios.get('https://i.maoyan.com/api/mmdb/movie/v3/list/hot.json?ct=%E4%B9%9D%E6%B1%9F&ci=115&channelId=4').then((res)=>{
console.log(res)
})
}
}
mounted(){
this.$store.dispatch('getHot')
}
actions里函数都默认含有对象context,与store有相同属性和对象 使用state:直接context.state.hotLists
cli的跨域问题 文件vue.config.js也是通过proxy代理解决问题
proxy:{
//通过proxy实现代理跨域
//自定义名字代理
'/path' : {
target: 'https://i.maoyan.com', //需代理的地址
changeOrigin: true, //开启代理,允许跨域
pathRewrite:{
'^/path': '' //匹配自定义代理的名字,重写路径
}
}
- 注意:只有mutations里的数据操作才具有响应式
module
项目过大会显得index.js过于臃肿
const moduleA={
state(){
},
getters:{
userName: function(state){//state为局部状态
}
}
}
使用:
const store = createStore{
modules:{
a: moduleA
},
}
模块A里的会合并到总的里面,可以直接store.state.commit('upDate') $store.state.dispatch('')
子模块想获取根模块数据: getters:
reverseMsg: function(state, getters, rooterState){}第二个属性就是getters,全局的,即可访问到所有的getters 第三个参数获取根节点实例数据
然后: views |-user-index.js |-source-index.js (记得导出) |-index.js (总的,将上面引入)
辅助函数
可以不用$store一层一层获取数据
computed:mapState({
count: state=>state.count
//count: "count"
}),
computed:mapState(['count', 'msg']) //同名
mapState需要引入import {mapState} from 'vuex'
需要私有的computed属性 - 解决:对象展开运算符
computed:{
addNum: function(){},
...mapState(['count']) //此时获取count->console.log(this.count)
}
其他同理
- 引入 mapMutatuion、mapGetters..
- mutations扩展到methods里使用,getters扩展到computed,ations在methods
- 使用都是this.babababa
命名空间
因为所有子模块都会到根模块,为了模块有更高的封装度和复用性,可以添加namespaced: true使其成为命名模块
使用
{{$store.getters['a/userName']}}
辅助函数...mapMutatuion('a', ['', ''])