首页 > 解决方案 > Vue组件中的无限更新循环

问题描述

我的导航选项卡组件中出现以下更新错误:

您可能在组件渲染函数中有无限更新循环。

在此处输入图像描述

回顾这里以前的问题,大多数似乎与计算属性有关,或者直接修改传递给组件的道具,迫使它们不断地重新渲染。然而,在这个组件中,我认为我也不想这样做。

Vue.component('navigation-tabs', {
    props: {
        tabs: Array,
        title: String,
        type: String
    },
    data() {
        return {
            navigationTabs: Vue.util.extend([], this.tabs),
            selectedTab: {},
            tabCounter: 0,
            tabType: this.type ? this.type : 'tabs'
        }
    },
    methods: {
        navItemClasses(selectedTab) {
            if (selectedTab.selected) {
                if (this.type) {
                    return 'bg-gradient-dark text-white';
                }
            } else if (selectedTab.disabled === true) {
                return 'text-danger';
            }
        },
        selectTab(selectedTab) {
            if (selectedTab.disabled !== true) {
                this.navigationTabs.forEach(tab => {
                    tab.selected = false;
                });
                selectedTab.selected = true;
            }
        }
    },
    computed: {
        activeComponent() {
            return this.navigationTabs.filter(x => x.selected === true)[0]
        }
    },
    template: `
        <div>
            <div>
                <ul class="text-md nav" :class="tabType === 'tabs' ? 'nav-tabs' : 'nav-pills'">
                    <li v-for="(tab, index) in navigationTabs" class="nav-item card-img-holder" v-if="tab.hideForSite !== $parent.site">
                         <img src="/shared/resources/images/circle.svg" class="card-img-absolute">
                         <a class="nav-link font-weight-bold" :class="navItemClasses(tab)" @click="selectTab(tab)">
                         {{ tabCounter++ + ': ' + tab.name }}
                         </a>
                    </li>   
                    <h3 v-if="title" class="nav-link font-weight-bold ml-auto pb-0">{{ title }}</h3>
                </ul>
            </div>
            <div v-if="tabType !== 'tabs'" class="border-top my-3"></div>
            <div class="my-4 mx-5">
                <component :is="activeComponent.component"></component>
            </div>
        </div>
    `,
});

我什至只是在尝试在屏幕上显示/记录tabCounter的值时才发现这一点,这样我就可以在每个显示的选项卡旁边显示一个准确的数字。如果我移除计数器,我根本不会收到错误,这对我来说似乎很不寻常,因为我并没有真正用它做太多事情。这让我担心后台出了什么问题,因为即使我只有 6 个选项卡要显示,计数器也会循环到超过 700 的值。

在此处输入图像描述

我在下面包含了父应用程序的副本以供参考,任何帮助将不胜感激。

let app = new Vue({
    el: '#app',
    data: {
        site: '1',
        myTabs: [
            {
                name: 'Example 1',
                selected: true,
                component: 'example-one'
            },
            {
                name: 'Example 2',
                component: 'example-two'
            },
            {
                name: 'Example 3',
                component: 'example-three'
            },
            {
                name: 'Example 4',
                component: 'example-four'
            },
            {
                name: 'Example 5',
                component: 'example-five',
                hideForSite: 'DC4'
            },
            {
                name: 'Example 6',
                component: 'example-six'
            },
            {
                name: 'Example 7',
                disabled: true
            },
        ]
    },
    created() {
        this.site = document.cookie.match('(^|;) ?' + 'Siteinstance' + '=([^;]*)(;|$)')[2].toUpperCase();
    }
});

编辑:最初我没有在模板中进行增量,而是调用了一个函数,但不明白为什么它被调用了 600 多次:

<a class="nav-link font-weight-bold" :class="navItemClasses(tab)" @click="selectTab(tab)">
    {{ retrievePosition() + ': ' + tab.name }}
</a>

    retrievePosition(){
        return this.tabCounter++;
    },

标签: javascriptvue.jsvuejs2vue-component

解决方案


tabCounter++tabCounter每次渲染组件时都会更新,这会导致重新渲染并导致无限循环。

如果需要计数器,则已经有索引值:

{{ (index + 1) + ': ' + tab.name }}

尽量避免在渲染过程中(在组件模板和函数内部)产生副作用,render因为这是一种不好的做法,可能会导致无限循环。如果应该不断执行副作用,那么观察者beforeUpdateupdated生命周期钩子是合适的地方。


推荐阅读