学无先后,达者为师

网站首页 编程语言 正文

UNI-APP页面通讯、组件子向父、父向子传递数据

作者:沧海龙腾LV 更新时间: 2024-02-29 编程语言

方法一(父向子传递数据):

父页面

<!--页面组件-->
<params v-if="tabs.length-TabCur>3" :tabcur='TabCur'></params>

子页面接收

props: {
			tabcur: {
				type: Number,
				default: ''
			}
		},

方法二:

通过全局变量(Vue原型挂载、或者App.vue golabledata)或者缓存uni.setStorageSync();实现

方法三:

uni.$emit(eventName,OBJECT)

触发全局的自定事件。附加参数都会传给监听器回调。

属性 类型 描述
eventName String 事件名
OBJECT Object 触发事件携带的附加参数

代码示例

uni.$emit('update',{msg:'页面更新'})

uni.$on(eventName,callback)

监听全局的自定义事件。事件可以由 uni.$emit 触发,回调函数会接收所有传入事件触发函数的额外参数。

属性 类型 描述
eventName String 事件名
callback Function 事件的回调函数

代码示例

uni.$on('update',function(data){
        console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
    })

uni.$once(eventName,callback)

监听全局的自定义事件。事件可以由 uni.$emit 触发,但是只触发一次,在第一次触发之后移除监听器。

属性 类型 描述
eventName String 事件名
callback Function 事件的回调函数

代码示例

uni.$once('update',function(data){
        console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
    })

uni.$off([eventName, callback])

移除全局自定义事件监听器。

属性 类型 描述
eventName Array<String> 事件名
callback Function 事件的回调函数

Tips

  • 如果没有提供参数,则移除所有的事件监听器;
  • 如果只提供了事件,则移除该事件所有的监听器;
  • 如果同时提供了事件与回调,则只移除这个回调的监听器;
  • 提供的回调必须跟$on的回调为同一个才能移除这个回调的监听器;

代码示例

$emit$on$off常用于跨页面、跨组件通讯,这里为了方便演示放在同一个页面

<template>
        <view class="content">
            <view class="data">
                <text>{{val}}</text>
            </view>
            <button type="primary" @click="comunicationOff">结束监听</button>
        </view>
    </template>

    <script>
        export default {
            data() {
                return {
                    val: 0
                }
            },
            onLoad() {
                setInterval(()=>{
                    uni.$emit('add', {
                        data: 2
                    })
                },1000)
                uni.$on('add', this.add)
            },
            methods: {
                comunicationOff() {
                    uni.$off('add', this.add)
                },
                add(e) {
                    this.val += e.data
                }
            }
        }
    </script>

    <style>
        .content {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
        }

        .data {
            text-align: center;
            line-height: 40px;
            margin-top: 40px;
        }

        button {
            width: 200px;
            margin: 20px 0;
        }
    </style>

注意事项

  • uni.$emit、 uni.$on 、 uni.$once 、uni.$off 触发的事件都是 App 全局级别的,跨任意组件,页面,nvue,vue 等
  • 使用时,注意及时销毁事件监听,比如,页面 onLoad 里边 uni.$on 注册监听,onUnload 里边 uni.$off 移除,或者一次性的事件,直接使用 uni.$once 监听

示例代码:

父页面

<template>
	<view class="whole_page">
		<!--导航栏-->
		<cu-custom bgColor="bg-blue" :isBack="true"><block slot="content">{{devInfo.adapterCode}}</block><block slot="right"><text class="mright_pt"></text></block></cu-custom>
		<!--tab栏-->
		<scroll-view scroll-x class="bg-white nav text-center" scroll-with-animation :scroll-left="scrollLeft">
			<view class="cu-item" :class="index==TabCur?'text-blue cur':''" v-for="(item,index) in tabs" :key="index" @tap="tabSelect" :data-id="index">
				{{item}}
			</view>
		</scroll-view>
		<!--页面组件-->
		<params v-if="tabs.length-TabCur>3" :tabcur='TabCur'></params>
		<charts v-if="tabs.length-TabCur===3"></charts>
		<configure v-if="tabs.length-TabCur===2"></configure>
		<basic-info v-if="tabs.length-TabCur===1"></basic-info>
	</view>
