VueJs 2 点击似乎不起作用

Posted

技术标签:

【中文标题】VueJs 2 点击似乎不起作用【英文标题】:VueJs 2 click doesn't seem to work 【发布时间】:2018-11-28 23:33:29 【问题描述】:

我没有收到任何错误,它正在编译,所以我不确定我做错了什么。我已经搜索了这个主题,但没有成功。

我有 BulkExpenses.vue 拉取并显示一些费用记录,然后 BulkExpense.vue 是一个嵌套组件,显示每条记录。我想单击垃圾桶图标并让它将费用 ID 发送回父组件以运行删除脚本。我在另一个项目中这样做并且它运行良好,所以我不确定我在这里做错了什么。

还有一个 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.log(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 会很棒 “不起作用”到底是什么意思?您期望会发生什么以及正在发生什么?清理不相关的东西。 【参考方案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 相关的问题。如果我将它与您的简化组件交换,它确实有效。但是,当我添加更多复杂性时,似乎垃圾桶图标不再可点击。任何嵌套数据都有问题 - 例如,我有一个相关的“付费方”记录,如果我在之后放置删除链接,由于某种原因它不可点击 - 几乎就像它在那里出错但我没有注册任何错误。 @DylanGlockler 可能是 CSS、格式错误的 html 等等。由于这解决了您的问题,您可能希望接受此答案并提出一个新问题。

以上是关于VueJs 2 点击似乎不起作用的主要内容,如果未能解决你的问题,请参考以下文章

VueJS计算过滤器功能不起作用

Vuejs计算的API响应过滤器不起作用

存储在 Vuex 4 中 Vuejs 3 不起作用并显示空白结果

如何使用 Vuejs 删除数组中的单击项?

VueJS数据()不起作用

条件渲染在 vuejs v-if 中不起作用