前端組件化封裝及npm部署


前端組件化封裝及npm部署

簡介

組件化思想是軟件編程的一個重要思想。如汽車的生產,將輪子、燈、座椅等作為單獨的組件,由各自的工廠去生產維護,各個組件都做好后再拿到組裝廠統一組裝使用。組件化思想就是將一個項目拆分成若干個組件,分而治之。

組件化開發好處

  • 高復用性:復用的好處可以得到 較高的生產效率以及隨之而來的成本降低、較高的軟件質量(錯誤可以更快的被糾正)以及 恰當的使用復用可以改善系統的可維護性。
  • 低耦合性:低耦合就是指各模塊依賴程度,減少模塊間調用。

高內聚和低耦合目的是使程序模塊的可重用性、移植性大大增強。

組件封裝

github地址:https://github.com/MengFangui/iview-table-page

項目中經常使用表格和分頁組件,目前比較流行的element UI,iview UI和Ant Design 3個UI庫都有表格和分頁組件,但是沒有將表格和分頁組件組合;同時分頁組件都有一個bug,即電梯(快速跳轉到某一頁)沒有綁定跳轉事件。本文將以iview ui的Table和Page為例,簡述前端組件封裝和npm打包部署。

iview-table-page 組件實現

<template>
<div>
     <Table
     :columns="columns"
     :data="data"
     :stripe='stripe'
     :border='border'
     :show-header='showHeader'
     :width='width'
     :height='height'
     :max-height='maxHeight'
     :loading='loading'
     :disabled-hover='disabledHover'
     :row-class-name='rowClassName'
     :size='size'
     :no-data-tex='noDataText'
     :no-filtered-data-text='noFilteredDataText'
     :draggable='draggable'
     :tooltip-theme='tooltipTheme'
     :row-key='rowKey'
     :highlight-row='highlightRow'

     @on-current-change='onCurrentChange'
     @on-select='onSelect'
     @on-select-cancel='onSelectCancel'
     @on-select-all='onSelectAll'
     @on-select-all-cancel='onSelectAllCancel'
     @on-selection-change='onSelectionChange'
     @on-sort-change='onSortChange'
     @on-filter-change='onFilterChange'
     @on-row-click='onRowClick'
     @on-row-dblclick='onRowDblclick'
     @on-expand='onExpand'
     @on-drag-drop='onDragDrop'>
      <template slot="header">
          <slot name='header'></slot>
      </template>
      <template slot="footer">
          <slot name='footer'></slot>
      </template>
      <template slot="loading">
          <slot name='loading'></slot>
      </template>
     </Table>
    <div :style="pageStyle" v-if="paginationShow">
        <Page
            :total="total"
            :current="current"
            :page-size='pageSize'
            :page-size-opts='pageSizeOpts'
            :placement='placement'
            :size='pageShapeSize'
            :simple='simple'
            :show-total='showTotal'
            :show-elevator='showElevator'
            :show-sizer='showSizer'
            :class-name='pageClassName'
            :styles='styles'
            :transfer='transfer'
            :prev-text='prevText'
            :next-text='nextText'

            @on-change='onChange'
            @on-page-size-change='onPageSizeChange'>
            <slot/>
            </Page>
    </div>
</div>
</template>

