1. 程式人生 > 實用技巧 >循序漸進VUE+Element 前端應用開發(26)--- 各種介面元件的使用(2)

循序漸進VUE+Element 前端應用開發(26)--- 各種介面元件的使用(2)

在我們使用Vue+Element開發前端的時候,往往涉及到很多介面元件的使用,其中很多直接採用Element官方的案例即可,有些則是在這個基礎上封裝更好利用、更少程式碼的元件;另外有些則是直接採用第三方開發好的元件,目的就是實現所需功能外,儘量簡化介面使用程式碼。本篇隨筆介紹在我的專案中經常用到的各種介面元件和它的介面效果,以便在實際開發中進行相應的參考,提高開發效率。

本篇繼續上一篇隨筆《循序漸進VUE+Element 前端應用開發(25)--- 各種介面元件的使用(1)》,對介面控制元件進行進一步的介紹。

7、樹列表及控制元件封裝

在很多資料展示場景中,都需要引入樹狀列表進行展示,包括無窮層級的樹列表,或者簡單的主從表關係,都可能用到樹列表的展示。

樹列表控制元件的使用,之前在隨筆中《循序漸進VUE+Element 前端應用開發(8)--- 樹列表元件的使用

這些都是基於Element的樹形控制元件進行使用或封裝元件使用的介面。

樹列表的簡單使用程式碼如下所示。

<el-tree :data="data" :props="defaultProps" @node-click="handleNodeClick"></el-tree>

資料這是一個巢狀的列表物件即可,如下程式碼所示

      treedata: [ // 初始化樹列表
        {
          label: '一級 1',
          children: [{
            label: 
'二級 1-1' }] }]

我們只要根據實際情況構建好這些資料給樹控制元件使用即可。一般樹形控制元件頂部會帶一個輸入框來進行鍵值查詢過濾的操作,以方便使用者快速檢索的。

如果設定有選擇框,得到介面如下所示。

主要設定show-checkbox 和@check-change="handleCheckChange" 即可。

介面程式碼如下所示

<el-tree
  style="padding-top:10px"
  :data="treedata"
  node-key="id"
  default-expand-all
  highlight-current
  show-checkbox
  :default-checked-keys
="['1-1-1']" @node-click="handleNodeClick" @check-change="handleCheckChange" > <span slot-scope="{ node, data }" class="custom-tree-node"> <span> <i :class="node.icon ? node.icon : 'el-icon-price-tag'" /> {{ node.label }} &nbsp;&nbsp; </span> </span> </el-tree>

有時候,我們樹列表控制元件的資料可能來源於常規的二維表,如下資料格式所示。

var data = [
   {"id":1,"parent":0,"addr":"重慶"},
   {"id":11,"parent":1,"addr":"重慶"},
   {"id":12,"parent":1,"addr":"重慶"},
   {"id":121,"parent":12,"addr":"重慶"},
   {"id":2,"parent":0,"addr":"重慶"},
   {"id":21,"parent":2,"addr":"重慶"},
   {"id":211,"parent":21,"addr":"重慶"},
   {"id":3,"parent":0,"addr":"重慶"},
   {"id":4,"parent":0,"addr":"重慶"},
   {"id":31,"parent":3,"addr":"重慶"},
   {"id":32,"parent":3,"addr":"重慶"}
];

而樹控制元件使用的data 則是巢狀資料,我們如果每次使用都需要為它們專門做一個函式有點多餘,我們可以用前端轉換的方式來實現樹資料的轉換。

具體操作可以參考:https://blog.csdn.net/unamattin/article/details/77152451

//二維列表轉樹形控制元件所需巢狀資料格式
export function getJsonTree(data, config) {
  const id = config.id || 'id'; const pid = config.pid || 'pid';
  const children = config.children || 'children';
  const label = config.label || 'name';// 預設label為name欄位

  const idMap = []; const jsonTree = [];
  data.forEach(function(v) {
    idMap[v[id]] = v;
  });
  data.forEach(function(v) {
    const parent = idMap[v[pid]];
    if (parent) {
      !parent[children] && (parent[children] = []);
      parent[children].push(v);
    } else {
      jsonTree.push(v);
    }
  });

  // treeAddIcon(jsonTree, label);// 迴圈遍歷給tree加圖示
  return jsonTree;
}

