前言
日常开发中经常会遇到组件之间传递参数问题,整理了几种常见的传参方式,方便日后复习梳理.
常见组件传参的三种方式:
1.父组件向子组件传参
2.子组件向父组件传参
3.子组件向非父组件传参
1.父组件向子组件传参
自定义组件:
<template>
<view class="my-componet-box">
<view class="view1">{{title}}</view>
<view class="view2">{{subTitle}}</view>
</view>
</template>
<script>
export default {
name:"my-componet",
data() {
return {
title:'主标题',
subTitle:"副标题"
};
},
// 自定义组件中设置属性方式一,数组方式添加属性名
// props:['title','subTitle']
// 自定义组件中设置属性方式二,对象式添加属性默认值等详情信息
props:{
title: {
type: String,
default: "主标题",
required: false
},
subTitle:{
type: String,
default: "副标题",
required: false,
}
}
}
</script>
<style lang="scss">
.my-componet-box{
width: 400rpx;
height: 200rpx;
background-color: green;
.view1{
font-size: 60rpx;
}
}
</style>
首页index.vue
引入自定义组件my-componet
,页面内容如下:
<template>
<view class="content">
<view>我是首页</view>
<!-- 不设置组件title和subTitle属性值则显示组件默认值 -->
<!-- <my-componet ></my-componet> -->
<!-- 设置组件title和subTitle属性值则显示设置的信息-->
<my-componet title="首页添加主标题" subTitle="首页添加副标题"></my-componet>
</view>
</template>
<script>
export default {
data() {
return {
}
},
onLoad() {
},
methods: {
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
首页中通过修改my-componet
组件的title
和subtitle
属性值就可以传递到组件中.组件中显示首页设置的属性信息.展示效果如下:
不设置组件title和subTitle属性值则显示组件默认值:
设置组件title和subTitle属性值则显示设置的信息:
2.子组件向父组件传参
自定义子组件my-componet-2:
<template>
<view>
文本输入框:<input placeholder="请输入内容..." @input="sendData" :value="content"/>
</view>
<view>子组件属性值content:{{content}}</view>
</template>
<script>
export default {
name:"my-componet-2",
data() {
return {
content:"子组件属性值"
};
},
methods:{
sendData(e){
this.$emit('myEvent',e.detail.value)
}
},
props:{
content:{
type:String,
default: "子组件默认内容",
}
}
}
</script>
<style lang="scss">
</style> -->
home页面引用子组件my-componet-2
:
<template>
<view>
<vie>home页面</vie>
<div>父子组件显示子组件属性值content:{{content}}</div>
<my-componet-2 :content="content" @myEvent="showData"></my-componet-2>
</view>
</template>
<script>
export default {
data() {
return {
content:''
};
},
methods:{
showData(e){
this.content=e
}
}
}
</script>
<style lang="scss">
</style>
实现效果:
文本框中输入8,子组件显示数据之后,父组件通过自定义事件进行获取数据,另外子组件向父组件传递值时支持对象或数组格式.
子组件数据变化之后需要使用this.$emit进行注册事件,通过事件进行传值;父组件在子组件中使用自定义事件进行获取数据.
3.子组件向非父组件传参
上面案例中my-componet-2
在home.vue
中引用,如何保证在index.vue
中进行传值?可以使用全局事件进行传参.my-componet-2
中注册全局事件,index.vue
中进行监听接口.具体代码如下:
my-componet-2:
<template>
<view>
文本输入框:<input placeholder="请输入内容..." @input="sendData" :value="content"/>
</view>
<view>子组件属性值content:{{content}}</view>
</template>
<script>
export default {
name:"my-componet-2",
data() {
return {
content:"子组件属性值"
};
},
methods:{
sendData(e){
// 注册全局事件
uni.$emit("gloableEvent",e.detail.value)
}
},
props:{
content:{
type:String,
default: "子组件默认内容",
}
}
}
</script>
<style lang="scss">
</style>
index.vue:
<template>
<view class="content">
<view>我是首页</view>
<!-- 设置组件title和subTitle属性值则显示设置的信息-->
<my-componet title="首页添加主标题" subTitle="首页添加副标题"></my-componet>
<text class="title">{{title}}</text>
</view> -->
<view>
获取自定义组件my-componet-2输入的文本内容content:{{content}}
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'Hello',
content:''
}
},
onLoad() {
// 监听注册的全局事件
uni.$on("gloableEvent",function(data){
console.log("首页监听到的data:"+data);
})
},
onUnload(){
uni.$off("gloableEvent")
},
methods: {
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
home.vue
中输入25,index.vue页面中就会打印输入的内容25,说明监听生效.展示效果如下:
注意:onload页面初始化时监听,onupload页面销毁时销毁事件.
更多页面通讯方法可以参考官方链接:
https://uniapp.dcloud.net.cn/tutorial/page.html#off
以上是关于组件进行参数传递整理的几种方式,如果感觉有所帮助欢迎评论区点赞留言!