呈现路由器视图组件之前未初始化Vuex状态-未定义错误

时间:2020-07-07 08:44:43

标签: vue.js vuex

我刚接触Vue,遇到了一个小问题。我正在渲染一个依赖于vuex中存储的状态的组件。我从应用程序主要部分的json文件中加载此信息。如果我在加载时始终位于应用程序的根目录(index.html)上,则一切正常。但是,如果我从路由器动态生成的页面刷新应用程序,则会出现错误:

[Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined"

found in

---> <Room>
       <RoomsOverview>
         <Root>

据我所知,正在发生的事情是该组件正在尝试访问vuex中的状态,但尚未初始化。这是组件(Room.vue):

<template>
    <div id="room">
        <h2>{{ roomName }}</h2>
        <div v-for="device in deviceList" v-bind:key="deviceList.name">
            {{ device.name }} - {{ device.function}}
            <svg-gauge v-bind:g-value="device.value" v-bind:g-min="0" v-bind:g-max="50" v-bind:g-decplace="1" g-units="&#8451;">
                <template v-slot:title>
                    Temperature
                </template>
            </svg-gauge>
        </div>
    </div>
</template>

<script>
module.exports = {
    name: 'room',

    /** Load external component files
     *  Make sure there is no leading / in the name
     *  To load from the common folder use like: 'common/component-name.vue' */
    components: {
        'svg-gauge': httpVueLoader('components/DisplayGauge.vue'),
    }, // --- End of components --- //
    
    data() {
        return {

        };
    },
    computed: {
        roomName() {
//            return this.$route.params.roomId;
            return this.$store.getters['rooms/getRoomById'](this.$route.params.roomId);
        },
        deviceList() {
            return this.$store.getters['rooms/getDevicesinRoom'](this.$route.params.roomId);
        },
    },
}
</script>

错误是由行触发的

            return this.$store.getters['rooms/getRoomById'](this.$route.params.roomId);

这会尝试访问getter中的当前状态:

    getRoomById: (state) => (id) => {
        return state.rooms.find(room => room.id === id).name; // Needs fixing!
    },

但似乎是数组:

// Initial state
const stateInitial = {
    rooms: [],
};
在这些情况下

尚未初始化。初始化发生在挂接的钩子中index.js中应用程序的主入口处

        // Load data from node-red into state
        vueApp.$store.dispatch('rooms/loadRooms')

在哪里loadRooms使用axios来获取数据。如果到达站点(http://192.168.0.136:1880/uibuilderadvanced/#/)的根目录,此操作将按预期工作,但是如果到达(http://192.168.0.136:1880/uibuilderadvanced/#/rooms/office)之类的链接,则不会按预期进行。我怀疑这完全取决于事情发生的顺序,而我的大脑还没有完全思考问题。如果有人对如何捕获它有任何想法,我将不胜感激-我认为需要某种类型的观察器,或者使用v-if(但是我无法看到放置在哪里,因为Room.vue是由路由器动态创建的) -见下文)。

谢谢

Martyn

更多信息:

房间组件本身是由路由器视图从父级内部(RoomsOverview.vue)生成的:

<template>
    <div id="rooms">
        <b-alert variant="info" :show="!hasRooms">
            <p>
                There are no rooms available yet. Pass a message that defines a room id and device id 
                to the uibuilder node first. See <router-link :to="{name: 'usage_info'}">the setup information</router-link> 
                for instructions on how start using the interface.
            </p>
        </b-alert>
        
        <router-view></router-view>
    </div>
</template>

<script>
module.exports = {
    name: 'RoomsOverview',
    data() {
        return {

        };
    },
    computed: {
        hasRooms() {
            return this.$store.getters['rooms/nRooms'] > 0;
        },
        roomList() {
            return this.$store.getters['rooms/getAllRooms'];
        },
    },
}
</script>

,并取决于路由器文件:

const IndexView = httpVueLoader('./views/IndexView.vue');
const AdminView = httpVueLoader('./views/AdminView.vue');

export default {
    routes: [
        {
            path: '/',
            name: 'index',
            components: {
                default: IndexView,
                menu: HeaderMenu,
            },
        },
        {
            path: '/rooms',
            name: 'rooms_overview',
            components: {
                default: httpVueLoader('./components/RoomsOverview.vue'),
                menu: HeaderMenu,
            },
            children: [
                {
                    path: ':roomId',
                    name: 'room',
                    component: httpVueLoader('./components/Room.vue'),
                },
            ],
        },
        {
            path: '/admin',
            name: 'admin', 
            components: {
                default: AdminView,
                menu: HeaderMenu,
            },
            children: [
                {
                    path: 'info',
                    name: 'usage_info',
                    component: httpVueLoader('./components/UsageInformation.vue'),
                }
            ]
        },
    ],
};

1 个答案:

答案 0 :(得分:1)

看来您已经找到问题所在了。 当您到达主入口点时,将触发axios调用,并且您将在商店中拥有所需的所有数据。但是,如果您登陆组件本身,则不会触发axios调用,并且您的商店为空。

要解决此问题,可以在组件中添加一些条件逻辑,如果所需数据未定义或为空,则可以进行axios调用。