前言

我们经常用element-ui做后台管理系统,经常会遇到父组件给子组件传递数据,下面一个简单的例子,点击按钮,把弹框显示变量数据通过子组件的props属性传递,子组件通过$emit事件监听把数据回传给父组件。

父组件代码:

<template>
<div>
<a href="javascript:;" @click="dialogshow = true">点击</a>
<common-dialog :show.sync="dialogshow"></common-dialog>
弹框是否显示:{{dialogshow}}
</div>
</template> <script>
import commondialog from '@/components/dialog'
export default {
name: 'parent',
components:{
'common-dialog':commondialog
},
data () {
return {
dialogshow:false
}
},
methods:{ }
}
</script>

子组件代码:

<template>
<el-dialog :visible.sync="elDialogShow" title="提示">
<span>这是一段弹框信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="elDialogShow = false">取 消</el-button>
<el-button type="primary" @click="elDialogShow = false">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
name:'children',
props:['show'],
computed:{
elDialogShow:{
get(){
return this.show
},
set(value){
this.$emit('update:show',value)
}
}
},
data() {
return { };
}
}
</script>

感觉这样挺麻烦,父组件通过设置子组件的属性(props)来向子组件传递数据,而父组件想获得子组件的数据,得向子组件注册事件,在子组件触发这个事件再把数据传递出来。一句话总结起来就是,props 向下传递数据,事件向上传递数据。

如果使用vuex,像下面这种方式就很简单:

<!--父组件-->
<template>
<div>
<a href="javascript:;" @click="$store.state.show = true">点击</a>
<common-dialog></common-dialog>
弹框是否显示:{{$store.state.show}}
</div>
</template> <!--子组件-->
<el-dialog :visible.sync="$store.state.show" title="提示">
<!--其它代码省略-->
</el-dialog>

当然,在这儿举这个例子似乎不恰当,只是为了说明vuex使用方便。

安装使用vuex

安装:

npm install vuex --save

在main.js添加配置:

import vuex from 'vuex'
Vue.use(vuex)
var store = new vuex.Store({
state:{
show:false
}
})
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})

然后子组件代码就能有效运行了。

<template>
<el-dialog :visible.sync="$store.state.show" title="提示">
<span>这是一段弹框信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="$store.state.show = false">取 消</el-button>
<el-button type="primary" @click="$store.state.show = false">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
name:'children',
data() {
return { };
}
}
</script>

modules

前面我们把store对象写到了main.js中,为了项目的好管理,我们可以新建一个store文件夹放于src文件夹下,在store文件夹下新建index.js,代码如下:

import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex); export default new vuex.Store({
state:{
show:false
}
})

那么对应的main.js得改成如下:

//vuex
import store from './store' new Vue({
el: '#app',
router,
store,//使用store
template: '<App/>',
components: { App }
})

这样虽然结构看着清晰了,但是如果多个模块,不同类型(比如用户基本信息,用户购物车等)放到同一个state下面不好管理,这就用modules。

那么store文件夹下的index.js就变成了这样,假如我们有app与user模块:

import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app' //app模块数据
import user from './modules/user' //用户模块数据
import getters from './getters' Vue.use(Vuex) const store = new Vuex.Store({
modules: {
app,
user
},
getters
}) export default store

getters

这儿说明下,上面我在Store实例对象中引入了getters,是为了后面页面可以直接调用经常用到的状态信息,也就相当于vue实例里面的computed计算属性,通过$store.getters.show方式得到相关数据,即通过上面的getters引入知道,是直接在store文件夹下创建了一个getters.js,代码如下:

const getters = {
show: state => state.app.show
}
export default getters

当然这个getters也可以放到具体的模块中,比如放到app模块中,官网的这块代码结构如下:

const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
} const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
} const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
}) store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

我们从index.js中看到,我们在store文件夹下创建了一个modules文件夹,也就是在该文件夹下放各个需要区分的状态模块,比如user.js,app.js等。

结构如下图:

上面我们通过$store.getters.show方式(即相当于通过计算属性)获得show的值,当然也可以通过$store.state.app.show获得。

app.js代码:

export default {
state:{
show:false
}
}

mutations

在我们点击按钮出现弹框或者点击弹框中的关闭按钮,需要修改app模块中的show的状态,这时候就需要通过mutations进行修改数据(同步操作)。

我们需要在app.js模块代码:

export default {
state:{
show:false
}, mutations:{
SET_DIALOG_STATE:(state,val) => { //改变弹框是否显示的状态
state.show = val
}
}
}

