Vuex详解与使用

Vuex是什么:

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 解决了多个视图依赖于同一状态来自不同视图的行为需要变更同一状态的问题,将开发者的精力聚焦于数据的更新而不是数据在组件之间的传递上 

状态管理模式包含以下几个部分

  • state,驱动应用的数据源;
  • view,以声明方式将 state 映射到视图;
  • actions,响应在 view 上的用户输入导致的状态变化

以下是一个表示“单向数据流”理念的简单示意:

 

安装: 

 npm

npm install vuex --save

yarn

yarn add vuex

在一个模块化的打包系统中,您必须显式地通过 Vue.use() 来安装 Vuex:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

 每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:

  1. Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

  2. 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

核心概念 :

 配置项

配置项含义注意
state单一状态树类似data
mutations数据管家(同步)唯一修改state的地方
actions异步请求要改state需要提交给mutations
gettersvuex计算属性类似computed
modules模块拆分

 关系图

 

定义与使用: 

 Vux-state数据源

 语法 :

 /*
const store = new Vuex.Store({
    state: {
        变量名: 初始值
    }
})    
*/

使用方式:

1、组件内直接使用

  this.$store.state.变量名  开启命名空间    this.$store.state.模块名.变量名

2、组件内 - 映射使用 (推荐)

// 1. 拿到mapState辅助函数
import { mapState } from 'vuex'
export default {
  computed: {
   
// 2. 把state里变量映射到计算属性中
    ...mapState(['state里的变量名'])   开启命名空间   ...mapState("模块名", ['state变量名'])
  }
                    

 Vuex-mutatons同步修改

 语法:

/*
const store  = new Vuex.Store({
    mutations: {
        函数名 (state, 可选值) {
            // 同步修改state值代码
        }
    }
})
*/

使用方式:

1、组件内直接使用

this.$store.commit("mutations里的函数名", 具体值)

开启命名空间

this.$store.commit("模块名/mutations里的函数名", 具体值)

2、组件内 - 映射使用 (推荐)

 // 1. 拿到mapMutations辅助函数
import { mapMutations } from 'vuex'
export default {
  methods: {
   
// 2. 把mutations里方法映射到原地
    ...mapMutations(['mutations里的函数名'])

    开启命名空间   ..mapMutations("模块名", ['mutations里方法名'])
  }
}

 

Vuex-actions异步修改 

语法:

/*
const store = new Vuex.Store({
    actions: {
        函数名 (store, 可选值) {
            // 异步代码, 把结果commit给mutations给state赋值
        }
    }
})
*/

 

使用方式:

1、组件内直接使用

this.$store.dispatch('actions函数名', 具体值)

开启命名空间

this.$store.dispatch("模块名/actions里的函数名", 具体值)

2、组件内 - 映射使用 (推荐)

// 1. 拿到mapActions辅助函数
import { mapActions } from 'vuex'
export default {
  methods: {
   
// 2. 把actions里方法映射到原地
    ...mapActions(['actions里的函数名'])

开启命名空间  ...mapActions("模块名", ['actions里方法名'])
  }
}

 

Vuex- getters计算属性

语法:

/*
const store = new Vuex.Store({
    getters: {
        计算属性名 (state) {
            return 值给计算属性
        }
    }
})
*/

 

使用方式:

1、组件内直接使用

this.$store.getters.计算属性名

开启命名空间

this.$store.getters['模块名/计算属性名']

 2、组件内 - 映射使用 (推荐)

// 1. 拿到mapGetters辅助函数
import { mapGetters } from 'vuex'
export default {
  computed: {
   
// 2. 把getters里属性映射到原地
    ...mapGetters(['getters里的计算属性名'])

开启命名空间

...mapGetters("模块名", ['getters里计算属性名'])
  }   
}

 Vuex-modules分模块

 由于使用单一状态图,应用的所有状态会集中到一个比较大的对象,当应用变得复杂时,store对象就有可能变得相当臃肿。为了解决所说的问题,Vuex允许我们将store分割成模块(modules)。每个模块拥有自己的state,mutations,actions,getters,嵌套的子模块

 创建modules模块对象

新建store/modules/user.js

新建store/modules/cart.js

语法: 每个模块对象里包含5个核心概念, 只有state变成函数形式

// user.js用户模块
const userModule = {
  // 开启命名空间
  // 防止不同模块下的 属性 和 方法 冲突
  namespaced: true,
  state() {
    return {
      name: '',
      token: ''
    }
  },
  mutations: {},
  actions: {},
  getters: {}
}

export default userModule
// cart.js购物车模块对象
import axios from 'axios'
const cartModule = {
  // 开启命名空间
  // 防止不同模块下的 属性 和 方法 冲突
  namespaced: true,
  state() {
    return {
      goodsList: []
    }
  },
  mutations: {
    setGoodsList(state, newList) {
      state.goodsList = newList
    }
  },
  actions: {
    async asyncGetGoodsList(store) {
      const url = `https://www.escook.cn/api/cart`
      // 发送异步请求
      const res = await axios({ url: url });
      store.commit('setGoodsList', res.data.list) // 提交mutation修改state中的数据
    }
  },
  getters: {
    allCount(state) {
      return state.goodsList.reduce((sum, obj) => {
        if (obj.goods_state === true) { // 选中商品才累加数量
          sum += obj.goods_count;
        }
        return sum;
      }, 0)
    },
    allPrice(state) {
      return state.goodsList.reduce((sum, obj) => {
        if (obj.goods_state) {
          sum += obj.goods_count * obj.goods_price
        }
        return sum;
      }, 0)
    }
  }
}
export default cartModule

定义modules(在根store中注册子模块)

import Vue from 'vue'
import Vuex from 'vuex'
import cartModule from './modules/cart'
import userModule from './modules/user'
Vue.use(Vuex)
const store = new Vuex.Store({
  modules: {
    user: userModule,
    cart: cartModule
  }
})
export default store

分模块-命名空间 

 防止多个模块之间, state/mutations/actions/getters的名字冲突

 

//在模块对象内设置namespaced: true
const cartModule = {
  namespaced: true,
  state () {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {}
}

代码示例: 

1、首先为了项目格式便于维护和相对规范一点,我们先在 目录下建立一个 store 文件夹,并且在下面建立一个 index.js 文件:

2、先引入 Vue 和 Vuex 并且别忘了 Vue.use(Vuex),当然你 Vuex 首先得跟 main.js 扯上点关系嘛

= > 引入 store 文件  = >   并且 Vue 实例上得将 挂载 store ,这下万无一失。可以继续了 

 

 然后我们就可以开始编写我们的vuex业务代码

3、现在开始 Vuex 的主宰部分 new Vuex.Store({}) 

  

 在这张图上可以清楚的看到 new Vuex.Store 里面有一个 state:{ } 注释也写了,

这是你要设置的全局访问的 state 对象,也就是你需要 count 就丢个 count进去,需要 price 就丢个 price进去,

这里我丢了个 count 和 ChangeShowCom 两个不同的数据类型 作为一个对比。

4、在页面中获取 state 里面的数据

 

 5、getters 和 组件的 computed 类似,方便直接生成一些可以直接用的数据。当组装的数据要在多个页面使用时,就可以使用 getters 来做。

6、那么, 我们如果想改变 count 的值,应该怎么做呢? 这时候就可以用到  mutations 。

要修改store中的值唯一的方法就是提交mutation来修改,我们现在App.vue文件中添加两个按钮,一个加1,一个减1;

这里我们点击按钮调用add(执行加的方法)和del(执行减法的方法),然后在里面直接提交mutations中的方法修改值:

修改index.js文件,添加mutations,在mutations中定义两个函数,用来对count加1和减1,

这里定义的两个方法就是上面commit提交的两个方法如下:

 

 

7、Action 类似于 mutation,不同在于:

  1、Action 提交的是 mutation,而不是直接变更状态。

  2、Action 可以包含任意异步操作。

这里我们把commit提交mutations修改为使用dispatch来提交actions;我们点击页面,效果是一样的。

 

 

8、来看一下 Vuex 里面的好东西,辅助函数 mapState、mapGetters、mapActions

如果我们不喜欢这种在页面上使用“this.$stroe.state.count”和“this.$store.dispatch('funName')”这种很长的写法,

那么我们可以使用mapState、mapGetters、mapActions就不会这么麻烦了;

并且我们配合 ... 拓展符 一起使用。

 正常显示,效果是一样的,我们就可以不再使用很长的写法来调用了。

9、Vuex与localStorage

vuex 是 vue 的状态管理器,存储的数据是响应式的。但是并不会保存起来,刷新之后就回到了初始状态,具体做法应该在vuex里数据改变的时候把数据拷贝一份保存到localStorage里面,刷新之后,如果localStorage里有保存的数据,取出来再替换store里的state。

这里需要注意的是:由于vuex里,我们保存的状态,都是数组,而localStorage只支持字符串,所以需要用JSON转换

JSON.stringify(state.'数据名')    array=>string

JSON.parse(window.localStorage.getItem(key))   string=>array

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值