Я хочу создать список действий (каждое из которых является компонентом) условно, если переменная объекта store.plan не пуста, я пробовал v-if, который хорошо работает для рендеринга, но не для создания компонента.
Я получаю сообщение об ошибке:
Uncaught (in promise) TypeError: action is undefined
Полный код этого компонента можно найти здесь.
Не могли бы вы рассказать мне, как я могу справиться с этой проблемой? заранее спасибо.

<template>
<div class = "planlist" v-if = "parse">
<ul id = "planOl">
<Action
v-for = "action in store.plan"
:action_id = "action.act_id"
:actor = "action.actor"
:color = "action.color"
:size = "action.size"
:lego_name = "action.lego"
:pick_pos = "action.pick"
:place_pos = "action.place"
:blocked = "action.blocked"
:status = "action.status"
:key = "action.act_id"
/>
</ul>
</div>
</template>
<script>
import Action from '../components/Action.vue';
import { store } from '../js/store.js'
export default {
name: 'Plan',
data() {
return {
store,
}
},
computed: {
parse() {
if (store.plan.length > 0) {
return true;
}
return false;
}
},
components: {Action}
}
</script>
@Duannx Я не знаю, как использовать stackblitz с ROS, но полный код доступен здесь , чтобы воспроизвести проблему, вы можете запустить код с помощью rosbridge и этого тестового издателя ros
Слишком много усилий, чтобы воспроизвести это самому. Вы можете легко имитировать свои данные и предоставить простую версию своего кода только с одним компонентом, который вызывает ошибку. Возможно, этот шаг поможет вам выяснить, в чем основная причина проблемы.



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


Вы пробовали с дополнительной цепочкой:
parse() {
return store?.plan?.length > 0 ? true : false
}
и не смешивайте v-if и v-for. Попробуйте создать div-оболочку с v-if вокруг вашего компонента:
<ul id = "planOl">
<div v-if = "parse">
<Action
v-for = "action in store.plan"
:action_id = "action.act_id"
:actor = "action.actor"
:color = "action.color"
:size = "action.size"
:lego_name = "action.lego"
:pick_pos = "action.pick"
:place_pos = "action.place"
:blocked = "action.blocked"
:status = "action.status"
:key = "action.act_id"
/>
</div>
</ul>
все же я сталкиваюсь с той же ошибкой, я обновил вопрос с точным сообщением об ошибке, если я правильно понимаю v-if просто влияет на рендеринг, а не на создание.
Я создал оболочку div с v-if снаружи, и эта проблема до сих пор не решена.
Можете ли вы представить, как выглядит магазин, когда у вас есть ошибка?
"store.plan выглядит так, когда у вас есть ошибка", на самом деле это массив (не пустой), как вы можете видеть здесь
Не рекомендуется использовать директивы v-if и v-for вместе для одного и того же элемента из-за неоднозначности синтаксиса.
Согласно вашему коду, свойство Computed parse используется для проверки длины массива. Вы можете переместить v-if в элемент container (например, ul).
В шаблоне:
<ul id = "planOl" v-if = "parse">
<Action v-for = "action in store.plan">...</Action>
</ul>
Скрипт:
computed: {
parse() {
return store.plan.length > 0 ? true : false;
}
}
Я создал оболочку div с v-if снаружи, и эта проблема все еще не решена, поэтому я соответствующим образом обновил вопрос.
@Bilal Поскольку у вас есть условие v-if поверх v-for, в идеале вы не должны получать action неопределенную ошибку. поскольку действие всегда будет доступно, если условие v-if выполнено.
Верно, но я получаю эту ошибку, когда план обновляется
@Bilal - я видел код и не нашел в этом ничего плохого, поскольку вы просто назначаете объекты в хранилище планов. Так что это должно работать, поскольку вы используете вычисляемое свойство для v-if
проблема была вызвана присвоением неправильного индекса store.plan[idx] при обновлении плана.
@Билал Это здорово. Я рад, что вы нашли корень проблемы.
store.plan в вычисляемое свойство для использования внутри шаблона и свойства parse.store.plan.length из вычисляемого свойства, вместо того, чтобы возвращать true и false в зависимости от условия.v-if сразу за компонентом Action, вы можете использовать template для этого. Нет необходимости в дополнительном элементе.Итак, приведенные ниже изменения могут помочь решить проблемы:
<template>
<div class = "planlist">
<ul id = "planOl">
<template v-if = "parse">
<Action
v-for = "action in plan"
:key = "action.act_id"
:action_id = "action.act_id"
:actor = "action.actor"
:color = "action.color"
:size = "action.size"
:lego_name = "action.lego"
:pick_pos = "action.pick"
:place_pos = "action.place"
:blocked = "action.blocked"
:status = "action.status"
/>
</template>
</ul>
</div>
</template>
<script>
import Action from "../components/Action.vue";
import { store } from "../js/store.js";
export default {
name: "Plan",
components: {
Action,
},
computed: {
// A computed property to access the plan ()
plan() {
return store.plan;
},
parse() {
/**
* 1. The plan should be available (not null or empty or undefined)
* 2. The plan should be an array so length property can be applied
* 3. If its an array then it should have data (length in other words)
*/
return this.plan && Array.isArray(this.plan) && this.plan.length;
},
},
};
</script>
Можете ли вы воспроизвести свою проблему на stackblitz.com?