<script>
export default {
  name: 'iviewTablePage',
  props: {
    // 表格數據
    data: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 表格列屬性
    columns: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 是否顯示間隔斑馬紋
    stripe: {
      type: Boolean,
      default: false
    },
    // 是否顯示縱向邊框
    border: {
      type: Boolean,
      default: false
    },
    // 是否顯示表頭
    showHeader: {
      type: Boolean,
      default: true
    },
    // 表格寬度,單位 px
    width: [String, Number],
    // 表格高度,單位 px,設置后,如果表格內容大於此值,會固定表頭
    height: [String, Number],
    // 表格最大高度,單位 px,設置后,如果表格內容大於此值,會固定表頭
    maxHeight: [String, Number],
    // 表格是否加載中
    loading: {
      type: Boolean,
      default: false
    },
    // 禁用鼠標懸停時的高亮
    disabledHover: {
      type: Boolean,
      default: false
    },
    // 是否支持高亮選中的行,即單選
    highlightRow: {
      type: Boolean,
      default: false
    },
    // 行的 className 的回調方法
    rowClassName: {
      type: Function,
      default: () => {
        return ''
      }
    },
    // 表格尺寸,可選值為 large、small、default 或者不填
    size: {
      type: String
    },
    // 數據為空時顯示的提示內容
    noDataText: {
      type: String,
      default: '暫無數據'
    },
    // 篩選數據為空時顯示的提示內容
    noFilteredDataText: {
      type: String,
      default: '暫無篩選結果'
    },
    // 是否開啟拖拽調整行順序,需配合 @on-drag-drop 事件使用
    draggable: {
      type: Boolean,
      default: false
    },
    // 列使用 tooltip 時,配置它的主題,可選值為 dark 或 light
    tooltipTheme: {
      type: String,
      default: 'dark'
    },
    // 是否強制使用內置的 row-key,開啟后可能會影響性能
    rowKey: {
      type: Boolean,
      default: false
    },
    // 當前頁碼,支持 .sync 修飾符
    currentPage: {
      type: Number,
      default: 1
    },
    // 數據總數
    total: {
      type: Number,
      default: 0
    },
    // 每頁條數
    pageSize: {
      type: Number,
      default: 10
    },
    // 每頁條數切換的配置
    pageSizeOpts: {
      type: Array,
      default: () => {
        return [10, 20, 30, 40]
      }
    },
    // 條數切換彈窗的展開方向,可選值為 bottom 和 top
    placement: {
      type: String,
      default: 'bottom'
    },
    // 可選值為small(迷你版)或不填(默認)
    pageShapeSize: {
      type: String
    },
    // 簡潔版
    simple: {
      type: Boolean,
      default: false
    },
    // 顯示總數
    showTotal: {
      type: Boolean,
      default: false
    },
    // 顯示電梯,可以快速切換到某一頁
    showElevator: {
      type: Boolean,
      default: false
    },
    // 顯示分頁,用來改變page-size
    showSizer: {
      type: Boolean,
      default: false
    },
    // 自定義 class 名稱
    pageClassName: {
      type: String,
      default: ''
    },
    // 自定義 style 樣式
    styles: {
      type: Object,
      default: () => {
        return {}
      }
    },
    // 是否將彈層放置於 body 內,在 Tabs、帶有 fixed 的 Table 列內使用時,建議添加此屬性,它將不受父級樣式影響,從而達到更好的效果
    transfer: {
      type: Boolean,
      default: false
    },
    // 替代圖標顯示的上一頁文字
    prevText: {
      type: String,
      default: ''
    },
    // 替代圖標顯示的下一頁文字
    nextText: {
      type: String,
      default: ''
    },
    // 是否顯示頁碼
    paginationShow: {
      type: Boolean,
      default: true
    },
    paginationPosition: {
      type: String,
      default: 'right'
    }
  },
  data () {
    return {
      pageStyle: {
        'text-align': this.paginationPosition,
        margin: '16px 0'
      },
      current: 1
    }
  },
  methods: {
    // 開啟 highlight-row 后有效,當表格的當前行發生變化的時候會觸發
    onCurrentChange (...arg) {
      this.$emit('on-current-change', ...arg)
    },
    // 在多選模式下有效,選中某一項時觸發
    onSelect (...arg) {
      this.$emit('on-select', ...arg)
    },
    // 在多選模式下有效,取消選中某一項時觸發
    onSelectCancel (...arg) {
      this.$emit('on-select-cancel', ...arg)
    },
    // 在多選模式下有效,點擊全選時觸發
    onSelectAll (...arg) {
      this.$emit('on-select-all', ...arg)
    },
    // 在多選模式下有效,點擊取消全選時觸發
    onSelectAllCancel (...arg) {
      this.$emit('on-select-all-cancel', ...arg)
    },
    // 在多選模式下有效,只要選中項發生變化時就會觸發
    onSelectionChange (...arg) {
      this.$emit('on-selection-change', ...arg)
    },
    // 排序時有效,當點擊排序時觸發
    onSortChange (...arg) {
      this.$emit('on-sort-change', ...arg)
    },
    // 篩選時有效,篩選條件發生變化時觸發
    onFilterChange (...arg) {
      this.$emit('on-filter-change', ...arg)
    },
    // 單擊某一行時觸發
    onRowClick (...arg) {
      this.$emit('on-row-click', ...arg)
    },
    // 雙擊某一行時觸發
    onRowDblclick (...arg) {
      this.$emit('on-row-dblclick', ...arg)
    },
    // 展開或收起某一行時觸發
    onExpand (...arg) {
      this.$emit('on-expand', ...arg)
    },
    // 拖拽排序松開時觸發,返回置換的兩行數據索引
    onDragDrop (...arg) {
      this.$emit('on-drag-drop', ...arg)
    },
    // 頁碼改變的回調,返回改變后的頁碼
    onChange (...arg) {
      this.$emit('on-change', ...arg)
    },
    // 切換每頁條數時的回調,返回切換后的每頁條數
    onPageSizeChange (...arg) {
      this.$emit('on-page-size-change', ...arg)
    },
    // 表格方法
    // 清除高亮項,僅在開啟 highlight-row 時可用
    clearCurrentRow (...arg) {
      this.$children[0].clearCurrentRow(...arg)
    },
    // 表格方法
    // 全選或者取消全選
    selectAll (status) {
      this.$children[0].selectAll(status)
    },
    // 表格方法
    exportCsv (...arg) {
      this.$children[0].exportCsv(...arg)
    }
  },
  mounted () {
    // 初始化頁碼
    this.current = this.currentPage
    let that = this
    // 獲取跳轉頁碼
    let dom = document.querySelector('.ivu-page-options-elevator input')
    if (dom) {
      // 定義事件onchange
      dom.onchange = function () {
        let pageNo = parseInt(dom.value, 10)
        if (!Number.isNaN(pageNo) && pageNo > 0 && pageNo <= that.total) {
          that.current = pageNo
        }
      }
    }
  }
}
</script>

