欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue.js實(shí)現(xiàn)可排序的表格組件功能示例

 更新時(shí)間:2019年02月19日 09:51:39   作者:deniro_li  
這篇文章主要介紹了Vue.js實(shí)現(xiàn)可排序的表格組件功能,涉及vue.js事件響應(yīng)、元素動(dòng)態(tài)操作、排序、運(yùn)算等相關(guān)操作技巧,需要的朋友可以參考下

本文實(shí)例講述了Vue.js實(shí)現(xiàn)可排序的表格組件功能。分享給大家供大家參考,具體如下:

我們基于 Vue.js 實(shí)現(xiàn)一個(gè)可根據(jù)某列進(jìn)行排序的表格組件。

一個(gè)表格包含表頭和數(shù)據(jù)兩部分內(nèi)容。因此,我們定義兩個(gè)數(shù)組,columns 表示表頭信息,在 <thread> 中渲染,并可在此指定某一列是否需要排序;data 表示數(shù)據(jù)。

html:

<div id="app" v-cloak>
  <v-table :data="data" :columns="columns"></v-table>
  <button @click="add">新增</button>
</div>

把父組件中定義的 data 與 columns 傳入 v-table 組件。

js:

Vue.component('vTable', {
  props: {
    //表頭列名稱
    columns: {
      type: Array,
      default: function () {
        return [];
      }
    },
    //數(shù)據(jù)
    data: {
      type: Array,
      default: function () {
        return [];
      }
    }
  },
  //為了不影響原始數(shù)據(jù),這里定義了相應(yīng)的需要操作的數(shù)據(jù)對(duì)象
  data: function () {
    return {
      currentColumns: [],
      currentData: []
    }
  },
  //render 實(shí)現(xiàn)方式
  render: function (createElement) {
    var that = this;
    /**
     * 創(chuàng)建列樣式與表頭
     */
    var ths = [];//<th> 標(biāo)簽數(shù)組
    var cols = [];//<cols> 標(biāo)簽數(shù)組
    this.currentColumns.forEach(function (col, index) {
      if (col.width) {//創(chuàng)建列樣式
        cols.push(createElement('col', {
          style: {
            width: col.width
          }
        }))
      }
      if (col.sortable) {
        ths.push(createElement('th', [
          createElement('span', col.title),
          //升序
          createElement('a', {
            class: {
              on: col.sortType === 'asc'
            },
            on: {
              click: function () {
                that.sortByAsc(index)
              }
            }
          }, '↑'),
          //降序
          createElement('a', {
            class: {
              on: col.sortType === 'desc'
            },
            on: {
              click: function () {
                that.sortByDesc(index);
              }
            }
          }, '↓')
        ]));
      } else {
        ths.push(createElement('th', col.title));
      }
    });
    /**
     * 創(chuàng)建內(nèi)容
     */
    var trs = [];//<tr> 標(biāo)簽數(shù)組
    this.currentData.forEach(function (row) {//遍歷行
      var tds = [];//<td> 標(biāo)簽數(shù)組
      that.currentColumns.forEach(function (cell) {//遍歷單元格
        tds.push(createElement('td', row[cell.key]));
      });
      trs.push(createElement('tr', tds));
    });
    return createElement('table', [
      createElement('colgroup', cols),
      createElement('thead', [
        createElement('tr', ths)
      ]),
      createElement('tbody', trs)
    ])
  },
  methods: {
    //初始化表頭
    initColumns: function () {
      this.currentColumns = this.columns.map(function (col, index) {
        //新建字段,標(biāo)識(shí)當(dāng)前列排序類(lèi)型;默認(rèn)為“不排序”
        col.sortType = 'normal';
        //新建字段,標(biāo)識(shí)當(dāng)前列在數(shù)組中的索引
        col.index = index;
        return col;
      });
    },
    //初始化數(shù)據(jù)
    initData: function () {
      this.currentData = this.data.map(function (row, index) {
        //新建字段,標(biāo)識(shí)當(dāng)前行在數(shù)組中的索引
        row.index = index;
        return row;
      });
    },
    //排序
    order: function (index, type) {
      this.currentColumns.forEach(function (col) {
        col.sortType = 'normal';
      });
      //設(shè)置排序類(lèi)型
      this.currentColumns[index].sortType = type;
      //設(shè)置排序函數(shù)
      var sortFunction;
      var key = this.currentColumns[index].key;
      switch (type) {
        default://默認(rèn)為 asc 排序
        case 'asc':
          sortFunction = function (a, b) {
            return a[key] > b[key] ? 1 : -1;
          };
          break;
        case 'desc':
          sortFunction = function (a, b) {
            return a[key] < b[key] ? 1 : -1;
          };
          break;
      }
      this.currentData.sort(sortFunction);
    },
    //升序
    sortByAsc: function (index) {
      this.order(index, 'asc');
    },
    //降序
    sortByDesc: function (index) {
      this.order(index, 'desc');
    }
  },
  watch: {
    data: function () {
      this.initData();
      //找出排序字段
      var sortedColumn = this.currentColumns.filter(function (col) {
        return col.sortType !== 'normal';
      });
      if (sortedColumn.length > 0) {
        if (sortedColumn[0].sortType === 'asc') {
          this.sortByAsc(sortedColumn[0].index);
        } else {
          this.sortByDesc(sortedColumn[0].index);
        }
      }
    }
  },
  mounted() {
    this.initColumns();
    this.initData();
  }
});
var app = new Vue({
  el: '#app',
  data: {
    //title 、key 與 width 必填;sortable 選填
    columns: [
      {
        title: '名稱',
        key: 'name',
        width:'60%'
      },
      {
        title: '數(shù)量',
        key: 'num',
        width:'20%',
        sortable: true
      },
      {
        title: '單價(jià)',
        key: 'unitPrice',
        width:'20%',
        sortable: true
      }
    ],
    data: [
      {
        name: '真果粒牛奶飲品',
        num: 2,
        unitPrice: 59.9
      },
      {
        name: '蘇泊爾(SUPOR)電壓力鍋 ',
        num: 1,
        unitPrice: 378.0
      },
      {
        name: '樂(lè)事(Lay\'s)薯片',
        num: 3,
        unitPrice: 63.0
      }
    ]
  },
  methods:{
    add:function () {
      this.data.push( {
        name: '良品鋪?zhàn)?休閑零食大禮包',
        num: 5,
        unitPrice: 59.80
      });
    }
  }
});