父组件:

<template>
<div>
<a href="javascript:;" @click="$store.commit('SET_DIALOG_STATE',true)">点击</a>
<common-dialog></common-dialog>
弹框是否显示:{{$store.state.app.show}}
</div>
</template> <script>
import commondialog from '@/components/dialog'
export default {
name: 'parent',
components:{
'common-dialog':commondialog
},
data () {
return { }
}, methods:{ }
}
</script>

子组件:

<template>
<el-dialog :visible.sync="$store.getters.show" title="提示">
<span>这是一段弹框信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="$store.commit('SET_DIALOG_STATE',false)">取 消</el-button>
<el-button type="primary" @click="$store.commit('SET_DIALOG_STATE',false)">确 定</el-button>
</span>
</el-dialog>
</template>

这儿就是用到了$store.commit('SET_DIALOG_STATE',false)来触发mutations中的SET_DIALOG_STATE方法来改变状态值。

需要注意的是:

  • mutations中的方法是不分模块的,比如你在app.js中定义了SET_DIALOG_STATE这个方法,也在user.js中定义了SET_DIALOG_STATE这个方法,那么在任一组件中调用$store.commit('SET_DIALOG_STATE',false),会执行所有的SET_DIALOG_STATE方法。
  • mutations里的操作必须是同步的。

如果在mutations 里执行异步操作会发生什么事情 , 实际上并不会发生什么奇怪的事情 , 只是官方推荐 , 不要在 mutations 里执行异步操作而已。

actions

我们在上面的app.js中通过mutations改变了一个状态,那么如果需要改变多个状态的值呢,需要执行mutations中定义的多个方法(也就是说需要调用多次$store.commit()方法),那么就需要actions

那么app.js代码如需要改成如下:

export default {
state:{
show:false
},
getters:{
showState(state){
return state.show
}
},
mutations:{
SET_DIALOG_STATE:(state,val) => { //改变弹框是否显示的状态
state.show = val
}
},
actions:{
set_dialog_state({commit,state},dialogVal){ //对象解构
commit('SET_DIALOG_STATE',dialogVal)
//commit('mutations其它方法','其它方法需要改变的值')
} //等价于下面的:
/*
set_dialog_state(context,dialogVal){
context.commit('SET_DIALOG_STATE',dialogVal)
context.commit('mutations其它方法','其它方法需要改变的值')
}
*/
}
}

那么父组件的调用方式就需要用$store.dispatch()方法,父组件代码如下:

<template>
<div>
<a href="javascript:;" @click="$store.dispatch('set_dialog_state',true)">点击</a>
<common-dialog></common-dialog>
弹框是否显示:{{$store.state.app.show}}
</div>
</template> <script>
import commondialog from '@/components/dialog'
export default {
name: 'parent',
components:{
'common-dialog':commondialog
},
data () {
return { }
}, methods:{ }
}
</script>

子组件的代码:

<template>
<el-dialog :visible.sync="$store.getters.show" title="提示">
<span>这是一段弹框信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="$store.dispatch('set_dialog_state',false)">取 消</el-button>
<el-button type="primary" @click="$store.dispatch('set_dialog_state',false)">确 定</el-button>
</span>
</el-dialog>
</template>

这儿就使用$store.dispatch('set_dialog_state',true)来触发actions中的set_dialog_state方法。官方推荐 , 将异步操作放在 action 中。

mapGetters、mapState、mapMutations、mapActions

很多时候 , $store.state.app.show$store.dispatch('set_dialog_state',true) 这种写法又长又臭 , 很不方便 , 我们没使用 vuex 的时候 , 获取一个状态只需要 this.show , 执行一个方法只需要 this.set_dialog_state就行了 , 使用 vuex 使写法变复杂了 ?

使用 mapState、mapGetters、mapActions 就变得简单了。

mapGetters

比如子组件原来是这样:

<template>
<el-dialog :visible.sync="$store.getters.show" title="提示">
<span>这是一段弹框信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="$store.dispatch('set_dialog_state',false)">取 消</el-button>
<el-button type="primary" @click="$store.dispatch('set_dialog_state',false)">确 定</el-button>
</span>
</el-dialog>
</template>

通过$store.getter.show得到状态值,我们也可以这样:

<template>
<el-dialog :visible.sync="show" title="提示">
<span>这是一段弹框信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="$store.dispatch('set_dialog_state',false)">取 消</el-button>
<el-button type="primary" @click="$store.dispatch('set_dialog_state',false)">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name:'children',
data() {
return { };
},
computed:{
...mapGetters([
'show'
])
} }
</script>

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。

