admin管理员组文章数量:1406060
I am using vue 3 template refs, in a nuxt project, with position API as I have done with other ponents which seem to work fine. However, in this instance, they are returning null.
Here is my template:
<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, puted, 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.logging the ref object returns the following:
RefImpl {__v_isShallow: false, dep: undefined, __v_isRef: true, _rawValue: undefined, _value: undefined}
UDPDATE
I have since been informed that I need to return the refs at the end of the set up script. so return { container, wrapper, viewport }
However, what is confusing is that all other ponents I have in my project, don't do this, but work fine. so what is different about this one that I am not seeing? Here is an example of another ponent that has template refs that works perfectly fine, and doesn't return the values:
<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, puted, 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>
I am using vue 3 template refs, in a nuxt project, with position API as I have done with other ponents which seem to work fine. However, in this instance, they are returning null.
Here is my template:
<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, puted, 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.logging the ref object returns the following:
RefImpl {__v_isShallow: false, dep: undefined, __v_isRef: true, _rawValue: undefined, _value: undefined}
UDPDATE
I have since been informed that I need to return the refs at the end of the set up script. so return { container, wrapper, viewport }
However, what is confusing is that all other ponents I have in my project, don't do this, but work fine. so what is different about this one that I am not seeing? Here is an example of another ponent that has template refs that works perfectly fine, and doesn't return the values:
<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, puted, 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>
Share
Improve this question
edited Oct 27, 2022 at 10:27
ToddPadwick
asked Oct 26, 2022 at 17:02
ToddPadwickToddPadwick
5051 gold badge7 silver badges14 bronze badges
1
- I think it works in other ponents because with <script setup> variables don't need to be returned at the end. – Gabriel Commented Oct 27, 2022 at 15:03
4 Answers
Reset to default 3You need to return the 3 variables at the end of the setup()
method :
setup() {
...
return {
container,
wrapper,
viewport
}
}
The method setup()
is called at the beginning of the lifespan of the ponent, just as renderer encounters it. That means that all elements used in the body of the <template>
must be known at the moment that setup()
finishes.
Body of your setup is missing the return of ref
values you wish to use in <template>
. In order to get the expected behavior, you should change your setup()
:
setup() {
const container = ref(null);
const wrapper = ref(null);
const viewport = ref(null);
// callbacks such as onMounted, onBeforeCreate, etc.
return { container, wrapper, viewport };
}
In my case, I was using client rendering, and needed this:
onMounted( async () => {
await nextTick(); // we need this for client rendering,
// get ref.value
});
see here: https://nuxt./docs/guide/directory-structure/ponents#client-ponents
It took me hours to find this, googling the error message, so I hope this helps someone else.
To answer @ToddPadwick about why other ponents don't return the refs and still work fine :
Nuxt 3 docs explain it by auto-import : https://nuxt./docs/guide/concepts/auto-imports#vue-auto-imports
Vue 3 exposes Reactivity APIs like ref or puted, as well as lifecycle hooks and helpers that are auto-imported by Nuxt.
So, you don't have to write return { container, wrapper, viewport }
at the end of your script. Nuxt 3 will do it for you except if you've turn it off like this :
https://nuxt./docs/guide/concepts/auto-imports#disabling-auto-imports
本文标签: javascriptVue 3 Template refs not returning a valueStack Overflow
版权声明:本文标题:javascript - Vue 3 Template refs not returning a value - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744959576a2634569.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论