API 說明

table 屬性

屬性 說明 類型 默認值
data 顯示的結構化數據,其中,字段 cellClassName 用於設置任意單元格的樣式名稱,因此數據不能使用該字段,詳見示例特定樣式。 Array []
columns 表格列的配置描述,具體項見后文 Array []
stripe 是否顯示間隔斑馬紋 Boolean false
border 是否顯示縱向邊框 Boolean false
show-header 是否顯示表頭 Boolean false
width 表格寬度,單位 px Number, String 自動
height 表格高度,單位 px,設置后,如果表格內容大於此值,會固定表頭 Number, String -
max-height 表格最大高度,單位 px,設置后,如果表格內容大於此值,會固定表頭 Number, String -
loading 表格是否加載中 Boolean false
disabled-hover 禁用鼠標懸停時的高亮 Boolean false
highlight-row 是否支持高亮選中的行,即單選 Boolean false
row-class-name 行的 className 的回調方法,傳入參數:row:當前行數據, index:當前行的索引 Function -
size 表格尺寸,可選值為 large、small、default 或者不填 String -
no-data-text 數據為空時顯示的提示內容 String 暫無數據
no-filtered-data-text 篩選數據為空時顯示的提示內容 String 暫無篩選結果
draggable 是否開啟拖拽調整行順序,需配合 @on-drag-drop 事件使用 Boolean false
tooltip-theme 列使用 tooltip 時,配置它的主題,可選值為 dark 或 light String dark
row-key 是否強制使用內置的 row-key,開啟后可能會影響性能 Boolean false

table事件

事件名 說明 返回值
on-current-change 開啟 highlight-row 后有效,當表格的當前行發生變化的時候會觸發 currentRow:當前高亮行的數據, oldCurrentRow:上一次高亮的數據
on-select 在多選模式下有效,選中某一項時觸發 selection:已選項數據, row:剛選擇的項數據, 即接收的參數是(selection,row)
on-select-cancel 在多選模式下有效,取消選中某一項時觸發 selection:已選項數據,row:取消選擇的項數據
on-select-all 在多選模式下有效,點擊全選時觸發 selection:已選項數據
on-select-all-cancel 在多選模式下有效,點擊取消全選時觸發 selection:已選項數據
on-selection-change 在多選模式下有效,只要選中項發生變化時就會觸發 selection:已選項數據
on-sort-change 排序時有效,當點擊排序時觸發 column:當前列數據,key:排序依據的指標,order:排序的順序,值為 asc 或 desc
on-filter-change 篩選時有效,篩選條件發生變化時觸發 當前列數據
on-row-click 單擊某一行時觸發 當前行的數據,index
on-row-dblclick 雙擊某一行時觸發 當前行的數據,index
on-expand 展開或收起某一行時觸發 row:當前行的數據,status:當前的狀態
on-drag-drop 拖拽排序松開時觸發,返回置換的兩行數據索引 index1, index2

page 屬性

