平時工做中,想必你必定會遇到無數次列表需求,而且是帶有搜索功能的列表需求,但無論怎麼怎麼樣,請相信這一切都是萬變不離其宗。css
不信?請看:html
基本就是上面這些了吧?咱們不妨看看下面這張截圖: vue
本文所說的組件封裝是指業務上的封裝,而不是組件底層的封裝,像這種底層封裝的組件庫不少,好比:antd、element。上面的截圖也算是簡單的了,只有一個兩種類型,一個是輸入框,一個是下拉框,但也足以說明問題了,回想一下,當你遇到這樣的需求你會如何實現?通常地咱們是否是會像下面這樣寫書:數組
<div class="container">
<a-row>
<a-col :span="20">
<a-form class="search-form" layout="inline" @submit="search">
<a-form-item label="維修項目">
<a-input placeholder="請輸入" />
</a-form-item>
<a-form-item label="維修師傅">
<a-select placeholder="請選擇">
<a-select-option
:value="item.id"
:key="item.id"
v-for="item of userOptions"
>{{item.name}}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="樓號">
<a-select placeholder="請選擇">
<a-select-option
:value="item.id"
:key="item.id"
v-for="item of floorOptions"
>{{item.name}}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="宿舍">
<a-select placeholder="請選擇">
<a-select-option
:value="item.id"
:key="item.id"
v-for="item of roomOptions"
>{{item.name}}</a-select-option>
</a-select>
</a-form-item>
<a-form-item class="button">
<a-button class="offset-right-12" type="primary" html-type="submit">搜索</a-button>
<a-button @click="reset">重置</a-button>
</a-form-item>
</a-form>
</a-col>
<a-col :span="4" class="text-right">
<a-button type="primary" @click="showModal()">新增</a-button>
</a-col>
</a-row>
<a-table
class="offset-top-12"
rowKey="id"
:pagination="pagination"
:loading="loading"
bordered
:columns="columns"
:dataSource="dataList"
>
<span slot="visitDate" slot-scope="scope">{{scope.visitDate | date}}</span>
<span slot="leaveDate" slot-scope="scope">{{scope.leaveDate | date}}</span>
<span slot="createDate" slot-scope="scope">{{scope.createDate | date}}</span>
<div slot="action" slot-scope="scope" class="text-right no-wrap">
<a-button type="link" @click="showModal(scope)">修改</a-button>
<a-divider type="vertical" />
<a-button type="link" @click="deleteModal(scope.id)">刪除</a-button>
</div>
</a-table>
</div>
</template>
複製代碼
示例基於 antd vueantd
若是過濾條件更多(常有的事),那麼頁面中的代碼量更加驚人,整個頁面瀰漫着反客爲主的味道,僅僅是過濾條件就已經佔了整個頁面的一半。ide
這會致使什麼問題?函數
若是以爲頁面代碼時過多,不會對你在開發以及維護上產生過多的負面影響,但至少有一個理由我以爲你應該選擇去把這些過濾條件進行封裝,那就是若是不去對列表頁過濾條件進行封裝,若遇到統一修改這些過濾條件(不論是業務性的,仍是樣式及結構的)你就會變得很被動,瞬間從高大尚的腦力活變成了出力不討好的苦力活。那麼如何去封裝呢?this
key
,分別爲:id
,name
)組件有至少有兩個參數以及兩個事件。其中一個參數是用於遍歷出過濾條件的一個數組,另外一個是保存了全部查詢參數的一個對象。spa
爲何分紅兩個參數,而不一個參數搞定。緣由以下:雙向綁定
兩個事件分別是 search
和 rest
,這兩個應該不用多說了。下面咱們就先來看看封裝好的條件過濾組件。
<template>
<a-row>
<a-col :span="20">
<a-form class="search-form" :form="form" layout="inline" @submit="search">
<a-form-item :label="item.name" v-for="(item, index) of items" :key="index">
<a-input v-model="searchParams[item.key]" v-if="!item.type || item.type === 'input'" :placeholder="item.placeholder || '請輸入'"/>
<a-select allowClear v-model="searchParams[item.key]" v-else-if="item.type === 'select'" :placeholder="item.placeholder || '請選擇'">
<a-select-option
:key="index"
v-for="(option, index) of item.options"
:value="option[item.optionValuekey || 'id']"
>{{option[item.optionNamekey || 'name']}}</a-select-option>
</a-select>
</a-form-item>
<a-form-item class="button">
<a-button type="primary" html-type="submit">搜索</a-button>
<a-button @click="reset">重置</a-button>
</a-form-item>
</a-form>
</a-col>
<a-col :span="4" class="text-right">
<slot name="right-content"></slot>
</a-col>
</a-row>
</template>
<script>
import deepClone from "@/utils/deepClone";
/**
* items 爲過濾條件,能夠在對應的項中自定義下拉選項的名稱(optionNamekey)和值(optionValuekey)的鍵,默認分別取 name 和 id
* items 如何要下拉框顯示 placeholder,對應的下拉框的初始值能夠設置爲 undefined 或者 不定義查詢參數,若是設置爲空, placeholder 不會顯示。
* searchParams 爲接口查詢參數對象
*/
export default {
model: {
prop: 'searchParams',
event: "change"
},
props: {
searchParams: {
type: Object,
default: () => {
return {};
}
},
items: {
type: Array,
default: () => {
return [];
}
}
},
data() {
return {
// 保存初始化時的項
initSearchParams:{},
form: this.$form.createForm(this, { name: "dynamic_search" })
};
},
created() {
this.init()
},
methods: {
init(){
// 保存初始值的
this.initSearchParams = deepClone(this.searchParams)
},
search() {
const cpValue = deepClone(this.searchParams)
this.$emit("change", cpValue);
this.$emit("search", cpValue);
},
reset() {
const cpValue = deepClone(this.initSearchParams)
this.$emit("change", cpValue);
this.$emit("reset", cpValue);
}
}
};
</script>
<style lang="scss" scoped>
.search-form {
@extend .offset-bottom-24;
.ant-form-item {
&.button {
margin-right: 0;
white-space: nowrap;
}
.ant-input {
width: 120px;
}
.ant-select {
min-width: 120px;
}
.ant-btn + .ant-btn {
@extend .offset-left-12;
}
}
}
</style>
複製代碼
上面的這個組件只是包涵了兩各狀況(輸入框,下拉框),其它的話能夠本身按需添加。deepClone()
方法爲深度拷貝。爲會把須要深度拷貝?緣由以下:
searchParams
數據。組件接收兩個 prop
屬性
items
是用以保存用於渲染過濾條件的一個數據。searchParams
初始化及收集請求接口參數,這個參數實現了雙向綁定,配合 v-model
使用。用法就很簡單了,引入,調用,傳參:
<template>
<div class="container">
<search-form :items="searchForm" v-model="searchParams" @search="findRepair">
<a-button slot="right-content" type="primary" @click="showModal()">新增</a-button>
</search-form>
<a-table
rowKey="id"
:pagination="pagination"
:loading="loading"
bordered
:columns="columns"
:dataSource="dataList"
>
<template slot="createDate" slot-scope="createDate">{{createDate | date }}</template>
<a-tag :color="scheduleMap[scope.schedule].color" slot="schedule" slot-scope="scope">{{ scheduleMap[scope.schedule].name }}</a-tag>
<div slot="action" slot-scope="scope" class="text-right no-wrap">
<a-button type="link" @click="showModal(scope)">修改</a-button>
<a-divider type="vertical" />
<a-button type="link" @click="deleteModal(scope.id)">刪除</a-button>
</div>
</a-table>
<EditModal ref="EditModal"></EditModal>
</div>
</template>
複製代碼
而後在 data 中定義兩個 searchForm 和 searchParams
data() {
return {
searchForm: [
{ name: "發起人", key: "name" },
{ name: "維修師傅", key: "repairerId", type: "select", options: [] },
{ name: "樓號", key: "floorId", type: "select", options: [] },
{ name: "宿舍", key: "roomId", type: "select", options: [] }
],
searchParams: {
pageNo: 1,
pageSize: 15,
name: "",
repairerId: undefined,
floorId: undefined,
roomId: undefined
}
};
},
複製代碼
searchParams
對象中有三個字段的值設置爲 undefined
,這三個屬性是用於收集下拉框的選中值,因此不能夠給空字符串,而若是你不想這麼寫,你也可能直接寫成:
searchParams: {
pageNo: 1,
pageSize: 15,
name: ""
}
複製代碼
兩種方式均可能,不過第一種方式相對來講會比較好一些,就是一看就知道這接口的請求參數都有哪些,有時寫代碼真的不能過於含蓄,要直白一點,畢竟公司裏都是團隊模式開發,要讓改你代碼的年輕小夥也能享受到如魚得水感受,而且可讓相似:「前人種樹,後人乘涼」 這樣的佳句一直傳承下去,而不是讓後來者接連 ***,何樂而不爲呢。