当前位置:网站首页>competed中访问ref为undefined
competed中访问ref为undefined
2022-08-09 18:40:00 【C_Cercis Chinensis】
1. 问题描述
级联选择器中的数据通过接口回传,当选中某项数据,获取value的同时须拿到uuid,用于页面跳转。uuid的获取在两个地方:一是级联选择器初始化时,若已有选中项,则需取出uuid赋值;二是用户改变选项时,需拿到新的uuid赋值。两个地方都是通过$refs访问级联选择器topicSelect实例,通过调用getCheckedNodes方法获取所选项的uuid。因此考虑在computed中调用ref获取uuid。但在computed中访问ref为undefined。
<el-cascader
filterable
v-model="uuidArray"
ref="topicSelect"
placeholder="请选择源表。支持按名称搜索"
@change="handleValue"
:disabled="onlyRead"
:props="{ expandTrigger: 'hover', lazy: true, lazyLoad: cascaderLazyLoad }"
:show-all-levels="false"
size="small"
>
</el-cascader>
tableUuid(){
return this.$refs.topicSelect.getCheckedNodes()[0] ? this.$refs.topicSelect.getCheckedNodes()[0].data.uuid: '';//TypeError: Cannot read properties of undefined (reading 'getCheckedNodes')
},
2. 分析过程
根据vue的生命周期,观测computed属性调用this.$refs的时期,以及ref在refs中挂载的时期。如图所示,computed中tableUuid是在beforeMount之后,mounted之前。而topicSelect是在 mounted之后才出现在this.$refs上的,因此在计算属性中通过$refs.tableUuid调用所需属性或方法时为undefined。
进一步观测发现,所要调用的topicSelect已经存在了,但调用的this.$refs为{},没有与topSelect建立联系,无法通过this.$refs.topicSelect的方式获取。
ref本身作为渲染结果被创建,在初始渲染的时候访问是不存在的,因此ref需要在DOM渲染完成后应用,使用时需确保DOM已经渲染完成。因此,有两种解决措施:1.使用this.$nextTick(),2.在mounted中调用。
3. 解决过程
解决措施1
首先尝试在computed中使用this.$nextTick(),发现可以获取ref。
继续朝着目标出发,尝试访问目标ref及其相关属性。再次遇到问题。可以访问到ref,也能看见相关属性是有数据的,但是单独获取,却是没有值的。
由于ref是页面完成渲染后才访问得到的,因此观测mounted之后的生命周期,调用this.topicSelect.checkedValue发生了什么变化。如图所示,数据是在更新完成后才出现的。
通过调试语句,期待数据发生变化时,再次调用computed中的属性,执行相关的方法。但是事与愿违,更新数据时,computed中的tableUuid并没有再次调用。
tableUuid(){
let tableuuid = 'default';
this.$nextTick(()=>{
tableuuid = this.$refs.topicSelect.checkedValue.length !== 0 ? this.$refs.topicSelect.getCheckedNodes()[0] ? this.$refs.topicSelect.getCheckedNodes()[0].data.uuid: 'getCheckedNodes()无数据' : 'checkedValue无数据';
console.log('tableUuid',tableuuid);
});
return tableuuid;
},
- 尝试在各生命周期中访问tableUuid,发现在生命周期中访问tableUuid得到的结果都是默认值,在nextTick中操作并未生效。
复习computed
● computed本质是一个惰性求值的观察者,具有缓存性,只有当依赖发生变化后,访问computed中的属性,才会重新计算。
● 初始化computed调用initComputed函数: ○ 注册一个watcher实例,并在其中实例化一个Dep消息订阅器用于收集依赖;
- 调用计算属性时会触发其Object.defineproperty的get访问函数;
- 调用watcher.depend()方法向自身的消息订阅器dep的subs中添加其他属性的watcher;
- 调用watcher.evaluate,进而调用get方法,让自身成为其他watcher的消息订阅器的订阅者,首先将watcher赋给Dep.target,执行getter,当访问getter中的属性(可能来自于data、props或其他computed)时,会同样触发它们的get访问器函数,从而将该计算属性的watcher添加到求值函数中属性的watcher的消息订阅器dep中,当这些操作完成,最后关闭Dep.target赋为null并返回求值函数结果
- 当某个属性发生变化,触发set拦截函数,然后调用自身dep的notify方法,遍历当前dep中保存着所有订阅者的subs数组,并逐个调用watcher的update方法,完成响应更新
● computed定义的属性接收return的结果,return是同步执行的,没办法拿到异步操作的结果。
- 在computed使用this.$nextTick失败
解决措施2 - 采用第二种方式,由解决措施1可知,在mounted中可以成功调用ref。为了动态获取数据,需要对ref进行监听,将监听到的数据赋给tableUuid。该方法验证可行。
mounted(){
let refTmp = this.$refs.topicSelect;
this.$watch(
function(){
return refTmp.getCheckedNodes()[0] ? refTmp.getCheckedNodes()[0].data.uuid: '';
},
(val, oval)=>{
this.tableUuid = val;
console.log('watch',val,oval);
}
)
},
4. 总结
● 对于ref的注册时间需注意️ 引用官网
因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 -
它们还不存在!$refs也不是响应式的,因此你不应该试图用它在模板中做数据绑定。
● computed的结果会被缓存,只有当依赖的响应式property变化时才会重新计算,但若某个依赖是非响应式的(例如:常量、Date.Now()),则计算属性是不会被更新的。computed是不支持异步操作的,因此,在computed中执行异步操作是无效的,异步操作的结果不会决定计算属性的返回结果。
边栏推荐
- Mysql table structure change scheme comparison and analysis
- Detailed explanation of VIT transformer
- MQTT X Web:在线的 MQTT 5.0 客户端工具
- ebook下载 | 《 企业高管IT战略指南——企业为何要落地DevOps》
- [免费专栏] Android安全之安卓APK浅析
- winpe工具WEPE微PE工具箱
- 英赛克工控安全项目入围《钢铁行业智能制造解决方案推荐目录》
- 数据库注入提权总结(一)
- 有文章说明或者证明MYSQL 嵌套子查询不足之处吗?
- 鹅厂机器狗花式穿越10m梅花桩:前空翻、单桩跳、起身作揖...全程不打一个趔趄...
猜你喜欢

