У меня есть функция, которая должна менять слова каждые несколько секунд. Все работает как положено, но каждые несколько секунд я получаю следующую ошибку в консоли VSC:
TypeError: невозможно установить свойства null (настройка textContent) в Timeout._onTimeout (.../components/home/Hero.vue:36:28) в listOnTimeout (узел: внутренний/таймеры: 564:17)
Я не понимаю, почему я получаю эту ошибку, потому что когда я запускаю console.info word.value, я получаю элемент. Так что у меня есть к нему доступ и функция работает, слова меняются каждые несколько секунд, как и положено. Я немного запутался и не знаю, как решить проблему. Я не получаю ошибку в консоли Google Chrome, только в VSC.
<span ref = "word"></span>
onMounted(() => {
randomizeText()
wordChanger
})
onBeforeRouteLeave(() => {
clearTimeout(wordChanger)
})
const wordChanger = setInterval(randomizeText, 4000)
const word = ref(null)
const words = reactive(['Word-1', 'Word-2'])
let i = 0
function randomizeText() {
i = randomNum(i, words.length)
const newWord = words[i]
setTimeout(() => {
word.value.textContent = newWord
}, 200) // time to allow opacity to hit 0 before changing word
}
function randomNum(num, max) {
let j = Math.floor(Math.random() * max)
// ensure diff num every time
if (num === j) {
return randomNum(i, max)
} else {
return j
}
}



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


Вместо того, чтобы использовать const word = ref(null) как refs. Вы можете напрямую назвать это константой word в своем шаблоне. Он должен работать так же.
<template>
<div>
<span>{{ word }}</span>
</div>
</template>Внутри функции setTimeout измените это word.value.textContent = newWord на это word.value = newWord.
Вот обновленные коды. Проверено, и это работает.
<script setup lang = "ts">
onMounted(() => {
randomizeText()
wordChanger
})
onBeforeRouteLeave(() => {
clearTimeout(wordChanger)
})
const wordChanger = setInterval(randomizeText, 4000)
const word = ref('') // UPDATED
const words = reactive(['Word-1', 'Word-2'])
let i = 0
function randomizeText() {
i = randomNum(i, words.length)
const newWord = words[i]
setTimeout(() => {
word.value = newWord // UPDATED
}, 200) // time to allow opacity to hit 0 before changing word
}
function randomNum(num, max) {
let j = Math.floor(Math.random() * max)
// ensure diff num every time
if (num === j) {
return randomNum(i, max)
} else {
return j
}
}
</script>
<template>
<div>
<span>{{ word }}</span>
</div>
</template>Надеюсь, это поможет вам.
Вероятно, это проблема синхронизации (элемент не смонтирован, пока он изменяется кодом)
Вы можете сделать это, не устанавливая свойство textContent напрямую, используя директиву v-html и просто изменяя ссылочную переменную (ref)
Кроме того, вы можете просто начать интервал в крючке onMounted().
import {onMounted, reactive, ref} from "vue";
import {onBeforeRouteLeave} from "vue-router";
let wordChanger;
onMounted(() => {
randomizeText()
wordChanger = setInterval(randomizeText, 4000);
})
onBeforeRouteLeave(() => {
clearTimeout(wordChanger)
})
let word = ref('Hoi')
const words = reactive(['Word-1', 'Word-2'])
let i = 0
function randomizeText() {
i = randomNum(i, words.length)
const newWord = words[i]
setTimeout(() => {
word.value = newWord
}, 200) // time to allow opacity to hit 0 before changing word
}
function randomNum(num, max) {
let j = Math.floor(Math.random() * max)
// ensure diff num every time
if (num === j) {
return randomNum(i, max)
} else {
return j
}
}<span v-html = "word"></span>Вы, вероятно, неправильно используете ref 'word' и некоторые другие детали, которыми я делюсь ниже: - примечание: я добавляю комментарии к строкам, которые я изменил, чтобы помочь вам лучше понять
setup() {
const word = ref(null);
const words = reactive(['Word-1', 'Word-2']);
function randomizeText(i) {
const p = randomNum(i, words.length);
const newWord = words[p];
setTimeout(() => {
word.value = newWord;
}, 200); // time to allow opacity to hit 0 before changing word
}
function randomNum(num, max) {
let j = Math.floor(Math.random() * max);
// ensure diff num every time
if (num === j) {
// notice here as well I use num instead of i
return randomNum(num, max);
} else {
return j;
}
}
const wordChanger = setInterval(randomizeText, 4000);
onMounted(() => {
randomizeText(0); // start with 0
// wordChanger; // no need using this here
});
onBeforeRouteLeave(() => {
clearTimeout(wordChanger);
});
return {
word,
};
},
<span>{{ word }}</span>
вот демо: - https://stackblitz.com/edit/vue-rap7bb?file=src/components/HelloWorld.vue