当然我们也可以给getters里面的状态show换一个名字,比如叫dialogShow,那么子组件就需要改成如下:

<template>
<el-dialog :visible.sync="dialogShow" title="提示">
<span>这是一段弹框信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="$store.dispatch('set_dialog_state',false)">取 消</el-button>
<el-button type="primary" @click="$store.dispatch('set_dialog_state',false)">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name:'children',
data() {
return { };
},
computed:{
...mapGetters({
dialogShow:'show'
})
} }
</script>

mapState

上面我们通过$store.getters.show拿到状态值,我们也可以通过$store.state.app.show拿到值,那么怎样使用mapState呢?

子组件写法:

<template>
<el-dialog :visible.sync="show" title="提示">
<span>这是一段弹框信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="$store.dispatch('set_dialog_state',false)">取 消</el-button>
<el-button type="primary" @click="$store.dispatch('set_dialog_state',false)">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
import { mapState } from 'vuex'
export default {
name:'children',
data() {
return { };
},
computed:{
...mapState({
show:state => state.app.show
})
} }
</script>

上面使用的是箭头函数,也可以使用常规函数,如下:

<template>
<el-dialog :visible.sync="showState" title="提示">
<span>这是一段弹框信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="$store.dispatch('set_dialog_state',false)">取 消</el-button>
<el-button type="primary" @click="$store.dispatch('set_dialog_state',false)">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
import { mapState } from 'vuex'
export default {
name:'children',
data() {
return { };
},
computed:{
...mapState({
show:state => state.app.show, //方式一 箭头函数
showState(state){ //方式二 常规函数
return state.app.show
}
})
} }
</script>

mapMutations

你可以在组件中使用 $store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用

父组件代码如下:

<template>
<div>
<a href="javascript:;" @click="SET_DIALOG_STATE(true)">点击</a>
<common-dialog></common-dialog>
弹框是否显示:{{$store.state.app.show}}
</div>
</template> <script>
import { mapMutations } from 'vuex'
import commondialog from '@/components/dialog'
export default {
name: 'parent',
components:{
'common-dialog':commondialog
},
data () {
return { }
}, methods:{
...mapMutations(['SET_DIALOG_STATE'])
}
}
</script>

给方法名换个名字:

<template>
<div>
<a href="javascript:;" @click="changeState(true)">点击</a>
<common-dialog></common-dialog>
弹框是否显示:{{$store.state.app.show}}
</div>
</template> <script>
import { mapMutations } from 'vuex'
import commondialog from '@/components/dialog'
export default {
name: 'parent',
components:{
'common-dialog':commondialog
},
data () {
return { }
}, methods:{
...mapMutations({
changeState:'SET_DIALOG_STATE' //改变名字
})
}
}
</script>

mapActions

你在组件中使用$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用

父组件代码:

<template>
<div>
<a href="javascript:;" @click="set_dialog_state(true)">点击</a>
<common-dialog></common-dialog>
弹框是否显示:{{$store.state.app.show}}
</div>
</template> <script>
import { mapActions } from 'vuex'
import commondialog from '@/components/dialog'
export default {
name: 'parent',
components:{
'common-dialog':commondialog
},
data () {
return { }
}, methods:{
...mapActions (['set_dialog_state'])
}
}
</script>

当然也可以换方法名,这儿就不贴代码了。

参考地址

