VueJs 2 click не работает

У меня нет ошибок, и он компилируется, поэтому я не уверен, что делаю не так. Я искал по этой теме безуспешно.

У меня есть BulkExpenses.vue, который извлекает и показывает некоторые записи о расходах, тогда BulkExpense.vue - это вложенный компонент, который отображает каждую запись. Я хочу щелкнуть значок корзины, и он вернет идентификатор расхода родительскому компоненту для запуска сценария удаления. Я делаю это в другом проекте, и он отлично работает, поэтому я не уверен, что делаю здесь не так.

Также есть компонент Lookup, который представляет собой TypeAhead для извлечения поездок для подключения к Expense, но он работает.

BulkExpenses.vue

<template>
    <div>
        <form action = "#" @submit.prevent = "createBulkExpense()" class = "publisher bt-1 border-fade bg-white" autocomplete = "off">
            <table>
                <thead>
                    <tr>
                        <td><input v-model = "bulk_name" type = "text" placeholder = "Name"></td>
                        <td><input id = "bulk_expensed_at" type = "text" name = "bulk_expensed_at" placeholder = "Date Expense Incurred"></td>
                        <td><input id = "bulk_type_id" type = "text" name = "bulk_type" placeholder = "Type"></td>
                        <td>
                            <lookup
                                source = "/api/lookup/trip"
                                placeholder = "Search your trips"
                                filter-key = "name"
                                :start-at = "3"
                                v-on:selected-link = "onSelectedTrip"
                                :modellink = "modellink">
                            </lookup>
                        </td>
                        <!-- <td><input id = "bulk_tags" type = "text" name = "bulk_tags" placeholder = "Tags"></td> -->
                        <td><input id = "bulk_vendor" type = "text" name = "bulk_vendor" placeholder = "Vendor"></td>
                        <td><input id = "bulk_method" type = "text" name = "bulk_method" placeholder = "Payment Method"></td>
                        <td><input id = "bulk_total" type = "text" name = "bulk_total" placeholder = "Total Amount"></td>
                        <td><input id = "bulk_paidby_user_id" type = "text" name = "bulk_paidby" placeholder = "Paid By"></td>
                        <td><input id = "bulk_status" type = "text" name = "bulk_status" placeholder = "Payment Status"></td>
                        <td><input id = "bulk_notes" type = "text" name = "bulk_notes" placeholder = "Notes"></td>
                    </tr>
                </thead>
                <tbody>
                    <expense v-for = "expense in expenses"
                        :key = "expense.id"
                        :expense = "expense"
                        @expense-deleted = "deleteExpense($event)">
                    </expense>
                </tbody>
            </table>
        </form>
    </div>
</template>
<script>
    // import CommentsManager from './CommentsManager.vue';
    var axios = require("axios");
    import lookup from './Lookup.vue';
    import expense from './BulkExpense.vue';
    export default {
        components: {
            lookup, expense
        },
        data: function() {
            return {
                modellink: {
                   "name": "n/a",
                   "description": "",
                   "id": null,
                   "model": "n/a"
                },
                bulk_trip: {
                   "name": "n/a",
                   "description": "",
                   "id": null
                },
                selectName: "",
                bulk_name: "",
                bulk_expensed_at: "",
                bulk_type: "",
                bulk_tags: "",
                bulk_vendor: "",
                bulk_method: "",
                bulk_total: "",
                bulk_paidby: {
                    name: "",
                    id: ""
                },
                bulk_status: "",
                bulk_notes: "",
                expense: {
                        id: 1,
                        name: "",
                        expensed_at: "",
                        type: {
                            id: "",
                            name: ""
                        },
                        trip: {
                            id: "",
                            name: ""
                        },
                        tags: [],
                        vendor: "",
                        method: "",
                        total: "",
                        paidby: {
                            id: "",
                            name: ""
                        },
                        status: {
                            id: "",
                            name: ""
                        },
                        notes: ""
                    },
                expenses: [
                    {
                        id: 1,
                        name: "",
                        expensed_at: "",
                        type: {
                            id: "",
                            name: ""
                        },
                        trip: {
                            id: "",
                            name: ""
                        },
                        tags: [],
                        vendor: "",
                        method: "",
                        total: "",
                        paidby: {
                            id: "",
                            name: ""
                        },
                        status: {
                            id: "",
                            name: ""
                        },
                        notes: ""
                    }
                ]
            };
        },        
        created() {
            this.fetchExpenses();
        },
        methods: {
            // onSelectedLink: function (talink) {
            //     // alert(JSON.stringify(talink.description, null, 4));
            //     this.modellink = talink
            // },
            onSelectedTrip: function (talink) {
                // alert(JSON.stringify(talink.description, null, 4));
                this.bulk_trip = talink
                this.modellink = talink
            },
            fetchExpenses() {
                axios.get('/api/expense').then((res) => {
                    //alert(JSON.stringify(res.data[0], null, 4));
                    this.expenses = res.data;
                });
            },

            createExpense() {
                axios.post('/api/expense', {name: this.expense.name, vessel_id: Laravel.vesselId, expensed_at: this.expense.expensed_at })
                    .then((res) => {
                        this.expense.content = '';
                        // this.expense.user_id = Laravel.userId;
                        // this.task.statuscolor = '#ff0000';
                        this.edit = false;
                        this.fetchExpenses();
                    })
                    .catch((err) => console.error(err));
            },
            deleteExpense(expense) {
                console.info(expense.id);
                alert(expense.id);
                axios.delete('/api/expense/' + expense.id)
                    .then((res) => {
                        this.fetchExpenses()
                    })
                    .catch((err) => console.error(err));
            },
        }
    }
