Vue 3 Composition API - 如何获取挂载组件的组件元素($el)
Vue 3 Composition API - How to get the component element ($el) on which component is mounted
我想用onMounted
启动第三方库。为此,我需要组件元素作为其上下文。在 Vue 2 中,我会使用 this.$el
来获取它,但不确定如何使用组合函数来获取它。 setup
有两个参数,其中 none 包含元素。
setup(props, context) {
onMounted(() => {
interact($el)
.resizable();
})
}
tl;博士:
在 Vue 3 中,组件不再仅限于 1 个根元素。隐含地,这意味着您不再有 $el
.
您必须使用 ref
与模板中的任何元素进行交互:
<div ref="root" />
在setup
函数中,您应该将root
实例化为const root = ref(null)
。
在 Options API 中,你可以在任何方法或钩子中使用 this.$refs.root
,只要它在 mounted()
.
之后
正如@AndrewSee 在评论中指出的那样,当使用渲染函数(不是模板)时,您可以在 createElement
选项中指定所需的 ref
:
render: function (createElement) {
return createElement('div', { ref: 'root' })
}
// or, in short form:
render: h => h('div', { ref: 'root' })
初始答案:
如 docs、
中所述
[...] the concepts of reactive refs and template refs are unified in Vue 3.
您还有一个关于如何 ref
“根”元素的示例。显然,您不需要将其命名为 root。如果您愿意,可以将其命名为 $el
。但是,这样做并不意味着它将以 this.$el
的形式提供,而是以 this.$refs.$el
.
的形式提供
<template>
<div ref="root"></div>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
setup() {
const root = ref(null)
onMounted(() => {
// the DOM element will be assigned to the ref after initial render
console.log(root.value) // this is your $el
})
return {
root
}
}
}
</script>
在 Vue 3 中,您不再局限于 <template>
中的一个根元素,因此您必须明确地 ref
erence 任何您想与之交互的元素。
更新,2 年后。
各种组件样式的具体语法(它们不是不同的解决方案,它们是同一事物的不同写法):
<script setup>
:
<script setup>
import { ref, onMounted } from 'vue';
const root = ref(null);
onMounted(() => console.log(root.value.outerHTML));
</script>
<template>
<div ref="root" />
</template>
<script setup lang="ts">
:
<script setup lang="ts">
import { ref, onMounted } from 'vue';
const root = ref<HTMLElement | null>(null);
onMounted(() => { console.log(root.value?.outerHTML) );
</script>
<template>
<div ref="root" />
</template>
选项API:
<script>
export default {
mounted() {
console.log(this.$refs.root.outerHTML);
}
}
</script>
<template>
<div ref="root" />
</template>
在 Vue 3 + Composition API 中没有提供 $el
替代方案。
即使您使用带选项 API 的 Vue 3,由于片段的可用性,建议使用模板引用直接访问 DOM 节点,而不是依赖 this.$el
.
如何发起third-part-library
假设我们有一个 div 元素用于 third-part-library:
<template>
Below we have a third-party-lib
<div class="third-party-lib"></div>
</template>
然后我们想从 Javascript:
启动它
Solution 1 (recommended): Using template refs
<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>
Solution 2 (not recommended): Using non-documented @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>
只是在这里添加我的 2 美分,并想更正一些其他答案所说的 Vue 3 不再有 $el
。
它还有它: https://vuejs.org/api/component-instance.html#el.
不鼓励使用它 在 multi-root 的情况下 $el
元素无法确定为特定的根元素,并且 为了与 single-root 组件保持一致(其中 $el 的工作方式与 Vue 2 相同),文档建议您改用 $refs。
对于 multi-root 组件,$el
ref 位于元素之前最近的文本节点(或 SSR hydration 的注释)。
这并不意味着$el
不可靠,相反,因为这种机制是内部使用的,用于SSR水合作用。
在大多数情况下,您可以使用 $refs
,您应该这样做。
但如果你不能,就像下面的情况,你仍然可以依靠 $el
:
<template>
# an empty text node exists here in the DOM.
<slot name="activator" :on="activatorEventHandlers">
<other-component />
</template>
在这种情况下(事件侦听器附加到用户槽的工具提示和上下文菜单的情况),第一个元素是槽,您不能在槽上添加 ref。
因此使用 $el
将指向第一个文本节点,因此 this.$el.nextElementSibling
将是通过用户槽指定的元素。
我想用onMounted
启动第三方库。为此,我需要组件元素作为其上下文。在 Vue 2 中,我会使用 this.$el
来获取它,但不确定如何使用组合函数来获取它。 setup
有两个参数,其中 none 包含元素。
setup(props, context) {
onMounted(() => {
interact($el)
.resizable();
})
}
tl;博士:
在 Vue 3 中,组件不再仅限于 1 个根元素。隐含地,这意味着您不再有 $el
.
您必须使用 ref
与模板中的任何元素进行交互:
<div ref="root" />
在setup
函数中,您应该将root
实例化为const root = ref(null)
。
在 Options API 中,你可以在任何方法或钩子中使用 this.$refs.root
,只要它在 mounted()
.
之后
正如@AndrewSee 在评论中指出的那样,当使用渲染函数(不是模板)时,您可以在 createElement
选项中指定所需的 ref
:
render: function (createElement) {
return createElement('div', { ref: 'root' })
}
// or, in short form:
render: h => h('div', { ref: 'root' })
初始答案:
如 docs、
中所述[...] the concepts of reactive refs and template refs are unified in Vue 3.
您还有一个关于如何 ref
“根”元素的示例。显然,您不需要将其命名为 root。如果您愿意,可以将其命名为 $el
。但是,这样做并不意味着它将以 this.$el
的形式提供,而是以 this.$refs.$el
.
<template>
<div ref="root"></div>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
setup() {
const root = ref(null)
onMounted(() => {
// the DOM element will be assigned to the ref after initial render
console.log(root.value) // this is your $el
})
return {
root
}
}
}
</script>
在 Vue 3 中,您不再局限于 <template>
中的一个根元素,因此您必须明确地 ref
erence 任何您想与之交互的元素。
更新,2 年后。
各种组件样式的具体语法(它们不是不同的解决方案,它们是同一事物的不同写法):
<script setup>
:
<script setup>
import { ref, onMounted } from 'vue';
const root = ref(null);
onMounted(() => console.log(root.value.outerHTML));
</script>
<template>
<div ref="root" />
</template>
<script setup lang="ts">
:
<script setup lang="ts">
import { ref, onMounted } from 'vue';
const root = ref<HTMLElement | null>(null);
onMounted(() => { console.log(root.value?.outerHTML) );
</script>
<template>
<div ref="root" />
</template>
选项API:
<script>
export default {
mounted() {
console.log(this.$refs.root.outerHTML);
}
}
</script>
<template>
<div ref="root" />
</template>
在 Vue 3 + Composition API 中没有提供 $el
替代方案。
即使您使用带选项 API 的 Vue 3,由于片段的可用性,建议使用模板引用直接访问 DOM 节点,而不是依赖 this.$el
.
如何发起third-part-library
假设我们有一个 div 元素用于 third-part-library:
<template>
Below we have a third-party-lib
<div class="third-party-lib"></div>
</template>
然后我们想从 Javascript:
启动它Solution 1 (recommended): Using template refs
<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>
Solution 2 (not recommended): Using non-documented
@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>
只是在这里添加我的 2 美分,并想更正一些其他答案所说的 Vue 3 不再有 $el
。
它还有它: https://vuejs.org/api/component-instance.html#el.
不鼓励使用它 在 multi-root 的情况下 $el
元素无法确定为特定的根元素,并且 为了与 single-root 组件保持一致(其中 $el 的工作方式与 Vue 2 相同),文档建议您改用 $refs。
对于 multi-root 组件,$el
ref 位于元素之前最近的文本节点(或 SSR hydration 的注释)。
这并不意味着$el
不可靠,相反,因为这种机制是内部使用的,用于SSR水合作用。
在大多数情况下,您可以使用 $refs
,您应该这样做。
但如果你不能,就像下面的情况,你仍然可以依靠 $el
:
<template>
# an empty text node exists here in the DOM.
<slot name="activator" :on="activatorEventHandlers">
<other-component />
</template>
在这种情况下(事件侦听器附加到用户槽的工具提示和上下文菜单的情况),第一个元素是槽,您不能在槽上添加 ref。
因此使用 $el
将指向第一个文本节点,因此 this.$el.nextElementSibling
将是通过用户槽指定的元素。