浅入不深出--vuex的简单使用
什么是vuex,官网的描述是:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
状态管理模式包含3个部分:
1、state,驱动应用的数据源;
2、view,以声明方式将state映射到视图;
3、actions,响应在view上的用户输入导致的状态变化。
接下来说说它们是如何工作的。
首先说说如何在项目中使用vuex
首先安装vuex:npm install vuex --save
然后 在src文件目录下新建一个名为store的文件夹,并在store文件夹里新建一个index.js,里面的内容如下
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex); //使用vuex
const store = new Vuex.Store(); //定义store export default store; //暴露store接口
接着,在项目的 main.js里面引入store,然后再全局注入一下
import store from './store'//引入store new Vue({
el: '#app',
router,
store,//使用store,即全局注入
template: '<App/>',
components: { App }
})
这样就可以在任何一个组件里面使用this.$store了。
搭建好vuex后,开始进入正题,如何使用vuex。
回到store文件的index.js里面,声明一个state变量,并赋值一个对象给它,对象里面随便定义两个初始属性值;然后再在实例化的Vuex.Store里面传入一个空对象,并把刚声明的变量state仍里面:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state={//要设置的全局访问的state对象
showFooter: true,
changableNum:0
//要设置的初始属性值
};
const store = new Vuex.Store({
state //把上面声明的state对象扔到实例化的Vuex.Store里
}); export default store;
至此,你就可以在任何一个组件里,通过this.$store.state.showFooter或this.$store.state.changebleNum获取showfooter和changebleNum定义的值了。
but这不是理想的获取方式。
vuex官方API提供了一个getters,来实时监听state值的变化(最新状态),照样在store文件的index.js里面修改,具体看下面:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state={ //要设置的全局访问的state对象
showFooter: true,
changableNum:0
//要设置的初始属性值
};
const getters = { //实时监听state值的变化(最新状态)
isShow(state) { //方法名随意,主要是来承载变化的showFooter的值
return state.showFooter
},
getChangedNum(){ //方法名随意,主要是用来承载变化的changableNum的值
return state.changebleNum
}
};
const store = new Vuex.Store({
state,
getters
});
export default store;
getters 只用来监听(获取)state的值,并不能用来改变state的值。改变state的值需要用mutations。照样在store文件的index.js里面修改,具体代码如下:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state={ //要设置的全局访问的state对象
showFooter: true,
changableNum:0
//要设置的初始属性值
};
const getters = { //实时监听state值的变化(最新状态)
isShow(state) { //承载变化的showFooter的值
return state.showFooter
},
getChangedNum(){ //承载变化的changebleNum的值
return state.changableNum
}
};
const mutations = {
show(state) { //自定义改变state初始值的方法,这里面的参数除了state之外还可以再传额外的参数(变量或对象);
state.showFooter = true;
},
hide(state) { //同上
state.showFooter = false;
},
newNum(state,sum){ //同上,这里面的参数除了state之外还传了需要增加的值sum
state.changableNum+=sum;
}
};
const store = new Vuex.Store({
state,
getters,
mutations
});
export default store;
mutattions也是一个对象,这个对象里面可以创建改变state的初始值的方法,方法里面的参数用state或者额外的参数,
定义好之后同样把mutations扔进Vuex.Store里面。
这时候就完全可以用 this.$store.commit('show') 或 this.$store.commit('hide') 以及 this.$store.commit('newNum',6)
在别的组件里面进行改变showfooter和changebleNum的值了,
但这不是理想的改变值的方式。
因为在 Vuex 中,mutations里面的方法都是同步事务,意思就是说:
比如这里的一个this.$store.commit('newNum',sum)方法,每个组件里用执行得到的值,每次都是一样的,这样肯定不是理想的需求。
vuex官方API还提供了一个actions,这个actions也是个对象变量,最大的作用就是里面的Action方法 可以包含任意异步操作,
这里面的方法是用来异步触发mutations里面的方法,actions里面自定义的函数接收一个context参数和要变化的形参,
context与store实例具有相同的方法和属性,所以它可以执行context.commit(' '),然后把actions也扔进Vuex.Store里面:
照样在store文件的index.js里面修改,具体代码如下:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state={ //要设置的全局访问的state对象
showFooter: true,
changableNum:0
//要设置的初始属性值
};
const getters = { //实时监听state值的变化(最新状态)
isShow(state) { //承载变化的showFooter的值
return state.showFooter
},
getChangedNum(){ //承载变化的changebleNum的值
return state.changableNum
}
};
const mutations = {
show(state) { //自定义改变state初始值的方法,这里面的参数除了state之外还可以再传额外的参数(变量或对象);
state.showFooter = true;
},
hide(state) { //同上
state.showFooter = false;
},
newNum(state,sum){ //同上,这里面的参数除了state之外还传了需要增加的值sum
state.changableNum+=sum;
}
};
const actions = {
hideFooter(context) { //自定义触发mutations里函数的方法,context与store 实例具有相同方法和属性
context.commit('hide');//commit里面的参数即为mutations对象里面的方法
},
showFooter(context) { //同上注释
context.commit('show');//同上注释
},
getNewNum(context,num){ //同上注释,num为要变化的形参
context.commit('newNum',num)//同上注释
}
};
const store = new Vuex.Store({
state,
getters,
mutations,
actions
});
export default store;
而在外部组件里进行全局执行actions里面方法的时候,你只需要用执行this.$store.dispatch('hideFooter')或this.$store.dispatch('showFooter')以及this.$store.dispatch('getNewNum',6) //6要变化的实参。
这样就可以全局改变改变showfooter或changebleNum的值了。
如下面的组件中,需求是跳转组件页面后,根据当前所在的路由页面进行隐藏或显示页面底部的tabs选项卡
<template>
<div id="app">
<router-view/>
<FooterBar v-if="isShow" />
</div>
</template> <script>
import FooterBar from '@/components/common/FooterBar'
import config from './config/index'
export default {
name: 'App',
components:{
FooterBar:FooterBar
},
data(){
return {
}
},
computed:{
isShow(){
return this.$store.getters.isShow;
}
},
watch:{
$route(to,from){ //跳转组件页面后,监听路由参数中对应的当前页面以及上一个页面
console.log(to)
if(to.name=='book'||to.name=='my'){ // to.name来获取当前所显示的页面,从而控制该显示或隐藏footerBar组件
this.$store.dispatch('showFooter') // 利用派发全局state.showFooter的值来控制
}else{
this.$store.dispatch('hideFooter')
}
} </script>
至此就可以做到一呼百应的全局响应状态改变了! modules 模块化 以及 组件中引入 mapGetters、mapActions 和 mapStates的使用
在实际项目中,很多时候需要模块管理,比如写一个商城项目,你
所用到的全局state可能是关于购物车这一块儿的也有可能是关于商品价格这一块儿的;像这样的情况我们就要考虑使用vuex
中的 modules 模块化了,具体怎么使用modules呢?咱们继续一步一步的走:
首先,在store文件夹下面新建一个modules文件夹,在modules文件夹里面建立需要管理状态的js文件,不同的状态需要用不同的js文件来管理,如下图:
在store文件夹下面的index.js 里面引入这两个文件,内容改写成:
import Vue from 'vue';
import Vuex from 'vuex';
import footerStatus from './modules/footerStatus'
import collection from './modules/collection'
Vue.use(Vuex); export default new Vuex.Store({
modules:{
footerStatus,
collection
}
});
相应的js文件如下:
//collection.js const state={
collects:[], //初始化一个colects数组
};
const getters={
renderCollects(state){ //承载变化的collects
return state.collects;
}
};
const mutations={
pushCollects(state,items){ //如何变化collects,插入items
state.collects.push(items)
}
};
const actions={
invokePushItems(context,item){ //触发mutations里面的pushCollects ,传入数据形参item 对应到items
context.commit('pushCollects',item);
}
};
export default {
namespaced:true,//用于在全局引用此文件里的方法时标识这一个的文件名
state,
getters,
mutations,
actions
}
//footerStatus.js const state={ //要设置的全局访问的state对象
showFooter: true,
changableNum:0
//要设置的初始属性值
};
const getters = { //实时监听state值的变化(最新状态)
isShow(state) { //承载变化的showFooter的值
return state.showFooter
},
getChangedNum(){ //承载变化的changebleNum的值
return state.changableNum
}
};
const mutations = {
show(state) { //自定义改变state初始值的方法,这里面的参数除了state之外还可以再传额外的参数(变量或对象);
state.showFooter = true;
},
hide(state) { //同上
state.showFooter = false;
},
newNum(state,sum){ //同上,这里面的参数除了state之外还传了需要增加的值sum
state.changableNum+=sum;
}
};
const actions = {
hideFooter(context) { //自定义触发mutations里函数的方法,context与store 实例具有相同方法和属性
context.commit('hide');
},
showFooter(context) { //同上注释
context.commit('show');
},
getNewNum(context,num){ //同上注释,num为要变化的形参
context.commit('newNum',num)
}
};
export default {
namespaced: true, //用于在全局引用此文里的方法时标识这一个的文件名
state,
getters,
mutations,
actions
}
其中的 namespaced:true 表示当你需要在别的文件里面使用( mapGetters、mapActions 接下来会说 )时,里面的方法需要注明来自哪一个模块的方法。
就这样,collection.js和footerStatus.js两个文件就写好了。如果现在运行当前的代码话,项目会报错!因为上面的代码模块化分开了,引用的地方还没有改。接下来一起来看看
mapState,mapGetters,mapActions的使用,首先 在需要用的 组件里面先导入 import {mapState,mapGetters,mapActions} from 'vuex';
咱们先修正一下隐藏或显示页面底部的tabs选项卡(就是上面举的临时例子)的组件代码
<template>
<div id="app">
<router-view/>
<FooterBar v-if="isShow" />
</div>
</template> <script>
import {mapState,mapGetters,mapActions} from 'vuex'; //先要引入
import FooterBar from '@/components/common/FooterBar'
import config from './config/index'
export default {
name: 'App',
components:{
FooterBar:FooterBar
},
data(){
return {
}
},
computed:{
...mapState({ //这里的...是超引用,ES6的语法,意思是state里有多少属性值我可以在这里放多少属性值
isShow:state=>state.footerStatus.showFooter //注意这些与上面的区别就是state.footerStatus。showFooter是指footerStatus.js里state的showFooter
}),
//你也可以用下面的mapGetters来获取isShow的值,貌似下面的更简洁
/*...mapGetters('footerStatus',{ //footerStatus指的是modules文件夹下的footerStatus.js模块
isShow:'isShow' //第一个isShow是我自定义的只要对应template里v-if="isShow"就行,
//第二个isShow是对应的footerStatus.js里的getters里的isShow
})*/
},
watch:{
$route(to,from){
if(to.name=='book'||to.name=='my'){
this.$store.dispatch('footerStatus/showFooter') //这里改为'footerStatus/showFooter',意思是指footerStatus.js里actions里的showFooter方法
}else{
this.$store.dispatch('footerStatus/hideFooter') //同上注释
}
}
}
}
</script>
现在项目代码应该就不会报错了,接下来看一下mapActions的用法。
实际上上面的this.$store.dispatch('footerStatus/showFooter')已经算是一种执行相应模块的action里的方法了,但有时会牵扯的事件的触发及传值,那就会有下面的mapActions用法了,还记得上面的另一个模块collection.js吗?来看一下里面的actions中的方法结构:
const state={
collects:[], //初始化一个colects数组
};
const getters={
renderCollects(state){ //承载变化的collects
return state.collects;
}
};
const mutations={
pushCollects(state,items){ //如何变化collects,插入items
state.collects.push(items)
}
};
const actions={
invokePushItems(context,item){ //触发mutations里面的pushCollects ,传入数据形参item 对应到items
context.commit('pushCollects',item);
}
};
需要传值来实时变动state.collects里的数据,那肯定要在执行它的地方进行传值了,所以下面用到它的地方我们用了个@click来执行这个invokePushItems方法了,并且传入相应的对象数据item,如下
<template>
<div >
<section class="joinState">
<div class="joinStateHead">
<span class="h3">全国改性料通讯录</span>
<span class="joinStatus" @click="invokePushItems(item)">加入收藏列</span>
</div>
</section>
</div>
</template> <script>
import { mapActions } from 'vuex'
export default {
components:{
conditionFilter
},
name: 'bookDetail',
data () {
return {
msg: '',
item:{
id:'01',
productName: '苹果',
price:'1.6元/斤'
}
}
},
mounted() {
this.$store.dispatch('footerStatus/hideFooter')
},
methods:{
...mapActions('collection',[ //collection是指modules文件夹下的collection.js
'invokePushItems' //collection.js文件中的actions里的方法,在上面的@click中执行并传入实参
])
} }
</script>
这样一来,在这个组件里面操作的 collecttion.js 中的state的数据,在其他的任何的一个组件里面都会得到相应的更新变化了,获取状态的页面代码如下:
<template>
</div>
<div>
<ul>
<li v-for="(val,index) in arrList" :key="index">
<h5>{{val.productName}}</h5>
<p>{{val.price}}</p>
</li>
</ul>
</div>
</template> <script>
import {mapState,mapGetters,mapActions} from 'vuex';
export default {
name: 'book',
data() {
return {
}
},
computed:{
// ...mapState({ //用mapState来获取collection.js里面的state的属性值
// arrList:state=>state.collection.collects
// }),
...mapGetters('collection',{ //用mapGetters来获取collection.js里面的getters
arrList:'renderCollects'
}) }
}
</script>
至此,vuex中的常用的一些知识点使用算是基本了解了。
参考文献:https://segmentfault.com/a/1190000015782272
浅入不深出--vuex的简单使用的更多相关文章
- 浅入深出之Java集合框架(上)
Java中的集合框架(上) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,如果已经有java基础的小伙伴可以直接跳到<浅入深出之Java集合框架 ...
- 浅入深出Vue:前言
浅入深出Vue系列文章 之前大部分是在做后端,后来出于某些原因开始接触Vue.深感前端变化之大,各种工具.框架令人眼花缭乱.不过正是这些变化,让前端开发更灵活. 博主在刚开始时,参考官网的各个步骤以及 ...
- 『浅入深出』MySQL 中事务的实现
在关系型数据库中,事务的重要性不言而喻,只要对数据库稍有了解的人都知道事务具有 ACID 四个基本属性,而我们不知道的可能就是数据库是如何实现这四个属性的:在这篇文章中,我们将对事务的实现进行分析,尝 ...
- 浅入深出Vue:代码整洁之封装
深入浅出vue系列文章已经更新过半了,在入门篇中我们实践了一个小小的项目. <代码整洁之道>一书中提到过一句话: 神在细节中 这句话来自20世纪中期注明现代建筑大师 路德维希·密斯·范·德 ...
- 浅入深出之Java集合框架(中)
Java中的集合框架(中) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,如果已经有java基础的小伙伴可以直接跳到<浅入深出之Java集合框架 ...
- 浅入深出之Java集合框架(下)
Java中的集合框架(下) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,哈哈这篇其实也还是基础,惊不惊喜意不意外 ̄▽ ̄ 写文真的好累,懒得写了.. ...
- 浅入深出Vue:环境搭建
浅入深出Vue:环境搭建 工欲善其事必先利其器,该搭建我们的环境了. 安装NPM 所有工具的下载地址都可以在导航篇中找到,这里我们下载的是最新版本的NodeJS Windows安装程序 下载下来后,直 ...
- 浅入深出Vue:工具准备之PostMan安装配置及Mock服务配置
浅入深出Vue之工具准备(二):PostMan安装配置 由于家中有事,文章没顾得上.在此说声抱歉,这是工具准备的最后一章. 接下来就是开始环境搭建了~尽情期待 工欲善其事必先利其器,让我们先做好准备工 ...
- 浅入深出Vue:工具准备之WebStorm安装配置
浅入深出Vue之工具准备(一):WebStorm安装配置 工欲善其事必先利其器,让我们先做好准备工作吧 导航篇 WebStorm安装配置 所有工具的下载地址都可以在导航篇中找到,这里我们下载的是最新版 ...
随机推荐
- Vue项目引入百度地图
先去百度开放平台申请ak.http://lbsyun.baidu.com/ 进来之后 按照步骤走,先登录百度账号,然后申请成为开发者,然后申请ak密钥 填写完毕后提交,会给你邮箱发个激活邮件 点击申请 ...
- A记录(主机名解析)、CNAME(别名解析)和URL转发(域名转发)
什么是 A记录(主机名解析).CNAME(别名解析)和URL转发(域名转发)? A记录(主机名解析)是最普通的域名解析,是把某一主机名解析到一个IP. 例如www.***.com-> 20.10 ...
- 去除Chrome“请停用以开发者模式运行的扩展程序”提示
将version.dll放在chrome同级目录,重启浏览器( 79.0.3945.79版本后已失效)
- [译]开发者须知的SOLID原则
原文:SOLID Principles every Developer Should Know – Bits and Pieces SOLID Principles every devloper sh ...
- Unity 代码提示符和UGUI屏幕自适应
[Header]("提示字符") Canvas Scaler 屏幕自适应
- Locust性能测试-no-web模式和csv报告保存 转自:悠悠
前言 前面是在web页面操作,需要手动的点start启动,结束的时候也需要手工去点stop,没法自定义运行时间,这就不太方便. locust提供了命令行运行的方法,不启动web页面也能运行,这就是no ...
- 一文快速入门Docker
Docker提供一种安全.可重复的环境中自动部署软件的方式,拉开了基于与计算平台发展方式的变革序幕.如今Docker在互联网公司使用已经非常普遍.本文用十分钟时间,带你快速入门Docker. Dock ...
- C#直接调用.mdf文件
一般情况下,.mdf文件都是作为MSSQL的数据库文件,只有在安装了Microsoft SQL Server才能实现调用. 事实上,除此之外,也可以直接调用.mdf文件,而无需安装Microsoft ...
- 测度(Measure)
测度概述 数学上,测度(Measure)是一个函数,它对一个给定集合的某些子集指定一个数,这个数可以比作大小.体积.概率等等.传统的积分是在区间上进行的,后来人们希望把积分推广到任意的集合上,就发展出 ...
- win10下jupyter修改默认路径的办法
查了很多资料,发现都不管用,最后亲测找到一种方法. 实现的方法就是修改快捷方式标签的目标栏,如下图: 后面有一个%USERPROFILE% 将%USERPROFILE%改成你要的路径就可以了 然后应用 ...