本篇文章从多个角度论述Vue中的数据传值,目前主要介绍传统的组件传值方式及目前开发使用较多的Vuex的传值方式
参考视频:Vuex从入门到实战 黑马程序员の刘龙宾
# 一、传统传值方式
适用于较为简单的情景模式下,逻辑较为简单,数据较少的情况下适用传统的传值方式
# 1.1 父传子
原理:采用v-bind
属性绑定的原理来传值
第一步:
父组件在嵌入子组件的时候绑定自定义属性,并将需要传递的值传进去
// 父组件
<template>
<div>
<my-child :msg='"父传子的信息"'></my-child>
</div>
</template>
2
3
4
5
6
第二步:
子组件在Vue实例下的props属性下声明传过来的值才能使用
// 子组件
<script>
export default {
...
props: ['msg']
}
</script>
2
3
4
5
6
7
第三步:
声明之后即可直接使用了
// 子组件
<template>
<div>
{{ msg }} /** 这里展示的就是传过来的 父传子的信息 */
</div>
</template>
methods:{
foo(){
//这里输出的也是 父传子的信息!
console.log(this.msg)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
# 1.2 子传父
原理:采用v-on
事件绑定的原理来传值
第一步:
子组件中先绑定一个触发事件,并且在事件触发函数中发布数据
// 子组件
<template>
<div>
/** 在这里绑定一个触发事件,点击后执行指定函数 */
<btn @click='btnHandler1'>按钮</btn>
</div>
</template>
<script>
export default {
...
methods:{
btnHandler1(){
// 发布了一个方法 transmit 他的第一个参数是吻
this.$emit('transmit':'子传父的信息')
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
第二步:
父组件直接通过方法的形参取到传过来的信息
// 父组件
<template>
<div>
/** 在这里绑定一个触发事件,事件名称就是子组件中发布的 */
<btn @transmit='showMsg'>按钮</btn>
</div>
</template>
<script>
export default {
...
data(){
return {
childMsg: ''
}
},
methods:{
showMsg(msg){
console.log(msg) // 输出 子传父的信息
this.childMsg = msg
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 1.3 兄弟间传值
原理:采用事件的发布订阅方式传值
$emit 发布事件,发送数据
$on 订阅事件,接收数据
第一步:
兄弟组件A直接通过函数触发发布数据
// 兄弟组件A
<script>
export default {
...
methods:{
bortherA(){
this.$emit('msg':'嘿!老二')
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
第二步:
兄弟组件B接收数据
// 兄弟组件B
<script>
export default {
...
methods:{
bortherB(){
this.on('msg',msg=>{
consolg.log(msg)
this.msg = msg
}
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
# 二、Vuex传值方式
Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。
一般情况下,只有组件之间共享的数据,才有必要存储到 vuex 中;对于组件中的私有数据,依旧存储在组件 自身的 data 中即可。
# 1.1 使用Vuex统一管理状态的好处
- 能够在 vuex 中集中管理共享的数据,易于开发和后期维护
- 能够高效地实现组件之间的数据共享,提高开发效率
- 存储在 vuex 中的数据都是响应式的,能够实时保持数据与页面的同步
# 1.2 Vuex的基本使用
- 安装依赖:
npm i vuex --save
- 导入包:
import Vuex from 'vuex'
Vue.use(Vuex)
2
3
- 创建store对象
const store = new Vuex.Store({
// state 中存放的就是全局共享数据
state: {
count: 0
}
})
2
3
4
5
6
- 将store对象挂载到vue实例中
new Vue({
render:
})
2
3
建议项目结构按vue-cli
中的来,更规范直观
# 1.3 Vuex的核心概念
Vuex的核心有有以下4点:
State 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 State 中进行存储。
Mutation 用于变更 Store中 的数据。
Action 用于处理异步任务。
Getter 用于对 Store 中的数据进行加工处理形成新的数据。
# State
// 创建store数据源,提供唯一公共数据
const store = new Vuex.Store({
state: { count: 0 }
})
2
3
4
组件访问 State 中数据的第一种方式:
this.$store.state.全局数据名称
组件访问 State 中数据的第二种方式:
// 1. 从 vuex 中按需导入 mapState 函数
import { mapState } from 'vuex'
// 2. 将全局数据,映射为当前组件的计算属性
computed: {
...mapState(['count'])
}
// 3. 这样就能通过{{ count }}来使用
2
3
4
5
6
7
8
9
# Mutation
① 只能通过 mutation 变更 Store 数据,不可以直接操作 Store 中的数据。
② 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化。
Mutation的定义:
// 定义Mutation
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
addN(state, step) {
// 变更状态
state.count += step
}
}
})
2
3
4
5
6
7
8
9
10
11
12
第一种触发方式:
// 触发mutation
methods: {
handle2() {
// 在调用 commit 函数,
// 触发 mutations 时携带参数
this.$store.commit('addN', 3)
}
}
2
3
4
5
6
7
8
第二种触发方式:
// 1. 从 vuex 中按需导入 mapMutations 函数
import { mapMutations } from 'vuex'
// 2. 将指定的 mutations 函数,映射为当前组件的 methods 函数
methods: {
...mapMutations(['add', 'addN'])
}
// 3. 跟使用正常 methods 函数一样去使用映射的方法
2
3
4
5
6
7
8
9
# Action
如果通过异步操作变更数据,必须通过 Action,而不能使用 Mutation,但是在 Action 中还是要通过触发 Mutation 的方式间接变更数据。
Action 的定义:
// 定义 Action
const store = new Vuex.Store({
// ...省略其他代码
mutations: {
add(state) {
state.count++
}
},
actions: {
// 第二个形参之后就是传递过来的参数
addAsync(context) {
setTimeout(() => {
context.commit('add')
}, 1000)
}
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
第一种触发方式:
// 触发 Action
methods: {
handle() {
// 触发 actions 的第一种方式
this.$store.dispatch('addAsync')
// this.$store.dispatch('addAsync', 3, 5) 这样可以传递2个参数
}
}
2
3
4
5
6
7
8
第二种触发方式:
// 1. 从 vuex 中按需导入 mapActions 函数
import { mapActions } from 'vuex
// 2. 将指定的 actions 函数,映射为当前组件的 methods 函数
methods: {
...mapActions(['addASync', 'addNASync'])
}
// 3. 跟使用正常 methods 函数一样去使用映射的方法
2
3
4
5
6
7
8
9
# Getter
① Getter 可以对 Store 中已有的数据加工处理之后形成新的数据,类似 Vue 的计算属性。
② Store 中数据发生变化,Getter 的数据也会跟着变化。
Getter 的定义:
// 定义 Getter
const store = new Vuex.Store({
state: {
count: 0
},
getters: {
showNum: state => {
return '当前最新的数量是【'+ state.count +'】'
}
}
})
2
3
4
5
6
7
8
9
10
11
使用 getters 的第一种方式:
this.$store.getters.名称
使用 getters 的第二种方式:
// 1. 从 vuex 中按需导入 mapGetters 函数
import { mapGetters } from 'vuex'
// 2. 将全局数据,映射为当前组件的计算属性
computed: {
...mapGetters(['showNum'])
}
// 3. 这样就能通过正常computed属性来使用
2
3
4
5
6
7
8
9