再不用寫查詢列表頁面了 | 減小低端重複勞動 vue+iview

在羣裏請教了一下這樣的頁面有沒有標準的稱謂,有的叫標準的CRUD頁面,有的說是表格信息頁,我也不知道叫什麼,上邊是查詢下邊是列表,索性就叫查詢列表頁了,藉助羅永浩的口頭禪:」少廢話,先看東西「。 演示地址 前端

高頻出現的列表頁面

從去年9月份換工做之後,參與了幾個項目,有數據BI平臺,有可視化平臺,有大屏項目,有JIRA的二次開發,種類繁多,技術棧也豐富多彩,學習到不少。vue

  • 基於vue的BI平臺用iview搭了一套後臺,
  • 基於react的熟悉了antDesign\umi\dva\bizcharts
  • 基於fis3+yog2的JIRA的二次開發
  • 最近後端同事又給過來三個基於vue-element-admin的中臺系統。

說了這麼多,想表達的是」查詢列表頁面出現的頻率過高了「,不論是BI系統、可視化系統,仍是toB的中臺系統,就前端崗位而言,不可避免的要開發不少這樣的查詢列表頁面,沒有什麼技術要求門檻,但就是得作,所謂的」低端重複勞動「。react

分頁組件的迭代

以前BI的項目裏用iview的table和Page組件封裝了一個分頁組件,只須要傳入表頭、api地址、查詢條件,就完成了,全部分頁列表都是用它實現的。ios

接到重構以前一箇中臺系統的需求,拆分紅三個應用,後端給過來三個基於vue-element-admin的git項目地址,粗略的瞄了一下以前的系統,幾乎全部左側頻道點進去都是查詢列表頁面,直接引入以前的分頁組件開發v0.1版本,v1.0需求愈來愈多,索性抽了兩天時間把查詢條件也一塊封裝了吧😃。git

五分鐘生成查詢列表頁面

查詢條件通常都是key:value的形式,好比後端給出的文檔以下圖。ajax

咱們把查詢條件和列表封裝成一個組件,查詢條件其實就是一個option配置,,組件必不可少的三個入參,接口地址、查詢條件配置、自定義表頭,開發過程當中每每都是先新建.vue組件、引入查詢列表組件、編寫入參,而後再引入必要的工具方法,其實也很繁瑣。json

因而咱們本身寫了個生成工具,按照文檔把入參填寫一下,點擊導出,vue組件代碼直接就複製到剪切板,新建.vue文件,而後ctrl+v便可。axios

工具地址後端

日光之下無新事,頁面可視化的工具不少,借用以前可視化文章裏的觀點,你們爲何不用可視化,可視化工具爲何沒火起來。api

  1. 學習成本高於開發難度
  2. 工具簡單,不能知足業務需求

這麼簡單的小東西,能知足業務需求嗎?入參類型夠全嗎?能夠加權限判斷嗎? 怎麼自定義表頭?

組件功能設計

這個組件也是在實際開發過程當中封裝出來的,不一樣的業務場景、開發的體驗、測試的反饋才能使這個組件更穩定、更好用,咱們也是在一個一個的實際需求版本迭代中才把api給肯定下來。

先看看組件作什麼,很簡單,組件分爲兩部分,上邊是查詢條件、下邊分頁表格。

這個組件就是在點擊查詢,把查詢條件的結果拼成入參傳入列表分頁,上半部分的將來就是封裝更多類型,代碼也很簡單,後續能夠在組件代碼裏本身增長。

主要仍是在下半部分,也能夠單獨使用列表組件,一塊兒看看列表分頁的主要入參吧。url是接口地址,每一個列表的接口地址確定不同,靈活配置;searchData是要查詢條件,Columns是iview的表格組件表頭,在巨人的肩膀子真的是有益,具體見iview的表格api文檔 能夠自定義列的展現;allDate是一個鉤子,能夠修改後端返回的結果,好比根據權限判斷是否增長操做按鈕等。

剩下的就是上一頁、下一頁、跳轉、修改頁數的操做了,和後端訂好格式就OK了。

列表的數據格式也有必定要求,dataCount總條數,tableData表體數據,Columns表頭,pageSize每頁條數,以下

