Vue笔记

Vuex 学习笔记

2018-07-16  本文已影响19人  许小花花

概要

官方解释Vuex是一个专为Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。状态?我把它理解为在data中的属性需要共享给其他vue组件使用的部分,就叫做状态。简单的说就是data中需要共用的属性。比如:我们有几个页面要显示用户名称和用户等级,或者显示用户的地理位置。如果我们不把这些属性设置为状态,那每个页面遇到后,都会到服务器进行查找计算,返回后再显示。在中大型项目中会有很多共用的数据,所以尤大神给我们提供了vuex。
在一些应用比较复杂的单页面项目里使用vuex比较合适,因为当兄弟、父子组件数据通信、共用状态过多时这些状态会变得让你难以管理,当某部分出现问题便要用大量时间去组件中查改代码,这并不是我们开发者想要的,因此用一个vuex来集中管理各个状态是比较好的选择。
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:

使用

一、创建
// main.js
import Vue form 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
var store = new Vuex.Store({  //store对象
    state:{
        show:false
    }
})
new Vue({
  el: '#app',
  data(){},
  router,
  store,  //使用store
  render: h => h(App) 
})

这是最直接的 vuex 的使用,为了方便 , 我们把 store 对象写在了 main.js 里面 , 但实际上为了便于日后的维护 , 我们分开写更好 , 我们在 src 目录下 , 新建一个 store 文件夹 , 然后在里面新建一个 index.js

// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);

export default new Vuex.Store({
    state:{
        show:false
    }
})

此时,main.js 就应该写成这样

// main.js
import store from './store'
import Vue from 'vue'
new Vue({
  el: '#app',
  data(){},
  router,
  store,  //使用store
  render: h => h(App) 
})

此时,所有的子组件可以通过 $store.state.show 来调用状态值 show
这样就把 store 分离出去了 , 那么还有一个问题是 : 这里 $store.state.show 无论哪个组件都可以使用 , 那组件多了之后 , 状态也多了 , 这么多状态都堆在 store 文件夹下的 index.js 不好维护怎么办 ? 使用 vuex 的 modules
我们把其作为一个状态文件分离出去

//  components/dialog_store.js
export default {
    state:{
        show:false
    }
}

再把 store 文件夹下的 index.js 改成 :

import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);

import dialog_store from '../components/dialog_store.js';   //引入某个store对象

export default new vuex.Store({
    modules: {
        dialog: dialog_store
    }
})

这时,在组件需要使用这个状态时,把使用方法 this.$store.state.show 改写为 this.$store.state.dialog.show 即可。
如果还有其他的组件需要使用 vuex , 就新建一个对应的状态文件 , 然后将他们加入 store 文件夹下的 index.js 文件中的 modules 中。

modules: {
    dialog: dialog_store,
    other: other,  //其他组件
}
二、访问

上面我们已经创建好了const state ,这个就是我们说的访问状态对象,它就是我们SPA(单页应用程序)中的共享值。现在我们要把这个const state 赋值给内部对象,也就是把 components/dialog_store.js 中的值赋值给我们模板里data中的值。

computed:{
    show(){
        return this.$store.state.dialog.show
    }
}
<template>
  <el-dialog :visible.sync="show"></el-dialog>
</template>

<script>
import {mapState} from 'vuex';
export default {
  computed:{

    //这里的三点叫做 : 扩展运算符
    ...mapState({
      show:state=>state.dialog.show
    }),
  }
}
</script>

相当于

<template>
  <el-dialog :visible.sync="show"></el-dialog>
</template>

<script>
import {mapState} from 'vuex';
export default {
  computed:{
    show(){
        return this.$store.state.dialog.show;
    }
  }
}
</script>
computed:mapState(["show"])
三、修改状态 (Mutations)

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

// components/dialog_store.js
export default {
    state:{//state
        show:false
    },
    mutations:{
        switch_dialog(state){//这里的state对应着上面这个state
            state.show = state.show?false:true;
            //你还可以在这里执行其他的操作改变state
        }
    }
}

而使用的组件则是通过 $store.commit 方法来修改状态,像下面这样使用 $store.commit('switch_dialog') 来触发 mutations 中的 switch_dialog 方法。

<template>
  <div id="app">
    <a href="javascript:;" @click="$store.commit('switch_dialog')">点击</a>
    <t-dialog></t-dialog>
  </div>
</template>

<script>
import dialog from './components/dialog.vue'
export default {
  components:{
    "t-dialog":dialog
  }
}
</script>

这里需要注意的是:

三、执行多个 mutations(action)

多个 state 的操作 , 使用 mutations 会来触发会比较好维护 , 那么需要执行多个 mutations 就需要用 action 了:

export default {
    state:{   //state
        show:false
    },
    mutations:{
        switch_dialog(state){   //这里的state对应着上面这个state
            state.show = state.show?false:true;
            //你还可以在这里执行其他的操作改变state
        }
    },
    actions:{
        switch_dialog(context){   //这里的context和我们使用的$store拥有相同的对象和方法
            context.commit('switch_dialog');
            //你还可以在这里触发其他的mutations方法
        },
    }
}

也就是说,在一个 action 中可以一次执行多个 mutation 。这时,我们用 $store.dispatch 来触发 action 中的方法。官方推荐 , 将异步操作放在 action 中。

<template>
  <div id="app">
    <a href="javascript:;" @click="$store.dispatch('switch_dialog')">点击</a>
    <t-dialog></t-dialog>
  </div>
</template>

<script>
import dialog from './components/dialog.vue'
export default {
  components:{
    "t-dialog":dialog
  }
}
</script>
四、getters

gettersvue 中的 computed 类似 , 都是用来计算 state 然后生成新的数据 ( 状态 ) 的。
假如我们需要一个与状态 show 刚好相反的状态 ,在使用时可以直接用 computed 这样算出来 :

computed(){
    not_show(){
        return !this.$store.state.dialog.show;
    }
}

如果很多很多个组件中都需要用到这个与 show 刚好相反的状态 , 那么我们每次使用都要在组件里写 not_show , 很冗余,使用 getters 就可以解决这种问题 :

export default {
    state:{   //state
        show:false
    },
    getters:{
        not_show(state){   //这里的state对应着上面这个state
            return !state.show;
        }
    },
    mutations:{
        switch_dialog(state){   //这里的state对应着上面这个state
            state.show = state.show?false:true;
            //你还可以在这里执行其他的操作改变state
        }
    },
    actions:{
        switch_dialog(context){   //这里的context和我们使用的$store拥有相同的对象和方法
            context.commit('switch_dialog');
            //你还可以在这里触发其他的mutations方法
        },
    }
}

这样,在使用时,直接在组件中使用 $store.state.dialog.show 来获得状态 show , 使用
$store.getters.not_show 来获得状态 not_show

参考文章

vuex最简单、最详细的入门文档
技术胖博客-Vuex

上一篇下一篇

猜你喜欢

热点阅读