я думаю, что это проблема области внутри моей вспомогательной функции, я успешно реализовал ту же логику в своем компоненте, и она работает отлично
я уже использовал составную функцию для использования ref() с переменной, которую я хочу вернуть
=> это рабочий код внутри моего компонента
// component.vue
setup() {
const subnavDiv = ref(false) // this is the variable that the bellow code update
onMounted(() => {
const routEl = document.querySelector('.main')
const fixedNav = document.querySelector('.main-nav')
const el = document.querySelector('.search')
let prevYPosition = 0
let directionVar = 'up'
const options = {
root: routEl,
rootMargin: `${fixedNav.offsetHeight * -1}px`,
threshold: 0.7
}
const setScrollDirection = () => {
if (routEl.scrollTop > prevYPosition) {
directionVar = 'down'
} else {
directionVar = 'up'
}
prevYPosition = routEl.scrollTop
}
const onIntersection = ([e]) => {
setScrollDirection()
if ((directionVar === 'down' && e.boundingClientRect.top > 0) || !e.isIntersecting) {
console.info('down')
subnavDiv.value = true
} else {
subnavDiv.value = false
}
if (
e.isIntersecting &&
(e.boundingClientRect.top < fixedNav.offsetHeight ||
e.boundingClientRect.top > fixedNav.offsetHeight)
) {
subnavDiv.value = false
}
}
const observer = new IntersectionObserver(onIntersection, options)
observer.observe(el)
})
return {
subnavDiv
}
}
}
}
=> после перемещения того же кода из компонента
// component.vue
setup() {
const subnavDiv = ref(false)
onMounted(() => {
const rootEl = document.querySelector('.main')
const fixedNav = document.querySelector('.main-nav')
const el = document.querySelector('.search')
subnavDiv.value = onIntersect(rootEl, 0.7, fixedNav, el) // the helper function call: this line is supposed to update the value of subnavDiv
})
})
/////////////////////// $$$$$$$$$$$$$$$$$$ ///////////////
onIntersect.js // the helper function
const onIntersect = (rootElement, thresholdValue, elementToChange, elementToWatch) => {
let prevYPosition = 0
let directionVar = 'up'
const options = {
root: rootElement,
rootMargin: `${elementToChange.offsetHeight * -1}px`,
threshold: thresholdValue
}
let bool = false // this is the variable that i am trying to return from this function
const setScrollDirection = () => {
if (rootElement.scrollTop > prevYPosition) {
directionVar = 'down'
} else {
directionVar = 'up'
}
prevYPosition = rootElement.scrollTop
}
const onIntersection = ([e]) => {
setScrollDirection()
if ((directionVar === 'down' && e.boundingClientRect.top > 0) || !e.isIntersecting) {
console.info('down')
bool = true
} else {
bool = false
}
if (
e.isIntersecting &&
(e.boundingClientRect.top < elementToChange.offsetHeight ||
e.boundingClientRect.top > elementToChange.offsetHeight)
) {
bool = false
}
}
const observer = new IntersectionObserver(onIntersection, options)
observer.observe(elementToWatch)
return bool // the return (not returning any thing)
}
export default onIntersect



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Важной частью является ссылка. Целью шаблона ссылки является передача значения по ссылке между областями видимости. onIntersect должен быть составным и следовать обычным для них соглашениям. Его следует вызывать setup, а не хуки жизненного цикла.
Прямой доступ к DOM нежелателен в Vue. Если main и т. д. создаются в одних и тех же компонентах, они должны быть ссылками на шаблоны, в противном случае они могут быть предоставлены компонуемому объекту как ссылки, чтобы он мог использовать реактивность. Использование onMounted внутри составного объекта сделало бы его негибким и склонным к гонкам. Учитывая, что сначала необходимо получить доступ к elementToWatch, это может быть:
const useIntersect = (rootElRef, threshold, changedElRef, watchedElRef) => {
const bool = ref(false);
let observer;
watchEffect(() => {
const rootEl = unref(rootElRef);
const changedEl = unref(changedElRef)
const watchedEl = unref(watchedElRef);
if (rootEl && watchedEl) {
...
observer = new IntersectionObserver(onIntersection, options)
observer.observe(watchedEl)
}
return () => {
// clean up
observer?.disconnect();
}
});
return bool;
};
При необходимости к элементам DOM по-прежнему можно получить прямой доступ, но в любом случае они являются ссылками:
...
const rootElRef = ref(null);
const isSubnav = useIntersect(rootElRef, ...);
onMounted(() => {
rootElRef.value = document.querySelector('.main');
...
В качестве побочного эффекта он может реагировать на изменения параметров, например. его можно принудительно воссоздать наблюдателя, если необходимо изменить параметры.
Тогда это будет похоже на последний фрагмент шоу. Ваш случай не уникален, подобные проблемы постоянно решаются с помощью составных элементов.
в последнем фрагменте вы не можете получить доступ к обновленному значению ref внутри хука onMounted, поэтому вы не можете вызвать составную функцию вне хука onMounted. еще раз спасибо за ваш ответ
Можете ли вы уточнить, что вы имеете в виду? rootElRef, ChangeElRef, WatchElRef содержат ссылки на элементы, которые недоступны в теле настройки, но доступны в смонтированном хуке, именно здесь вы назначаете значения, как только они становятся доступными. И наблюдатель не запустится, пока не будут доступны все элементы. Последний фрагмент должен заменять первый фрагмент в вопросе. Если по какой-то причине это у вас не работает, можете ли вы предоставить работоспособную демо-версию, чтобы ее можно было исправить?
это работоспособная демо: ссылка. все, что я хочу, это создать функцию многократного использования, чтобы я мог использовать ее повсюду в своем проекте. Спасибо
Хорошо, спасибо. Именно так он и должен работать с минимальными изменениями имен и использования ссылок, codeandbox.io/p/sandbox/peaceful-goodall-4fxtgr. Если можно получить доступ к ссылкам на шаблоны «main» и т. д. напрямую вместо querySelector, как в этом примере, это будет лучший дизайн, но любой способ будет работать.
большое спасибо, но есть небольшая проблема; codeandbox говорит: «Вероятно, песочница, к которой вы пытаетесь получить доступ, не существует или у вас нет необходимых разрешений для доступа к ней». пожалуйста, проверьте разрешения, возможно, это не публично
Я обновил, проверь
Я не знаю, как вас благодарить, все работает отлично, спасибо за поддержку
Пожалуйста.
Благодарю за ваш ответ. но невозможно получить значения ссылок вне ловушки onMounted. поэтому ваши предложения не будут работать, и именно поэтому я использую вспомогательную функцию вместо составной функции, чтобы я мог вызывать ее внутри крючка onMounted