這樣樹列表的繫結操作如下程式碼所示。

    getTree() { // 樹列表資料獲取
      var param = {
        SkipCount: 0,
        MaxResultCount: 1000
      }
      category.GetAll(param).then(data => {
        this.treedata = [];// 樹列表清空
        var list = data.result.items
        if (list) {
          // console.log(list)
          // 使用getJsonTree函式,實現對二維錶轉換為巢狀樹物件集合
          var newTreedata = getJsonTree(list, {
            id: 'id',
            pid: 'pid',
            children: 'children',
            label: 'categoryName'
          });
          // console.log(newTreedata)
          this.treedata = newTreedata
        }
      });
    },

順便說一下,由於引入一些原始控制元件需要實現很多相應的操作,一般情況下,我們可以把樹控制元件常規的處理封裝成一個元件的方式使用,其中包括了常規的過濾、選中等操作處理。如下是我們簡單封裝的樹控制元件的自定義元件,用於處理常規的樹列表資訊。

這樣使用起來,介面程式碼減少很多,只需要實現對應的事件即可。

<myTree :data="treedata" :default-expand-all="false" icon-class="el-icon-price-tag" @nodeClick="nodeClick" />

另外,更高維度上,我們還可以把業務介面按模組分離出來,實現不同的介面的組裝,這樣可以減輕程式碼的臃腫程度,提高程式碼可讀性。

如之前說過的機構資訊,頁面邏輯比較多,可以簡化為各個不同的模組,然後拼裝元件即可。

例如:對於許可權系統中的每個角色,除了包含基本資訊外,還會包含擁有的許可權(功能控制點)、包含使用者,以及擁有的選單,其中許可權是用來控制介面元素,如操作按鈕的顯示的,而擁有的選單,則是使用者以指定賬號登入系統後,獲得對應角色的選單,然後構建對應的訪問入口的。角色介面模組UML類圖如下所示。

那麼對應介面元素上,我們就應該以不同的Tab來展示這些資訊,每個Tab內容部分就可以作為一個獨立的介面元件來開發。

8、按鈕及按鈕組

按鈕比較常用,一般我們依照常規的方式使用,並設定樣式即可。

程式碼如下所示

<el-row>
  <el-button>預設按鈕</el-button>
  <el-button type="primary">主要按鈕</el-button>
  <el-button type="success">成功按鈕</el-button>
  <el-button type="info">資訊按鈕</el-button>
  <el-button type="warning">警告按鈕</el-button>
  <el-button type="danger">危險按鈕</el-button>
</el-row>

<el-row>
  <el-button plain>樸素按鈕</el-button>
  <el-button type="primary" plain>主要按鈕</el-button>
  <el-button type="success" plain>成功按鈕</el-button>
  <el-button type="info" plain>資訊按鈕</el-button>
  <el-button type="warning" plain>警告按鈕</el-button>
  <el-button type="danger" plain>危險按鈕</el-button>
</el-row>

<el-row>
  <el-button round>圓角按鈕</el-button>
  <el-button type="primary" round>主要按鈕</el-button>
  <el-button type="success" round>成功按鈕</el-button>
  <el-button type="info" round>資訊按鈕</el-button>
  <el-button type="warning" round>警告按鈕</el-button>
  <el-button type="danger" round>危險按鈕</el-button>
</el-row>

<el-row>
  <el-button icon="el-icon-search" circle></el-button>
  <el-button type="primary" icon="el-icon-edit" circle></el-button>
  <el-button type="success" icon="el-icon-check" circle></el-button>
  <el-button type="info" icon="el-icon-message" circle></el-button>
  <el-button type="warning" icon="el-icon-star-off" circle></el-button>
  <el-button type="danger" icon="el-icon-delete" circle></el-button>
</el-row>

我在之前的介面中採用的按鈕樣式如下所示。

後來我覺得把按鈕組合起來更好看,也更節省空間。

這裡其實就是使用了按鈕組的作用。

    <!--功能操作按鈕 -->
    <el-row style="float:right;padding-bottom:10px">
      <el-button-group>
        <el-button icon="el-icon-search" type="primary" size="mini" round @click="search()">查詢</el-button>
        <el-button icon="el-icon-refresh-left" type="warning" size="mini" round plain @click="resetSeachForm('searchForm')">重置</el-button>
      </el-button-group>
      <el-button-group>
        <el-button icon="el-icon-plus" type="success" size="mini" round @click="showAdd()">新增</el-button>
        <el-button icon="el-icon-document-remove" type="danger" size="mini" round :disabled="listSelection.length === 0" @click="batchDelete()">批量刪除</el-button>
      </el-button-group>
      <el-button-group>
        <el-button icon="el-icon-upload2" type="warning" size="mini" round @click="showImport()">匯入</el-button>
        <el-button icon="el-icon-download" :loading="downloadLoading" type="primary" size="mini" round @click="handleDownload()">匯出</el-button>
      </el-button-group>
    </el-row>

