competed中访问ref为undefined_computed中找不到$refs-程序员宅基地

技术标签: 前端  vue.js  问题总结与思考  javascript  

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. 分析过程

  1. 根据vue的生命周期,观测computed属性调用this.$refs的时期,以及ref在refs中挂载的时期。如图所示,computed中tableUuid是在beforeMount之后,mounted之前。而topicSelect是在 mounted之后才出现在this.$refs上的,因此在计算属性中通过$refs.tableUuid调用所需属性或方法时为undefined。

  2. 进一步观测发现,所要调用的topicSelect已经存在了,但调用的this.$refs为{},没有与topSelect建立联系,无法通过this.$refs.topicSelect的方式获取。

  3. ref本身作为渲染结果被创建,在初始渲染的时候访问是不存在的,因此ref需要在DOM渲染完成后应用,使用时需确保DOM已经渲染完成。因此,有两种解决措施:1.使用this.$nextTick(),2.在mounted中调用。

3. 解决过程

解决措施1

  1. 首先尝试在computed中使用this.$nextTick(),发现可以获取ref。

  2. 继续朝着目标出发,尝试访问目标ref及其相关属性。再次遇到问题。可以访问到ref,也能看见相关属性是有数据的,但是单独获取,却是没有值的。

  3. 由于ref是页面完成渲染后才访问得到的,因此观测mounted之后的生命周期,调用this.topicSelect.checkedValue发生了什么变化。如图所示,数据是在更新完成后才出现的。

  4. 通过调试语句,期待数据发生变化时,再次调用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;
},
  1. 尝试在各生命周期中访问tableUuid,发现在生命周期中访问tableUuid得到的结果都是默认值,在nextTick中操作并未生效。

复习computed
● computed本质是一个惰性求值的观察者,具有缓存性,只有当依赖发生变化后,访问computed中的属性,才会重新计算。
● 初始化computed调用initComputed函数: ○ 注册一个watcher实例,并在其中实例化一个Dep消息订阅器用于收集依赖;

  1. 调用计算属性时会触发其Object.defineproperty的get访问函数;
  2. 调用watcher.depend()方法向自身的消息订阅器dep的subs中添加其他属性的watcher;
  3. 调用watcher.evaluate,进而调用get方法,让自身成为其他watcher的消息订阅器的订阅者,首先将watcher赋给Dep.target,执行getter,当访问getter中的属性(可能来自于data、props或其他computed)时,会同样触发它们的get访问器函数,从而将该计算属性的watcher添加到求值函数中属性的watcher的消息订阅器dep中,当这些操作完成,最后关闭Dep.target赋为null并返回求值函数结果
  4. 当某个属性发生变化,触发set拦截函数,然后调用自身dep的notify方法,遍历当前dep中保存着所有订阅者的subs数组,并逐个调用watcher的update方法,完成响应更新

● computed定义的属性接收return的结果,return是同步执行的,没办法拿到异步操作的结果。

  1. 在computed使用this.$nextTick失败
    解决措施2
  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中执行异步操作是无效的,异步操作的结果不会决定计算属性的返回结果。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_43128157/article/details/126220537

智能推荐

艾美捷Epigentek DNA样品的超声能量处理方案-程序员宅基地

文章浏览阅读15次。空化气泡的大小和相应的空化能量可以通过调整完全标度的振幅水平来操纵和数字控制。通过强调超声技术中的更高通量处理和防止样品污染,Epigentek EpiSonic超声仪可以轻松集成到现有的实验室工作流程中,并且特别适合与表观遗传学和下一代应用的兼容性。Epigentek的EpiSonic已成为一种有效的剪切设备,用于在染色质免疫沉淀技术中制备染色质样品,以及用于下一代测序平台的DNA文库制备。该装置的经济性及其多重样品的能力使其成为每个实验室拥有的经济高效的工具,而不仅仅是核心设施。

11、合宙Air模块Luat开发:通过http协议获取天气信息_合宙获取天气-程序员宅基地

文章浏览阅读4.2k次,点赞3次,收藏14次。目录点击这里查看所有博文  本系列博客,理论上适用于合宙的Air202、Air268、Air720x、Air720S以及最近发布的Air720U(我还没拿到样机,应该也能支持)。  先不管支不支持,如果你用的是合宙的模块,那都不妨一试,也许会有意外收获。  我使用的是Air720SL模块,如果在其他模块上不能用,那就是底层core固件暂时还没有支持,这里的代码是没有问题的。例程仅供参考!..._合宙获取天气

EasyMesh和802.11s对比-程序员宅基地

文章浏览阅读7.7k次,点赞2次,收藏41次。1 关于meshMesh的意思是网状物,以前读书的时候,在自动化领域有传感器自组网,zigbee、蓝牙等无线方式实现各个网络节点消息通信,通过各种算法,保证整个网络中所有节点信息能经过多跳最终传递到目的地,用于数据采集。十多年过去了,在无线路由器领域又把这个mesh概念翻炒了一下,各大品牌都推出了mesh路由器,大多数是3个为一组,实现在面积较大的住宅里,增强wifi覆盖范围,智能在多热点之间切换,提升上网体验。因为节点基本上在3个以内,所以mesh的算法不必太复杂,组网形式比较简单。各厂家都自定义了组_802.11s

