业务场景
最近给 一个项目调错,遇到需要在筛选条件页面添加环比周期,环比周期的出现是通过判断筛选条件是学习通则出现,否则不出现。这样简单的需求看似很简单,但难在这个值是通过跨页面传过来的,跨页面传值其实也比较容易实现,难就难在筛选条件页面是一个子页面,而我需要的又是这个页面初始化时就调取环比周期显示的方法,所以我写在生命周期created()里是无效的,他会在首页面一加载时就调取这个方法,但传的值是空的,所以无法调取环比周期显示的方法,解决这个问题所用到的技术就是监听和父子传值。在这记录下,也希望能帮助到其他人
一、监听
根据上面业务所描述的,既然我不能在created调取这个方法,那我可以用watch监听的方式,父页面的值变化这个方法也就可以调取了。废话不说,代码说话
watch: {
dataName(val, newval) {
this.filter = val;
this.handelDataName(this.filter);
},
methods里的方法
handelDataName(filter) {
if (this.filter == "学习通") {
this.monthCycleIsDisplay = true;
}
},
通过props接收父组件传过来的数据,简单来说子组件需要父组件的某个值,就在子组件内部定义一个props属性。我再筛选条件页面定义的属性如下,其中dataName就有我要接收的学习通的值。props写在export default{}里面,data上面
props: [
"optionsOne",
"optionsTwo",
"policyAllConditionList",
"dateCycleIsDisplay",
"dataName",
],
二、父子传值
1、父组件调取子组件方法
监听方法虽然能解决我所存在的问题,但不能解决全部问题。正所谓站在用户的角度考虑,就需要考虑到用户所有的操作习惯,当用户点击返回不重新点击选择值,又点回筛选条件页面时因为没有发生值的改变,因此监听无效。这个问题试了很多种方法,最终用父组件调取子组件方式实现了。具体实现细节看代码
父组件注册子组件
<div v-show="isFilter">
<!--设置筛选条件 -->
<policerFilter
ref="policerFilter" //这里的ref就是父调子采取的方式
:optionsOne="optionsOne"
:optionsTwo="optionsTwo"
:dataName="filterNameGetData"
:policyAllConditionList="this.policyAllConditionList"
@ListenFifter="transFifter"
@ListenDelCondition="transDelCondition"
@ListenConditionNum="transConditionNum"
/>
</div>
注意这里的policerFilter是需要引入进来的,引入代码:
import policerFilter from "../policer/components/filter";
export default{
components: {
policerFilter,
},
}
在methods方法里写这个方法,这个方法具体在哪调呢,根据你的业务和页面所设置的位置根据实际情况来定。
//父组件调子组件的方法
handleClick() {
// this.$refs.policerFilter.monthCycleDateDisplay();
if (this.filterNameGetData == "学习通") {
this.dateDisplay = true;
this.$refs.policerFilter.$emit("monthCycleDateDisplay"); //这里通过$emit方法调取
}
},
子组件
mounted(){
this.$nextTick(()=>{
this.$on("monthCycleDateDisplay",function(){
this.monthCycleIsDisplay = true;
});
});
},
三、解决过程中遇到的错
在用监听事件时还算顺利,但用父调子方法时,报了这样的错
Error in created hook: “TypeError: Cannot read property ‘monthCycleDateDisplay‘ of undefined“
最后查了下,是因为vue中数据渲染和DOM元素时异步的,可能会存在加载先后的问题,在dom元素未渲染完成时去操作dom元素就会报错。一般在created上容易出现这个问题。
如何解决?
在父组件中,将之前写在created里的handleClick方法,换了一个位置,根据实际情况写在了一个控件里。完美解决了这个问题
四、总结
这次收获到了父子传值和监听的具体实战方法,收获颇多!除此之前,也了解到了页面刷新问题可用provide()和inject,具体实现方法参考下篇博客