使用.NET简单实现一个Redis的高性能克隆版(四、五)

What is the Treasure Project (TPC), a dark horse with wings in 2022!

三星旗舰优惠千八,苹果优惠过千,国产旗舰只降五百打发叫花子
![[Free Column] Android Security for Peace Elite (FZ) APK Reverse Analysis](/img/22/a5129a310eec5ee1bf6f1cf90d05de.png)
[Free Column] Android Security for Peace Elite (FZ) APK Reverse Analysis

hdu 2094 产生冠军(STL map || 拓扑 || STL set)

qq机器人账号不能发送群消息,被风控

双屏协作更高效,华硕灵耀X 双屏Pro 2022创作体验再升级

Open Source Summer | List Details Display Based on Ruoyi Architecture

渗透测试——CFS三层靶机内网渗透实操

最新BEV感知基线 | 你确定需要激光雷达?(卡内基梅隆大学)
随机推荐
hdu 2647 Reward(拓扑排序)
Flume (六) --------- Flume 数据流监控
全自动化机器学习建模!效果吊打初级炼丹师!
shell脚本编写 hash方法,shell中字符到ascii码或数字的转换
工大科雅深交所上市:市值45亿 齐承英家族是大股东
数据分散情况的统计图-盒须图
grafana docks local ldap
数学建模代码速成~赛前一个月~matlab~代码模板~吐血总结~三大模型代码(预测模型、优化模型、评价模型)
Go-Excelize API源码阅读(五)—— Close()
这年头还不来尝试线稿图视频??
基于Web的疫情隔离区订餐系统
放下手机吧:实验表明花20分钟思考和上网冲浪同样快乐
一图详解沃土云创计划高校教师参与全流程
明明加了唯一索引,为什么还是产生重复数据?
为什么数字钱包需要引入小程序生态
[Free column] Xposed plug-in development for Android security [from scratch] tutorial
关于加强专业学位研究生课程体系建设的意见
2022深圳(软考中级)系统集成项目管理工程师报名
切绳子【洛谷P1577】【二分】
pat链表专题训练+搜索专题