线程的几种状态_线程状态-程序员宅基地

文章浏览阅读5.2k次,点赞8次,收藏21次。线程的几种状态_线程状态

stack的常见用法详解_stack函数用法-程序员宅基地

文章浏览阅读4.2w次,点赞124次,收藏688次。stack翻译为栈,是STL中实现的一个后进先出的容器。要使用 stack,应先添加头文件include<stack>,并在头文件下面加上“ using namespacestd;"1. stack的定义其定义的写法和其他STL容器相同, typename可以任意基本数据类型或容器:stack<typename> name;2. stack容器内元素的访问..._stack函数用法

2018.11.16javascript课上随笔(DOM)-程序员宅基地

文章浏览阅读71次。<li> <a href = "“#”>-</a></li><li>子节点:文本节点(回车),元素节点,文本节点。不同节点树:  节点(各种类型节点)childNodes:返回子节点的所有子节点的集合,包含任何类型、元素节点(元素类型节点):child。node.getAttribute(at...

随便推点

layui.extend的一点知识 第三方模块base 路径_layui extend-程序员宅基地

文章浏览阅读3.4k次。//config的设置是全局的layui.config({ base: '/res/js/' //假设这是你存放拓展模块的根目录}).extend({ //设定模块别名 mymod: 'mymod' //如果 mymod.js 是在根目录,也可以不用设定别名 ,mod1: 'admin/mod1' //相对于上述 base 目录的子目录}); //你也可以忽略 base 设定的根目录,直接在 extend 指定路径(主要:该功能为 layui 2.2.0 新增)layui.exten_layui extend

5G云计算:5G网络的分层思想_5g分层结构-程序员宅基地

文章浏览阅读3.2k次,点赞6次,收藏13次。分层思想分层思想分层思想-1分层思想-2分层思想-2OSI七层参考模型物理层和数据链路层物理层数据链路层网络层传输层会话层表示层应用层OSI七层模型的分层结构TCP/IP协议族的组成数据封装过程数据解封装过程PDU设备与层的对应关系各层通信分层思想分层思想-1在现实生活种,我们在喝牛奶时,未必了解他的生产过程,我们所接触的或许只是从超时购买牛奶。分层思想-2平时我们在网络时也未必知道数据的传输过程我们的所考虑的就是可以传就可以,不用管他时怎么传输的分层思想-2将复杂的流程分解为几个功能_5g分层结构

基于二值化图像转GCode的单向扫描实现-程序员宅基地

文章浏览阅读191次。在激光雕刻中,单向扫描(Unidirectional Scanning)是一种雕刻技术,其中激光头只在一个方向上移动,而不是来回移动。这种移动方式主要应用于通过激光逐行扫描图像表面的过程。具体而言,单向扫描的过程通常包括以下步骤:横向移动(X轴): 激光头沿X轴方向移动到图像的一侧。纵向移动(Y轴): 激光头沿Y轴方向开始逐行移动,刻蚀图像表面。这一过程是单向的,即在每一行上激光头只在一个方向上移动。返回横向移动: 一旦一行完成,激光头返回到图像的一侧,准备进行下一行的刻蚀。

算法随笔:强连通分量-程序员宅基地

文章浏览阅读577次。强连通:在有向图G中,如果两个点u和v是互相可达的,即从u出发可以到达v,从v出发也可以到达u,则成u和v是强连通的。强连通分量:如果一个有向图G不是强连通图,那么可以把它分成躲个子图,其中每个子图的内部是强连通的,而且这些子图已经扩展到最大,不能与子图外的任一点强连通,成这样的一个“极大连通”子图是G的一个强连通分量(SCC)。强连通分量的一些性质:(1)一个点必须有出度和入度,才会与其他点强连通。(2)把一个SCC从图中挖掉,不影响其他点的强连通性。_强连通分量

Django(2)|templates模板+静态资源目录static_django templates-程序员宅基地

文章浏览阅读3.9k次,点赞5次,收藏18次。在做web开发,要给用户提供一个页面,页面包括静态页面+数据,两者结合起来就是完整的可视化的页面,django的模板系统支持这种功能,首先需要写一个静态页面,然后通过python的模板语法将数据渲染上去。1.创建一个templates目录2.配置。_django templates

linux下的GPU测试软件,Ubuntu等Linux系统显卡性能测试软件 Unigine 3D-程序员宅基地

文章浏览阅读1.7k次。Ubuntu等Linux系统显卡性能测试软件 Unigine 3DUbuntu Intel显卡驱动安装,请参考:ATI和NVIDIA显卡请在软件和更新中的附加驱动中安装。 这里推荐: 运行后,F9就可评分,已测试显卡有K2000 2GB 900+分,GT330m 1GB 340+ 分,GT620 1GB 340+ 分,四代i5核显340+ 分,还有写博客的小盒子100+ 分。relaybot@re...

推荐文章

热门文章

相关标签