VUE - 组件间的传值问题

在vue项目中,不可避免的会在不同组件之间进行传值,不同需求下有不同的传值方式。比如,兄弟组件传值,父子组件传值,路由传值,ref方式传值等,都是各有各的使用场景且有可能不经常使用导致容易忘记,记录一下方便自己以后更好运用自如。

一. 使用props属性传值

1.父子组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template lang="html">
<div class="">
<h1>首页</h1>
<home1 :msg='str'></home1>
</div>
</template>

<script>
import home1 from './home1'

export default {
data(){
return {
str:'我是在父组件的数据通过props传递给子组件'
}
},
components: {
home1
}
}
</script>
<style>
</style>

2.子组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div id="">
<h2>{{msg}}</h2>
</div>
</template>
<script>
export default {
props: ['msg'],
name: "",
data: () => ({

})
}
</script>
<style scoped>
</style>

小结:通过以上代码,就可以明显看出,在子组件声明props属性以及在父元素中子组件进行赋值操作,即可实现父子组件传值。

二. 使用function函数传值

在父组件中,传值的是函数名,而不是函数的执行结果
在子组件中触发函数时:通过this.函数名取得父传子的函数,并传参(即是子向父传递的数据)执行。这样父可以拿到子的数据。

父组件代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<template lang="html">
<div class="">
<h1>首页</h1>
<home1 :fn='parent'></home1>
<!-- 来展示从子组件传来的值 -->
<h2>{{ num }}</h2>
</div>
</template>

<script>
import home1 from './home1'

export default {
data(){
return {
// 来保存从子组件传来的值
num:''
}
},
components: {
home1
},
methods: {
parent(data) {
// 如果子组件触发函数会调转到父组件来执行该函数,即把传递进来的参数赋值给vue实例中的data数据中的num变量中
this.num = data;
}
}
}
</script>


<style media="screen">

</style>

子组件代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div id="">
<h2>hello</h2>
</div>
</template>
<script>
export default {
props: ['fn'],
name: "",
data: () => ({
str:'我是子组件里面的数据要通过props传递给父组件'
}),
mounted() {
//do something after mounting vue instance
// 在子组件渲染完毕时,触发从父组件传递过来的函数
this.fn(this.str)
}
}
</script>
<style scoped>
</style>

三. 使用路由传值

路由传值:主要分为在同一路由下传值(同一组件)和不同路由跳转传值(不同组件)

路由传值有两种情况:
通过this.$route.params.? 来接收路由参数(这一般存放小数据),而this.$route.query.?来接收存放在路由的数据,一般是存放大数据
当然如果是同一路由下传参,要配置路由如格式:{name:’home’,path:’/home/:id’,component:Home},…

1.同一路由下传值实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<template lang="html">
<div class="">
<h1>首页</h1>
<!-- 点击路由链接向当前路由传递参数 -->
<!-- 1.声明式传参 -->
<router-link :to="{ name: 'home', params: { id: 'hello'}}">1</router-link>
<!-- 2.编程式参参 -->
<p @click='fn1'>2</p>
<!-- 点击按钮获取当前url路径的参数 -->
<button @click="fn" type="button" name="button">获取动态路由参数</button>
<h4>我是动态数据:{{num}}</h4>
<!-- 通过query中值获得数据 -->
<h5>{{num1.name}}</h5>
<h5>{{num1.age}}</h5>
</div>
</template>

<script>
// import home1 from './home1'

export default {
data(){
return {
num:'',
// 在路由的query对象存放大量数据方便存取
num1:''
}
},
methods: {
// 点击按钮获取当前url路径的参数的函数
fn() {
this.num = this.$route.params.id;
this.num1 = this.$route.query;
},
// 点击’2‘后,进行编程式路由跳转并传递参数
fn1() {
this.$router.push(
{name:'home',params:{id:'world'},query:{
name:'zhangsna',
age:23
}}
)
}
},
components: {
// home1
}
}
</script>


<style media="screen">

</style>

2.不同路由下实现传值:
跳转前路由组件代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template lang="html">
<div class="">
<h1 @click='fn'>首页</h1>

</div>
</template>

<script>
export default {
data(){
return {
num:''
}
},
methods: {
fn(){
this.$router.push({
name:'car',
query:{
name:'xioahang',
age:23
}
})
}
}
}
</script>

<style media="screen">
</style>

调转后路由组件代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template lang="html">
<div class="car">
<h1>我的购物车</h1>
<h2>{{ msg.name }}</h2>
<h2>{{ msg.age }}</h2>
</div>

</template>

<script>
export default {
data() {
return {
msg:{}
}
},
created() {
//do something after creating vue instance
this.msg = this.$route.query
}
}
</script>


<style media="screen">

</style>

四. 使用Ref传值

感觉这个比较简单吧
父组件代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<template lang="html">
<div class="">
<h1>首页</h1>
<!-- 在子组件书写ref属性以及值 -->
<home1 ref='mark'></home1>
<!-- 在父组件中,测试从子组件拿到的值 -->
<h2>通过ref来拿到子组件的数据传递给 {{num}}</h2>
</div>
</template>

<script>
// 导入子组件
import home1 from './home1'

export default {
data(){
return {
num:''
}
},
methods: {

},
components: {
home1
},
mounted() {
// 向子组件拿到的数据赋值给父vue实例中的变量
this.num = this.$refs.mark.str;
// 在父组件中,测试从子组件拿到的函数
this.$refs.mark.fn();
}

}
</script>

<style media="screen">
</style>

子组件代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div id="">
<h2>hello</h2>
</div>
</template>
<script>
export default {
name: "",
data: () => ({
str:'我是子组件里面的数据,父组件通过ref来向子组件拿值'
}),
methods: {
fn() {
console.log('我是子组件的方法,父组件可通过ref来拿到我这里的值!');
}
}
}
</script>
<style scoped>
</style>

五. 总结

在vue中传值的方法有很多种,在项目过程中要特别注意,什么方法适合什么场景,以及每种方法的使用限制。

六. 哈哈vuex了解一下

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

1.一个表示“单向数据流”理念的极简示意:

只能适用于逻辑比较简单的场景

小结:vue的MVC思想也应该差不多是这个意思吧,模型(model)-视图(view)-控制器(controller)
控制C确保把模型M与视图C同步更新

2.当遇到复杂场景时,就必须使用另外的方式:

  • state:存放状态,即数据
  • mutations:存放改变state数据的同步方法
  • actions:存放改变state数据的异步方法
  • getters:相当于计算属性,避免了直接向state数据取值

创建store实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

export default new Vuex.Store({
state:{
// 共享状态
num:0
},
mutations:{
addNum(state,step){
state.num += step;
},
reduceNum(state,step){
state.num -= step;
}
},
actions:{

},
getters:{
getNum(state){
return state.num
}
}
})

在任意组件中,取共享状态中数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<template lang="html">
<div class="">
<h1>首页</h1>
<p>{{getNum}}</p>
<button @click='fn' type="button" name="button">点我增加共享数据</button>
<button @click='fn1' type="button" name="button">点我减少共享数据</button>
</div>
</template>

<script>

export default {
data(){
return {
num:''
}
},
methods: {
fn(){
this.$store.commit('addNum',1)
},
fn1(){
this.$store.commit('reduceNum',1)
}
},
components: {

},
computed:{
getNum(){
return this.$store.state.num;
}
},
created() {
//do something after creating vue instance

}

}
</script>

<style media="screen">
</style>

厉害啦,我的Vue。有了vuex感觉方便多了。