如果目标是 Vue3 中的异步组件,为什么我无法获得 ref?



如果我正在使用import SearchBarPopper from './xxx':导入组件

import SearchBarPopper from './search-bar-popper';
export default {
components: {
SearchBarPopper,
},
};

在模板中定义引用名称:

<search-bar-popper ref="popper" />

然后在其他组件触发@click:时调用其函数

methods: {
onClick(index) {
console.log(this.$refs.popper);
if (this.$refs.popper) {
this.$refs.popper.setSearchListIndex(index);
}
},
}

它是有效的。我有这样的代理:

[[Target]]: Object
searchBar: Proxy {setPopperRelativeIndex: ƒ, onInputFocus: ƒ, onInputBlur: ƒ, onInputKeyUp: ƒ, 
onInputKeyDown: ƒ, …}
setSearchListIndex: ƒ ()
show: (...)
$: (...)
$attrs: (...)
$data: (...)
$el: (...)
$emit: (...)
$forceUpdate: (...)
$nextTick: (...)
$options: (...)
$parent: (...)
$props: (...)
$refs: (...)
$root: (...)
$router: (...)
$slots: (...)
$store: (...)
$watch: (...)
_: (...)

它有我需要的功能。

现在让我们重试,让我们用defineAsyncComponent():导入组件

export default {
components: {
SearchBarPopper: defineAsyncComponent(() => import('./search-bar-popper'))
},
};

仍然在手动事件@click中触发,而不是从mounted()或其他什么中触发。

这一次我不能正确地得到参考:

[[Target]]: Object
$: (...)
$attrs: (...)
$data: (...)
$el: (...)
$emit: (...)
$forceUpdate: (...)
$nextTick: (...)
$options: (...)
$parent: (...)
$props: (...)
$refs: (...)
$root: (...)
$router: (...)
$slots: (...)
$store: (...)
$watch: (...)
_: (...)

参考内容仍然打印,但在里面我找不到setSearchListIndex()的功能。

顺便说一下,组件SearchBarPopper看起来是这样的:

<template>
<div class="ls-view-home-search__popper">
<ls-collapse class="ls-view-home-search__popper__wrap" :show="show">
<search-bar-list ref="search-bar-list" />
</ls-collapse>
</div>
</template>

这是怎么回事?

这是因为当您将组件定义为async(使用defineAsyncComponent(时,您得到的是包装器组件。包装器组件作为父组件的直接子组件安装,它管理SeachBarPopper组件的异步加载。

如果您查看vue devtools中的组件树,您会发现在真正的SearchBarPopper周围有一个额外的AsyncComponentWrapper组件。在这种情况下,您的ref指向的是AsyncComponentWrapper,而不是其中的SearhBarPopper

在版本3.0.4+中

当您将ref绑定到异步组件(使用defineAsyncComponent(时,他们解决了这个问题。

ref将绑定到CCD_ 15内部的实际组件。

顺便说一句,如果您在自定义组件中使用<script setup>。应该使用defineExpose来公开要在父上下文中使用的方法或其他内容。

// child component
import { defineExpose } from 'vue'
// cannot be accessed from outside
function hello(){
console.log('hello')
}
// can be accessed from outside cause defineExpose
function hello2(){
console.log('hello2')
}
defineExpose({ hello2 })

最新更新