9、表格控制元件的使用

表格控制元件是我們展示資料庫二維表內容的重要承載,一般在主列表頁面中展示表格資料。

表格控制元件的使用也比較簡單,簡單案例的程式碼所示。

<template>
  <el-table
    :data="tableData"
    border
    style="width: 100%">
    <el-table-column
      prop="date"
      label="日期"
      width="180">
    </el-table-column>
    <el-table-column
      prop="name"
      label="姓名"
      width="180">
    </el-table-column>
    <el-table-column
      prop="address"
      label="地址">
    </el-table-column>
  </el-table>
</template>

但往往我們處理表格列的各種內容承載的時候,需要豐富很多,如包括標籤、Switch開關,按鈕操作、日期格式化、內容轉換等操作。

如標籤列,可以進行迴圈處理。

      <el-table-column align="center" label="標籤" width="100">
        <template slot-scope="scope">
          <el-tag
            v-for="tag in scope.row.tags.split(',')"
            :key="tag"
            type="primary"
          >
            {{ tag }}
          </el-tag>
        </template>
      </el-table-column>

或者結合過濾器進行處理。

      <el-table-column align="center" label="狀態">
        <template slot-scope="scope">
          <el-tag :type="(scope.row.state === 0) ? 'success' : 'danger'" effect="dark">
            {{ scope.row.state | stateFilter }}</el-tag>
        </template>
      </el-table-column>

日期,我們也用日期過濾器實現轉換。

<el-table-column align="center" label="建立時間" width="160" prop="creationTime" :formatter="timeFormat" />

表格的操作列,整個對單個記錄操作的各種操作入口。

      <!--表格行操作按鈕 -->
      <el-table-column align="center" label="操作" width="110">
        <template scope="scope">
          <el-row>
            <el-button-group>
              <el-tooltip effect="light" content="檢視" placement="top-start">
                <el-button icon="el-icon-search" type="success" circle size="mini" @click="showView(scope.row.id)" />
              </el-tooltip>
              <el-tooltip effect="light" content="編輯" placement="top-start">
                <el-button icon="el-icon-edit" type="primary" circle size="mini" @click="showEdit(scope.row.id)" />
              </el-tooltip>
              <el-tooltip effect="light" content="刪除" placement="top-start">
                <el-button icon="el-icon-delete" type="danger" circle size="mini" @click="showDelete(scope.row.id)" />
              </el-tooltip>
            </el-button-group>
          </el-row>
        </template>
      </el-table-column>

如果是開關操作,我們也可以結合一起展示和操作處理。

操作程式碼如下所示

          <el-table-column align="center" label="狀態">
            <template slot-scope="scope">
              <el-tag :type="scope.row.status==0 ? 'success' : 'warning'" effect="dark">
                {{ scope.row.status==0 ? '正常' : '停用' }}
              </el-tag>
              <el-switch
                v-model="scope.row.status"
                :active-value="0"
                :inactive-value="1"
                @change="changeStatus(scope.$index, scope.row)"
              />
            </template>
          </el-table-column>

另外表格資料,一般還涉及到Excel的匯出操作,這個其實是採用了SheetJS的處理方式草操作XLSX的方式匯出Excel的,這裡引用了前人開發的Export2Excel 元件進行處理。

    handleDownload() { // 匯出Excel檔案
      this.downloadLoading = true
      import('@/vendor/Export2Excel').then(excel => {
        const tHeader = ['父ID', '分類編碼', '分類名稱', '分類描述', '分類圖片封面', '分類圖示', '排序', '狀態']
        const filterVal = ['pid', 'categoryCode', 'categoryName', 'note', 'pictureUrl', 'icon', 'sortCode', 'status']

        const list = this.list
        const data = this.formatJson(filterVal, list)
        excel.export_json_to_excel({
          header: tHeader,
          data,
          filename: '商品分類',
          autoWidth: true,
          bookType: 'xlsx'
        })
        this.downloadLoading = false
      })
    },
    formatJson(filterVal, jsonData) {
      return jsonData.map(v => filterVal.map(j => {
        if (j === 'creationTime') {
          return this.parseTime(v[j], '{y}-{m}-{d} {h}:{i}:{s}')
        } else {
          return v[j]
        }
      }))
    },

