vuex总结 | 青训营笔记

66 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第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.a.userNameastate后面)以及:store.state.a.userName(a在state后面) 以及: 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', ['', ''])