屬性 說明 類型 默認值
currentPage 當前頁碼 Number 1
total 數據總數 Number 0
page-size 每頁條數 Number 10
page-size-opts 每頁條數切換的配置 Array [10, 20, 30, 40]
placement 條數切換彈窗的展開方向,可選值為 bottom 和 top String bottom
page-shape-size 可選值為small(迷你版)或不填(默認) String -
simple 簡潔版 Boolean false
show-total 顯示總數 Boolean false
show-elevator 顯示電梯,可以快速切換到某一頁 Boolean false
show-sizer 顯示分頁,用來改變page-size Boolean false
page-class-name 自定義 class 名稱 String -
styles 自定義 style 樣式 Object -
transfer 是否將彈層放置於 body 內,在 Tabs、帶有 fixed 的 Table 列內使用時,建議添加此屬性,它將不受父級樣式影響,從而達到更好的效果 Boolean false
prev-text 替代圖標顯示的上一頁文字 String -
next-text 替代圖標顯示的下一頁文字 String -

新增屬性

屬性 說明 類型 默認值
pagination-show 是否顯示頁面 Boolean true
pagination-position 頁碼位置 String 可選值為 left、center 和 right right

其中大多數都是ivew UI上的事件和屬性,新增了pagination-show和pagination-position屬性。

電梯(跳轉到某一頁)事件綁定實現

獲取跳轉頁面input dom,將dom綁定onchange事件。

// 獲取跳轉頁碼dom
let dom = document.querySelector('.ivu-page-options-elevator input')
if (dom) {
  // 定義事件onchange
  dom.onchange = function () {
    let pageNo = parseInt(dom.value, 10)
    if (!Number.isNaN(pageNo) && pageNo > 0 && pageNo <= that.total) {
      that.current = pageNo
    }
  }

demo

iview-table-page 組件使用

安裝組件

$ npm i --save iview-table-page
or
$ yarn add iview-table-page

組件注冊

全局注冊組件

main.js中:

import Vue from 'vue'
import iviewTablePage from 'iview-table-page'
Vue.use(iviewTablePage)
局部注冊組件
<template>
<div>
  <iviewTablePage
  border
  :columns="columns7"
  :data="data6"
  :total='total'
  >
  </iviewTablePage>
</div>
</template>

<script>
import iviewTablePage from 'iview-table-page'
export default {
  components: { iviewTablePage },
  data () {
    return {
      columns7: [
        {
          title: 'Name',
          key: 'name',
          render: (h, params) => {
            return h('div', [
              h('Icon', {
                props: {
                  type: 'person'
                }
              }),
              h('strong', params.row.name)
            ])
          }
        },
        {
          title: 'Age',
          key: 'age'
        },
        {
          title: 'Address',
          key: 'address'
        },
        {
          title: 'Action',
          key: 'action',
          width: 150,
          align: 'center',
          render: (h, params) => {
            return h('div', [
              h(
                'Button',
                {
                  props: {
                    type: 'primary',
                    size: 'small'
                  },
                  style: {
                    marginRight: '5px'
                  },
                  on: {
                    click: () => {
                      this.show(params.index)
                    }
                  }
                },
                'View'
              ),
              h(
                'Button',
                {
                  props: {
                    type: 'error',
                    size: 'small'
                  },
                  on: {
                    click: () => {
                      this.remove(params.index)
                    }
                  }
                },
                'Delete'
              )
            ])
          }
        }
      ],
      data6: [
        {
          name: 'John Brown',
          age: 18,
          address: 'New York No. 1 Lake Park'
        },
        {
          name: 'Jim Green',
          age: 24,
          address: 'London No. 1 Lake Park'
        },
        {
          name: 'Joe Black',
          age: 30,
          address: 'Sydney No. 1 Lake Park'
        },
        {
          name: 'Jon Snow',
          age: 26,
          address: 'Ottawa No. 2 Lake Park'
        }
      ],
      total: 4
    }
  }
}
</script>

npm 打包

package.json核心配置

"build-bundle": "vue-cli-service build --target lib --name iviewTablePage ./src/components/index.js",

"main": "dist/iviewTablePage.umd.js",
  • 打包為lib。
  • 入口文件為umd規范的js。
  • keywords:便於搜索npm 包。
  • repository: 代碼存放地址(一般是git地址)。
  • devDependencies: 你要發的包,所依賴的開發環境下的包。
  • dependencies:你要發的包,所依賴的線上環境下的包。

package.json的完整配置見:https://github.com/MengFangui/iview-table-page/blob/master/package.json

npm注冊賬號

https://www.npmjs.com/signup

發包

在你將要發包的目錄下,執行

npm adduser
npm publish

到此完成前端組件化封裝和npm打包部署工作。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM