Vue.js -自动更新v-for无法分配新数组

rekjcdws  于 2023-08-07  发布在  Vue.js
关注(0)|答案(1)|浏览(137)

我一直在使用vue 3:Vue.js教程:初学者到前端开发人员https://www.youtube.com/watch?v=1GNsWa_EZdw&t=48s
一切似乎都在我这边工作太多,除了‘更新‘的导航列表。他谈到了从04:01:20开始的页面更新的Eventlistener。
为什么为'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>

Events.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));
        }
    }
};

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();
    }
}

czq61nw1

czq61nw11#

简答:

您的Navbar.vue data()应该更改为:

data() {
    return {
        theme: 'dark',
        pages: [], // <--- was previously data: []
        counter: 0
    }
},

字符串

长回答:

调试完完整的Navbar.vue组件后,问题是computed属性引用了错误的this.pages

publishedPages() {
    return this.pages.filter(p => p.published);
}


上面的this.pages实际上来自created()钩子:

created() {
    this.getThemeSetting();

    this.pages = this.$pages.getAllPages();          
    ...
}


但这里的this.pages不是React变量。当它更新时,计算属性不会重新运行。
这可能会提出一个问题,“为什么它最初会起作用?“.
这是因为计算属性在组件创建时运行一次以获取其初始值,您实际上是使用语句this.pages = ...this上定义pages,因此在初始化期间一切正常。但是因为created()钩子中的this.pages不是一个React变量,this.pages没有被Vue“监视”,所以当this.pages更新时,computed属性永远不会再次运行。只有在data()中定义的变量是React性的。
解决方案是将pages添加到data()

data() {
    return {
        theme: 'dark',
        pages: [],  // <--- was originally "data: []"
        counter: 0
    }
},


现在,任何this.pages的引用都将是对thisReact数据变量的引用。代码的其余部分现在可以工作了。当这个运行时:

this.pages = [...this.$pages.getAllPages()];


它将更新data变量,因为pages是计算属性publishedPagesReact性依赖项,它将重新运行自己。最后,模板中的v-for将重新呈现,因为计算的属性值已经更新:

<navbar-link v-for="(page, index) in publishedPages" />


P.S.从data[]pages[]的更改发生在3:22:00和3:22:30之间的教程视频中
他最初将数据属性设置为data: [],但几秒钟后很快将其更改为pages: []。在编写沿着时可能很难注意到这一点

相关问题