</template>

<script>
	import params from './params/params.vue'
	import charts from './charts/charts.vue'
	import configure from './configure/configure.vue'
	import basicInfo from './basicinfo/basicinfo.vue'
	
	export default {
		components:{
			params,
			charts,
			configure,
			basicInfo
		},
		data() {
			return {
				cmuid: '',
				devInfo: {},
				tabs: ['参数1','参数2','参数3','信息'],
				//tab栏
				TabCur: 0,
				scrollLeft: 0,
				devRtmDatasTimer: null,
				isPageShow: true,
				rtmData: {},
				tagParams: {}
			}
		},
		onLoad(option) {
			//获取传递的参数
			this.devInfo = JSON.parse(decodeURIComponent(option.item));
			//获取cmuid
			this.cmuid = uni.getStorageSync('cmuid');
			//获取tag和参数
			this.getTagAndParams();
			//获取参数实时数据
			this.getDeviceRtmDatas();
			//定时获取实时数据
			this.setDeviceRtmDatasTimer();
		},
		onShow() {
			this.isPageShow = true;
		},
		onHide() {
			this.isPageShow = false;
		},
		onUnload(){
			//清除定时器
			clearInterval(this.devRtmDatasTimer);
			//移除全局自定义事件监听器
			//uni.$off('paramsUpdate', null);
		},
		methods: {
			/*tab栏*/
			tabSelect(e) {
				this.TabCur = e.currentTarget.dataset.id;
				this.scrollLeft = (e.currentTarget.dataset.id - 1) * 80;
				//触发事件
				this.triggerEvent();
			},
			/*获取tag和参数*/
			getTagAndParams(){
				let tagParam = {
					'cmuid': this.cmuid,
					'typeId': this.devInfo.type
				}
				this.api.tagAndParams(tagParam).then(res=>{
					if(res.data.msgCode && res.data.msgCode == "0"){
						//处理tag和参数数据
						this.handleTagsAndParamsData(res.data.data);
					}else{
						this.api.showComToast(res.data.message);
					}
				})
			},
			/*处理tag和参数数据*/
			handleTagsAndParamsData(data){
				//处理tag数据,显示tag标签
				if(data.hasOwnProperty('paramTagList') && data.paramTagList){
					this.tabs = [...data.paramTagList, ...this.tabs];
				}
				//存储数据
				if(data){
					this.tagParams = data;
				}
			},
			/*获取参数实时数据*/
			getDeviceRtmDatas(){
				let rtmDatas = {
					'cmuid': this.cmuid,
					'adaptorCode': this.devInfo.adapterCode
				}
				this.api.deviceRtmDatas(rtmDatas).then(res=>{
					if(res.data.msgCode && res.data.msgCode == "0"){
						//处理参数实时数据
						this.handleDeviceRtmDatas(res.data.data)
					}else{
						this.api.showComToast(res.data.message);
					}
				})
			},
			/*处理参数实时数据*/
			handleDeviceRtmDatas(data){
				//在线离线
				if(data.hasOwnProperty('enabled') && data.enabled == '1'){
					this.devInfo.runStatus = 1;
					if(data.hasOwnProperty('C485on') && data.C485on == '1'){
						this.devInfo.C485on = 1;
					}else{
						this.devInfo.C485on = 0;
					}
				}else{
					this.devInfo.runStatus = 0;
					this.devInfo.C485on = 0;
				}
				//存储数据
				if(data){
					this.rtmData = data;
				}
				//触发事件
				this.triggerEvent();
			},
			/*定时获取实时数据*/
			setDeviceRtmDatasTimer(){
				this.devRtmDatasTimer = setInterval(()=>{
					if(!this.isPageShow){
						return;
					}
					this.getDeviceRtmDatas();
				}, 3*1000);
			},
			/*触发全局事件*/
			triggerEvent(){
				uni.$emit("paramsUpdate", this.$data);
			}
		}
	}
