Vue父子组件/页面相互传值方法具体场景应用($refs props $emit)

本文详细解析了在线考试系统中交卷流程的设计与实现,包括业务需求分析、页面效果展示、页面结构与技术点分析,重点介绍了父组件与子组件之间的数据传递方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、业务需求分析:用户在某个模块试卷答完需要交卷时,点击当前页面交卷按钮,弹出层展示,弹出层上需能显示该试卷还剩余的时分秒,并有可供用户选择的 “否” 和 “是” 按钮,如果用户点击“否”,则不提交答卷,且弹出层隐藏,并停留在原页面;如果用户点击“是”,则提交答卷记录,且弹出层隐藏,并跳转到该模块的成绩单页。

二、页面效果展示如下

三、页面结构分析:有交卷按钮的页面为父页面,子页面是弹出层页面,是嵌套在父页面上的,行业术语为:父组件引入子组件。

四、技术点分析

a(父传子).由于是某个模块的答卷,且成功提交答卷结果后会跳转到对应模块的成绩单页,所以我把模块值传向子页面写在父页面上点击交卷按钮触发事件里,此为父组件向子组件传值,这里使用 $refs 父传子的方式进行实现。

b(父传子).弹出层页面也得同步展示答卷页面所剩于的时分秒,也涉及父组件向子组件,这里使用 props 父传子的方式进行实现。

c(子传父).点击交卷时,弹出层展现,用户点击弹出层页面的 “否” 和 “是” 按钮触发相应的事件(此两事件都在子组件中),对应的事件里需通过传值的方式告诉父页面用户的选择,父页面根据拿到子页面的传值来判断并进行相应业务逻辑处理。如果父页面拿到代表用户选择“是”的值,即提交试卷答案并隐藏弹出层;如果父页面拿到代表用户选择“否”的值,即只隐藏弹出层。此处子组件向父组件传值通过 $emit 子传父的方式进行实现。

五、代码展示(以上面分析的技术点依次贴代码)

a(父传子)相关代码展示如下:

a(父传子)父页面相关代码:
<!-- 是否提交试卷的弹层,不点击交卷按钮为隐藏状态 -->
<van-popup-sue round :show="submitShow" @close="submitShow = false">
   <!--ref="pushModeId" 为父传子的标志 写在子组件SubmitPopup上-->
   <!--父页面使用子组件-->
   <SubmitPopup ref="pushModeId"></SubmitPopup>
</van-popup-sue>

<button form-type="submit" class="submit-btn" @click="jiaoJuanClick()">交卷</button>

//父页面引入子组件的标志
import SubmitPopup from '../../components/******/submit-popup.vue';

//注册子组件
components: {	
    SubmitPopup	
},

methods: {
    //交卷点击事件
    jiaoJuanClick(){
       //subjectParam为已经知道的模块类型值
       //$refs向子组件传值,pushParams为子页面接受父页面传值的方法名
       this.$refs.pushModeId.pushParams(this.subjectParam)
       //打开弹出层
       this.submitShow = true
    }
}
a(父传子)子页面即弹出层页面相关代码:
methods:{
    //子页面接受父页面传值的对应的同名方法	
    pushParams(getSubjectId){
       //拿到父页面传过来的模块类型值
       this.subjectId = getSubjectId
    }
}

b(父传子)相关代码展示如下:

b(父传子)父页面相关代码:
<!--小程序倒计时组件-->
<!--time为试卷规定时长-->
<van-count-down use-slot :time="time" @change="onChange">
    <!--根据试卷时长进行时分秒展示-->
	<text>
    {{ timeData.hours }}:{{ timeData.minutes }}:{{ timeData.seconds }}
    </text>
</van-count-down>

<!-- 是否提交试卷的弹层 -->
<van-popup-sue round :show="submitShow" @close="submitShow = false">
    <!--:timeData="timeData" 为b(父传子)的标志 写在子组件SubmitPopup上-->
    <!--父页面使用子组件-->
    <SubmitPopup :timeData="timeData"></SubmitPopup>
</van-popup-sue>

//父页面引入子组件的标志
import SubmitPopup from '../../components/******/submit-popup.vue';