一般來說,Element的表格控制元件已經具有非常豐富的功能了,包括固定行列、展開行、懶載入資料、多級表頭、排序篩選、自定義列、合計行列等操作,

如果有需要直接編輯表格資料的操作,建議可以採用第三方表格元件來實現:https://github.com/huangshuwei/vue-easytable

10、樹形下拉列表框及封裝

除了常規的樹列表展示內容外,我們也需要一個在下拉列表中展示樹內容的介面元件。

這裡又得引入一個第三方的介面元件,因此Element的Select元件不支援樹列表。

GitHub地址:https://github.com/riophae/vue-treeselect

官網地址:https://vue-treeselect.js.org/

常規的介面程式碼如下使用

<treeselect v-model="value" :multiple="true" :options="options" />

複雜一點的使用介面程式碼,可以指定更多的屬性設定,以及處理事件操作。

<treeselect
  v-model="value"
  :options="treedata"
  :multiple="true"
  :flat="true"
  :default-expand-level="Infinity"
  :open-on-click="true"
  :open-on-focus="true"
  clearable
  :max-height="200"
/>

這裡的options就是樹控制元件的資料,是一個巢狀結構的列表物件

 options: [ {
          id: 'a',
          label: 'a',
          children: [ {
            id: 'aa',
            label: 'aa',
          } ],

另外,有時候我們可能在樹選擇框中需要用來設定父級列表的處理,由於這個業務比較常見,而且邏輯相對比較通用,那麼我們可以考慮把它封裝為一個元件的方式,然後再在介面上使用。

介面使用效果如下所示

這樣勾選【作為頂級目錄項】,那麼則會自動置空內容,也就是父ID為空了,如果選擇具體的樹節點,那麼就以該節點的ID作為PID,這樣操作把呼叫介面處理的邏輯簡化了,更方便使用。

  <el-col :span="24">
    <el-form-item label="父項名稱" prop="pid">
      <MyTreeselectTop v-model="addForm.pid" :options="treedata" />
    </el-form-item>
  </el-col>

這樣我們可以在多處使用這個帶有樹列表展示,以及設定頂級節點的樹列表框選擇控制元件了,如在批量錄入商品分類的操作介面中一樣使用。

11、其他元件

元件不可能一一介紹完,一般情況下,我們依照我們的資料展示需要,引入不同的介面元件,一般可以在GitHub上找到很多對比,找適合自己的且評分較高的即可。

如條碼和二維碼元件,我使用@chenfengyuan/vue-barcode和 @chenfengyuan/vue-qrcode,一般在Github上搜索下關鍵字,總能找到一些很受歡迎的第三方元件。

安裝這些元件都有具體的說明,如下所示(如果解除安裝,直接修改install為uninstall即可)。

npm install @chenfengyuan/vue-barcode vue

以及

npm install @chenfengyuan/vue-qrcode vue

條碼和二維碼的展示效果如下所示

如果全域性引入barcode和qrcode 元件,我們在main.js裡面引入即可,如下程式碼所示

// 引入barcode,qrcode
import VueBarcode from '@chenfengyuan/vue-barcode';
import VueQrcode from '@chenfengyuan/vue-qrcode';
Vue.component(VueBarcode.name, VueBarcode);

圖表元件,我們這裡使用了基於vue-echarts元件模組來處理各種圖表vue-echarts是對echarts圖表元件的封裝。

首先使用npm 安裝vue-echarts元件。

git地址:https://github.com/ecomfe/vue-echarts

NPM安裝命令

npm install echarts vue-echarts

然後在對應模組頁面裡面引入對應的元件物件,如下程式碼所示。

import ECharts from 'vue-echarts' // 主圖表物件
import 'echarts/lib/chart/line' // 曲線圖表
import 'echarts/lib/chart/bar' // 柱狀圖
import 'echarts/lib/chart/pie' // 餅狀圖
import 'echarts/lib/component/tooltip' // 提示資訊

在Vue模組頁面的Template 裡面,我們定義介面程式碼如下即可。

<v-chart
  ref="simplebar"
  :options="simplebar"
  autoresize
/>

然後在data裡面為它準備好資料即可,如下程式碼所示。

 data() {
    return {
      simplebar: {
        title: { text: '柱形圖Demo' },
        tooltip: {},
        xAxis: {
          data: ['襯衫', '羊毛衫', '雪紡衫', '褲子', '高跟鞋', '襪子']
        },
        yAxis: {},
        series: [{
          name: '銷量',
          type: 'bar',
          data: [5, 20, 36, 10, 10, 20]
        }]
      }
    }
  }

詳細可以參考我的隨筆:《循序漸進VUE+Element 前端應用開發(10)--- 基於vue-echarts處理各種圖表展示

綜上這些介面控制元件的使用原則,原則上經常重用的部分,可以把它簡單化包裝為一個元件,這樣可以減少很多介面程式碼和常規的處理JS函式,如果更高維度上還有抽離邏輯的可能呢,如我之前在角色、機構模組裡面處理很多公用邏輯介面一樣,我們把這些抽離出來作為一個元件模組,加上一些特殊的開關或者屬性設定變數,就可以響應不同介面上的操作。

還有就是這些介面元件的使用,我們不可能一一的記住,那麼使用合適的程式碼生成工具來處理就會跟提高效率了,程式碼生成工具,一般會根據欄位的資料型別,名稱等資訊,進行不同的處理,把常規的列表介面、檢視、編輯、新增、匯入、匯入等介面和功能處理函式整合一起生成,我們在這個基礎上進行微調修改,效率更高。

我們的程式碼生成工具Database2sharp,專門為優化過的框架結構進行程式碼生成,在介面工具欄或者選單中選擇【程式碼生成】【ABP的Vue+Element介面程式碼】,如下所示。

接著在出來的對話方塊上選擇對應資料庫和表進行生成,一步步執行即可。

使用程式碼生成工具快速生成基於ABP框架的Vue+Element的前端介面,能夠使得我們提高程式碼的開發效率,以及降低出錯的機會,同時可以很好的統一整套介面的介面樣式和做法,事半功倍。

生成的列表介面,包括查詢、表格、分頁等資訊,查詢框中包含一些關鍵欄位的資訊查詢,而表格中則包含重要欄位資訊的展示或者相關操作。

然後編輯介面,簡單的如下所示。

為了方便讀者理解,我列出一下前面幾篇隨筆的連線,供參考:

循序漸進VUE+Element 前端應用開發(1)--- 開發環境的準備工作

循序漸進VUE+Element 前端應用開發(2)--- Vuex中的API、Store和View的使用

循序漸進VUE+Element 前端應用開發(3)--- 動態選單和路由的關聯處理

循序漸進VUE+Element 前端應用開發(4)--- 獲取後端資料及產品資訊頁面的處理

循序漸進VUE+Element 前端應用開發(5)--- 表格列表頁面的查詢,列表展示和欄位轉義處理

循序漸進VUE+Element 前端應用開發(6)--- 常規Element 介面元件的使用

循序漸進VUE+Element 前端應用開發(7)--- 介紹一些常規的JS處理函式

循序漸進VUE+Element 前端應用開發(8)--- 樹列表元件的使用

循序漸進VUE+Element 前端應用開發(9)--- 介面語言國際化的處理

循序漸進VUE+Element 前端應用開發(10)--- 基於vue-echarts處理各種圖表展示

循序漸進VUE+Element 前端應用開發(11)--- 圖示的維護和使用

循序漸進VUE+Element 前端應用開發(12)--- 整合ABP框架的前端登入處理

循序漸進VUE+Element 前端應用開發(13)--- 前端API介面的封裝處理

循序漸進VUE+Element 前端應用開發(14)--- 根據ABP後端介面實現前端介面展示

循序漸進VUE+Element 前端應用開發(15)--- 使用者管理模組的處理

循序漸進VUE+Element 前端應用開發(16)--- 組織機構和角色管理模組的處理

循序漸進VUE+Element 前端應用開發(17)--- 選單管理

循序漸進VUE+Element 前端應用開發(18)--- 功能點管理及許可權控制

循序漸進VUE+Element 前端應用開發(19)--- 後端查詢介面和Vue前端的整合

循序漸進VUE+Element 前端應用開發(20)--- 使用元件封裝簡化介面程式碼

循序漸進VUE+Element 前端應用開發(21)--- 省市區縣聯動處理的元件使用

循序漸進VUE+Element 前端應用開發(22)--- 簡化main.js處理程式碼,抽取過濾器、全域性介面函式、元件註冊等處理邏輯到不同的檔案中

循序漸進VUE+Element 前端應用開發(23)--- 基於ABP實現前後端的附件上傳,圖片或者附件展示管理

循序漸進VUE+Element 前端應用開發(24)--- 修改密碼的前端介面和ABP後端設定處理

循序漸進VUE+Element 前端應用開發(25)--- 各種介面元件的使用(1)