前面讲完表单这样常见又复杂的制作方式,其实在对付的是一种「以物件为根的」资料结构。并且同时又处理掉了物件的物件,以及物件的阵列。那麽所有的表单其实就没有什麽好害怕的了,是吧?(是吗?)
那麽,如果以要处理「以阵列为根的」资料结构呢?通常,我们会使用 UI component 来处理这个问题。哈哈~~
这一次,我就以 BootstrapVue 为例。(这一招可以适用於其它 UI component 唷!)
来看看我们会遇到什麽难题吧!
以 Table | Components | BootstrapVue 这个元件为主角
要处理一个这样的资料
[
{ age: 40, first_name: 'Dickerson', last_name: 'Macdonald' },
{ age: 21, first_name: 'Larsen', last_name: 'Shaw' },
{ age: 89, first_name: 'Geneva', last_name: 'Wilson' },
{ age: 38, first_name: 'Jami', last_name: 'Carney' }
]
[
{
key: 'first_name',
label: '名',
},
{
key: 'last_name',
label: '姓',
},
{
key: 'age',
label: '年纪',
},
]
设定到表格 component 时,其实就是放进两个
<b-table striped hover :items="items" :fields="fields"></b-table>
画面像这样
这样的需求,是不是能够做一个 list 的 component 了呢?
src/components/list.vue
<div class="list">
<b-table striped hover :items="items" :fields="fields"></b-table>
</div>
export default {
name: 'List',
props: {
items: {
type: Array,
required: true
},
fields: {
type: Array,
required: true
}
}
}
src/views/Users.vue
<List :items="$store.getters.users" :fields="fields"></List>
src/views/Departments.vue
<List :items="$store.getters.departments" :fields="fields"></List>
做完了。谢谢 还没完!
咦?我们不是做到这两点了吗?
但是,如果我们想要客制栏位,怎办?
Slots - Table | Components | BootstrapVue
在我们重新封装了 UI Component 的元件之後,是不是就受限了使用方式了呢?
还可以依照官网的说明使用我们封装过的元件吗?
这样一来,就可以封装「共用特定的使用方式」,依官网的使用方式,又可以依不同的资料客制使用方式。
听不太懂?!没关系,先看结果,究竟是要做到什麽效果呢?
在 Custom data rendering 这一段有介绍怎麽样写。而最终就是想要照着写。
记住,任何自己发明的 props、slot 最好都要写一份文件,不要以为别人都看得懂你的设计。QQ
因为我不想写文件,所以致力於「别人的文件,就是我的文件」
只要用法和 UI Component 一样,基本上就可以使用它强大的功能与文件。
<List :items="$store.getters.users" :fields="fields">
<template #cell(name)="{ item }">
{{ item.last_name }} {{ item.last_name }}
</template>
</List>
[
{
key: 'name',
label: '姓名',
},
{
key: 'age',
label: '年纪',
},
]
透过前面介绍的技巧知道 $attrs 和 $listeners 可以在自订的 component 上使用 UI Component 。但是,<slot>
呢?
<div class="list">
<b-table striped hover :items="items" :fields="fields">
<!-- 在这里究竟要放什麽呢? -->
</b-table>
</div>
探索之前,先印出来看
export default {
name: 'List',
mounted() {
console.log('在这里印出要测试的 API')
}
}
$scopedSlot
<div class="list">
<pre>{{ Object.keys($scopedSlot) }}</pre>
</div>
export default {
name: 'List',
mounted() {
console.log(this.$scopedSlot)
}
}
$slots
<div class="list">
<pre>{{ Object.keys($slots) }}</pre>
</div>
export default {
name: 'List',
mounted() {
console.log(this.$scopedSlot)
}
}
总之,我们得了一个长得像这样的东西
[ "cell(name)" ]
由於因为 BootstrapVue 还不支援 Vue3 所以剩下部份,我们就用 Vue2 实现吧! (目前看起来就 API 不太一样而已)
<b-table :items="items" :fields="fields">
<template v-for="(value, key) in $scopedSlots" v-slot:[key]="{ item }">
<slot :name="key" v-bind:item="item"></slot>
</template>
</b-table>
这样一来,原本我们写成这样的东西
<b-table striped hover :items="$store.getters.users" :fields="fields">
<template #cell(name)="{ item }">
{{ item.last_name }} {{ item.last_name }}
</template>
</b-table>
就可以写成下面这两个组合
src/views/users.vue
<List :items="$store.getters.users" :fields="fields">
<template #cell(name)="{ item }">
{{ item.last_name }} {{ item.last_name }}
</template>
</List>
src/components/list.vue
<b-table striped hover :items="items" :fields="fields">
<template v-for="(value, key) in $scopedSlots" v-slot:[key]="{ item }">
<slot :name="key" v-bind:item="item"></slot>
</template>
</b-table>
成功的将 bootstrap-vue 的 table,其中的 slot 移植到我们自己的 component 上使用。
这样一来,还有什麽可以阻止得了我呀!哈哈哈
之後,不管是 props, events 甚至是 slot 都可以任意使用啦,任何的 component 我就可以自由的封装共用的设定,而开放非共用的设定。包装成自己想要的 component 了!
我们实作过下面这四种变化了
未来遇到任何奇奇怪怪的资料结构,就完全不用害怕罗!
不用再说「呃...後端这个结构太复杂,是不是可以拆开做呢?」
最後,你觉得这一系列有进阶吗?
欢迎留言告诉我。
也欢迎你留下自己习惯的写法 (repo),与我分享唷!
<<: 自动化测试,让你上班拥有一杯咖啡的时间 | Day 30 - 学习cypress intercept 与後记
>>: IT铁人DAY 29-Template Method 模板模式
前言 前几天讲完了行程管理的部分,其中有个部分讲到,所谓的ready 或者说 task_runnin...
课程内容与代码会放在 Github 上: https://github.com/chechiacha...
作为软件工程师的我们应该都曾有过一个疑问,开始写程序之前,要不要先做规划。 这个问题也曾经困扰着我跟...
RelativeLayout(相对布局) 在RelativeLayout中,元件的位置可以是相对於整...
这次练习的题目是做出商城中订单付款与付款後产生送货单的功能 功能主要需求:记录是否付款、付款方式是什...