Vue 3 Composition API - 如何获取安装组件的组件元素($el)

Dam*_*nov 15 vue.js vuejs3 vue-composition-api

我想用来onMounted启动第三方库。为此,我需要组件元素作为其上下文。在 Vue 2 中,我会使用它,this.$el但不确定如何使用组合函数来实现。setup有两个参数,没有一个包含元素。

setup(props, context) {
    onMounted(() => {
        interact($el)
            .resizable();
    })
}
Run Code Online (Sandbox Code Playgroud)

And*_*hiu 18

tl;博士:

在 Vue 3 中,组件不再仅限于 1 个根元素。隐含地,这意味着您不再拥有$el.
您必须使用ref与模板中的任何元素进行交互。

正如@AndrewSee 在评论中指出的那样,当使用渲染函数(不是模板)时,您可以refcreateElement选项中指定所需的内容:

render: function (createElement) {
  return createElement('div', { ref: 'root' })
}
// or, in short form:
render: h => h('div', { ref: 'root' })
Run Code Online (Sandbox Code Playgroud)

初步回答:

正如文档中所述

[...]响应式引用模板引用的概念在 Vue 3 中是统一的。

你还有一个关于如何ref“根”元素的例子。显然,您不需要将其命名为 root。命名它$el,如果你愿意。但是,这样做并不意味着它将作为 提供this.$el,而是作为this.$refs.$el.

render: function (createElement) {
  return createElement('div', { ref: 'root' })
}
// or, in short form:
render: h => h('div', { ref: 'root' })
Run Code Online (Sandbox Code Playgroud)

在 Vue 3 中,您不再仅限于 中的一个根元素<template>,因此您必须特别确定ref要与之交互的任何元素。

  • @curly,“ref”已经绑定,就像“v-on”和“v-bind”一样。最终,唯一能回答你问题的人是 Vue 的创建者 Evan You。 (3认同)
  • 找到我的问题的答案,使用 `h('div', {ref: root})`。 (2认同)

rol*_*oli 6

在 Vue 3 + Composition API 中没有$el提供替代方案。

即使您使用带有Options API的Vue 3,由于Fragments的可用性,建议使用模板引用来直接访问DOM节点,而不是依赖于this.$el.


如何启动第三方库

假设我们有一个用于第三方库的 div 元素:

<template>
  Below we have a third-party-lib
  <div class="third-party-lib"></div>
</template>
Run Code Online (Sandbox Code Playgroud)

然后我们想从 Javascript 启动它:

解决方案 1(推荐):使用模板引用

<script setup>
import { ref, onMounted } from 'vue';

const $thirdPartyLib = ref(null); // template ref

onMounted(() => {
  $thirdPartyLib.value.innerText = 'Dynamically loaded';
});
</script>

<template>
  Below we have a third-party-lib
  <div ref="$thirdPartyLib" class="third-party-lib"></div>
</template>
Run Code Online (Sandbox Code Playgroud)

解决方案2(不推荐):使用未记录的@VnodeMounted

<script setup>
function initLib({ el }) {
  el.innerText = 'Dynamic content';
}
</script>

<template>
  Below we have a third-party-lib
  <div class="third-party-lib" @VnodeMounted="initLib"></div>
</template>
Run Code Online (Sandbox Code Playgroud)

实时查看这两种解决方案


ant*_*oni 5

只是在这里添加我的 2 美分,并想纠正其他一些答案所说的 Vue 3 不再有的内容$el

它仍然有它: https: //vuejs.org/api/component-instance.html#el

$el在多根元素无法确定为特定根元素的情况下,不鼓励使用它,并且为了与单根组件保持一致(其中 $el 的工作方式与 Vue 2 相同),文档建议您使用 $refs 代替。

对于多根组件,$el引用位于元素之前最近的文本节点(或 SSR 水合的注释)。

$el相反,这并不意味着不可靠,因为这种机制是内部使用的,用于 SSR 水合。

在大多数情况下,您可以使用$refs并且应该使用。

但如果你不能,就像下面的例子一样,你仍然可以依靠$el

<template>
  # an empty text node exists here in the DOM.
  <slot name="activator" :on="activatorEventHandlers">
  <other-component />
</template>
Run Code Online (Sandbox Code Playgroud)

在这种情况下(工具提示和上下文菜单的情况,其中事件侦听器附加到用户槽),第一个元素是槽,并且您无法在槽上添加引用。

因此 using$el将指向第一个文本节点,因此this.$el.nextElementSibling将指向通过用户槽给出的元素。

  • 展示如何在 Vue 3 中访问 `$el` 会很有用 (4认同)