官方解释是:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.
我的理解是由于vue各个组件是相对独立的,要共享数据,就变的很麻烦.vuex就是为了解决各个组件传递数据与共享数据.html
vuex的核心概念是store,store中包括了state,mutation,action,gettervue
1.state:须要用到的状态变量
2.mutation:同步修改state
3.action:异步方法和commit mutation
4.getter:至关于computed,主要用做对state进行计算后,生成新的数据状态ios
通常流程是组件dispatch一个action,action再commit一个mutation,mutation对state作更改;须要计算后的state,则使用getter.es6
1.需求:
根据id来获取用户信息ajax
2.安装vuex,安装axios(ajax需求)vuex
3.在src下新建目录store,创建store.js文件,代码以下所示axios
import Vue from 'vue' import Vuex from 'vuex' import axios from 'axios' import qs from 'qs' Vue.use(Vuex) axios.defaults.baseURL = '/api' const store = new Vuex.Store({ state: { username: '暂无用户名,请获取数据' }, // Vue 建议咱们mutation 类型用大写常量表示 mutations: { SET_USER_NAME (state, user) { state.username = user.name } }, actions: { getData (context, id) { axios.post( 'http://127.0.0.1:9000/mobile/info', qs.stringify({id: id}) ).then(function (res) { context.commit('SET_USER_NAME', res.data) }).catch(function (error) { console.info(error) }) } }, getters: { username: (state) => state.username === '暂无用户名,请获取数据' ? state.username : '用户名:[' + state.username + ']' } }) export default store
ps:
a.getters中的username方法并没有实际做用,只是演示计算生成新的一个状态数据
b.username用了es6的箭头函数;等价于:
username(state){
return username: (state) => state.username === '暂无用户名,请获取数据' ? state.username : '用户名:[' + state.username + ']'
}segmentfault
4.main.js中注入store;关键代码api
import store from '@/store/store' /* eslint-disable no-new */ new Vue({ el: '#app', router, store, template: '<App/>', components: { App } })
5.在components中新建query.vue;代码以下:缓存
<template> <div> <span>{{ this.$store.getters.username }}</span> <input type="text" v-model="id" /> <button @click="$store.dispatch('getData', id)">获取数据</button> </div> </template> <script> export default { data () { return {id: 0} } } </script>
6.在App.vue中:
<template> <div id="app"> <img src="./assets/logo.png"> <span>{{ $store.getters.username }}</span> <query></query> </div> </template> <script> import query from '@/components/query' export default { methods: { }, components: { query } } </script>
至此完成了一个简单的示例
输入id,点击获取数据后
以上就是基本的用法,但还有些瑕疵,咱们继续改进:
1.上面的示例中,在query.vue中咱们常见的应该是用computed属性去访问state,由于它是依赖缓存的;代码改进以下:
<template> <div> <span>比较好看的username:{{ humanUserName }}</span> <br> <span>普通的username:{{ username }}</span> <br> <input type="text" v-model="id" /> <button @click="$store.dispatch('getData', id)">获取数据</button> </div> </template> <script> export default { data () { return {id: 0} }, computed: { humanUserName () { return this.$store.getters.username }, username () { return this.$store.state.username } } } </script>
ps:能够看到咱们定义了两个computed属性,humanUserName和username;前者从store的getters取数据,后者直接从state取数据.
2.咱们在store.js中再增长一些状态:
const store = new Vuex.Store({ state: { username: '暂无用户名,请获取数据', sex: '未知', age: '0' }, ........................... })
3.在query.vue中咱们仍然打印这些状态:
<template> <div> <span>比较好看的username:{{ humanUserName }}</span> <br> <span>普通的username:{{ username }}</span> <br> <span>性别: {{ sex }}</span> <br> <span>年龄: {{ age }}</span> <input type="text" v-model="id" /> <button @click="$store.dispatch('getData', id)">获取数据</button> </div> </template> <script> export default { data () { return {id: 0} }, computed: { humanUserName () { return this.$store.getters.username }, username () { return this.$store.state.username }, age () { return this.$store.state.age }, sex () { return this.$store.state.sex } } } </script>
你会发现如今的代码变的冗长了,缘由在于咱们在computed挨个获取state;改进这一点
4.使用Vuex的mapState来改进,改进部分代码以下
<script> import {mapState} from 'vuex' export default { data () { return {id: 0} }, computed: { humanUserName () { return this.$store.getters.username }, ...mapState({ username: 'username', // 'username' 直接映射到state 对象中的username, 它至关于 this.$store.state.username, age: 'age', sex: 'sex' }) } } </script>
ps:
在...mapState前面的...叫作扩展运算符
固然<button @click="$store.dispatch('getData', id)">获取数据</button>这个也不是很好,应该将他放入组件的methods中
1.改进代码以下:
<template> <div> <span>比较好看的username:{{ humanUserName }}</span> <br> <span>普通的username:{{ username }}</span> <br> <span>性别: {{ sex }}</span> <br> <span>年龄: {{ age }}</span> <input type="text" v-model="id" /> <button @click="getRemoteData()">获取数据</button> </div> </template> <script> import {mapState} from 'vuex' export default { data () { return {id: 0} }, methods: { getRemoteData () { this.$store.dispatch('getData', this.id) } }, computed: { humanUserName () { return this.$store.getters.username }, ...mapState({ username: 'username', // 'username' 直接映射到state 对象中的username, 它至关于 this.$store.state.username, age: 'age', sex: 'sex' }) } } </script>
2.若是有十个dispatch,this.$store.dispatch('XXX', XXX)这样的代码势必要写十遍;可使用...mapActions,改进部分代码以下:
<template> <div> <span>比较好看的username:{{ humanUserName }}</span> <br> <span>普通的username:{{ username }}</span> <br> <span>性别: {{ sex }}</span> <br> <span>年龄: {{ age }}</span> <input type="text" v-model="id" /> <button @click="getRemoteData(id)">获取数据</button> </div> </template> <script> import {mapState, mapActions} from 'vuex' export default { data () { return {id: 0} }, methods: { ...mapActions({getRemoteData: 'getData'}) /* 若是名称相同,能够直接写成,...mapActions(['getData']) */ }, computed: { humanUserName () { return this.$store.getters.username }, ...mapState({ username: 'username', // 'username' 直接映射到state 对象中的username, 它至关于 this.$store.state.username, age: 'age', sex: 'sex' }) } } </script>
然还有个...mapGetters,用法和mapState,mapActions是同样的,在此不作介绍了.
如今彷佛是完善了,但忽略了一点是,咱们的数据是从服务器获取的,因此为了好的用户体验,应该加个loading.在获取数据的时候显示,获取完了隐藏.
1.store.js
import Vue from 'vue' import Vuex from 'vuex' import axios from 'axios' import qs from 'qs' Vue.use(Vuex) axios.defaults.baseURL = '/api' const store = new Vuex.Store({ state: { username: '暂无用户名,请获取数据', sex: '未知', age: '0', waiting: false // loading状态 }, mutations: { SET_USER_NAME (state, user) { state.username = user.name }, // 显示和隐藏waiting SHOW_WAITING_MESSAGE (state) { state.waiting = true }, HIDE_WAITING_MESSAGE (state) { state.waiting = false } }, actions: { getData ({commit}, id) { commit('SHOW_WAITING_MESSAGE') axios.post( 'http://127.0.0.1:9000/mobile/info', qs.stringify({id: id}) ).then(function (res) { commit('HIDE_WAITING_MESSAGE') commit('SET_USER_NAME', res.data) }).catch(function (error) { console.info(error) }) } }, getters: { username: (state) => state.username === '暂无用户名,请获取数据' ? state.username : '用户名:[' + state.username + ']' } }) export default store
2.query.vue
<template> <div> <span v-if="show">正在加载....</span> <br> <span>比较好看的username:{{ humanUserName }}</span> <br> <span>普通的username:{{ username }}</span> <br> <span>性别: {{ sex }}</span> <br> <span>年龄: {{ age }}</span> <input type="text" v-model="id" /> <button @click="getRemoteData(id)">获取数据</button> </div> </template> <script> import {mapState, mapActions} from 'vuex' export default { data () { return {id: 0} }, methods: { ...mapActions({getRemoteData: 'getData'}) /* 若是名称相同,能够直接写成,...mapActions(['getData']) */ }, computed: { humanUserName () { return this.$store.getters.username }, ...mapState({ username: 'username', // 'username' 直接映射到state 对象中的username, 它至关于 this.$store.state.username, age: 'age', sex: 'sex', show: 'waiting' }) } } </script>
ps:对于store中的actions中的方法
getData (context, id) { ...... }
会自动得到一个默认参数context,它是一个store 实例,经过它能够获取到store 实例的属性和方法,如 context.state 就会获取到 state 属性, context.commit 就会执行commit命令.其实actions 还能够简写一下, 由于函数的参数是一个对象,函数中用的是对象中一个方法,咱们能够经过对象的解构赋值直接获取到该方法。能够修改以下
getData ({commit}, id) { ...... }
本文参考了:
http://www.cnblogs.com/SamWeb/p/6527240.html
https://segmentfault.com/a/1190000009404727