Похоже, не удается передать данные компоненту через реквизиты в Vue

#vue.js #vue-component #vuejs3

Вопрос:

Я создаю динамическую таблицу, используя Vue 3 в качестве учебного проекта, в котором пользователь, среди прочего, может добавлять или удалять строки из таблицы. Я использую table-row компонент для создания строки и table-data компонент для создания ячеек данных в этой строке. Добавление строки выполняется с помощью следующего кода:

 const app = Vue.createApp({
    data() {
        return {
            tableRows: [],
        }
    },

    methods: {
        addRow() {
            this.tableRows.push(-1);
        },
    },
})
 

Что мне нужно сделать, так это передать массив TableRows и index table-row компоненту, чтобы выполнить операцию удаления строки, как показано в этом коде:

 app.component('table-row', {
    props: {
        tableRows: Array,
        index: Number,
    },

    methods: {
        deleteRow(index) {
            this.tableRows.splice(index, 1);
        }
    },

    template: `
        <tr>
            <table-data></table-data>
            <table-data></table-data>
            <table-data></table-data>
            <table-data></table-data>
            <button @click="deleteRow">Delete Row</button>
        </tr>
    `
})
 

Проблема в том, что оба значения TableRows и index не определены (как показано в Vue DevTools), что означает, что реквизиты не передаются от родительского компонента к дочернему компоненту. Я думаю, что именно по этой причине эта ошибка появляется всякий раз, когда я нажимаю кнопку Удалить строку:

Неперехваченная ошибка типа: Не удается прочитать свойства неопределенного (чтение «сращивания»)

Вот скриншот из Vue DevTools. Вы можете видеть, что переменные реквизита имеют неопределенные значения:

Скриншот Vue DevTools

Я не совсем уверен, почему это происходит, или что я могу сделать, чтобы исправить это. Мы будем очень признательны за любую помощь.

Комментарии:

1. Не на 100% об этом, но я думал, что вы должны были передать реквизиты, используя v-on привязку от родителя, чтобы использовать их в ребенке. Вы можете попробовать добавить html-шаблон к родительскому, а не к дочернему, и привязать реквизит, используя v-on его.

2. @Chaos_Is_Harmony Насколько я понимаю компоненты и реквизит, это не обязательно так. Примеры на странице руководства Vue передают реквизит… напрямую, я полагаю? Я не уверен, как называется их метод. Что касается перемещения шаблона в родительский, я думаю, это идея. Я попробую это сделать и посмотрю, что я могу с этим сделать, но это не решит проблему, с которой я сейчас сталкиваюсь.

3. @Chaos_Is_Harmony, Ты был прав. Мне пришлось привязать переменную к компоненту в самом HTML. Что-то вроде <table-row :tableRow="tableRow" :index="index"></table-row> . Тем не менее, tableRow значение все еще не определено, даже несмотря index на то, что переменная передается в компонент. Я подозреваю, что данные не совпадают, но я не уверен.

4. Изменить предыдущий комментарий: Это не несоответствие типов. Похоже tableRows , это атрибут (если бы я поверил Ву ДевТулсу), а не реквизит. Нужно ли мне сейчас открывать новый вопрос ?-? ?

5. Я опубликовал ответ с более подробным ответом, который, надеюсь, поможет.

Ответ №1:

Я думаю, что все реквизиты сначала должны быть объявлены в родительских данных, прежде чем они будут привязаны к дочерним реквизитам

 "PARENT"
<template>
...
  <Child :tableRows="tableRows" />
...
</template>

...
<script>
 ...
  data() {
    return {
      tableRows: []
    }
  }
  ...
</script>
 
 "CHILD"
...
</script>
  ...
  props: {
    tableRows: Array
  }
  ...
</script>
 

Что касается индекса, вам, скорее всего, придется отправить emit событие обратно родителю по щелчку мыши.

 "CHILD"
<template>
...
  <button @click="$emit('deleteRow')">Delete Row</button>
...
</template>
 

Здесь вам придется иметь дело с этим в родительском, где e-значение, связанное с событием-в данном случае, предположительно, нужный вам индекс.

 "PARENT"
<template>
...
  <Child @deleteRow="deleteRow(e)" :tableRows="tableRows" />
...
</template>
 

Комментарии:

1. Да! Это сработало идеально. Мне пришлось кое-что подправить, но то, что вы описали, было ответом, который я искал. Спасибо. Забавно, но когда я прошел i вместо index этого , функция все еще работала так, как должна была, хотя и не раньше, чем выдала предупреждение в консоли. Сталкивался ли я с некоторыми ошибками JavaScript из-за того, что он не был напечатан?

2. Хотел бы я знать. Я довольно новичок в Vue.js и javascript, но я уже сталкивался с этой проблемой ранее. Вот почему я вспомнил: Родитель->Ребенок = Реквизит; Ребенок->>Родитель = Излучать.

Ответ №2:

Вы не прошли index , @click="deleteRow" Попробуйте изменить метод на :

 deleteRow() {
   this.tableRows.splice(this.index, 1);
}
 

или перейти index к методу:

 @click="deleteRow(index)"
 

Комментарии:

1. Извините, пробовал и то, и другое, но все равно не работает. Я добавил скриншот Vue DevTools, на котором по-прежнему отображаются значения реквизитов как неопределенные.