Vue 使用 ref 注册组件的特性

一直以来,我对于 VueJS 中对于使用 ref 注册的组件,在使用 $refs 调用时,为什么有时候是一个 DOM元素/组件实例,是时候会是一个实例数组

所以在很长一段时间内我觉得 ref 注册的的组件在使用 $refs 调用时有很大的不确定性,虽然我的弹窗组件一直都是用的 $refs.modal.open() 来打开的。

直到前一段时间,我在一个场景下想在 v-for 循环渲染的组件下 slot 模板中想使用 ref 注册成一个实例集合来调用时,发现怎么样重写返回的都只是一个组件实例,而不是一个组件实例集合。

所以有了这样一篇笔记。

注册 | ref

用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。

  • 如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;
  • 如果用在子组件上,引用就指向组件实例:

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

所以不要在 mounted() 之前的生命周期钩子里边直接使用 $refs 来获取元素,
或者在没有渲染组件的情况下调用元素内的属性或方法,如果一定要的话,记得放在 $nextTick() 里。


使用 | $refs

一个对象,持有注册过 ref attribute 的所有 DOM 元素和组件实例。

  • 只读
  • 允许父级组件通过 $refs 来访问子组件实例内部元素的访问,比如来访问子组件实例内的 datamethods
  • refv-for 一起使用的时候,将得到一个 DOM 节点数组 或 包含了对应数据源 的组件实例的。

1、什么时候只返回一个组件/DOM实例

一般来说,直接在一个没有使用 v-for 循环的元素上使用 ref 注册的元素,在使用 this.$refs.xxx 获取时,返回的只会是一个组件实例。

2、什么时候返回一个实例集合

按照文档上边来看,在使用 v-for 循环的元素上使用 ref 注册的元素,在使用 this.$refs.xxx 获取时,会返回一个实例集合。

有没有其他办法?比如我不是使用 v-for 循环出来的实例,但是我想注册在同一个 ref 下。

暂时没有办法。

附:

ref — Vue.js
vm.$refs — Vue.js
访问子组件实例或子元素 — Vue.js
Document.querySelectorAll - MDN
querySelectorAll 方法相比 getElementsBy 系列方法有什么区别?- 知乎

如何评价 Vue 的 ref 语法糖提案?尤雨溪的回答 - 知乎