{
	"code": 1,
	"msg": "",
	"data": {
		"dataCount": 444,
		"tableData": [{
			"id": 443,
			"order_no": "1016410719705984",
			"source": 10,
			"order_type": 1,
			"order_status": 1,
			"car_name": "奧迪 A6 2006款 1.8 手動"
		}, {
			"id": 443,
			"order_no": "1016410719705984",
			"source": 10,
			"order_type": 1,
			"order_status": 1,
			"car_name": "奧迪 A6 2006款 1.8 手動"
		}],
		"Columns": [{
			"key": "order_no",
			"title": "訂單ID"
		}, {
			"key": "order_type",
			"title": "訂單類型"
		}, {
			"key": "source",
			"title": "來源"
		}, {
			"key": "car_name",
			"title": "車型"
		}, {
			"key": "order_status",
			"title": "狀態"
		}],
		"pageSize": 10
	}
}

複製代碼

咱們再回顧一下,整個組件的功能。

  1. 查詢條件組件根據文檔列成配置文件並展現
  2. 用戶輸入後把查詢條件封裝,給到列表分頁組件
  3. 分頁根據自定義表頭展現內容,完成機械的上下頁、跳轉等操做

說了這麼多,到底有哪些api能夠講下吧?

數據格式與api

template部分

除了組件上的props,須要提一下的就是buttons這個solt了,除了頁面上的搜索和重置按鈕,每每須要增長其餘的按鈕,最多見的好比新建

url 接口地址

字符串類型,每一個列表都有本身不一樣的地址

apiType 全局地址

字符串類型,咱們ajax使用的是axios,若是是微服務的項目會有多個域名配置,把axios的實例名稱填上便可,默認爲http,在main.js中給vue原型指向。

// 引入微服務apis
import { http, OderApi, ReportApi} from '@/lib/apis.js'
Vue.prototype.$http = http            // 默認地址
Vue.prototype.$OderApi = OderApi      // 訂單服務
Vue.prototype.$reportApi = ReportApi  // 報表服務
複製代碼
fromOption 表單配置

數組類型,每個查詢項爲一個對象,目前僅支持四種輸入項,後續會增長其餘類型,本着小步快跑原則,先把文章發出來,省的要夭折在本身的筆記軟件中(我太懶)。

select:下拉項 date-picker:開始-結束日期 input:輸入框 selectAndInput:下拉+輸入

select

{
  label:'沿途城市',     // 標籤名稱
  name:['cityId'],     // *入參名稱 必須惟一
  type:'select',       // *元素類型 selectAndInput
  dataType:'arr',      // 數據格式 arr/json
  arrKey:{             // arr數組格式下爲必填
    value:'city_id',
    key:'name'
  },
  value:'',            // *默認選中值
  options:{            // *element組件屬性 
    data:[             // 列表數據 僅在select類型下可用
      {
        city_id:'',
        name:'所有'
      },
      {
        city_id:1001,
        name:'北京'
      },
      {
        city_id:1002,
        name:'上海'
      }
    ]
  }
},
複製代碼

下拉菜單的數據支持數組和對象兩種格式,分別爲arrjson表示,後續可能會優化掉這一入參,直接用類型判斷。 dataTypejson時的數據格式,推薦使用json,能夠減小遍歷操做。

options:{             // *element組件屬性 
    data:[             // 列表數據 僅在select類型下可用
      {
       所有:'',
       北京:1001,
       上海:1002
      }
    ]
  }
複製代碼

date-picker

使用的elementUI的日期組件,options能夠傳入elementUI組件的官方屬性,type目前僅支持daterangeelementUI 日期date-picker文檔

注:由於目前項目是基於vue-element-admin,封裝時沒有考慮,結果上半部分是elementUI的表單組件,下半部分爲iviewUI的表格組件,後期會統一。

{
    label:'操做時間',
    name:['start_time','end_time'],     // *入參名稱2個
    type:'date-picker',
    value:'',
    options:{
        'value-format':"yyyy-MM-dd",
        type:"daterange"
    }
}
複製代碼

input

{
    label:'車牌號',
    name:['car_no'],    // *入參名稱2個
    value:'',           // *默認值
    type:'input'
}
複製代碼

selectAndInput

{
    label: "ID",
    type: "selectAndInput",
    value: "",
    defaulType:"id",       // 默認選中的下拉項值
    name:                  // 下拉菜單數據
      {
        運單:'transport_order_id',
        主運單:'transport_order_main_id'
      },
    selectOption:{},       // 下拉框官網api設置
    inputOtions:{}         // 輸入框官網api設置
}
複製代碼

以往咱們在生成這類查詢條件時,會特別檢查一下後端的接口。 謹防接口設計爲類型字段和id字段,不利於拆分爲單個查詢條件。

// 錯誤類型入參實例
{
    type:'transport_order_id',
    id:'99234i88845'
}

// 正確入參實例
{
   transport_order_main_id:'99234i88845' 
}
// 或
{
   transport_order_id:'99234i88845' 
}
複製代碼
Columns 自定義表頭

