vuex简单示例
一.vuex是什么,解决了什么问题?
官方解释是:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.
个人理解是因为vue各个组件是相对独立的,要共享数据,就变的很麻烦.vuex就是为了解决各个组件传递数据与共享数据.
二.vuex的核心概念
vuex的核心概念是store,store中包括了state,mutation,action,getter
1.state:需要用到的状态变量
2.mutation:同步修改state
3.action:异步方法和commit mutation
4.getter:相当于computed,主要用作对state进行计算后,生成新的数据状态
一般流程是组件dispatch一个action,action再commit一个mutation,mutation对state做更改;需要计算后的state,则使用getter.
三.一个简单的示例
1.需求:
根据id来获取用户信息
2.安装vuex,安装axios(ajax需求)
3.在src下新建目录store,建立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: '暂无用户名,请获取数据'
},
// 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 + ']'
}
4.main.js中注入store;关键代码
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,点击获取数据后
四.继续改进(引入mapState)
以上就是基本的用法,但还有些瑕疵,我们继续改进:
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提示
现在似乎是完善了,但忽略了一点是,我们的数据是从服务器获取的,所以为了好的用户体验,应该加个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
vuex简单示例的更多相关文章
- 超简单入门Vuex小示例
写在前面 本文旨在通过一个简单的例子,练习vuex的几个常用方法,使初学者以最快的速度跑起来一个vue + vuex的示例. 学习vuex需要你知道vue的一些基础知识和用法.相信点开本文的同学都具备 ...
- Linux下的C Socket编程 -- server端的简单示例
Linux下的C Socket编程(三) server端的简单示例 经过前面的client端的学习,我们已经知道了如何创建socket,所以接下来就是去绑定他到具体的一个端口上面去. 绑定socket ...
- C# 构建XML(简单示例)
C# 构建XML的简单示例: var pars = new Dictionary<string, string> { {"url","https://www. ...
- 根据juery CSS点击一个标签弹出一个遮罩层的简单示例
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- ACEXML解析XML文件——简单示例程序
掌握了ACMXML库解析XML文件的方法后,下面来实现一个比较完整的程序. 定义基本结构 xml文件格式如下 <?xml version="1.0"?> <roo ...
- demo工程的清单文件及activity中api代码简单示例
第一步注册一个账户,并创建一个应用.获取app ID与 app Key. 第二步下载sdk 第三步新建工程,修改清单文件,导入相关的sdk文件及调用相应的api搞定. 3.1 修改清单文件,主要是加入 ...
- spring-servlet.xml简单示例
spring-servlet.xml简单示例 某个项目中的spring-servlet.xml 记下来以后研究用 <!-- springMVC简单配置 --> <?xml versi ...
- SignalR 简单示例
一.什么是 SignalR ASP.NET SignalR is a library for ASP.NET developers that simplifies the process of add ...
- Web API 简单示例
一.RESTful和Web API Representational State Transfer (REST) is a software architecture style consisting ...
随机推荐
- Android 的保活的两种解决方案
原文链接:http://blog.csdn.net/pan861190079/article/details/72773549 详细的阐述了 Android 的保活的两种解决方案 —— 由panhao ...
- knockout 表单绑定 要怎么Mapping才好
问题 之前有了解过knockout,学习过绑定语法,结合帮助文档,做个Demo倒也不成问题,但是部分地方很不爽,不知道是我的用法不对,还是功力不够. 比如说,标签里定义的data-bind属性名,必须 ...
- Android 系统启动过程详解
android 使用 linux 内核,一般运行在 ARM 体系架构上,android 设备启动的过程,应用层之下基本等同于linux, 从应用层第一个程序init开始有所区别,下面开始介绍. ste ...
- java基础练习 12
public class Twelfth { /*海滩上有一堆桃子,五只猴子来分.第一只猴子把这堆桃子凭据分为五份,多了一个,这只猴子把多的一个扔入海中,拿走了一份.第二只猴子把剩下的桃子又平均分成五 ...
- Git 的使用教程
Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的项目版本管理. 安装Git 1.方法一:安装homebrew,然后通过homebrew安装Git. 第一步:在终端输入如下命令 ...
- JQuery实现多个菜单的显示隐藏
(如有错敬请指点,以下是我工作中遇到并且解决的问题) 效果图: 点击各个菜单显示/隐藏,以及点击灰色部分隐藏. 比如点击了第一个菜单,然后点击第二个菜单,第一个菜单会隐藏,再显示第二个菜单,不会叠加. ...
- CodeSmith Professional 5与VS2010有冲突
最近VS2010莫名其妙无法正常使用了,新建工程和打开工程就提示“Microsoft Visual Studio发生问题需要关闭”的错误提示,然后就是重新启动VS2010,最后经过分析和查证,确定是某 ...
- ReportView控件的使用
ReportView控件的使用Posted on 2012-01-06 17:02 随遇 阅读(3006) 评论(0) 编辑 收藏 最近使用了ReportView控件绑定数据,总结下: 1.在设计器 ...
- Linux下多进程服务端客户端模型二(粘包问题与一种解决方法)
一.Linux发送网络消息的过程 (1) 应用程序调用write()将消息发送到内核中 ( 2)内核中的缓存达到了固定长度数据后,一般是SO_SNDBUF,将发送到TCP协议层 (3)IP层从TCP层 ...
- Code+ A 晨跑【三个数的最小公倍数】
时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 262144K,其他语言524288K64bit IO Format: %lld 题目描述 “无体育,不清华”.“每天锻炼一小时,健康工作 ...