為了讓排序后的 columns 與 data 不影響原始數(shù)據(jù),我們?cè)诮M件的 data 中定義了相應(yīng)的當(dāng)前數(shù)據(jù)對(duì)象。因此在 method 中使用傳入的值,初始化這些數(shù)據(jù)對(duì)象,最后在 mounted() 調(diào)用這些初始化方法。

columns 中的每一項(xiàng)都是包含 title(列名)、key(對(duì)應(yīng) data 中的字段名)、width(寬度) 以及 sortable(是否可排序) 的對(duì)象。其中,只有 sortable 為可選項(xiàng),如果設(shè)定為 true,則表示該列可點(diǎn)擊排序。

map() 會(huì)對(duì)數(shù)組的每一項(xiàng)運(yùn)行給定函數(shù),返回每次函數(shù)調(diào)用的結(jié)果組成的數(shù)組。

排序分為升序與降序,因?yàn)橹荒軐?duì)某一列進(jìn)行排序,所以是互斥操作。我們?yōu)槊恳涣行略鲆粋€(gè) sortType ,用于標(biāo)識(shí)該列的排序類(lèi)型,初始值為 normal,表示不排序。

因?yàn)榕判蜃侄慰赡苁侨我饬?,所以我們?yōu)槊恳涣行略鲆粋€(gè) index,用于標(biāo)識(shí)當(dāng)前列在數(shù)組中的索引。

在 Render 函數(shù)中,首先創(chuàng)建列樣式與表頭,接著創(chuàng)建內(nèi)容。

Render 函數(shù)中的 createElement 可以簡(jiǎn)寫(xiě)為 h,這樣代碼會(huì)變得更簡(jiǎn)潔:

render: function (h) {
  var that = this;
  /**
   * 創(chuàng)建列樣式與表頭
   */
  var ths = [];//<th> 標(biāo)簽數(shù)組
  var cols = [];//<cols> 標(biāo)簽數(shù)組
  this.currentColumns.forEach(function (col, index) {
    if (col.width) {//創(chuàng)建列樣式
      cols.push(h('col', {
        style: {
          width: col.width
        }
      }))
    }
    if (col.sortable) {
      ths.push(h('th', [
        h('span', col.title),
        //升序
        h('a', {
          class: {
            on: col.sortType === 'asc'
          },
          on: {
            click: function () {
              that.sortByAsc(index)
            }
          }
        }, '↑'),
        //降序
        h('a', {
          class: {
            on: col.sortType === 'desc'
          },
          on: {
            click: function () {
              that.sortByDesc(index);
            }
          }
        }, '↓')
      ]));
    } else {
      ths.push(h('th', col.title));
    }
  });
  /**
   * 創(chuàng)建內(nèi)容
   */
  var trs = [];//<tr> 標(biāo)簽數(shù)組
  this.currentData.forEach(function (row) {//遍歷行
    var tds = [];//<td> 標(biāo)簽數(shù)組
    that.currentColumns.forEach(function (cell) {//遍歷單元格
      tds.push(h('td', row[cell.key]));
    });
    trs.push(h('tr', tds));
  });
  return h('table', [
    h('colgroup', cols),
    h('thead', [
      h('tr', ths)
    ]),
    h('tbody', trs)
  ])
}

創(chuàng)建內(nèi)容時(shí),我們首先遍歷所有行,然后在循環(huán)內(nèi)部遍歷所有列,得出 <td> 與 <tr> 內(nèi)容。

創(chuàng)建表頭時(shí),對(duì)是否排序做了相應(yīng)的處理,并綁定了相應(yīng)的點(diǎn)擊事件。

點(diǎn)擊事件定義在 methods 中,因?yàn)樯蚺c降序邏輯大體相同,所以又封裝了一層 order() 排序函數(shù)。

order() 排序函數(shù)內(nèi)部使用了數(shù)組的 sort() 方法。sort() 方法會(huì)調(diào)用每個(gè)數(shù)組項(xiàng)的 toString() 方法,然后比較得到的字符串,即使數(shù)組中的每一項(xiàng)是數(shù)值,比較的也是字符串。這里傳入了一個(gè)比較函數(shù)作為參數(shù)。為了兼容所有瀏覽器,在比較函數(shù)中,我們返回的是 1 或者 -1。

排序之前,先把所有列的排序類(lèi)型都設(shè)置為不排序,然后再更新當(dāng)前列的排序狀態(tài)。這就會(huì)對(duì)應(yīng)到 render 函數(shù)里綁定 <a> 標(biāo)簽的 class 中的 on 樣式,即當(dāng)前列排序狀態(tài)會(huì)被高亮顯示。

表格被初始化渲染之后,如果 data 發(fā)生變化,那么表格組件數(shù)據(jù)應(yīng)該也要同步更新。因此,我們?cè)?watch 中做了數(shù)據(jù)更新以及數(shù)據(jù)重排操作。

css:

[v-cloak] {
  display: none;
}
table {
  width: 100%;
  margin-bottom: 24px;
  /*合并邊框模型*/
  border-collapse: collapse;
  border-spacing: 0;
  /*在空單元格周?chē)L制邊框*/
  empty-cells: show;
  border: 1px solid #e9e9e9;
}
table th {
  font: bold 14px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
  background: #CAE8EA;
  color: #5c6b77;
  /*設(shè)置文本粗細(xì)*/
  font-weight: 600;
  /*段落中的文本不進(jìn)行換行*/
  white-space: nowrap;
  border-top: 1px solid #C1DAD7;
}
table td, table th {
  padding: 8px 16px;
  text-align: left;
  border-right: 1px solid #C1DAD7;
  border-bottom: 1px solid #C1DAD7;
}
table th a {
  /*不獨(dú)占一行的塊級(jí)元素*/
  display: inline-block;
  margin: 0 4px;
  cursor: pointer;
}
table th a.on {
  color: #3399ff;
}
table th a:hover {
  color: #3399ff;
}