</script>

<style lang="scss">

</style>

params组件

<template>
	<view class="content">
		<!--监控参数组件-->
		<scroll-view scroll-y class="scroll_pt">
			<view class="cnt_pt">
				<view class="title_pt">
					<view class="t_flag"></view>
					<view class="t_text">数据信息</view>
				</view>
				<view v-for="(item,index) in dataList" :key="index">
					<view class="item_pt">
						<view class="left_pt">{{item.paramName}}</view>
						<view class="right_pt">{{item.cvalue}}{{item.unit}}</view>
					</view>
				</view>
			</view>
			<view class="cnt_pt">
				<view class="title_pt">
					<view class="t_flag"></view>
					<view class="t_text">指令控制</view>
				</view>
				<view class="btns_pt">
					<view v-for="(item,index) in btnsList" :key="index">
						<view @click="sendCmd(item)" class="btns" :style="[{'background-color':item.ccolor}]">{{item.paramName}}</view>
					</view>
				</view>
			</view>
		</scroll-view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				datas: null,
				colors: ['#007aff', '#ff0000', '#00ff00', '#ffff00', '#00ffff', '#ff00ff']
			}
		},
		props: {
			tabcur: {
				type: Number,
				default: ''
			}
		},
		computed: {
			//数据列表
			dataList(){
				let res = [];
				if(this.datas){
					let currTab = this.datas.tabs[this.datas.TabCur];
					let paramlist = this.datas.tagParams.paramsList;
					for (let i = 0; i < paramlist.length; i++) {
						let paramsitem = paramlist[i];
						if(paramsitem.paramTag == '' && currTab == '参数1'){
							let v = this.getRunParamValue(paramsitem);
							paramsitem.cvalue = v;
							res.push(paramsitem);
						}
						if(paramsitem.paramTag != '' && paramsitem.paramTag.indexOf(currTab) >= 0){
							let v = this.getRunParamValue(paramsitem);
							paramsitem.cvalue = v;
							res.push(paramsitem);
						}
					}
				}
				return res;
			},
			//btn列表
			btnsList(){
				let res = [];
				if(this.datas){
					let colorindex = 0;
					let currTab = this.datas.tabs[this.datas.TabCur];
					let btnlist = this.datas.tagParams.buttonList;
					for (let i = 0; i < btnlist.length; i++) {
						let btnitem = btnlist[i];
						if(btnitem.paramTag == '' && currTab == '参数1'){
							btnitem.ccolor = this.colors[colorindex++ % this.colors.length];
							res.push(btnitem);
						}
						if(btnitem.paramTag != '' && btnitem.paramTag.indexOf(currTab) >= 0){
							btnitem.ccolor = this.colors[colorindex++ % this.colors.length];
							res.push(btnitem);
						}
					}
				}
				return res;
			}
		},
		mounted() {
			//获取传递的参数
			console.log(this.tabcur)
			//监听全局事件
			this.setOnUpdateListener();
		},
		beforeDestroy() {
			this.setOffUpdateListener();
		},
		methods: {
			getRunParamValue(paramsitem){
				let runData = this.datas.rtmData;
				let cvalue = '';
				//判断双地址,单地址
				if(paramsitem.paramKey.indexOf(':') >= 0){//双地址
					let idstr = paramsitem.paramKey;//地址列表
					let ftitle = paramsitem.operationRule;//操作规则
					let addrs = idstr.split(":");
					if(addrs.length == 2){
						let v0 = runData["C"+addrs[0]];
						let v1 = runData["C"+addrs[1]];
						if(v0 && v1){
							let intV0 = parseInt(v0);
							let intV1 = parseInt(v1);
							if(paramsitem.floatPoint && paramsitem.floatPoint == 1){
								//双字节浮点数
								let intr = intV0 * 65536 + intV1;
								//符号位
								let sign = (intr & 0x80000000) ? -1 : 1;
								//指数位
								let exponent = ((intr >> 23) & 0xff) - 127;
								//尾数位
								let mantissa = 1 + ((intr & 0x7fffff) / 0x7fffff);
								//保留小数
								let desv = (sign * mantissa * Math.pow(2, exponent)) + '';
								if(desv.indexOf(".") == -1){
									cvalue = desv;
								}else{
									cvalue = desv.substring(0, desv.indexOf(".")+3);
								}
							}else{
								let numPoint = 0;//小数点位数
								if(ftitle.indexOf("0.000") > -1){
									numPoint = 4;
								}else if(ftitle.indexOf("0.00") > -1){
									numPoint = 3;
								}else if(ftitle.indexOf("0.0") > -1){
									numPoint = 2;
								}else if(ftitle.indexOf("0.") > -1){
									numPoint = 1;
								}
								if(ftitle == ''){
									cvalue = intV0 * 65536 + intV1;
								}else{
									cvalue = eval(ftitle.replace("?",intV0).replace("$",intV1)).toFixed(numPoint);
								}
							}
						}
					}
				}else{
					//判断值是否存在
					let pvalue = runData['C'+paramsitem.paramKey];
					if(pvalue){
						let kvalue = parseInt(pvalue);
						//计算参数值,判断是否是有符号数
						let isSigned = paramsitem.isSigned;
						if(isSigned == 1){//负数范围(-32768---32767)
							if(kvalue>32767){
								kvalue=kvalue-65536;//65535对应-1	
							}					
						}
						//判断操作规则
						if(paramsitem.operationRule == ''){
							cvalue = kvalue;
						}else{
							//判断小数点位数
							let numPoint = 0;
							if(paramsitem.operationRule.indexOf("0.000") > -1){
								numPoint = 4;
							}else if(paramsitem.operationRule.indexOf("0.00") > -1){
								numPoint = 3;
							}else if(paramsitem.operationRule.indexOf("0.0") > -1){
								numPoint = 2;
							}else if(paramsitem.operationRule.indexOf("0.") > -1){
								numPoint = 1;
							}
							//计算运算规则
							cvalue = eval(paramsitem.operationRule.replace("?",kvalue)).toFixed(numPoint);
						}
					}else{
						cvalue = '';
					}
				}
				return cvalue;
			},
			/*下发指令*/
			sendCmd(btninfo){
				let cmdparam = {
					'adaptorCode': this.datas.devInfo.adapterCode,
					'address': btninfo.paramKey,
					'value': btninfo.paramVal,
					'deviceId': this.datas.devInfo.id,
					'commandDesc': btninfo.paramName,
					'phonePlatFrom': '2',
					'floatMark': btninfo.floatPoint
				}
				this.api.sendCommand(cmdparam).then(res=>{
					console.log(res)
				})
			},
			
			/*监听全局事件*/
			setOnUpdateListener(){
				uni.$on('paramsUpdate', (data)=>{
					this.datas = data;
				})
			},
			/*移除全局自定义事件监听器*/
			setOffUpdateListener(){
				uni.$off('paramsUpdate', null);
			}
		}
	}
