Я следил за этим руководством по vue3: Учебное пособие по Vue.js: от новичка до разработчика интерфейса https://thewikihow.com/video_1GNsWa_EZdw&t=48s
На моей стороне тоже все работает, кроме «обновления» навигационного списка. Он говорит о Eventlistener для обновления страницы, начиная с 04:01:20.
Почему назначение нового массива для this.pages не работает для обновления v-for на моей стороне и что я могу попробовать/отладить?
this.$bus.$on('page-updated', () => {
this.pages = [...this.$pages.getAllPages()];
});
Соответствующие части сценария:
Navbar.vue
<template>
...
<navbar-link
v-for = "(page, index) in publishedPages"
class = "nav-item"
:key = "index"
:page = "page"
:index = "index"
></navbar-link>
...
</template>
<script>
import NavbarLink from './NavbarLink.vue';
export default {
components: {
NavbarLink
},
inject: ['$pages', '$bus'],
created() {
this.pages = this.$pages.getAllPages();
this.$bus.$on('page-updated', () => {
this.pages = [...this.$pages.getAllPages()];
});
},
data() {
return {
theme: 'dark',
data: []
}
},
computed: {
publishedPages() {
return this.pages.filter(p => p.published)
}
},
..
}
}
</script>
PadeEdit.vue
<script setup>
import { useRouter } from 'vue-router';
import { inject } from 'vue';
const router = useRouter();
const pages = inject('$pages');
const bus = inject('$bus');
const {index} = defineProps(['index']);
let page = pages.getSinglePage(index);
function submit() {
pages.editPage(index, page);
bus.$emit('page-updated', {
index,
page
});
...
}
...
</script>
События.js
const events = new Map();
export default {
$on(eventName, fn) {
if (!events.has(eventName)) {
events.set(eventName, [])
}
events.get(eventName).push(fn);
},
$emit(eventName, data) {
if (events.has(eventName)) {
events.get(eventName).forEach(fn => fn(data));
}
}
};
данные.js
const pagesKey = 'pages';
let pagesJson = localStorage.getItem(pagesKey);
let pagesStore = JSON.parse(pagesJson);
function save() {
localStorage.setItem(pagesKey, JSON.stringify(pagesStore));
}
export default {
addPage(page){
pagesStore.push(page);
save();
},
getAllPages() {
return pagesStore;
},
getSinglePage(index) {
return pagesStore[index];
},
editPage(index, page) {
pagesStore[index] = page;
save();
}
}
Я выложил проект на github: https://github.com/qumundo/vue-cli-starter
@yoduh Я выложил проект на github: github.com/qumundo/vue-cli-starter
Привет, Филипп, можешь ли ты убедиться, что все файлы загружены в проект github? Единственным компонентом Vue сейчас является App.vue, и кроме .js нет файлов main.js. Как только весь проект будет загружен, я посмотрю на него. Спасибо
@yoduh Извините, я пропустил некоторые ... все файлы должны быть доступны сейчас. Спасибо, что заглянули!



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


Ваш Navbar.vue data() должен быть изменен на:
data() {
return {
theme: 'dark',
pages: [], // <--- was previously data: []
counter: 0
}
},
После отладки полного компонента Navbar.vue проблема заключается в том, что вычисляемое свойство ссылается на неправильную ссылку this.pages
publishedPages() {
return this.pages.filter(p => p.published);
}
Вышеупомянутое this.pages на самом деле исходит от крючка created():
created() {
this.getThemeSetting();
this.pages = this.$pages.getAllPages();
...
}
Но this.pages здесь не реактивная переменная. При обновлении вычисляемое свойство не запускается повторно.
Это может вызвать вопрос: «Почему это работает изначально?».
Это потому, что вычисляемые свойства запускаются один раз при создании компонента, чтобы получить их начальные значения, и вы буквально определяете pages на this с помощью инструкции this.pages = ..., поэтому во время инициализации все работает нормально. Но поскольку this.pages в хуке created() не является реактивной переменной, this.pages не «отслеживается» Vue, поэтому вычисляемое свойство никогда не запускается снова при обновлении this.pages. Только переменные, определенные в data(), являются реактивными.
Тогда решение состоит в том, чтобы добавить pages к data()
data() {
return {
theme: 'dark',
pages: [], // <--- was originally "data: []"
counter: 0
}
},
Теперь любая ссылка на this.pages будет ссылкой на эту реактивную переменную данных. Остальной код теперь будет работать. Итак, когда это работает:
this.pages = [...this.$pages.getAllPages()];
Он обновит переменную data, а поскольку pages является реактивной зависимостью вычисляемого свойства publishedPages, он перезапустится. Наконец, v-for в шаблоне будет перерисован, потому что вычисленное значение свойства обновилось:
<navbar-link v-for = "(page, index) in publishedPages" />
P.S. это изменение с data[] на pages[] происходит в обучающем видео между 3:22:00 и 3:22:30
Сначала он устанавливает свойство данных как data: [], но через несколько секунд очень быстро меняет его на pages: []. Вероятно, это было очень трудно заметить во время кодирования.
Спасибо, что заглянули и заметили! Также отличный ответ и объяснение! С наилучшими пожеланиями
Вы можете загрузить весь код в репозиторий или онлайн-песочницу? это множество частей, взаимодействующих друг с другом, и было бы проще всего отладить работающий пример. некоторые из моих вопросов включают, обновляется ли свойство
publishedпри редактировании? обновляет лиeditPagepagesStore, как ожидалось, и обновляет ли функцияsavelocalStorage, как ожидалось? какое фактическое значение массива возвращаетgetAllPages? и т. д.