Vue 父组件循环使用refs调用子组件方法出现undefined的问题

1. 背景

最近前端项目遇到一个问题,我在父组件中使用了两个相同的子组件child,分别设置ref为add和update。其中A组件的功能是新增,也就是说在页面上A页面只有一个。而update组件是放在表格里的,表格中的每一行数据都有update组件。跟update组件并列还有一个删除按钮,每次删除完都会重新获取数据

2.问题描述

界面第一次加载时我对表格的组件B进行操作的时候是没问题的,但是当我删除某一行的数据之后再点击B组件,出现了update组件变为undefined的问题。

	<el-table-column label="操作" min-width="100px">
<template slot-scope="scope">
<UpdateButton title="修改" @click.native="updateClick(scope.row)" size="mini"></UpdateButton>
<DeleteButton class="resource_pause_delete_button" @click.native="ruleDelete(scope.$index, scope.row)" />
<TimeSelectDialog ref="updateTime" title="修改暂停规则">
<update-button @click.native="updateData()" size="mini">
</update-button>
</TimeSelectDialog>
</template>
</el-table-column>

3.定位问题

因为add和update是相同的组件,所以我一开始认为是两个组件的冲突。但是当我把add组件完全去掉之后,还是出现了undefined的问题。所以排除了add组件是干扰这个原因。

继续猜想以为是组件渲染问题,于是我给update组件添加了nextTick和setTimeOut来让组件渲染完成。但是这依然不起作用。

紧接着我看了下vue中关于ref的文档。

v-for 用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组。

关于 ref 注册时间的重要说明:因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。

我的组件用了element-UI的el-table组件,这个组件的内部肯定是使用了v-for循环的。于是我就把问题定位在v-for引起的数据绑定问题。

我把update组件从el-table中拿出来,放在表格之外。此时表格行内的按钮只是调用update组件,并且每次调用的都是同一个组件。这次问题果然解决了。

4.总结

ref 本身是作为渲染结果被创建的,这句话应该是这样理解的。如果在循环中使用了包含ref的组件,那么循环出来的就是ref组件渲染的结果。当数据改变需要重新循环的时候,因为ref并不是响应式的,这导致包含了ref组件的行就无法再被渲染出来,因此出现了undefined的问题。

反过来想,既然update组件是一个可重用的组件,那么我们每次都让组件渲染其实并不是一个好的实现。实际上我的页面中的update组件每次改变的只有数据。从这个角度思考,我的设计是不合理的。

Vue 父组件循环使用refs调用子组件方法出现undefined的问题的更多相关文章

  1. 九、React中的组件、父子组件、React props父组件给子组件传值、子组件给父组件传值、父组件中通过refs获取子组件属性和方法

    一.概述 React中的组件: 解决html 标签构建应用的不足. 使用组件的好处:把公共的功能单独抽离成一个文件作为一个组件,哪里里使用哪里引入. [父子组件]:组件的相互调用中,我们把调用者称为父 ...

  2. Angular 中的 dom 操作(ViewChild)以及父子组件中通过 ViewChild 调用子组件的方法

    <app-header #header></app-header> <div #myBox> 我是一个dom节点 </div> <button ( ...

  3. Vue 父页面 值传递 不到 子组件....

    ...各种百度无果..最后发现 这两个值 都是绑定的一个 ajax....... 坑爹啊..所以注意了....以后的写法.... 比如 data:{ data1: data2: } 假如 data1 ...

  4. vue组件之间的通信以及如何在父组件中调用子组件的方法和属性

    在Vue中组件实例之间的作用域是孤立的,以为不能直接在子组件上引用父组件的数据,同时父组件也不能直接使用子组件的数据 一.父组件利用props往子组件传输数据 父组件: <div> < ...

  5. Vue 父组件调用子组件函数的方法

    parent.vue(父组件的内容): <template> <div @click="divClick"> <info-wnd ref=" ...

  6. vue 父组件调用子组件方法

    情景: 父组件中引入上传附件的子组件:点击组件可以分别上传对应要求的图片,子组件内部循环可创建多个模块. 父组件传入数组子组件循环来创建不同的组件模块,所有事件都在子组件内部. 父组件页面的上方同时有 ...

  7. Vue 父组件调用子组件的方法

    qwq  前两天看了下vue,父子组件方法的调用,怕忘记,所以做个小记录. 一.父组件调用子组件的方法 1.父组件 <template> <div id="rightmen ...

  8. 【vue】父组件主动调用子组件 /// 非父子组件传值

    一  父组件主动调用子组件: 注意:在父组件使用子组件的标签上注入ref属性,例如: <div id="home"> <v-header ref="he ...

  9. Vue父组件调用子组件的方法

    vue中如果父组件想调用子组件的方法,可以在子组件中加上ref,然后通过this.$refs.ref.method调用,例如: 父组件: <template> <div @click ...

随机推荐

  1. Iwconfig/aircrack-ng

    BT5 aircrack-ng破解无线密码(wpa/wep) - 星明月稀 - 博客频道 - CSDN.NET             BT5 aircrack-ng破解无线密码(wpa/wep) - ...

  2. FCoin API

    本文介绍FCoin API 介绍 通过了解以下信息,您可以方便的使用 FCoin 提供的 API 来接入 FCoin 交易平台. 认证 执行下面的代码进行用户验证: import fcoin api ...

  3. Python 字典 setdefault() 方法

    描述 Python 字典 setdefault() 方法和 get() 方法类似,返回指定键的值,如果键不在字典中,将会添加键并将值设置为一个指定值,默认为None. get() 和 setdefau ...

  4. Set-cookie无效(失效)

    今天做爬虫的时候遇到网站响应response返回的数据中有Set-Cookie,但是使用Linux的curl请求网页保存cookie始终为空,换句话说也就是Set-Cookie设置无效,所以我一直Go ...

  5. nginx分区域名转发 tp5域名分目录配置

    需求 本来我们一般情况下都是域名abc.com解析到网站的根目录/root/public这种.但是客户突然提出了一个奇葩的需求,客户要求以后可能网站会增多,需要增加分区的功能,比如abc.com/wh ...

  6. 如何删除word中多余的空格和空行

    去除word中多余的空格及空行 一.去掉表格和格式 为了版面的整齐,网页文档都是以表格的形式存在的,只是一般情况下表格的颜色被设为无色或表格宽度被设为0,所以我们在网页上看不到表格.另外,网 页文档中 ...

  7. hadoop备战:yarn框架的简单介绍(mapreduce2)

    新 Hadoop Yarn 框架原理及运作机制 重构根本的思想是将 JobTracker 两个基本的功能分离成单独的组件,这两个功能是资源管理和任务调度 / 监控.新的资源管理器全局管理全部应用程序计 ...

  8. js-jquery-SweetAlert2【一】使用

    概述:SweetAlert2是SweetAlert-js的升级版本,它解决了SweetAlert-js中不能嵌入HTML标签的问题,并对弹出对话框进行了优化,同时提供对各种表单元素的支持,还增加了5种 ...

  9. keras搭建深度学习模型的一些小tips

    定义模型两种方法:  1.sequential 类仅用于层的线性堆叠,这是目前最常用的网络架构 2.函数式API,用于层组成的有向无环图,让你可以构建任意形式的架构 from keras import ...

  10. input text文本框内部最后面放一个按钮

    .ContSpan { border: 1px solid #; display: inline-block; } .ContSpan span { cursor: pointer; backgrou ...