一、业务需求分析:用户在某个模块试卷答完需要交卷时,点击当前页面交卷按钮,弹出层展示,弹出层上需能显示该试卷还剩余的时分秒,并有可供用户选择的 “否” 和 “是” 按钮,如果用户点击“否”,则不提交答卷,且弹出层隐藏,并停留在原页面;如果用户点击“是”,则提交答卷记录,且弹出层隐藏,并跳转到该模块的成绩单页。
二、页面效果展示如下:
三、页面结构分析:有交卷按钮的页面为父页面,子页面是弹出层页面,是嵌套在父页面上的,行业术语为:父组件引入子组件。
四、技术点分析:
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>
如果能稍微打动到您,那就点个赞呗!嘿嘿!