<strike id="cy2gs"><menu id="cy2gs"></menu></strike>
  • <del id="cy2gs"><dfn id="cy2gs"></dfn></del>
  • 封裝element-ui表格

    2020-7-30    seo達人

    表格需求

    一般管理系統對表格會有以下需求


    可以分頁(需要有分頁條)

    可以多選(表格帶復選框)

    頂部需要加一些操作按鈕(新增,刪除等等)

    表格每行行尾有操作按鈕

    表格行可以編輯

    如下圖為一個示例表格




    如果我們直接使用element-ui提供的組件的話,那么開發一個這樣的表格就需要使用到以下內容


    需要使用表格的插槽功能,開發每一行的按鈕

    需要通過樣式調整頂部按鈕,表格,分頁條的布局樣式

    需要監聽分頁的事件然后去刷新表格數據

    頂部按鈕或操作按鈕如果需要獲取表格數據,需要調用表格提供的api

    對于有行編輯的需求,還需要通過插槽去渲染行編輯的內容,同時要控制行編輯的開關

    不僅僅開發表格比較麻煩,而且還要考慮團隊協作,如果每個人實現表格的方式存在差別,那么可能后期的維護成本也會變得很高。那怎么辦呢?


    項目安裝

    安裝插件

    在使用element-ui的項目中,可以通過以下命令進行安裝


    npm install vue-elementui-table -S

    在項目中使用

    在main.js中添加以下代碼


    import ZjTable from 'vue-element-table'


    Vue.use(ZjTable)

    然后即可像下文中的使用方式進行使用


    表格配置

    為了滿足團隊快速開發的需要,小編對上面提出來的需求進行了封裝,然后使用的時候,開發人員只需要配置一些JSON便可以完成以上功能的開發。


    基礎配置

    一個基礎的表格包含了數據和列信息,那么如何用封裝的表格去配置呢?


    <template>

     <zj-table

       :columns="columns"

       :data="data"

       :pagination="false"

     />

    </template>

    <script>

    export default {

     data() {

       return {

         // 表格的列信息, 數組每一項代表一個字段,可以使用element 列屬性的所有屬性,以下僅為示例

         columns: Object.freeze([

           {

             // 表頭顯示的文字

             label: '姓名',

             // 對應數據里面的字段

             prop: 'name'

           },

           {

             label: '性別',

             prop: 'sex',

             // 格式化表格,與element-ui 的表格屬性相同

             formatter(row, column, cellValue) {

               return cellValue === 1 ? '男' : '女'

             }

           },

           {

             label: '年齡',

             prop: 'age'

           }

         ]),

         data: [

           {

             name: '子君',

             sex: 1,

             age: 18

           }

         ]

       }

     }

    }

    </script>

    通過上面的配置,就可以完成一個基礎表格的開發,完整代碼見 https://github.com/snowzijun/vue-element-table/blob/master/example/views/demo/base.vue,效果如下圖所示




    表格默認會顯示復選框,也可以通過配置selectable屬性來關閉掉


    添加分頁

    簡單的表格用封裝之后的或未封裝的開發工作量區別并不大,我們繼續為表格添加上分頁


    <template>

       <!--

       current-page.sync 表示頁碼, 添加上 .sync 在頁碼發生變化時自動同步頁碼

       page-size.sync 每頁條數

       total  總條數

       height="auto" 配置height:auto, 表格高度會根據內容自動調整,如果不指定,表格將保持充滿父容器,同時表頭會固定,不跟隨滾動條滾動

       @page-change 無論pageSize currentPage 哪一個變化,都會觸發這個事件

     -->

     <zj-table

       v-loading="loading"

       :columns="columns"

       :data="data"

       :current-page.sync="currentPage"

       :page-size.sync="pageSize"

       :total="total"

       height="auto"

       @page-change="$_handlePageChange"

     />

    </template>

    <script>

    export default {

     data() {

       return {

         columns: Object.freeze([

           // 列字段與上例一樣,此處省略

         ]),

         data: [],

         // 當前頁碼

         currentPage: 1,

         // 每頁條數

         pageSize: 10,

         // 總條數

         total: 0,

         // 是否顯示loading

         loading: false

       }

     },

     created() {

       this.loadData()

     },

     methods: {

       // 加載表格數據

       loadData() {

         this.loading = true

         setTimeout(() => {

           // 假設總條數是40條

           this.total = 40

           const { currentPage, pageSize } = this

           // 模擬數據請求獲取數據

           this.data = new Array(pageSize).fill({}).map((item, index) => {

             return {

               name: `子君${currentPage + (index + 1) * 10}`,

               sex: Math.random() > 0.5 ? 1 : 0,

               age: Math.floor(Math.random() * 100)

             }

           })

           this.loading = false

         }, 1000)

       },

       $_handlePageChange() {

         // 因為上面設置屬性指定了.sync,所以這兩個屬性會自動變化

         console.log(this.pageSize, this.currentPage)

         // 分頁發生變化,重新請求數據

         this.loadData()

       }

     }

    }

    </script>

    完整代碼請參考 https://github.com/snowzijun/vue-element-table/blob/master/example/views/demo/pagination.vue


    通過封裝,表格將自帶分頁功能,通過上面代碼,實現效果如下所示,是不是變得簡單了一些。接下來我們繼續給表格添加按鈕




    添加頂部按鈕

    表格上面可能會有新增,刪除等等按鈕,怎么辦呢,接下來我們繼續通過配置去添加按鈕


    <template>

     <zj-table

       :buttons="buttons"

     />

    </template>

    <script>

    export default {

     data() {

       return {

         buttons: Object.freeze([

           {

             // id 必須有而且是在當前按鈕數組里面是唯一的

             id: 'add',

             text: '新增',

             type: 'primary',

             icon: 'el-icon-circle-plus',

             click: this.$_handleAdd

           },

           {

             id: 'delete',

             text: '刪除',

             // rows 是表格選中的行,如果沒有選中行,則禁用刪除按鈕, disabled可以是一個boolean值或者函數

             disabled: rows => !rows.length,

             click: this.$_handleRemove

           },

           {

             id: 'auth',

             text: '這個按鈕根據權限顯示',

             // 可以通過返回 true/false來控制按鈕是否顯示

             before: (/** rows */) => {

               return true

             }

           },

           // 可以配置下拉按鈕哦

           {

             id: 'dropdown',

             text: '下拉按鈕',

             children: [

               {

                 id: 'moveUp',

                 text: '上移',

                 icon: 'el-icon-arrow-up',

                 click: () => {

                   console.log('上移')

                 }

               },

               {

                 id: 'moveDown',

                 text: '下移',

                 icon: 'el-icon-arrow-down',

                 disabled: rows => !rows.length,

                 click: () => {

                   console.log('下移')

                 }

               }

             ]

           }

         ])

       }

     },

     created() {},

     methods: {

       // 新增

       $_handleAdd() {

         this.$alert('點擊了新增按鈕')

       },

       // 頂部按鈕會自動將表格所選的行傳出來

       $_handleRemove(rows) {

         const ids = rows.map(({ id }) => id)

         this.$alert(`要刪除的行id為${ids.join(',')}`)

       },

       // 關注作者公眾號

       $_handleFollowAuthor() {}

     }

    }

    </script>

    表格頂部可以添加普通的按鈕,也可以添加下拉按鈕,同時還可以通過before來配置按鈕是否顯示,disabled來配置按鈕是否禁用,上面完整代碼見 https://github.com/snowzijun/vue-element-table/blob/master/example/views/demo/button.vue


    通過上面的代碼就可以配置出下面的表格,是不是很簡單呢?




    表格頂部可以有按鈕,行尾也是可以添加按鈕的,一起來看看


    行操作按鈕

    一般我們會將一些單行操作的按鈕放在行尾,比如編輯,下載等按鈕,那如何給行尾配置按鈕呢?


    <template>

     <zj-table

       :columns="columns"

     />

    </template>

    <script>

    export default {

     data() {

       return {

         columns: Object.freeze([

           {

             // 可以指定列的寬度,與element-ui原生用法一致

             width: 220,

             label: '姓名',

             prop: 'name'

           },

           // 行編輯按鈕,在表格末尾出現,自動鎖定右側

           {

             width: 180,

             label: '操作',

             // 通過 actions 指定行尾按鈕

             actions: [

               {

                 id: 'follow',

                 text: '關注作者',

                 click: this.$_handleFollowAuthor

               },

               {

                 id: 'edit',

                 text: '編輯',

                 // 可以通過before控制按鈕是否顯示,比如下面年齡四十歲的才會顯示編輯按鈕

                 before(row) {

                   return row.age < 40

                 },

                 click: this.$_handleEdit

               },

               {

                 id: 'delete',

                 text: '刪除',

                 icon: 'el-icon-delete',

                 disabled(row) {

                   return row.sex === 0

                 },

                 // 為了拿到this,這里需要用箭頭函數

                 click: () => {

                   this.$alert('女生被禁止刪除了')

                 }

               }

             ]

           }

         ])

       }

     },

     methods: {

       // 關注作者公眾號

       $_handleFollowAuthor() {

               console.log('微信搜索【前端有的玩】,這是對小編最大的支持')

       },

       /**

        * row 這一行的數據

        */

       $_handleEdit(row, column) {

         this.$alert(`點擊了姓名為【${row.name}】的行上的按鈕`)

       }

     }

    }

    </script>

    行操作按鈕會被凍結到表格最右側,不會跟隨滾動條滾動而滾動,上面完整代碼見, https://github.com/snowzijun/vue-element-table/blob/master/example/views/demo/button.vue


    通過上面的代碼就可以完成以下效果




    最后再來一起看看行編輯


    行編輯

    比如上例,我希望點擊行尾的編輯按鈕的時候,可以直接在行上面編輯用戶的姓名與性別,如何配置呢?


    <template>

     <zj-table

       ref="table"

       :columns="columns"

       :data="data"

     />

    </template>

    <script>

    export default {

     data() {

       return {

         columns: Object.freeze([

           {

             label: '姓名',

             prop: 'name',

             editable: true,

             field: {

               componentType: 'input',

               rules: [

                 {

                   required: true,

                   message: '請輸入姓名'

                 }

               ]

             }

           },

           {

             label: '性別',

             prop: 'sex',

             // 格式化表格,與element-ui 的表格屬性相同

             formatter(row, column, cellValue) {

               return cellValue === '1' ? '男' : '女'

             },

             editable: true,

             field: {

               componentType: 'select',

               options: [

                 {

                   label: '男',

                   value: '1'

                 },

                 {

                   label: '女',

                   value: '0'

                 }

               ]

             }

           },

           {

             label: '年齡',

             prop: 'age',

             editable: true,

             field: {

               componentType: 'number'

             }

           },

           {

             label: '操作',

             actions: [

               {

                 id: 'edit',

                 text: '編輯',

                 // 如果當前行啟用了編輯,則不顯示編輯按鈕

                 before: row => {

                   return !this.editIds.includes(row.id)

                 },

                 click: this.$_handleEdit

               },

               {

                 id: 'save',

                 text: '保存',

                 // 如果當前行啟用了編輯,則顯示保存按鈕

                 before: row => {

                   return this.editIds.includes(row.id)

                 },

                 click: this.$_handleSave

               }

             ]

           }

         ]),

         data: [

           {

             // 行編輯必須指定rowKey字段,默認是id,如果修改為其他字段,需要給表格指定row-key="字段名"

             id: '0',

             name: '子君',

             sex: '1',

             age: 18

           },

           {

             // 行編輯必須指定rowKey字段,默認是id,如果修改為其他字段,需要給表格指定row-key="字段名"

             id: '1',

             name: '子君1',

             sex: '0',

             age: 18

           }

         ],

         editIds: []

       }

     },

     methods: {

       $_handleEdit(row) {

         // 通過調用 startEditRow 可以開啟行編輯

         this.$refs.table.startEditRow(row.id)

         // 記錄開啟了行編輯的id

         this.editIds.push(row.id)

       },

       $_handleSave(row) {

         // 點擊保存的時候,通過endEditRow 結束行編輯

         this.$refs.table.endEditRow(row.id, (valid, result, oldRow) => {

           // 如果有表單驗證,則valid會返回是否驗證成功

           if (valid) {

             console.log('修改之后的數據', result)

             console.log('原始數據', oldRow)

             const index = this.editIds.findIndex(item => item === row.id)

             this.editIds.splice(index, 1)

           } else {

             // 如果校驗失敗,則返回校驗的第一個輸入框的異常信息

             console.log(result)

             this.$message.error(result.message)

           }

         })

       }

     }

    }

    </script>

    不需要使用插槽就可以完成行編輯,是不是很開心。上述完整代碼見 https://github.com/snowzijun/vue-element-table/blob/master/example/views/demo/row-edit.vue


    效果如下圖所示:




    其他功能

    除了上面的功能之外,表格還可以配置其他許多功能,比如


    可以指定字段為鏈接列,需要給列配置link屬性

    可以通過插槽自定義頂部按鈕,行操作按鈕,行字段等

    可以在按鈕區域右側通過插槽配置其他內容

    其他等等

    表格開發說明

    通過上面的代碼示例,我們已經知道了封裝之后的表格可以完成哪些事情,接下來一起來看看表格是如何實現的。完整代碼見 https://github.com/snowzijun/vue-element-table/tree/master/src/components/zj-table


    表格布局

    整個表格是通過JSX來封裝的,因為JSX使用起來更加靈活。對于我們封裝的表格,我們從豎向可以分為三部分,分別是頂部按鈕區,中間表格區,底部分頁區,如何去實現三個區域的布局呢,核心代碼如下


    render(h) {

       // 按鈕區域

       const toolbar = this.$_renderToolbar(h)

       // 表格區域

       const table = this.$_renderTable(h)

       // 分頁區域

       const page = this.$_renderPage(h)


       return (

         <div class="zj-table" style={{ height: this.tableContainerHeight }}>

           {toolbar}

           {table}

           {page}

         </div>

       )

     }

    通過三個render函數分別渲染對應區域,然后將三個區域組合在一起。


    渲染表格列

    通過前文的講解,我們可以將表格的列分為以下幾種


    常規列

    行編輯列

    操作按鈕列

    插槽列

    鏈接列(文檔后續完善)

    嵌套列(文檔后續完善)

       $_renderColumns(h, columns) {

         // 整體是否排序

         let sortable = this.sortable ? 'custom' : false

         return columns

           .filter(column => {

             const { hidden } = column

             if (hidden !== undefined) {

               if (typeof hidden === 'function') {

                 return hidden({

                   columns,

                   column

                 })

               }

               return hidden

             }

             return true

           })

           .map(column => {

             const {

               useSlot = false,

               // 如果存在操作按鈕,則actions為非空數組

               actions = [],

               // 是否可編輯列, 對于可編輯列需要動態啟用編輯

               editable = false,

               // 是否有嵌套列

               nests,

               // 是否可點擊

               link = false

             } = column

             let newSortable = sortable

             if (column.sortable !== undefined) {

               newSortable = column.sortable ? 'custom' : false

             }

             column = {

               ...column,

               sortable: newSortable

             }

             if (nests && nests.length) {

               // 使用嵌套列

               return this.$_renderNestColumn(h, column)

             } else if (editable) {

               // 使用編輯列

               return this.$_renderEditColumn(h, column)

             } else if (useSlot) {

               // 使用插槽列

               return this.$_renderSlotColumn(h, column)

             } else if (actions && actions.length > 0) {

               // 使用操作列

               column.sortable = false

               return this.$_renderActionColumn(h, column)

             } else if (link) {

               // 使用鏈接列

               return this.$_renderLinkColumn(h, column)

             } else {

               // 使用默認列

               return this.$_renderDefaultColumn(h, column)

             }

           })

       },

    行編輯列

    當前表格行編輯支持input,select,datepicker,TimeSelect,InputNumber等組件,具體渲染代碼如下所示


    // 編輯單元格

       $_renderEditCell(h, field) {

         const components = {

           input: Input,

           select: ZjSelect,

           date: DatePicker,

           time: TimeSelect,

           number: InputNumber

         }

         const componentType = field.componentType

         const component = components[componentType]

         if (component) {

           return this.$_renderField(h, field, component)

         } else if (componentType === 'custom') {

           // 如果自定義,可以通過component指定組件

           return this.$_renderField(h, field, field.component)

         }

         return this.$_renderField(h, field, Input)

       },

       $_renderField(h, field, Component) {

         // 編輯行的id字段

         const { rowId, events = {}, nativeEvents = {} } = field


         const getEvents = events => {

           const newEvents = {}

           Object.keys(events).forEach(key => {

             const event = events[key]

             newEvents[key] = (...rest) => {

               const args = [

                 ...rest,

                 {

                   rowId,

                   row: this.editRowsData[rowId],

                   value: this.editRowsData[rowId][field.prop]

                 }

               ]

               return event(...args)

             }

           })

           return newEvents

         }

         // 事件改寫

         const newEvents = getEvents(events)

         const newNativeEvents = getEvents(nativeEvents)

         return (

           <Component

             size="small"

             on={newEvents}

             nativeOn={newNativeEvents}

             v-model={this.editRowsData[rowId][field.prop]}

             {...{

               attrs: field,

               props: field

             }}

           />

         )

       }

    藍藍設計www.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務


    日歷

    鏈接

    個人資料

    藍藍設計的小編 http://www.skdbbs.com

    存檔

    主站蜘蛛池模板: 久久久精品午夜免费不卡| 亚洲精品国产精品乱码不99| 日韩精品无码中文字幕一区二区| 日韩精品一二三区| 日韩精品人成在线播放| 久久精品中文字幕久久| 人妻精品久久无码区| 欧美ppypp精品一区二区| 亚洲线精品一区二区三区| 人妻精品久久无码区| 久久久久一级精品亚洲国产成人综合AV区 | 久久精品国产亚洲麻豆| 精品不卡一区二区| 午夜精品美女写真福利| 国产精品尹人在线观看| 一本一道久久a久久精品综合| 久久99久久99精品免视看动漫| 老司机69精品成免费视频| 精品一区二区三区自拍图片区| 亚洲欧洲久久久精品| 欧美成人精品欧美一级乱黄一区二区精品在线| 国产福利精品在线观看| 色一乱一伦一图一区二区精品 | 国产精品网站在线观看| 国产精品欧美久久久久天天影视| 亚洲精品视频免费| 91精品国产综合久久婷婷| 久久久久无码精品| 精品久久久久久国产牛牛app | 久久亚洲精品无码AV红樱桃| 人妻少妇偷人精品无码| 久久精品九九亚洲精品| 久久精品中文字幕无码绿巨人| 色国产精品一区在线观看| 人妻少妇精品无码专区二区| 精品无码人妻夜人多侵犯18| 国产三级精品三级在线专区1| 国产综合精品女在线观看| 999国内精品永久免费视频| 欧美成人精品网站播放| 婷婷成人国产精品|