繁体   English   中英

Laravel + Vue,最佳实践

[英]Laravel + Vue, best practices

我正在 Laravel 中构建一个简单的发票系统。 所以很明显我需要建立一个视图,当我能够编辑它时。 这是一个表,我可以在其中动态添加和删除行。

所以我的想法是:好的,我可以用 jQuery 很容易地做到这一点,但是添加一个具有多个输入的行,特别是当我使用顺风时,这意味着有很多奇怪的类,会很混乱,所以我会尝试Vue。 我没有这方面的经验,但总的来说它看起来很容易。

然后我制作了一个 Vue 组件,其中包含<table><tr> ,其中包含输入:

<document-items-table:items='@json($document->items)' />

它不是 SPA,所以我不想在里面进行 AJAX 调用,我已经加载了我的文档,所以我通过一个 vue 道具将文档项传递为 Json。 它工作正常。

接下来是,在每个文档行中,我添加了删除一行的删除按钮。 我还有一个添加空行的按钮。

我的组件如下所示:

<template>
    <div class="w-full">
        <div class="relative flex flex-col min-w-0 break-words w-full rounded bg-white">
            <div class="block w-full overflow-x-auto">
                <table class="items-center w-full bg-transparent border-collapse pb-4">
                    <thead>
                    <tr>
                        <th style="width: 30px" class="pl-6 pr-2 align-middle border-b border-solid py-3 text-xs uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left bg-blueGray-50 text-blueGray-500 border-blueGray-100">
                            No.
                        </th>
                        <th style="min-width: 600px" class=" align-middle border-b border-solid py-3 text-xs uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left bg-blueGray-50 text-blueGray-500 border-blueGray-100">
                            Name
                        </th>
                        <th style="width: 60px" class="align-middle border-b border-solid py-3 text-xs uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left bg-blueGray-50 text-blueGray-500 border-blueGray-100">
                            Quantity
                        </th>
                        <th style="width: 60px"  class="align-middle border-b border-solid py-3 text-xs uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left bg-blueGray-50 text-blueGray-500 border-blueGray-100">
                            Unit
                        </th>
                        <th style="width: 120px"  class="align-middle border-b border-solid py-3 text-xs uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left bg-blueGray-50 text-blueGray-500 border-blueGray-100">
                            Price
                        </th>
                        <th style="width: 60px"  class="align-middle border-b border-solid py-3 text-xs uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left bg-blueGray-50 text-blueGray-500 border-blueGray-100">
                            Tax rate
                        </th>
                        <th style="width: 60px"  class="align-middle border-b border-solid py-3 text-xs uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left bg-blueGray-50 text-blueGray-500 border-blueGray-100">

                        </th>
                    </tr>
                    </thead>
                    <tbody class="border-b-4 border-white">
                    <tr v-for="(item, i) in this.itemsLocal" :key="item.id">
                        <td class="border-t-0 pl-6 align-middle border-l-0 border-r-0 text-xs whitespace-nowrap py-1">
                            {{ i + 1 }}
                        </td>
                        <td class="border-t-0 align-middle border-l-0 border-r-0 text-xs whitespace-nowrap py-1">
                            <item-input name="title" id="title" :value="item.title" />
                        </td>
                        <td class="border-t-0 align-middle border-l-0 border-r-0 text-xs whitespace-nowrap py-1">
                            <item-input class="w-full" name="quantity" id="quantity" :value="item.quantity" />
                        </td>
                        <td class="border-t-0 align-middle border-l-0 border-r-0 text-xs whitespace-nowrap py-1">
                            <item-input class="w-full" name="unit" id="unit" :value="item.unit" />
                        </td>
                        <td class="border-t-0 align-middle border-l-0 border-r-0 text-xs whitespace-nowrap py-1">
                            <item-input class="w-full" name="price" id="price" :value="item.price / 100" />
                        </td>
                        <td class="border-t-0 align-middle border-l-0 border-r-0 text-xs whitespace-nowrap py-1">
                            <item-input class="w-full" name="tax" id="tax" :value="item.tax_rate" />
                        </td>
                        <td class="border-t-0 align-middle border-l-0 border-r-0 text-xs whitespace-nowrap py-1">
                            <button @click="() => deleteRow(item.id)" class="p-2 px-4 bg-rose-500 text-white rounded"><i class="fas fa-times fa-sm"></i> </button>
                        </td>
                    </tr>
                    </tbody>
                </table>
            </div>
        </div>
        <div class="w-full text-center">
            <button @click="addRow" class="bg-lightBlue-600 px-4 py-2 text-white rounded text-sm font-bold">Add row</button>
        </div>
    </div>
</template>

<script>
export default {
    props: {
        items: Array,
    },
    mounted() {
    },

    data () {
        return {
            itemsLocal: [...this.items],
            newRowCount: 1
        }
    },
    methods: {
        deleteRow(itemID) {
            this.itemsLocal = _.reject(this.itemsLocal, ['id', itemID]);
        },
        addRow() {
            this.itemsLocal.push({
                id: -this.newRowCount
            })
            this.newRowCount++;
        }
    }
}
</script>

现在我有一些问题要问那些对 Vue 更有经验的人

  1. 使用 json 将一组 PHP 对象传递给 Vue 组件是一个干净的解决方案吗?
  2. 由于不允许修改props ,并且我需要添加和删除行,我将我的itemsprops克隆到data ,然后添加和删除它们。 有没有更好的解决方案?
  3. 在我的桌子旁边,我将有一些汇总框,其中包含所有元素的一些“总价”。 我想根据我输入这些输入的值动态更新这个值。 我可以把它做成一个单独的组件,但我知道在两个组件之间传递值没有好的方法,那么我应该如何解决呢? 我是否应该再制作一个包含我的表格和摘要框的父包装器组件,将数据发送到该包装器,然后再发送到摘要组件? 或者只是使用一些 jQuery 并且不打扰?
  4. 你看到我在这里使用的任何其他错误做法吗? (我知道 html id 和名称重复 - 我会处理它)

我尽量让它干净。 这不是一个工作项目,而是提高我的技能的事情。

  1. 使用 JSON 将数据作为道具发送可以很好地初始化组件,只需确保在需要的地方进行正确的编码和解码。
  2. 您不能直接修改道具,但是一旦您将道具中的值分配给本地数据,您几乎可以使用该本地数据做您想做的事情。 安装后,您实际上可以将 JSON 数据的值分配给相同类型的各个组件。 在这些组件中,如果需要,您实际上可以将数据发送回父级。 例如,如果您修改子组件中的值,您可以将其发送回父组件,以便父组件在其本地数据中始终具有更新的值,并且由于 vue 是响应式的,它也会将该值分配回为给孩子的道具。 所以间接地你会修改道具。 我建议为它创建一个组件,因为它可以让您更轻松地创建和删除它的实例,并最大限度地减少您需要在父级别上执行的工作量。
  3. 对于计算,vue 有一个计算属性,您可以使用它来计算一个值并将其分配给可以在组件中显示的数据。 请注意这一点,因为如果您的计算量很大,它确实会减慢速度。 也有观察者可以尝试解决这个问题,但我认为计算总价最容易。 计算文档与观看文档
  1. 您正在尝试学习最佳实践真是太好了。 我也在学习中。 到目前为止,我唯一建议的是创建一个新的组件类型并在创建时初始化它们并将新的组件添加到列表中。 操作和删除也会更容易。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM