Vuex 状态管理模式
1 概念
1.1 官方
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能
1.2 理解
- 是全局模式 所有组件可以都可以访问的数据(共享数据)
1.3 作用
- 通信
- 所有的库或者依赖出现的原因都是解决原生实例上的痛点
- 在vue实例上子父组件通信,比较麻烦,如果组件多.组件之间的通信杂乱无章
- vuex可以解决组件之间通信的问题
- 共享
- 就好像是一个共享存储,子组件可以调用共享数据的方法和数据
- 模块化思想
- 把单独的共享部分提取出来,方便项目管理
- 保证数据统一
- 每一个组件都是从共享存储中拿数据,所有组件数据统一
- vuex实例上的mutations对象可以监听次方法被调用,方便找到那部分出错
2 配置
2.1 原生创建
- 在vue项目创建的时候直接选上vuex
- 项目会配置好并且可以直接使用
- 比原来项目多了一个store文件夹/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
2.2 后期创建
安装
cnpm i vuex -S
配置
- 在src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
- 在main.js中引入
import store from './store'
使用
1 定义
- 在src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 1,
number: 2
},
mutations: {
},
actions: {
},
modules: {
}
})
2 配置
- mapState
import { mapState } from 'vuex'
export default {
name: 'index',
methods: {
},
computed: {
...mapState(['count', 'number'])
}
}
3 使用
- 直接变量名使用
<div class="home">
{{count}}------>count
{{number}}----->number
</div>
3 实例对象使用
- state 数据
- mutations 同步方法
- actions 异步方法
- getters 计算
- mudules 模型
3.1 state的使用
- 相当于vue实例中data,但是这个是全局的(所有组件都可以访问到)
3.1.1 定义
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 1,
number: 2
}
})
3.1.2 配置
- 使用数据的组件中
- …mapState() 定义可以接受多个参数
import { mapState } from 'vuex'
export default {
name: 'index',
methods: {
},
computed: {
...mapState(['count', 'number'])
}
}
3.1.3 使用
<div class="home">
{{count}}------>count
{{number}}----->number
</div>
3.2 mutations
- 相当于vue实例中的methods,但是这个可以监听
- 调用组件中需要
this.$state.commit
可完成监听 - 只能做同步的请求
3.2.1 普通使用
- 类似vue中子父组件的方法调用
无参
1 定义
- index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 1,
number: 2
},
mutations: {
addCount (state) {
state.count += 1
}
},
actions: {
},
modules: {
}
})
2 配置
import { mapState } from 'vuex'
export default {
name: 'index',
methods: {
addCount () {
this.$store.commit('addCount')
}
},
computed: {
...mapState(['count', 'number'])
}
}
3 使用
<div class="home">
{{count}}
{{number}}
<button @click="addCount"> ++</button>
</div>
有参(数值或对象)
1 定义
mutations: {
addCount (state, num) {
state.count += num
}
// addCount (state, obj) {
// state.count += obj.value
// }
},
2 配置
methods: {
addCount () {
this.$store.commit('addCount', 2)
// this.$store.commit({type:'addCount',value:2})
}
},
3 使用
<div class="home">
{{count}}
{{number}}
<button @click="addCount"> ++</button>
</div>
3.2.2 推荐使用
- …mapMutations
无参
- 这样定义的不能传参
1 定义
export default new Vuex.Store({
state: {
count: 1,
number: 2
},
mutations: {
addCount (state) {
state.count += 1
}
},
actions: {
},
modules: {
}
})
2 配置
import { mapState, mapMutations } from 'vuex'
export default {
name: 'index',
methods: {
...mapMutations(['addCount'])
},
computed: {
...mapState(['count', 'number'])
}
}
3 使用
<div class="home">
{{count}}
{{number}}
<button @click="addCount"> ++</button>
</div>
有参(对象)
1 定义
mutations: {
addCount (state, obj) {
state.count += obj.value
}
},
2 配置
methods: {
...mapMutations({
addCount: {
type: 'addCount',
value: 2
}
})
},
3 使用
<div class="home">
{{count}}
{{number}}
<button @click="addCount"> ++</button>
</div>
3.3 actions
-
可以做异步请求axios
-
commit + dispatch来实现
1 定义
export default new Vuex.Store({
state: {
count: 1,
number: 2
},
mutations: {
addCount (state, obj) {
state.count += obj.value
}
},
actions: {
addCount ({ commit }, obj) {
commit('addCount', obj)
}
},
modules: {
}
})
2 配置
methods: {
addCount () {
// this.$store.dispatch('addCount', 2)
this.$store.dispatch({ type: 'addCount', value: 2 })
}
},
3 使用
<div class="home">
{{count}}
{{number}}
<button @click="addCount"> ++</button>
</div>
3.4 getters
- 类似于 computed和filter的组合
1 定义
getters: {
getCount (state) {
return state.count + '100000'
}
}
2 配置
import { mapState, mapGetters } from 'vuex'
export default {
name: 'index',
methods: {
addCount () {
this.$store.dispatch({ type: 'addCount', value: 2 })
}
},
computed: {
...mapState(['count', 'number', 'data']),
...mapGetters(['getCount'])
}
}
3 使用
<template>
<div class="home">
{{count}}
{{number}}
{{data}}
{{getCount}}
<button @click="addCount"> ++</button>
</div>
</template>
3.5 module
- 字面意思模块 主模块
- 用来存放子模块的容器
- 子模块与主模块一样(有state,mutations,actions,getters)
1 定义
- 需要创建module/users/index.js
- 创建module/users/state/index.js …
子模块
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
Vue.use(Vuex)
export default {
namespaced: true,
state
}
state/index.js
export default {
name: 'lay',
age: 15
}
主模块
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import users from './modules/users'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
users
}
})
2 配置
computed: {
...mapState(['count', 'num', 'data', 'users'])
}
3 使用
<h1>{{users}}</h1>
3.6 state+action+请求
-
下载axios 依赖
cnpm i axios -S
-
引用
import axios from 'axios'
1 定义
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 1,
number: 2,
data: []
},
mutations: {
addCount (state, obj) {
state.data = obj
}
},
actions: {
addCount ({ commit }, obj) {
axios.get('http://jsonplaceholder.typicode.com/todos').then(res => {
commit('addCount', res)
})
}
},
modules: {
}
})
2 配置
import { mapState } from 'vuex'
export default {
name: 'index',
methods: {
addCount () {
this.$store.dispatch({ type: 'addCount', value: 2 })
}
},
computed: {
...mapState(['count', 'number', 'data'])
}
}
3 使用
{{data}}
4 模块化开发
主模块
1 index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
import actions from './actions'
import getters from './getters'
import users from './modules/users'
Vue.use(Vuex)
export default new Vuex.Store({
state,
mutations,
actions,
getters,
modules: {
users
}
})
2 state/index.js
export default {
count: 1,
num: 2,
data: []
}
3 mutations/index.js
import { types } from '../types'
export default {
[types.ADD] (state, obj) {
state.data = obj
state.count++
}
}
4 actions/index.js
import axios from 'axios'
import { types } from '../types'
export default {
[types.ADD] ({ commit }, obj) {
axios.get('http://jsonplaceholder.typicode.com/todos').then(res => {
console.log(res)
commit(types.ADD, res)
})
}
}
5 getters/index.js
import { types } from '../types'
export default {
[types.GETDATA] (state) {
return state.num + '5555555'
}
}
6 types/index/js
export const types = {
ADD: 'ADD',
GETDATA: 'GETDATA'
}
子模块
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
Vue.use(Vuex)
export default {
namespaced: true,
state
}
state/index.js
export default {
name: 'lay',
age: 15
}
主模块使用
<template>
<div class="home">
<h1> count: {{count}}</h1> <button @click="ADD">+++</button>
<h1> num: {{num}}</h1>
<h1>{{data.data}}</h1><button>{{GETDATA}}</button>
<h1>{{users}}</h1>
</div>
</template>
<script>
import { mapState, mapMutations, mapGetters, mapActions } from 'vuex'
import { types } from '@/store/types'
export default {
name: 'Home',
components: {
},
methods: {
...mapMutations([types.ADD]),
...mapActions([types.ADD])
},
computed: {
...mapState(['count', 'num', 'data', 'users']),
...mapGetters([types.GETDATA])
}
}
</script>
5 接口的反向代理
配置
- /api接口将会被代理
vue.config.js
const data = require('./src/data.json')
module.exports = {
devServer: {
proxy: {
// 配置跨域
'/api': {
target: 'https://www.baidu.com/',
ws: true,
changOrigin: true,
pathRewrite: {
'^/api': '/'
}
}
},
before (app) {
app.get('/api/data', (req, res) => {
// res.send({ status: 0, message: [{ id: 0, name: 'fly' }] })
res.send({ status: 0, message: data })
console.log(1)
})
}
}
}
数据
- 可通过/api/data进行访问
data.json
[
{
"name": "lay",
"age": 13
}
]