//注册子组件
components: {	
    SubmitPopup	
}

methods:{
    //获取倒计时的时间
    onChange(e){
      //e中即可拿到时分秒
      this.timeData = e.detail;
    }
}

b(父传子)子页面即弹出层页面相关代码:
<form @submit="formSubmit" @reset="formReset">
  <view class="submit-tips">
	<view class="tips">继续提交试卷</view>
    <view class="time">
    倒计时 {{ timeData.hours }}:{{ timeData.minutes }}:{{ timeData.seconds }}
    </view>
  </view>
  <view class="options-btn">
	<button type="default" form-type="reset">否</button>
	<button form-type="submit">是</button>
  </view>
</form>

export default {
  name:'SubmitPopup',
  //父组件的数据需要通过props才能下发到子组件中,子页面在此处进行申明
  props:{
   //timeData为子页面需要监听父页面的值timeData,名称和父页面一样
   timeData:{
     //类型申明
     type:Object,
     //默认值
     default(){
      return {}
     }
   } 
  }
}

c(子传父)相关代码展示如下:

c(子传父)父页面相关代码:
<!-- 是否提交试卷的弹层,不点击交卷按钮为隐藏状态 -->
<van-popup-sue round :show="submitShow" @close="submitShow = false">
   <!--@closePopup="closePopup" 为c(子传父)的标志 写在子组件SubmitPopup上-->
   <!--父页面使用子组件-->
   <SubmitPopup @closePopup="closePopup"></SubmitPopup>
</van-popup-sue>

<button form-type="submit" class="submit-btn" @click="jiaoJuanClick()">交卷</button>

//父页面引入子组件的标志
import SubmitPopup from '../../components/******/submit-popup.vue';

//注册子组件
components: {	
    SubmitPopup	
},
methods: {
    //子传父触发的事件,data为子页面传的值
    closePopup(data){
      if(data == "true"){
        //父页面拿到用户选择“是”的值,继续相关业务代码,之后关闭弹出层
	this.submitShow = false
      }else if(data == "false"){
        //父页面拿到用户选择“否”的值,直接关闭弹出层
	this.submitShow = false
      }
    }
}
c(子传父)子页面即弹出层页面相关代码:
<form @submit="formSubmit" @reset="formReset">
  <view class="submit-tips">
	<view class="tips">继续提交试卷</view>
    <view class="time">
    倒计时 {{ timeData.hours }}:{{ timeData.minutes }}:{{ timeData.seconds }}
    </view>
  </view>
  <view class="options-btn">
	<button type="default" form-type="reset">否</button>
	<button form-type="submit">是</button>
  </view>
</form>

export default {
  name:'SubmitPopup',
  
  methods:{
     //用户选择“是”的触发事件
     formSubmit: function(e) {
        //向父页面传值,告诉父页面用户选择为“是”,closePopup为父页面接受方法
        //'true'这里代表“是”
        this.$emit('closePopup','true')
        //提交答案后,以下为小程序跳转成绩单页的链接,subjectId为之前拿到的类型值
        uni.navigateTo({
          url: '/pages/****/*****/report?subjectId='+this.subjectId
        });
     },
     //用户选择“否”的触发事件
     formReset: function(e) {
        //向父页面传值,告诉父页面用户选择为“否”,closePopup为父页面接受方法
        //'false'这里代表“否”
        this.$emit('closePopup','false')
     }
  }
}

六、温馨提示

a.@closePopup="closePopup" 也可以用 v-on:closePopup="closePopup" 代替!

b.以上按技术点,只贴相关的代码!其实以上用到的父子组件相互传值方法的标志都是放在一起的!如下所示:

<van-popup-sue round :show="submitShow" @close="submitShow = false">
 <!--ref="pushModeId" :timeData="timeData" @closePopup="closePopup" 都是一起写在引用子组 
 件中-->
 <!--@closePopup="closePopup" 也可以用 v-on:closePopup="closePopup"代替 效果是一样的-->
 <SubmitPopup ref="pushModeId" :timeData="timeData" @closePopup="closePopup"></SubmitPopup>
</van-popup-sue>

如果能稍微打动到您,那就点个赞呗!嘿嘿!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值