數組類型

使用過iview的表格組件應該就很熟悉了文檔

[
    { key: "order_no", minWidth:200, fixed: 'left'},
    {
      key: "order_status",
      minWidth:90,
      render:(h, params) => {
          let text = this.matchType('order_status',params)
          return h('div',text)
      }
    },
    {
      key: "source",
      render:(h, params) => {
          let text = this.matchTypeArr('source',params)
          return h('div',text)
      }
    },
    {title: "操做", key: "action",align:'center', minWidth:200, fixed: 'right',
        render:(h, params) => {

          let setingBtn = h('Button', {
                    props: {
                        type: 'primary',
                        size: 'small'
                    },
                    on: {
                        click: () => {
                            this.showSet(params.row)
                        }
                    }
                }, '發運設置')


          let editBtn = h('Button', {
                    props: {
                        type: 'primary',
                        size: 'small'
                    },
                    style:{
                        marginLeft:'10px'
                    },
                    on: {
                        click: () => {
                          this.$router.push('/constExplorer/editorLine/' + params.row.id)
                        }
                    }
                }, '班車設置')

            return h('div',[setingBtn,editBtn])
        }
    }
]
複製代碼
allDate 修改返回結果

函數類型

其實就是一個鉤子函數,在每次翻頁、搜索的時候,拿到數據並作一些修改,好比給每列加一個最小寬度,或者根據權限判斷是否展現操做按鈕。

addWidth(data){

    // 列最小寬度
    data.data.Columns.forEach(item => {
        item.minWidth = 170
    })

    // 操做按鈕權限判斷
    if(_.get(this.powers, 'oderList')){
        data.data.Columns.push({title: "操做", key: "action"})
    }
}
複製代碼

經常使用方法

平常的實際開發中,除了api,還有不少咱們經常使用的操做,好比下拉菜單是接口,格式化表格數據等,咱們來一塊兒過一下吧,把代碼貼一下,提升咱們的開發效率。

下拉菜單調接口數據在組件初始化時獲取下拉菜單的數據

created(){

    this.$http.get('/mock/city.json').then(res => {

        // 城市列表 數組格式
        let formIndex = _.findIndex(this.form, ['name', ['cityid']]);
        this.form[formIndex].options.data = this.form[formIndex].options.data.concat(res.data)

          })
        // 城市列表 對象格式 
        let formIndex = _.findIndex(this.form, ['name', ['cityid']]);
        this.form[formIndex].options.data = Object.assign(this.form[formIndex].options.data,res.data)

          })

        },
複製代碼

表格列數據格式化 好比這樣的場景,查詢條件中存儲了狀態碼,咱們須要根據查詢條件中的數據格式化表格的列數據。

查詢條件

列數據中返回的是1100這樣的格式,咱們封裝了兩個方法,分別進行格式化,後期會優化爲一個方法。

// 表頭格式
{
  key: "order_type",
  render:(h, params) => {
      let text = this.matchType('order_type',params)
      return h('div',text)
  }
},
{
  key: "source",
  render:(h, params) => {
      let text = this.matchTypeArr('source',params)
      return h('div',text)
  }
},
複製代碼
matchType(key,params){

  let formIndex = _.findIndex(this.form, ['name', [key]]);
  let formType = this.form[formIndex].options.data

  let text = _.findKey(formType, item => {
    return item == params.row[key]
  });

  return text
}

matchTypeArr(key,params){

  let formIndex = _.findIndex(this.form, ['name', [key]]);
  let formType = this.form[formIndex].options.data
  let keyName = this.form[formIndex].arrKey.value
  let text = _.find(formType, item => {
    return item[keyName] == params.row[key]
  });

  return text.name
}

複製代碼

按鈕權限

權限管理有一些須要精確到按鈕,咱們有專門的接口獲取權限並存在store裏,在allData裏進行判斷,是否展現操做按鈕。

addWidth(data){
    // 操做按鈕權限判斷
    if(_.get(this.powers, 'oderList')){
        data.data.Columns.push({title: "操做", key: "action"})
    }
}
複製代碼

未解決問題列表

  • 獲取篩選項下拉後再請求列表接口
  • 下拉菜單數據格式判斷
  • 列數據格式化方法封裝
  • 權限多按鈕的判斷
  • 查詢條件單日期類型配置項目

演示地址與源碼

碼雲 gitee.com/nihaojob/fo…

表單演示 nihaojob.gitee.io/formandlist…

可視化生成 nihaojob.gitee.io/formandlist…

相關文章
相關標籤/搜索