</script>

<style lang="scss">
	.content{
		width: 100%;
		height: calc(100vh - var(--status-bar-height) - 45px - 37px - 40px - 3px);
		padding: 0rpx 10rpx;
	}
	.scroll_pt{
		height: 100%;
		padding: 10rpx 0rpx 0rpx;
		.cnt_pt{
			background-color: #FFFFFF;
			border-radius: 15rpx;
			padding: 15rpx 15rpx 30rpx;
			margin-bottom: 10rpx;
			.title_pt{
				display: flex;
				flex-wrap: wrap;
				align-items: center;
				padding: 20rpx 0rpx;
				border-bottom: 1rpx solid #EFEFEF;
				.t_flag{
					width: 8rpx;
					height: 25rpx;
					border-radius: 15rpx;
					background-color: $uni-color-primary;
				}
				.t_text{
					font-size: 32rpx;
					margin-left: 10rpx;
				}
			}
			
			.item_pt{
				display: flex;
				flex-wrap: wrap;
				align-items: center;
				justify-content: space-between;
				border-bottom: 1rpx solid #EFEFEF;
				padding: 20rpx 0rpx;
				.left_pt{
					
				}
				.right_pt{
					color: $uni-color-primary;
				}
			}
			
			.btns_pt{
				display: flex;
				flex-wrap: wrap;
				justify-content: space-between;
				padding: 10rpx;
				.btns{
					width: 325rpx;
					padding: 15rpx 0rpx;
					margin: 15rpx 0rpx;
					color: #FFFFFF;
					text-align: center;
					border-radius: 15rpx;
				}
			}
		}
	}
