store文件夹index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
lists: [
// { id: 4, name: 'DS', ctime: "2020/01/01" },
// { id: 3, name: '奥迪', ctime: "2020/01/01" },
// { id: 2, name: '宝马', ctime: "2020/01/01" },
// { id: 1, name: '奔驰', ctime: "2020/01/01" },
],
brand: {}
},
mutations: {
init(state, list) {
state.lists = list
},
del(state, id) { //state 上下文的state id外界传过来的值
const index = state.lists.findIndex(item => item.id == id)
state.lists.splice(index, 1)
},
add(state, brand) {
state.lists.unshift(brand)
}
},
getters: {
getCount(state) {
return state.lists.length
}
},
actions: {
getList(context) {
console.log(context)
const list = [
{ id: 4, name: 'DS', ctime: "2020/01/01" },
{ id: 3, name: '奥迪', ctime: "2020/01/01" },
{ id: 2, name: '宝马', ctime: "2020/01/01" },
{ id: 1, name: '奔驰', ctime: "2020/01/01" },
]
setTimeout(() => {
context.commit('init', list)
}, 2000)
}
},
modules: {}
})
add.vue 文件
立即创建
父组件
品牌总数:{{getCount}}
编辑
删除
Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。
① 能够在 vuex 中集中管理共享的数据,易于开发和后期维护
② 能够高效地实现组件之间的数据共享,提高开发效率
③ 存储在 vuex 中的数据都是响应式的,能够实时保持数据与页面的同步
一般情况下,只有组件之间共享的数据,才有必要存储到 vuex 中;对于组件中的私有数据,依旧存储在组件自身的 data 中即可
npm install vuex --save 安装 vuex 依赖包
import Vuex from 'vuex'
Vue.use(Vuex) 导入 vuex 包
const store = new Vuex.Store({
// state 中存放的就是全局共享的数据
state: { count: 0 }
})
new Vue({
el: '#app',
render: h => h(app),
router,
// 将创建的共享数据对象,挂载到 Vue 实例中
// 所有的组件,就可以直接从 store 中获取全局的数据了
store
})
State
提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 State 中进行存储。
// 创建store数据源,提供唯一公共数据
const store = new Vuex.Store({
state: { count: 0 }
})
组件访问 State 中数据的第一种方式:
this.$store.state
.全局数据名称
组件访问 State 中数据的第二种方式:
// 1\. 从 vuex 中按需导入 mapState 函数
import { mapState } from 'vuex'
通过刚才导入的 mapState 函数,将当前组件需要的全局数据,映射为当前组件的 computed 计算属性:
// 2\. 将全局数据,映射为当前组件的计算属性
computed: {
...mapState(['count'])
}
Mutation
用于变更 Store中 的数据。
只能通过 mutation 变更 Store 数据,不可以直接操作 Store 中的数据。
通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化。
// 定义 Mutation
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
add(state) {
// 变更状态
state.count++
}
}
})
// 触发mutation
methods: {
handle1() {
// 触发 mutations 的第一种方式
this.$store.commit('add')
}
}
可以在触发 mutations 时传递参数:
// 定义Mutation
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
addN(state, step) {
// 变更状态
state.count += step
}
}
})
// 触发mutation
methods: {
handle2() {
// 在调用 commit 函数,
// 触发 mutations 时携带参数
this.$store.commit('addN', 3)
}
}
this.$store.commit()
是触发 mutations 的第一种方式
触发 mutations 的第二种方式:
// 1\. 从 vuex 中按需导入 mapMutations 函数
import { mapMutations } from 'vuex'
通过刚才导入的 mapMutations 函数,将需要的 mutations 函数,映射为当前组件的 methods 方法:
// 2\. 将指定的 mutations 函数,映射为当前组件的 methods 函数
methods: {
...mapMutations(['add', 'addN'])
}
Action
用于处理异步任务。
如果通过异步操作变更数据,必须通过 Action,而不能使用 Mutation,但是在 Action 中还是要通过触发
Mutation 的方式间接变更数据
// 定义 Action
const store = new Vuex.Store({
// ...省略其他代码
mutations: {
add(state) {
state.count++
}
},
actions: {
addAsync(context) {
setTimeout(() => {
context.commit('add')
}, 1000)
}
}
})
// 触发 Action
methods: {
handle() {
// 触发 actions 的第一种方式
this.$store.dispatch('addAsync')
}
}
触发 actions 异步任务时携带参数:
// 定义 Action
const store = new Vuex.Store({
// ...省略其他代码
mutations: {
addN(state, step) {
state.count += step
}
},
actions: {
addNAsync(context, step) {
setTimeout(() => {
context.commit('addN', step)
}, 1000)
}
}
})
// 触发 Action
methods: {
handle() {
// 在调用 dispatch 函数,
// 触发 actions 时携带参数
this.$store.dispatch('addNAsync', 5)
}
}
this.$store.dispatch()
是触发 actions 的第一种方式
触发 actions 的第二种方式:
// 1\. 从 vuex 中按需导入 mapActions 函数
import { mapActions } from 'vuex'
通过刚才导入的 mapActions 函数,将需要的 actions 函数,映射为当前组件的 methods 方法:
// 2\. 将指定的 actions 函数,映射为当前组件的 methods 函数
methods: {
...mapActions(['addASync', 'addNASync'])
}
Getter
用于对 Store 中的数据进行加工处理形成新的数据。
Getter 可以对 Store 中已有的数据加工处理之后形成新的数据,类似 Vue 的计算属性。
Store 中数据发生变化,Getter 的数据也会跟着变化。
// 定义 Getter
const store = new Vuex.Store({
state: {
count: 0
},
getters: {
showNum: state => {
return '当前最新的数量是【' + state.count + '】'
}
}
})
使用 getters 的第一种方式:this.$store.getters.名称
使用 getters 的第二种方式:
import { mapGetters } from 'vuex'
computed: {
...mapGetters(['showNum'])
}
mutations
是操作state
数据的方法的集合,比如对该数据的修改、增加、删除等等。
mutations
方法都有默认的形参:
([state] [,payload])
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.store({
state:{
name:'helloVueX'
},
mutations:{
//es6语法,等同edit:funcion(){...}
edit(state){
state.name = 'jack'
}
}
而在组件中,我们需要这样去调用这个mutation——例如在App.vue的某个method中:
this.$store.commit('edit')
在实际生产过程中,会遇到需要在提交某个mutation
时需要携带一些参数给方法使用。
单个值提交时:
this.$store.commit('edit',15)
当需要多参提交时,推荐把他们放在一个对象中来提交:
this.$store.commit('edit',{age:15,sex:'男'})
接收挂载的参数:
edit(state,payload){
state.name = 'jack'
console.log(payload) // 15或{age:15,sex:'男'}
}
另一种提交方式
this.$store.commit({
type:'edit',
payload:{
age:15,
sex:'男'
}
})
为了配合Vue的响应式数据,我们在
Mutations
的方法中,应当使用Vue提供的方法来进行操作。如果使用delete
或者xx.xx = xx
的形式去删或增,则Vue不能对数据进行实时响应。
Vue.set(state,"age",15)
Vue.delete(state,'age')
getters中的方法有两个默认参数:
([state] , [getters])
state:当前VueX对象中的状态对象
getters:当前getters对象,用于将getters下的其他getter拿来用
getters:{
nameInfo(state){
return "姓名:"+state.name
},
fullInfo(state,getters){
return getters.nameInfo+'年龄:'+state.age
}
}
this.$store.getters.fullInfo
mutations
只能处理同步函数,直接在mutation
方法中进行异步操作,将会引起数据失效。所以提供了Actions
来专门进行异步操作,最终提交mutation
方法。actions
和mutations
的区别:
Actions
提交的是mutations
,而不是直接变更状态。也就是说,actions
会通过mutations
,让mutations
帮他提交数据的变更。
Action
可以包含任意异步操作。ajax
、setTimeout
、setInterval
不在话下。
Actions中的方法有两个默认参数:([
context
] , [payload
])
context
:上下文(相当于箭头函数中的this)对象
payload
:挂载参数
actions:{
edit(context,payload){
setTimeout(()=>{
context.commit('edit',payload)
},2000)
}
}
this.$store.dispatch('edit',{age:15})
拓展:由于是异步操作,所以我们可以对异步操作封装为一个Promise对象,上面的异步方法可优化为:
actions:{
edit(context,payload){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
context.commit('edit',payload)
resolve()
},2000)
})
}
}
当项目庞大,状态非常多时,可以采用模块化管理模式。Vuex 允许我们将
store
分割成模块(module
)。每个模块拥有自己的state
、mutation
、action
、getter
、甚至是嵌套子模块——从上至下进行同样方式的分割。
Modules :{
a:{
state:{},
getters:{},
....
}
}
组件内调用模块a的状态:
this.$store.state.a
而提交或者dispatch某个方法和以前一样,会自动执行所有模块内的对应type的方法:
this.$store.commit('editKey')
this.$store.dispatch('aEditKey')
模块中 mutations
和getters
中的方法接受的第一个参数是自身局部模块内部的state
Modules :{
a:{
state:{key:5},
mutations:{
editKey(state){
state.key = 9
}
},
....
}
}
getters
中方法的第三个参数是根节点状态Modules :{
a:{
state:{key:5},
getters:{
getKeyCount(state,getter,rootState){
return rootState.key + state.key
}
},
....
}
}
actions
中方法获取局部模块状态是context.state
,根节点状态是context.rootState
Modules :{
a:{
state:{key:5},
actions:{
aEidtKey(context){
if(context.state.key === context.rootState.key){
context.commit('editKey')
}
}
},
....
}
}
如果把整个store
都放在index.js
中是不合理的,所以需要拆分。比较合适的目录格式如下:
store:.
│ actions.js
│ getters.js
│ index.js
│ mutations.js
│ mutations_type.js ##该项为存放mutaions方法常量的文件,按需要可加入
│
└─modules
Astore.js
对应的内容存放在对应的文件中,和以前一样,在index.js
中存放并导出store
。state
中的数据尽量放在index.js
中。而modules
中的Astore
局部模块状态如果多的话也可以进行细分。
// 假设你有如下的store模块
const moduleA = {
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
}
};
// 在store中注册模块
const store = new Vuex.Store({
modules: {
a: moduleA
}
});
// 在组件中使用mapState获取模块状态
import { mapState } from 'vuex';
export default {
computed: {
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
count: state => state.a.count // 这里的'a'是模块名,'count'是状态名
})
},
methods: {
increment() {
this.$store.commit('a/increment'); // 使用模块名调用模块的mutation
}
}
};
喜欢的朋友记得点赞、收藏、关注哦!!!