当前位置:网站首页>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中执行异步操作是无效的,异步操作的结果不会决定计算属性的返回结果。
边栏推荐
- Win10系统80端口被占用的解决方法
- 渗透测试——CFS三层靶机内网渗透实操
- [免费专栏] Android安全之Android应用的汉化功能(修改so中的字符串内容)
- OpenHarmony如何查询设备类型
- Office 365 Group概述以及创建方法
- 这年头还不来尝试线稿图视频??
- IS31FL3737B general 12 x 12 LED drive 40 QFN I2C 42 ma
- 鹅厂机器狗花式穿越10m梅花桩:前空翻、单桩跳、起身作揖...全程不打一个趔趄...
- Flume (五) --------- 自定义 Interceptor、自定义 Source 与 自定义 Sink
- Swift -- 数组高阶函数
猜你喜欢
qq机器人账号不能发送群消息,被风控
IS31FL3737B 通用12×12 LED驱动器 I2C 42mA 40QFN
Codesys结构变量编程应用(STRUCT类型)
为什么数字钱包需要引入小程序生态
Iptables防火墙常见的典型应用场景
[] free column Android dynamic debugging GDB APP of safety
uniapp离线推送华为厂商申请流程
Paper sharing: "FED BN" uses the LOCAL BATCH NORMALIZATION method to solve the Non-iid problem
mysql 重复数据 分组 多条最新的记录
华为云全流程护航《流浪方舟》破竹首发,打造口碑爆款
随机推荐
毕昇编译器优化:Lazy Code Motion
Why is the data of maxcompute garbled when imported into mysql?The table of mysql is the encoding of udf8mb4
明明加了唯一索引,为什么还是产生重复数据?
2022了你还不会『低代码』?数据科学也能玩转Low-Code啦!
hdu 1285 确定比赛名次(拓扑排序)
听音识情绪 | 程序员手把手教你搭建神经网络,更快get女朋友情绪,求生欲max!
基于Web的疫情隔离区订餐系统
[Free column] Xposed plug-in development for Android security [from scratch] tutorial
[免费专栏] Android安全之Android Fragment注入
pat链表专题训练+搜索专题
Swift -- 数组高阶函数
基于SSM实现手机销售商城系统
laravel 中配置文件.env解读
Leetcode 739.每日温度 单调栈
[免费专栏] Android安全之Android Studion 动态调试APK的两种方法
php安装make出现“collect2:error:ldreturned1exitstatus
宝塔面板安装使用
Pytorch 固定部分参数训练
[免费专栏] Android安全之和平精英(FZ)APK逆向分析
[免费专栏] Android安全之GDB动态调试APP