</script>

BulkExpense.vue

<template>
    <tr>
        <td><input v-model = "expense.name" type = "text" name = "name"></td>
        <td><input v-model = "expense.expensed_at"></td>
        <td v-if = "expense.type"><input v-model = "expense.type.name"></td>
        <td>
            <trip-select  v-bind:tripId = "expense.trip_id" selectName = "trip_id"></trip-select>
        </td>
        <td><input v-model = "expense.vendor"></td>
        <td><input v-model = "expense.method"></td>
        <td><input v-model = "expense.total"></td>
        <td v-if = "expense.paidby"><input v-model = "expense.paidby.name" ></td>
        <td v-if = "expense.status"><input v-model = "expense.status.name" ></td>
        <td><input v-model = "expense.notes"></td>
        <td>
            <a class = "text-lighter hover-light"  v-on:click = "deleteExpense" href = "#"><i class = "fas fa-trash"></i></a>
        </td>
    </tr>
</template>
<script>
    import TripSelect from './TripSelect.vue';
    import typeahead from './Typeahead.vue';
    export default {
      name: 'expense',
      components: { TripSelect, typeahead },
      props: {
            bulk_name: {
                type: String,
                required: false
            },
            expense: {
                required: true,
                type: Object,
                default: function () {
                  return {
                        id: 1,
                        name: "",
                        expensed_at: "",
                        type: {
                            id: "",
                            name: ""
                        },
                        trip: {
                            id: "",
                            name: ""
                        },
                        tags: [],
                        vendor: "",
                        method: "",
                        total: "",
                        paidby: {
                            id: "",
                            name: ""
                        },
                        status: {
                            id: "",
                            name: ""
                        },
                        notes: ""
                  }
                }
            }
        },
        data() {
            return {
            }
          },
          methods: {
            deleteExpense() {
                alert(this.expense.id)
                this.$emit('expense-deleted', {
                    'id': this.expense.id,
                });
            }
          }
    }
</script>

alert(this.expense.id) работает? MCVE было бы здорово

Jacob Goh 20.06.2018 04:36

Что именно означает «не работает»? Что вы ожидаете, и что происходит вместо этого? Удалите ненужные вещи.

Lubo Antonov 20.06.2018 05:22
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
2
2
373
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Хотя он может не дать прямого ответа на ваш вопрос, это наверняка сработает. Кроме того, это решает вашу фундаментальную проблему, которая является примером антипаттерна.

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

Не нужно объявлять $event, так как он уже может быть у вас по умолчанию, если вы этого хотите.

<expense v-for = "expense in expenses" :key = "expense.id" :expense = "expense" @expense-deleted = "deleteExpense"></expense>

Затем в обработчике кликов просто emit действие и передайте расходы обратно:

<a class = "text-lighter hover-light"  
    @click = "$emit('expense-deleted', expense)" 
    href = "#">
    <i class = "fas fa-trash"></i>
</a>

Это решит указанные выше фундаментальные проблемы и, вероятно, вашу проблему в процессе.

Также я вижу, что вы смешиваете v-on:click и @click, но это одно и то же, одно - просто сокращение для другого. Я бы посоветовал для единства просто @click.

Наконец, вот MCVE для этого подхода.

Редактировать

На всякий случай, если вам интересно, вы можете удалить его из существующей коллекции после выполнения вашего обещания, выполнив следующие действия:

this.expenses.slice(this.expenses.findIndex(o => o.id === expense.id), 1)

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

Или вы можете заменить весь массив, но для этого вам понадобится Vue.set:

Vue.set(this, 'expenses', this.expenses.filter(o => o.id !== expense.id))

Это здорово, и это приближает меня ... но я думаю, что все еще существует проблема, связанная с визуализированной DOM. Если я заменю его вашим упрощенным компонентом, он действительно сработает. Однако, когда я добавляю больше сложности, кажется, что значок корзины больше не доступен. Что-то не так с любыми вложенными данными - например, у меня есть связанная запись «оплачено», если я помещаю ссылку на удаление после этого, по какой-то причине она не активируется - почти как ошибки там, но я не регистрирую никаких ошибок.

Dylan Glockler 20.06.2018 23:31

@DylanGlockler Может быть CSS, искаженный HTML, множество вещей. Поскольку это решает вашу проблему, вы можете принять этот ответ и задать новый вопрос.

Ohgodwhy 21.06.2018 15:26

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