十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
1、背景
興安盟網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)公司!從網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站設(shè)計(jì)等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營維護(hù)。創(chuàng)新互聯(lián)公司2013年開創(chuàng)至今到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)公司。
vue后臺(tái)管理系統(tǒng),會(huì)有很多表格頁面,表格上方會(huì)有一些搜索選項(xiàng),表格直接使用el-table即可,而搜索欄區(qū)域每次寫起來都很繁瑣,而且多人開發(fā)情況下每個(gè)人寫的樣式都不相同,布局樣式無法統(tǒng)一。
所以要考慮對(duì)搜索欄做一個(gè)封裝,統(tǒng)一配置引用,提升開發(fā)維護(hù)效率和界面統(tǒng)一。
完成后的效果大概就是長這樣:
2、分析
項(xiàng)目使用的是elementui框架,搜索欄這種表單提交,首先要使用el-form組件來封裝,而復(fù)雜點(diǎn)就是表單項(xiàng)可能有很多種,例如input輸入框、select選擇框、日期時(shí)間選擇框、日期時(shí)間范圍選擇框、cascader級(jí)聯(lián)選擇框等,每一項(xiàng)的字段名prop、名稱label、綁定的屬性方法都不盡相同。所以不能通過普通的綁定個(gè)別屬性的方式來處理,而slot插槽的方式也無法簡化,最終決定通過傳遞一個(gè)配置項(xiàng)數(shù)組的形式來解析生成相應(yīng)的結(jié)構(gòu)。
3、實(shí)現(xiàn)
目前實(shí)現(xiàn)的方式由兩部分組成,一部分是form表單組件,接受父組件傳遞的配置項(xiàng)數(shù)組,一部分是封裝一些常用的表單項(xiàng)組件,通過v-if來控制,form表單組件里引入該表單項(xiàng)組件,循環(huán)遍歷,根據(jù)傳遞的表單項(xiàng)類型來匹配顯示具體的表單項(xiàng)。
form表單組件(searchForm.vue)示例代碼:
formItem表單項(xiàng)組件(formItem.vue)示例代碼:
4、關(guān)鍵點(diǎn)
由于elementui表單組件本身有很多配置屬性,不可能把所有的屬性和方法都寫死封裝,要想無縫支持,需要用到vue的v-bind和v-on特性,vue的v-bind和v-on支持賦值為對(duì)象類型,vue會(huì)自動(dòng)遍歷對(duì)象里的屬性依次綁定,v2.4.0+支持。
5、參數(shù)配置項(xiàng)解釋
(1)示例:
[{ label: '用戶名', // label文字 prop: 'username', // 字段名 element: 'el-input', // 指定elementui組件 initValue: '阿黃', // 字段初始值 placeholder: '請(qǐng)輸入用戶名', // elementui組件屬性 rules: [{ required: true, message: '必填項(xiàng)', trigger: 'blur' }], // elementui組件屬性 events: { // elementui組件方法 input (val) { console.log(val) }, } }]
label 用于綁定給el-form-item上的label,表單項(xiàng)標(biāo)題
prop 用于綁定給el-form-item上的prop,字段名,必填
element 指定elementui表單項(xiàng)的組件名,必填
initValue 表單項(xiàng)的初始值,可選
events 對(duì)象,對(duì)象里加方法,js原生方法或者elementui表單項(xiàng)組件支持的方法都可以加進(jìn)去,通過v-on遍歷綁定
… 其他elementui表單項(xiàng)組件支持的屬性或者h(yuǎn)tml原生屬性都可以添加,常用的例如rules表單校驗(yàn)、placeholder提示,通過v-bind遍歷綁定
(2)參數(shù)傳遞解析的流程:
首先,searchForm.vue組件里通過props接收參數(shù):
formOptions: { type: Array, required: true, default () { return [] } },
created組件里處理初始值:
// 添加初始值 addInitValue () { const obj = {} this.formOptions.forEach(v => { if (v.initValue !== undefined) { obj[v.prop] = v.initValue } }) this.formData = obj }
一部分配置項(xiàng)綁定在el-form-item上,一部分傳遞給formItem表單項(xiàng)組件再綁定:
formItem.vue表單項(xiàng)組件里props接受傳參:
itemOptions: { type: Object, default () { return {} } }
computed里處理接收的參數(shù)itemOptions,生成要綁定的所有屬性對(duì)象bindProps:
// 綁定屬性 bindProps () { let obj = { ...this.itemOptions } // 移除已使用的或不相關(guān)的冗余屬性 delete obj.label delete obj.prop delete obj.element delete obj.initValue delete obj.rules delete obj.events if (obj.element === 'el-select') { delete obj.options } return obj },
computed里生成要綁定的所有方法對(duì)象bindEvents:
// 綁定方法 bindEvents () { return this.itemOptions.events || {} },
最后dom里使用這些數(shù)據(jù)綁定:
(3)特殊情況的處理
由于elementui的el-select里是通過el-option遍歷實(shí)現(xiàn)的,而遍歷數(shù)組options按elementui官方不是綁定在el-select上的,所以針對(duì)el-select的配置項(xiàng)再加一個(gè)options里屬性,即select選擇項(xiàng)的數(shù)據(jù)數(shù)組。
elementui的日期時(shí)間選擇器分了很多種,根據(jù)業(yè)務(wù)需要分別處理一下,我這里是根據(jù)type劃分成了三種分開處理,最常用的是datetimerange日期時(shí)間范圍選擇器,作為默認(rèn)項(xiàng),還有一種monthrange,其余的都劃為一種。(具體處理見文章末尾的完整代碼)
6、按鈕組
按鈕其實(shí)就那么幾個(gè),沒必要做太多的封裝,根據(jù)業(yè)務(wù)有哪些按鈕就封裝進(jìn)去,目前我這里就封裝了三個(gè)按鈕。
通過props接受一個(gè)字符串標(biāo)識(shí)按鈕組:
// 提交按鈕項(xiàng),多個(gè)用逗號(hào)分隔(query搜索, export導(dǎo)出, reset重置) btnItems: { type: String, default () { return 'search' } }
7、使用方式示例
dom:
vue data里:
formOptions: [ { label: '意見內(nèi)容', prop: 'content', element: 'el-input' }, { label: '類型', prop: 'type', element: 'el-select', options: [ { label: '給點(diǎn)意見', value: '1' }, { label: '售后問題', value: '2' } ] }, { label: '狀態(tài)', prop: 'status', element: 'el-select', options: getFeedbackStatus() }, { label: '提交時(shí)間', prop: 'timeRange', element: 'el-date-picker' } ],
vue methods里:
// 獲取搜索表單提交的數(shù)據(jù) onSearch (val) { console.log(val) }
8、完整代碼
(1)searchForm.vue
/** * Created by hanxueqiang on 200107 * * 搜索欄公共組件 */搜索 導(dǎo)出 重置
(2)formItem.vue
/** * Created by hanxueqiang on 200107 * * 表單匹配項(xiàng) */
(3)依賴引入的一些函數(shù)方法 tools.js
/** * 創(chuàng)建唯一的字符串 * @return {string} ojgdvbvaua40 */ function createUniqueString () { const timestamp = +new Date() + '' const randomNum = parseInt((1 + Math.random()) * 65536) + '' return (+(randomNum + timestamp)).toString(32) } // elementui日期時(shí)間范圍 快捷選項(xiàng) const pickerOptionsRange = { shortcuts: [ { text: '今天', onClick (picker) { const end = new Date() const start = new Date(new Date().toDateString()) start.setTime(start.getTime()) picker.$emit('pick', [start, end]) } }, { text: '最近一周', onClick (picker) { const end = new Date() const start = new Date() start.setTime(end.getTime() - 3600 * 1000 * 24 * 7) picker.$emit('pick', [start, end]) } }, { text: '最近一個(gè)月', onClick (picker) { const end = new Date() const start = new Date() start.setTime(start.getTime() - 3600 * 1000 * 24 * 30) picker.$emit('pick', [start, end]) } }, { text: '最近三個(gè)月', onClick (picker) { const end = new Date() const start = new Date() start.setTime(start.getTime() - 3600 * 1000 * 24 * 90) picker.$emit('pick', [start, end]) } } ] } // elementui月份范圍 快捷選項(xiàng) const pickerOptionsRangeMonth = { shortcuts: [ { text: '今年至今', onClick (picker) { const end = new Date() const start = new Date(new Date().getFullYear(), 0) picker.$emit('pick', [start, end]) } }, { text: '最近半年', onClick (picker) { const end = new Date() const start = new Date() start.setMonth(start.getMonth() - 6) picker.$emit('pick', [start, end]) } }, { text: '最近一年', onClick (picker) { const end = new Date() const start = new Date() start.setMonth(start.getMonth() - 12) picker.$emit('pick', [start, end]) } } ] }
(4)一些elmentui全局樣式的修改
// el-input-number (controls-position="right") .el-input-number.is-controls-right { .el-input-number__decrease { display: none; } .el-input-number__increase { display: none; top: 2px; // fix style bug } &:hover { .el-input-number__decrease { display: inline-block; } .el-input-number__increase { display: inline-block; } } .el-input__inner { text-align: left; padding-left: 5px; padding-right: 40px; } } // el-date-picker datetimerange .el-date-editor.el-date-editor--datetimerange { .el-range-separator { width: 24px; color: #999; padding: 0; } .el-range__icon { margin-left: 0; } &.el-input__inner { vertical-align: middle; padding: 3px 5px; } &.el-range-editor--medium { width: 380px; .el-range-separator { line-height: 30px; } } &.el-range-editor--mini { width: 330px; .el-range-separator { line-height: 22px; } } } // el-date-picker not datetimerange .el-date-editor { .el-input__prefix { left: 0; top: 1px; } .el-input__suffix { right: 0; top: 1px; } .el-input__inner { padding: 0 25px; } &.el-input--mini { width: 175px; } &.el-input--medium { width: 195px; } } // input padding .el-input__inner { padding: 0 5px; }
總結(jié)
以上所述是小編給大家介紹的vue elementui 實(shí)現(xiàn)搜索欄公共組件封裝,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)創(chuàng)新互聯(lián)網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!