Vue 3模板引用未返回值



我在一个nuxt项目中使用vue 3模板refs,使用composition API,就像我对其他组件所做的那样,这些组件似乎运行良好。但是,在这种情况下,它们返回null。

这是我的模板:

<template>
<div class="horizontal-scroll-fix" ref="container">
<div class="horizontal-scroll-fix__scroll-fix">
<container class="horizontal-scroll-fix__container">
<div class="horizontal-scroll-fix__viewport" ref="viewport">
<div class="horizontal-scroll-fix__wrapper" ref="wrapper">
<slot></slot>
</div>
</div>
</container>
</div>
</div>
</template>

<script>
import { ref, computed, onMounted, onBeforeUnmount, useSlots } from 'vue';
export default { // tried also to use shorthand <script setup> but no luck either
setup() {
const container = ref(null);
const wrapper = ref(null);
const viewport = ref(null);

onMounted(() => {
if (process.client) {
console.log(container?.value) // returns undefined
}
});

}
}
</script>

console.log ref对象返回以下内容:

RefImpl {__v_isShallow: false, dep: undefined, __v_isRef: true, _rawValue: undefined, _value: undefined}

更新

从那以后,我被告知我需要在设置脚本结束时返回裁判。所以return { container, wrapper, viewport }然而,令人困惑的是,我的项目中的所有其他组件都没有这样做,但运行良好。那么我没有看到的这个有什么不同呢?下面是另一个组件的例子,它的模板引用工作得非常好,并且不返回值:

<template>
<container>
<div :class="'sequence sequence--'+section.displayAs">
<div class="sequence__content" ref="content">
// removed inner content for the purpose of demonstrating
</div>
</div>
</container>
</template>
<script setup> 
import { ref, computed, onMounted, onUnmounted } from 'vue';
const props = defineProps({
section: {
required:true,
type:Object
}
});
const isDesktop = ref(false);
const currentSectionIndex = ref(0);
const fixedVisual = ref(null);
const content = ref(null);
function initMediaQuery() {
const mediaQuery = window.matchMedia('(min-width:1024px)');
checkDeviceSize(mediaQuery);
mediaQuery.addListener(checkDeviceSize);

};
function checkDeviceSize(query) {
if (query && query.matches) {
isDesktop.value = true
} else {
isDesktop.value = false
}
};
function initObserver() {
if (props.section?.displayAs === 'timeline' && isDesktop) {
console.log(isDesktop);
const target = fixedVisual;
const sections = content?.value.querySelectorAll('.sequence__section');
if (target && sections?.length) {
let callback = (entries, observer) => {
entries.forEach((entry,index) => {
if (entry.isIntersecting) {
currentSectionIndex.value = parseInt(entry.target.getAttribute('data-index'));
}   
})
}
let options = {
rootMargin: '0px',
threshold:1.0
}
let observer = new IntersectionObserver(callback,options);
sections.forEach(section => {
observer.observe(section);
});
}
}
}

onMounted(() => {
if (process.client) {
initMediaQuery();
initObserver();
window.addEventListener("resize", initObserver);
}
});
onUnmounted(()=> {
if (process.client) {
window.removeEventListener("resize", initObserver);
}
});


</script>

您需要在setup()方法的末尾返回3个变量:

setup() {
...
return {
container,
wrapper,
viewport
}
}

方法setup()在组件生命周期开始时调用,就像渲染器遇到它一样。这意味着<template>主体中使用的所有元素必须在setup()完成时已知。

设置的主体缺少要在<template>中使用的ref值的返回。为了获得预期的行为,您应该更改setup():

setup() {
const container = ref(null);
const wrapper = ref(null);
const viewport = ref(null);
// callbacks such as onMounted, onBeforeCreate, etc.

return { container, wrapper, viewport };
}

要回答@ToddPadwick关于为什么其他组件没有返回refs并且仍然工作正常的问题:

Nuxt 3文档通过自动导入进行解释:https://nuxt.com/docs/guide/concepts/auto-imports#vue-汽车进口

Vue 3公开了Reactivity API,如ref或computed,以及Nuxt自动导入的生命周期挂钩和助手。

因此,您不必在脚本末尾编写return { container, wrapper, viewport }。Nuxt 3会为你做这件事,除非你像这样关闭它:

https://nuxt.com/docs/guide/concepts/auto-imports#disabling-汽车进口

最新更新