效果:

點(diǎn)擊此處查看本文示例代碼

PS:感興趣的朋友還可以使用如下在線工具測(cè)試上述代碼:

在線HTML/CSS/JavaScript前端代碼調(diào)試運(yùn)行工具:
http://tools.jb51.net/code/WebCodeRun

在線HTML/CSS/JavaScript代碼運(yùn)行工具:
http://tools.jb51.net/code/HtmlJsRun

希望本文所述對(duì)大家vue.js程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • Vue中自定義全局組件的實(shí)現(xiàn)方法

    Vue中自定義全局組件的實(shí)現(xiàn)方法

    這兩天學(xué)習(xí)了Vue.js 感覺(jué)組件這個(gè)地方知識(shí)點(diǎn)挺多的,而且很重要,所以這篇文章主要給大家介紹了關(guān)于Vue中自定義全局組件的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12
  • vue3中?provide?和?inject?用法及原理

    vue3中?provide?和?inject?用法及原理

    這篇文章主要介紹vue3中?provide?和?inject?用法及原理,provide?和?inject可以?解決多次組件傳遞數(shù)據(jù)的問(wèn)題,下面文章是具體的用法和實(shí)現(xiàn)原理,具有一定的參考價(jià)值,需要的朋友可以參考一下,希望對(duì)大家有所幫助
    2021-11-11
  • vue框架制作購(gòu)物車(chē)小球動(dòng)畫(huà)效果實(shí)例代碼

    vue框架制作購(gòu)物車(chē)小球動(dòng)畫(huà)效果實(shí)例代碼

    最近在學(xué)習(xí)前端制作了一個(gè)購(gòu)物車(chē)小球的動(dòng)畫(huà)效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2019-09-09
  • Vue2.0 組件傳值通訊的示例代碼

    Vue2.0 組件傳值通訊的示例代碼

    本篇文章主要介紹了Vue2.0 組件傳值通訊的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • 分享一個(gè)基于Ace的Markdown編輯器

    分享一個(gè)基于Ace的Markdown編輯器

    相信開(kāi)發(fā)中或多或少都會(huì)有使用md的時(shí)候。那么一個(gè)簡(jiǎn)易的md編輯器顯得尤為重要,如果想要在自己的項(xiàng)目中添加一個(gè)md編輯器,那么不妨來(lái)看看這篇文章
    2021-10-10
  • vue中如何防止用戶頻繁點(diǎn)擊按鈕詳解

    vue中如何防止用戶頻繁點(diǎn)擊按鈕詳解

    在后臺(tái)使用過(guò)程中經(jīng)常會(huì)因?yàn)榘粹o重復(fù)點(diǎn)擊,而造成發(fā)送多次重復(fù)請(qǐng)求 以下方法可以避免這種情況,下面這篇文章主要給大家介紹了關(guān)于vue中如何防止用戶頻繁點(diǎn)擊按鈕的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • 前端主流框架vue學(xué)習(xí)筆記第二篇

    前端主流框架vue學(xué)習(xí)筆記第二篇

    一步一步學(xué)Vue,這篇文章為大家分享了第二篇前端主流框架vue學(xué)習(xí)筆記,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 詳解Vue項(xiàng)目編譯后部署在非網(wǎng)站根目錄的解決方案

    詳解Vue項(xiàng)目編譯后部署在非網(wǎng)站根目錄的解決方案

    這篇文章主要介紹了Vue項(xiàng)目編譯后部署在非網(wǎng)站根目錄的解決方案,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • Vue完整版和runtime版的區(qū)別詳解

    Vue完整版和runtime版的區(qū)別詳解

    這篇文章主要為大家介紹了Vue完整版和runtime版的區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Vue.js遞歸組件實(shí)現(xiàn)組織架構(gòu)樹(shù)和選人功能

    Vue.js遞歸組件實(shí)現(xiàn)組織架構(gòu)樹(shù)和選人功能

    這篇文章主要介紹了Vue.js遞歸組件實(shí)現(xiàn)組織架構(gòu)樹(shù)和選人功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07

最新評(píng)論