参考资料:
https://vuex.vuejs.org/zh-cn/mutations.html 【官方文档】
http://www.cnblogs.com/wisewrong/p/6344390.html
http://www.cnblogs.com/fayin/p/6445385.html
http://binlive.cn/details/59941d24971b027d7be1b215
常用命令:(mutation只能作同步,action可以作异步)
- //读取全局变量值
- this.$store.state.author
- //根据mutations方法newAuthor 中进行重新赋值为123
- this.$store.commit('newAuthor','123');
- //使用actions方法getCategoryData
- this.$store.dispatch("getCategoryData");
关于使用异步数据这一块,要在页面中写回调:
- this.$store.dispatch("getCategoryData").then(response => {
- this.$store.commit("changeCategoryData", response.data.items);
- this.categorys = response.data.items;
- }, response => {
- // error callback
- })
vuex分模块:
store.js:
- import Vue from 'vue'
- import Vuex from 'vuex'
- import axios from 'axios'
- import commonModule from "./modules/commonModule";
- import categoryModule from "./modules/categoryModule"
- Vue.use(Vuex)
- const store = new Vuex.Store({
- modules: {
- common: commonModule,
- category: categoryModule,
- }
- })
- export default store
categoryModule.js
- import axios from 'axios'
- // 首先声明一个状态 state
- const state = {
- pageTitle: '课程分类', //页面标题
- provinces: {}
- }
- // 更新状态
- const mutations = {
- provinces(state, payload) {
- state.provinces = payload
- }
- }
- // 然后给 actions 注册一个事件处理函数,当这个函数被触发时,将状态提交到 mutaions中处理
- const actions = {
- //rootState为根state
- getCategoryData ({ state, commit, rootState }) {
- return rootState.common.api.getCategory;
- },
- }
- // 获取状态信息
- const getter = {
- showState(state) {
- console.log(state.msg)
- }
- }
- export default {
- namespaced: true, //重点就在这一句,命名空间
- state,
- mutations,
- actions,
- getter,
- }
使用:
- this.$store.commit('category/provinces', "123");
- console.log(this.$store.state.category.provinces);
- this.$store.dispatch("category/getCategoryData");
在A模块调用B模块action或mutation:
- actions: {
- // 在这个模块中, dispatch 和 commit 也被局部化了
- // 他们可以接受 `root` 属性以访问根 dispatch 或 commit
- someAction ({ dispatch, commit, getters, rootGetters }) {
- getters.someGetter // -> 'foo/someGetter'
- rootGetters.someGetter // -> 'someGetter'
- dispatch('someOtherAction') // -> 'foo/someOtherAction'
- dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'
- commit('someMutation') // -> 'foo/someMutation'
- commit('someMutation', null, { root: true }) // -> 'someMutation'
- },
- someOtherAction (ctx, payload) { ... }
- }
如果在页面中绑定了数据,但数据在vuex模块中是异步请求过来的 ,数据渲染就不能再用data来赋值,原因如下:
data
是有缓存的,一旦Vuex
中值改变了,没法做到响应。
而放在computed
中,虽然也有缓存,但会自动监视依赖。
- //实时监控数据
- computed: {
- categorys() {
- return this.$store.state.category.categoryData;
- }
- },
demo1:检测标题是否重复
如需捕捉异步后回调需要加await,需要使用异步的方法,或者函数,需要加async:
- async checkTitle() {
- // 检测标题是否重复
- let checkparams = {
- type: 1,
- id: this.linkId,
- title: this.course_name
- };
- try {
- await this.$store.dispatch("course/uniquenessTitle", checkparams); // 这里得到了一个返回错误
- this.titleFocusActive = false; // 失去焦点
- this.titleIfCheck = true; // 标题检测成功
- } catch (err) {
- let instance = this.$toast(this.$t("course.titleAlreadyExisted"));
- setTimeout(() => {
- instance.close();
- this.titleFocusActive = true; // 聚焦
- this.titleIfCheck = false; // 标题检测失败
- }, 1000);
- // console.log(err); // 这里捕捉到错误 `error`
- return false;
- }
- // 检测end
- },
(参照ele后台方法)action:
- // 获取用户信息
- GetUserInfo({ commit, state }) {
- return new Promise((resolve, reject) => {
- getUserInfo(state.token).then(response => {
- if (!response.data) { // 由于mockjs 不支持自定义状态码只能这样hack
- reject('error')
- }
- const data = response.data
- commit('SET_ROLES', data.roles)
- commit('SET_NAME', data.name)
- commit('SET_AVATAR', data.avatar)
- commit('SET_INTRODUCTION', data.introduction)
- resolve(response)
- }).catch(error => {
- reject(error)
- })
- })
- },
demo2:检测是否有列表数据
vue文件中的方法:
- async chooseCourse() {
- // 选择资料的同时,保存当前路由和详情以前发布ID
- this.insertSession();
- // 检测是否有问卷列表数据
- let params= {
- pageIndex: 1,
- pageSize: 30,
- courseId: this.$route.params.courseId, //测试的时候 可以将课程id隐藏
- userId: this.$store.state.common.userId
- };
- let res = await this.$store.dispatch("course/checkExamination",params);
- if(!res){
- return false;
- }
- // 检测end
在分模块中的courseModule中,添加action:
- checkExamination({ commit, state,rootState },params){
- if(!params){
- params = {};
- }
- let sendData = {};
- sendData.pageIndex = params.hasOwnProperty("pageIndex") ? params.pageIndex : 1; // 页码
- sendData.pageSize = params.hasOwnProperty("pageSize") ? params.pageSize : 15; // 个数
- sendData.user_id = params.hasOwnProperty("userId") ? params.userId : rootState.common.userId; // 当前用户
- sendData.course_id = params.hasOwnProperty("courseId") ? params.courseId : 0;
- let api = rootState.exam.api.getExamList;
- return new Promise((resolve, reject) => {
- request.post(api, sendData).then(response => {
- if (!response) {
- return false;
- }
- let data = response.result;
- if(data.length == 0){
- MessageBox.confirm('还没有试卷,先去创建吧!').then(action=>{
- router.push("/exam/question-paper-lib");
- }).catch(err=>{});
- resolve(false);
- }else{
- resolve(response)
- }
- })
- });
- },
在 Vue.js 的项目中,如果项目结构简单, 父子组件之间的数据传递可以使用 props 或者 $emit 等方式
但是如果是大型项目,很多时候都需要在子组件之间传递数据,使用之前的方式就不太方便。Vue 的状态管理工具 Vuex 完美的解决了这个问题。
一、安装并引入 Vuex
项目结构:
首先使用 npm 安装 Vuex
- cnpm install vuex -S
然后在 main.js 中引入(与参考资料中有出入,视情况而定)
- import Vue from 'vue'
- import App from './App'
- import store from './vuex/store' ##引用
- /* eslint-disable no-new */
- new Vue({
- el: '#app',
- store,
- render: h => h(App)
- })
在 src 目录下创建一个 vuex 目录,将 store.js 放到 vuex 目录下
- import Vue from 'vue'
- import Vuex from 'vuex'
- Vue.use(Vuex)
- const store = new Vuex.Store({
- // 定义状态
- state: {
- author: 'Wise Wrong'
- }
- })
- export default store
将状态映射到组件
- <template>
- <footer class="footer">
- <ul>
- <li v-for="lis in ul">{{lis.li}}</li>
- </ul>
- <p>
- Copyright © {{author}} - 2016 All rights reserved
- </p>
- </footer>
- </template>
- <script>
- export default {
- name: 'footerDiv',
- data () {
- return {
- ul: [
- { li: '琉璃之金' },
- { li: '朦胧之森' },
- { li: '缥缈之滔' },
- { li: '逍遥之火' },
- { li: '璀璨之沙' }
- ]
- }
- },
- computed: {
- author () {
- return this.$store.state.author
- }
- }
- }
- </script>
这是 footer.vue 的 html 和 script 部分
主要在 computed 中,将 this.$store.state.author 的值返回给 html 中的 author
页面渲染之后,就能获取到 author 的值
在组件中修改状态
然后在 header.vue 中添加一个输入框,将输入框的值传给 store.js 中的 author
这里我使用了 Element-UI 作为样式框架
上面将输入框 input 的值绑定为 inputTxt,然后在后面的按钮 button 上绑定 click 事件,触发 setAuthor 方法
- methods: {
- setAuthor: function () {
- this.$store.state.author = this.inpuTxt
- }
- }
在 setAuthor 方法中,将输入框的值 inputTxt 赋给 Vuex 中的状态 author,从而实现子组件之间的数据传递
官方推荐的修改状态的方式
上面的示例是在 setAuthor 直接使用赋值的方式修改状态 author,但是 vue 官方推荐使用下面的方法:
- mutations: {
- newAuthor(state, msg) {
- state.author = msg;
- }
- }
然后修改 header.vue 中的 setAuthor 方法
- this.$store.commit('newAuthor','123');
这里使用 $store.commit 提交 newAuthor,并将 this.inputTxt 传给 msg,从而修改 author
这样显式地提交(commit) mutations,可以让我们更好的跟踪每一个状态的变化,所以在大型项目中,更推荐使用第二种方法。
添加actions方法,全局函数 :
- import Vue from 'vue'
- import Vuex from 'vuex'
- import axios from 'axios'
- Vue.use(Vuex)
- const store = new Vuex.Store({
- actions: {
- getCategoryData() {
- return axios.get(this.state.api.getCategory);
- }
- }
- })