我想用
onMounted
来启动第三方库。为此,我需要组件元素作为其上下文。在 Vue 2 中,我会使用 this.$el
来获取它,但不知道如何使用组合函数来实现它。 setup
有两个参数,但都不包含该元素。
setup(props, context) {
onMounted(() => {
interact($el)
.resizable();
})
}
tl;博士:
在 Vue 3 中,组件不再仅限于 1 个根元素。隐含地,这意味着您不再拥有
$el
。
您必须使用
ref
与模板中的任何元素进行交互:
<div ref="root" />
在
setup
函数中,您应该将 root
实例化为 const root = ref(null)
。
在选项 API 中,您可以在任何方法或挂钩中使用
this.$refs.root
,只要它位于 mounted()
之后即可。
正如@AndrewSee在评论中指出的,当使用渲染函数(而不是模板)时,您可以在
ref
选项中指定所需的createElement
:
render: function (createElement) {
return createElement('div', { ref: 'root' })
}
// or, in short form:
render: h => h('div', { ref: 'root' })
初步回答:
如文档中所述,
[...] reactive refs 和 template refs 的概念在 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>
只是在这里添加我的 2 美分,并想纠正其他一些答案所说的 Vue 3 不再有
$el
的内容。
它仍然有它:https://vuejs.org/api/component-instance.html#el.
在多根情况下不鼓励使用它,其中
$el
元素无法确定为特定的根元素,并且为了保持一致性与单根组件(其中$el的工作方式与Vue相同) 2),文档建议您使用 $refs 代替。
对于多根组件,
$el
ref 位于元素之前最近的文本节点(或 SSR 水合的注释)。
这并不意味着
$el
不可靠,相反,因为该机制是内部使用的并且用于SSR水合作用。
在大多数情况下,您可以使用
$refs
并且您应该使用。
但如果你不能,就像下面的例子,你仍然可以信赖
$el
:
<template>
# an empty text node exists here in the DOM.
<slot name="activator" :on="activatorEventHandlers">
<other-component />
</template>
在这种情况下(工具提示和上下文菜单的情况,其中事件侦听器附加到用户槽),第一个元素是槽,并且您无法在槽上添加引用。
因此使用
$el
将指向第一个文本节点,因此 this.$el.nextElementSibling
将是通过用户槽给出的元素。
$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>
然后我们想从 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>
解决方案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>
有些答案给出了很好的方法,我会添加两个方法。
一个:
instance.proxy.$el
拖曳: onVnodeMounted
挂钩
<script setup>
const instance = getCurrentInstance()
onMounted(() => {
console.log(instance.proxy.$el)
})
function onVNodeMounted(VNode) {
console.log('onVNodeMounted', VNode.el)
}
</script>
<template>
<div :onVnodeMounted="onVNodeMounted">
</div>
</template>
注意 @VnodeMounted="onVNodeMounted" 当我回答时不起作用。 Vue的版本是3.3.4.
Plus
、onVnodeMounted
没有放在vue的文档中,将来可能会更改。您可以在模板和 jsx 中使用它们。onVnodeUpdated
更好。getCurrentInstance
使用getCurrentInstance时,注意模板构建。
<script setup>
const instance = getCurrentInstance()
onMounted(() => {
console.log(instance.proxy.$el)
console.log(instance.proxy.$el.nextElementSibling)
})
</script>
<template>
<!-- comment -->
<div>
get #text node by proxy.$el . nextElementSibling is root node
</div>
</template>
也是文本节点。proxy.$el
<script setup>
const instance = getCurrentInstance()
onMounted(() => {
console.log(instance.proxy.$el)
console.log(instance.proxy.$el.nextElementSibling)
})
</script>
<template>
<div>tow root</div>
<div>
get #text node by proxy.$el . nextElementSibling is first div
</div>
</template>