</style>

basicinfo组件

<template>
	<view class="content">
		<!--基本信息组件-->
		<scroll-view scroll-y class="scroll_pt">
			<view class="cnt_pt">
				<view class="title_pt">
					<view class="t_flag"></view>
					<view class="t_text">基本信息</view>
				</view>
				<view v-for="(item,index) in datas" :key="index">
					<view class="item_pt">
						<view class="left_pt">{{item.key}}</view>
						<view class="right_pt">{{item.value}}</view>
					</view>
				</view>
			</view>
		</scroll-view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				datas:[{'key':'dsafdsa', 'value':'0612345678'},
					{'key':'dsafdsa', 'value':'345678'},
					{'key':'dsafdsa', 'value':'5678'},
					{'key':'dsafdsa', 'value':'612345678'}]
			}
		},
		mounted() {
			//监听全局事件
			//this.setOnUpdateListener();
			//监听一次全局事件
			this.setOnceUpdateListener();
		},
		beforeDestroy() {
			//this.setOffUpdateListener();
		},
		methods: {
			/*只监听一次全局事件,然后移除*/
			setOnceUpdateListener(){
				uni.$once('paramsUpdate',(data)=>{
				        
				})
			},
			/*监听全局事件*/
			setOnUpdateListener(){
				uni.$on('paramsUpdate', (data)=>{
					this.datas = data;
				})
			},
			/*移除全局自定义事件监听器*/
			setOffUpdateListener(){
				uni.$off('paramsUpdate', null);
			}
		}
	}
</script>

<style lang="scss">
	.content{
		width: 100%;
		height: calc(100vh - var(--status-bar-height) - 45px - 37px - 40px - 3px);
		padding: 0rpx 10rpx;
	}
	.scroll_pt{
		height: 100%;
		padding: 10rpx 0rpx 0rpx;
		.cnt_pt{
			background-color: #FFFFFF;
			border-radius: 15rpx;
			padding: 15rpx 15rpx 30rpx;
			margin-bottom: 10rpx;
			.title_pt{
				display: flex;
				flex-wrap: wrap;
				align-items: center;
				padding: 20rpx 0rpx;
				border-bottom: 1rpx solid #EFEFEF;
				.t_flag{
					width: 8rpx;
					height: 25rpx;
					border-radius: 15rpx;
					background-color: $uni-color-primary;
				}
				.t_text{
					font-size: 32rpx;
					margin-left: 10rpx;
				}
			}
			
			.item_pt{
				display: flex;
				flex-wrap: wrap;
				align-items: center;
				justify-content: space-between;
				border-bottom: 1rpx solid #EFEFEF;
				padding: 20rpx 0rpx;
				.left_pt{
					
				}
				.right_pt{
					color: $uni-color-primary;
				}
			}
		}
	}

</style>

完!!!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

原文链接:https://ly9527.blog.csdn.net/article/details/115723229

  • 上一篇:没有了
  • 下一篇:没有了
栏目分类
最近更新