Условное создание компонента Vue

Я хочу создать список действий (каждое из которых является компонентом) условно, если переменная объекта store.plan не пуста, я пробовал v-if, который хорошо работает для рендеринга, но не для создания компонента.

Я получаю сообщение об ошибке:

Uncaught (in promise) TypeError: action is undefined

Полный код этого компонента можно найти здесь.

Не могли бы вы рассказать мне, как я могу справиться с этой проблемой? заранее спасибо.

Условное создание компонента Vue

<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>

Можете ли вы воспроизвести свою проблему на stackblitz.com?

Duannx 13.12.2022 08:12

Слишком много усилий, чтобы воспроизвести это самому. Вы можете легко имитировать свои данные и предоставить простую версию своего кода только с одним компонентом, который вызывает ошибку. Возможно, этот шаг поможет вам выяснить, в чем основная причина проблемы.

Duannx 13.12.2022 08:38
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
113
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы пробовали с дополнительной цепочкой:

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 просто влияет на рендеринг, а не на создание.

Bilal 08.12.2022 07:50

Я создал оболочку div с v-if снаружи, и эта проблема до сих пор не решена.

Bilal 08.12.2022 08:47

Можете ли вы представить, как выглядит магазин, когда у вас есть ошибка?

Nikola Pavicevic 08.12.2022 09:13

"store.plan выглядит так, когда у вас есть ошибка", на самом деле это массив (не пустой), как вы можете видеть здесь

Bilal 12.12.2022 09:13

Не рекомендуется использовать директивы 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 13.12.2022 07:45

@Bilal Поскольку у вас есть условие v-if поверх v-for, в идеале вы не должны получать action неопределенную ошибку. поскольку действие всегда будет доступно, если условие v-if выполнено.

Rohìt Jíndal 13.12.2022 07:50

Верно, но я получаю эту ошибку, когда план обновляется

Bilal 13.12.2022 08:37

@Bilal - я видел код и не нашел в этом ничего плохого, поскольку вы просто назначаете объекты в хранилище планов. Так что это должно работать, поскольку вы используете вычисляемое свойство для v-if

Rohìt Jíndal 13.12.2022 08:47

проблема была вызвана присвоением неправильного индекса store.plan[idx] при обновлении плана.

Bilal 13.12.2022 10:03

@Билал Это здорово. Я рад, что вы нашли корень проблемы.

Rohìt Jíndal 13.12.2022 14:29
  1. Чтобы упростить процесс, мы можем переместить store.plan в вычисляемое свойство для использования внутри шаблона и свойства parse.
  2. Просто верните store.plan.length из вычисляемого свойства, вместо того, чтобы возвращать true и false в зависимости от условия.
  3. Если вы хотите использовать 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>

Другие вопросы по теме