我刚接触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="℃">
<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'),
}
]
},
],
};
答案 0 :(得分:1)
看来您已经找到问题所在了。 当您到达主入口点时,将触发axios调用,并且您将在商店中拥有所需的所有数据。但是,如果您登陆组件本身,则不会触发axios调用,并且您的商店为空。
要解决此问题,可以在组件中添加一些条件逻辑,如果所需数据未定义或为空,则可以进行axios调用。