值得一试的vuex

312 阅读2分钟

Vuex

1.1 安装

npm install vuex --save

1.2 使用

1.2.1 初始化

store/index.js

import vue from 'vue'
import vuex from 'vuex'
vue.use(vuex)
const store=new vuex.Store({
  state:{
    name:'foo'
  }
})
export default store

1.2.2 挂载到Vue实例上

main.js

import store from "./store";  //引入
new Vue({
  el: '#app',
  store,	//es6写法
  router,
  render: h => h(App)
})

1.2.3 简单使用

 <h1>{{$store.state.name}}</h1>		//foo

1.3 State

管理全局状态

1.3.1 基本使用

store/index.js

const store=new vuex.Store({
  state:{
    age:18
  }
})

xxx.vue

 <h1>{{$store.state.age}}</h1>		//18

1.3.2 mapState

xxx.vue

<h2>{{globalAge}}</h2>
-----------------------------
import {mapState} from 'vuex'
computed:{
    ...mapState({
        globalAge:(state)=>state.age	//globalAge是自定义得到名字
    })
},

1.4 Mutation

修改同步状态,这是更改state的唯一方式,调用store.commit()来实现更改state

1.4.1 基本使用

store/index.js

const store=new vuex.Store({
  state:{
    name:'foo'
  },
  mutations:{
    changeName (state) {	//创建一个函数,供commit调用
      state.name="bar"
    }
  }
})

xxx.vue

<template>
    <div class="indexContainer">
      <h1>hello</h1>
      <h1>{{$store.state.name}}</h1>
      <button @click="change">改变name</button>
    </div>
</template>
<script>
    export default {
        name: "index",
        data () {
          return {}
        },
        methods:{
          change () {
            //调用commit(),改变state,changeName需要和mutations定义的函数名一致
            this.$store.commit('changeName')	
          }
        }
    }
</script>

1.4.2 参数

mutations接受2个参数(state,payload)

​ state是当前vuex对象的state

​ payload是当前方法被调用时接收传递的参数

store/index.js

mutations:{
    changeName (state,payload) {
      state.name=payload.aName
    }
  }

xxx.vue

change () {
    this.$store.commit('changeName',{aName:'bar'})  //以对象的形式传参
}

1.4.3 其他方式提交

store/index.js

mutations:{
    changeName (state,payload) {
      state.name=payload.aName
    }
  }

xxx.vue

 change () {
     this.$store.commit({
         type:'changeName',
         aName:'bar'
     })
 }

1.4.4 mapMutations

import { mapMutations } from 'vuex'
 methods: {
    ...mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
        ])
    ...mapMutations({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
  }

1.5 Action

类似Mutation,Action提交的是Mutation,不是直接改变state,是异步改变state的方法,通过dispatch()方法实现

1.5.1 基本使用

store/index.js (参数和提交方式同Mutation一样,这里就不一一详细说明了)

actions:{
    getChangeName ({commit},payload) {	//{commit}是es6中对象解构的写法 let {commit}=context
        commit('changeName',payload)	//changeName与Mutation中的方法对应
    }
  }

xxx.vue

change () {
    this.$store.dispatch('getChangeName',{aName:'bar'})		
}

1.5.2 mapActions

import { mapActions } from 'vuex'
 methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }

1.6 Getter

Getter是对state进行修改,相当于computed

1.6.1 基本使用

store/index.js\

 state:{
    list:[
      {name:'foo',age:18},
      {name:'bar',age:20},
      {name:'tim',age:22},
    ]
  },
  getters:{
    bigAge (state) {
      return state.list.filter(item=>item.age>20)
    }
  }

xxx.vue

<h1>{{$store.getters.bigAge}}</h1>

1.6.2 参数

Getter接收2个参数(state,getters)

​ state---全局状态

​ getters---其他getters

getters: {
  domain: (state, getters) => {
    return getters.doneTodos.length
  }
}

1.6.3 访问方式

属性访问

 getters:{
    bigAge (state) {
      return state.list.filter(item=>item.age>20)
    }
  }
---------------------------------------------------------------------------
<h1>{{$store.getters.bigAge}}</h1>

方法访问

getters: {
  getTodoById: (state) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}
---------------------------------------------------------------------------
<h1>{{$store.getters.getTodoById(2) 

1.6.4 mapGetters

import { mapGetters } from 'vuex'
computed: {
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
    ])
  }

1.7 Module

想象一下,如果项目大,state比较多,我们应该怎么办,这时候就用到module,他可以将store分割成若干个模块,每个模块拥有自己的state,mutation、action、getter

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

但是这样有一定缺点,若模块非常多,这导致模块都挤到一个文件里面,不易于维护,正确做法参考进阶。

1.8 进阶

目录结构

store
    --modules	 //存放各个模块
  --a.js			//a模块
  --b.js			//b模块
--getters.js	//操作公共state
--index.js	   //统一导入各个模块,向外暴露

1.8.1 基本使用

store/modules/a.js

const state = {
     name:'foo'
}
const mutations = {
    changeName (state) {
        state.name='bar'
    }}
const actions = {
    getChangeName ({commit}) {
        setTimeout(()=>{
          commit('changeName')
    },1000)
  }}

export default {
  namespaced: true,	//带命名空间的模块,不与其他模块冲突
  state,
  mutations,
  actions
}

store/getters.js

const getters={
  add (state) {
    return state.a.count	//需要带上文件名
  }
}
export default getters

store/index.js 需要在index.js中进行统以暴露

import vue from 'vue'
import vuex from 'vuex'
import  getters from './getters'
vue.use(vuex)
//将所以模块在index中进行统一引入
const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  const value = modulesFiles(modulePath)
  modules[moduleName] = value.default
  return modules
}, {})
const store = new vuex.Store({
  modules,
  getters
})
export default store

xxx.vue

<h1>{{$store.state.a.name}}</h1>		//使用state  需要带上文件名
<h2>{{$store.commit('a/changeName')}}</h2>	//使用mutations  需要带上文件名
<h2>{{$store.dispatch('a/getChangeName')}}s</h2>	//使用actions 需要带上文件名
<h2>{{$store.getters.add}}</h2>			//使用getters 

如果觉得有帮助欢迎点赞、评论。 上述内容仅仅代表个人观点,如有错误,请指正。如果你也对前端感兴趣,欢迎访问我的个人博客sundestiny.github.io/myblog/