vuex最简单、最直白、最全的入门文档的更多相关文章

  1. [转] vuex最简单、最直白、最全的入门文档

    前言 我们经常用element-ui做后台管理系统,经常会遇到父组件给子组件传递数据,下面一个简单的例子,点击按钮,把弹框显示变量数据通过子组件的props属性传递,子组件通过$emit事件监听把数据 ...

  2. vuex最简单、最详细的入门文档

    如果你在使用 vue.js , 那么我想你可能会对 vue 组件之间的通信感到崩溃 . 我在使用基于 vue.js 2.0 的UI框架 ElementUI 开发网站的时候 , 就遇到了这种问题 : 一 ...

  3. vuex入门文档

    如果你在使用 vue.js , 那么我想你可能会对 vue 组件之间的通信感到崩溃 . 我在使用基于 vue.js 2.0 的UI框架 ElementUI 开发网站的时候 , 就遇到了这种问题 : 一 ...

  4. IDEA / WebStorm / PhpStorm 添加jQuery自动提示,自动补全,提醒文档

    应该是JetBrains系列IDE通用的方法,网上其他一些方法有的过时了,有的不全 默认情况下没有JQuery补全,按照以下方法添加 1. 打开Settings,Languages & Fra ...

  5. MongoDB入门---文档查询之$type操作符&limit方法&skip方法&简单排序(sort)操作

    上一篇文章呢,已经分享过了一部分查询操作了,这篇文章呢?就来继续分享哈.接下来呢我们直接看MongoDB中的$type操作符哈.它呢是基于BSON类型来检索集合中匹配的数据类型,并且返回结果,在Mon ...

  6. FullPage.js全屏插件文档及使用方法

    简介 fullPage.js是一个基于jQuery的全屏滚动插件,它能够很方便.很轻松的制作出全屏网站 下载地址 下载地址 相关示例:基于fullpage.js实现的360全屏滑动效果 支持功能 支持 ...

  7. 最简单,最实用的数据库CHM文档生成工具——DBCHM

    DBCHM支持SqlServer/MySql/Oracle/PostgreSQL等数据库的表列批注维护管理. DBCHM有以下几个功能 表,列的批注可以编辑保存到数据库. 表,列的批注支持通过pdm文 ...

  8. hadoop2.2.0_hbase0.96_zookeeper3.4.5全分布式安装文档下载

    本文档主要内容有: 1.hadoop 2.2.0 集群安装与部署 2.HBase 0.96 集群安装与部署 3.Zookeeper 3.4.5集群安装部署 备注:安装文档可能有所遗漏,后续将持续更新. ...

  9. Java全系列帮助文档下载

    JDK(Java Development Kit,Java开发包,Java开发工具)是一个写Java的applet和应用程序的程序开发环境.它由一个处于操作系统层之上的运行环境还有开发者编译,调试和运 ...

随机推荐

  1. 使用Kubernetes演示金丝雀发布

    使用Kubernetes演示金丝雀发布 为了更直观的看出金丝雀发布的效果,我们这里使用了Prometheus监控来观察这个过程.不知道怎么使用Prometheus的同学请看使用Prometheus监控 ...

  2. NumPy 超详细教程(2):数据类型

    系列文章地址 NumPy 最详细教程(1):NumPy 数组 NumPy 超详细教程(2):数据类型 NumPy 超详细教程(3):ndarray 的内部机理及高级迭代 文章目录 NumPy 数据类型 ...

  3. spring boot整合mybatis方式一

    方式一: 导入maven依赖: <!--web依赖配置--> <dependency> <groupId>org.springframework.boot</ ...

  4. android 自定义权限管理

    在Android6.0后有些权限就需要进行询问,虽然可以将targetSdkVersion设置成小于等于23,但是这样可能有些东西无法使用,所以要进行权限的管理. 实现逻辑:打开页面就询问权限,如果没 ...

  5. Error:Execution failed for task ':app:processDebugManifest'.

    Attribute meta-data#android.support.VERSION@value value=(26.1.0) from AndroidManifest.xml:28:13-35 i ...

  6. 安卓开发笔记(十二):SQLite数据库储存(上)

    SQLite数据库存储(上) 创建数据库 Android专门提供了一个 SQLiteOpenHelper帮助类对数据库进行创建和升级 SQLiteOpenHelper需要创建一个自己的帮助类去继承它并 ...

  7. Alpha阶段Scrum Meeting合集(江山代有才人秃队)

    Day URL 第一天 第1篇Scrum冲刺博客 第二天 第2篇Scrum冲刺博客 第三天 第3篇Scrum冲刺博客 第四天 第4篇Scrum冲刺博客 第五天 第5篇Scrum冲刺博客 第六天 第6篇 ...

  8. 浅论各种调试接口(SWD、JTAG、Jlink、Ulink、STlink)的区别

    JTAG协议 JTAG(Joint Test Action Group,联合测试行动小组)是一种国际标准测试协议(IEEE 1149.1兼容),主要用于芯片内部测试.现在多数的高级器件都支持JTAG协 ...

  9. 网络协议 20 - RPC 协议(上)- 基于XML的SOAP协议

    [前五篇]系列文章传送门: 网络协议 15 - P2P 协议:小种子大学问 网络协议 16 - DNS 协议:网络世界的地址簿 网络协议 17 - HTTPDNS:私人定制的 DNS 服务 网络协议 ...

  10. .NET Core微服务之基于Ocelot+IdentityServer实现统一验证与授权

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.案例结构总览 这里,假设我们有两个客户端(一个Web网站,一个移动App),他们要使用系统,需要通过API网关(这里API网关始终作为 ...