handsontable的簡(jiǎn)單使用

1.使用步驟

1.1 安裝(個(gè)人建議安裝12.2及之后的版本)

npm install handsontable @handsontable/vue

1.2 使用

import { HotTable } from '@handsontable/vue'
<hot-table :settings="hotSettings" class="w-100 h-100"></hot-table>

hotSettings里面配置需要的屬性和回調(diào)函數(shù)
例如:

hotSettings: {
  data: [
    [1, 2, 3, 4],
    [a, b, c, d]
  ]
}

2.基礎(chǔ)配置

2.1 data
data里面有兩種形式:
a. 二維數(shù)組 [[], []] (里面的每個(gè)數(shù)組代表一行數(shù)據(jù))
b. 對(duì)象數(shù)組 [{}, {}] (里面的每個(gè)對(duì)象代表一行數(shù)據(jù), 但是這是需要結(jié)合columns屬性一起使用)

2.2 columns
是一個(gè)對(duì)象數(shù)組([{}, {}]), 里面的每一個(gè)對(duì)象數(shù)據(jù)都代表對(duì)應(yīng)的這一列(hot-table的列排列位置就是根據(jù)這個(gè))
例如:
{
type: 'numeric', // 限制這一列的值得類型(data配置項(xiàng)中數(shù)據(jù)第一次渲染的時(shí)候不會(huì)報(bào)錯(cuò),修改的時(shí)候會(huì)提示)
readOnly: true, // 這一列只讀
data: 'column property' // 如果data配置項(xiàng)中數(shù)據(jù)是對(duì)象數(shù)組類型的話赘被,就可以使用這個(gè)屬性來(lái)制定這一列是對(duì)應(yīng)哪個(gè)屬性
title: 'column title', // 這一列的標(biāo)題(體現(xiàn)在表頭上)
dateFormat: 'YYYY-MM-DD', // 這一列如果type: date(會(huì)出現(xiàn)一個(gè)日期插件)口渔,這一列的選擇后的日期的形式就是'2022-11-09'
}

2.3 列寬, 行高
colWidths: 150, // 有多種格式(可以是數(shù)字,也可以是字符串('150px'), 也可以是數(shù)組([100, 200, ...])給每一列都設(shè)置一個(gè)寬度,也可以是方法(需要有個(gè)返回值return)淤堵, 也可以是undefined(由modifyColWidth鉤子使用))
rowHeights: '150px', // 同上
autoRowSize: true/false, // 給每一列設(shè)置一個(gè)自適應(yīng)寬度
autoColumnSize: true/false // 同上

2.4 表頭
rowHeaders: true/false/[]/function, // 行表頭 true采用默認(rèn)的表頭('1', '2', '3', ...) false禁用表頭 []自定義表頭([1, 2, 3, 4]) function自定義表頭(function(){ return 'AB'})
colHeaders: true/false/[]/function, // 列表頭 同上

2.5 hot-table根據(jù)寬度橫向擴(kuò)展
stretchH: 'all'/'last'/'none', // all擴(kuò)展全部列 last只擴(kuò)展最后一列 none默認(rèn)不擴(kuò)展

2.6 viewportColumnRenderingOffset
在網(wǎng)格視口之外呈現(xiàn)的列數(shù)
hot-table為了渲染的效率,它采用的默認(rèn)渲染方式是只渲染可視區(qū)域部分的內(nèi)容捶枢,有超出可視區(qū)域內(nèi)容通過(guò)橫向滾動(dòng)條來(lái)加載,就會(huì)出現(xiàn)幾個(gè)問(wèn)題(1: 用戶體驗(yàn)飞崖。橫向滾動(dòng)條會(huì)反復(fù)橫跳烂叔;2:預(yù)先設(shè)置的一些樣式不起作用(比如:合并行))
viewportColumnRenderingOffset: 100, // 可以通過(guò)設(shè)置超出最大列數(shù)的值,來(lái)讓hot-table一次性渲染所有的數(shù)據(jù)

2.7 設(shè)置hot-table的寬高
width: 500, // 可以是數(shù)字固歪,方法(需要一個(gè)返回值return)蒜鸡,CSS Unit
height: 500, // 同上

2.8 mergeCells(合并單元格)
是一個(gè)對(duì)象數(shù)組([{}, {}, ...]),里面的對(duì)象包含四個(gè)屬性:
row: 1, // 合并部分開(kāi)頭的行索引
col: 1, // 合并部分開(kāi)頭的列索引
rowspan: 2, // 合并的行數(shù)
colspan: 2, // 合并的列數(shù)

2.9 選中拖拽復(fù)制
fillHandle: true/false/'vertical'/'horizontal', // 'vertical'啟用垂直自動(dòng)填充 'horizontal'啟用橫向自動(dòng)填充

2.10 回調(diào)鉤子函數(shù)
beforeCreateRow(index) {} // index新行索引
新增行之前回調(diào),return false代表取消掉本次新增行操作

afterCreateRow(index, amount) {} // index新行索引 amount新增行數(shù)目
添加行后被調(diào)用

afterChange(changes, source) {} // changes是一個(gè)二維數(shù)組([[row, prop, oldValue, newValue]]) row修改單元格所在的行         prop修改單元格列對(duì)應(yīng)的屬性 oldValue修改前的值 newValue修改后的值

在一個(gè)或多個(gè)單元格被更改后觸發(fā)牢裳,當(dāng)使用編輯器輸入值或使用API更改值時(shí)逢防,會(huì)在任何情況下觸發(fā)更改

beforeRemoveRow(index, amount, physicalRows) {} // index刪除行索引 amount刪除行數(shù)量 physicalRows從數(shù)據(jù)源中刪除的物理行數(shù)組

行刪除前回調(diào),return false代表取消掉本次刪除行操作

afterOnCellMouseDown(event, value) {} // event點(diǎn)擊事件 value單元格對(duì)應(yīng)的位置信息
單元格點(diǎn)擊回調(diào)(包括左鍵蒲讯,右鍵忘朝,滾輪)

2.11 右鍵功能
contextMenu: false/true/[]/{items: {}} // 給右鍵配置功能
false 禁用ContextMenu插件(禁止掉右鍵功能)
true 啟用ContextMenu插件(使用默認(rèn)設(shè)置的右鍵功能)
['row_above', 'row_below'] 修改單個(gè)菜單選項(xiàng)('row_above'既是名字也是對(duì)應(yīng)的功能)
{items: {}} 可以自定義每個(gè)鍵

{
items: {
    row_above: {
      name: '上面插入一行'
    }, // 鍵名是插件原本就有(也有已經(jīng)對(duì)應(yīng)好的操作)
    remove_row: {
      name: '移除當(dāng)前行'
    }, // 鍵名是插件原本就有(也有已經(jīng)對(duì)應(yīng)好的操作)
    insert_above_rows: {
      name() {
        const insertBox = document.getElementsByClassName('insert_input')[0]
        if(insertBox) {
          insertBox.addEventListener('keyup', (e) => {
            console.log('e', e)
            const event = e || window.event
            const keyValue = event.which || event.keyCode || event.charCodes
            if (keyValue === 13) { 
              const number = Number(event.target.value)
              if (number !== NaN && number >= 0) {
                this.alter('insert_row_above', window.clickRowIndex, number) // this指向hot-table alter方法允許你通過(guò)在指定位置添加或刪除行個(gè)列來(lái)更改網(wǎng)格結(jié)構(gòu)
                const elMenu = document.getElementsByClassName('htMenu')[0]
                elMenu.style.display = 'none' // 關(guān)閉右鍵的菜單欄
              } else {
                this.$message.warning('請(qǐng)輸入正確的數(shù)字')
              }
            } // 監(jiān)聽(tīng)回車事件
          })
        }
        return `在上方插入<input class="insert_input" style="width: 40px; height: 20px;"></input>行`
      },
      isCommand: false, // 防止后續(xù)點(diǎn)擊命令關(guān)閉菜單
      // 自定義時(shí)renderer與name的區(qū)別
      renderer(hot, wrapper, row, col, prop, itemValue){
        // 參數(shù)里面的hot是指向菜單欄的,所以沒(méi)辦法調(diào)用alter方法
      }
    }, // 鍵名是自定義的(操作也是自定義的--插入多行)
  }
}

2.11 定義某些單元格特殊的配置或邏輯
cells(roww, column, prop) {} // row單元格所在行 column單元格所在列 prop(如果data是二維數(shù)組的話判帮,就是與column相同的數(shù)字局嘁;如果是對(duì)象數(shù)組的話,就是所在列的屬性)
使用案例:
cells() {
const cellProperties = {
readOnly: false
}
return cellProperties
}
cells會(huì)出現(xiàn)重復(fù)渲染的問(wèn)題

3. 其它用法

handsontable類似于el-table晦墙,對(duì)列表可以實(shí)現(xiàn)其它操作
3.1 hot-column類似于el-table的el-column

<hot-table :settings="hotSettings">
  <hot-column :width="120" title="headerTitle" data="dataColumnProperty"></hot-column>
</hot-table>

這一塊比較靈活悦昵,它可以單獨(dú)設(shè)置某一些屬性,像title晌畅、data這種旱捧,也可以像hot-table一樣一個(gè)settings掛在所有的參數(shù)配置項(xiàng),
還是單獨(dú)設(shè)置一部分屬性踩麦,再使用settings屬性枚赡,hot-table也可以同樣如此操作。

 3.2 類似于插槽的操作
 要將組件標(biāo)記為Handsontable渲染器谓谦,只需為其添加一個(gè)hot-renderer屬性贫橙,通常作為渲染函數(shù)的參數(shù)將被注入到渲染組件的$data對(duì)象中,有以下幾個(gè)數(shù)據(jù):

row 行索引
col 列索引
prop 如果data是二維數(shù)組的話反粥,就是與column相同的數(shù)字卢肃;如果是對(duì)象數(shù)組的話,就是所在列的屬性
TD 單元格HTML節(jié)點(diǎn)
cellProperties 已編輯單元格的cellProperties對(duì)象
例子:

<hot-table :settings="hotSettings">
  <hot-column>
    <div hot-renderer>類似于插槽操作</div>
  </hot-column>
</hot-table>
特殊點(diǎn):使用這種操作才顿,并且想拿到數(shù)據(jù)(插槽數(shù)據(jù)),就不能直接將節(jié)點(diǎn)掛載上去莫湘,需要如下操作:

1. 定義一個(gè)組件實(shí)例
   const CustomRenderer = {
     template: '<div>{{ row }} {{ col }} {{ value }}</div>'
   }

2. 將這個(gè)組件實(shí)例在components里聲明 
   components: {
     CustomRenderer
   }

3. 使用
   <hot-table :settings="hotSettings">
     <hot-column>
    <CustomRenderer hot-renderer>類似于插槽操作</CustomRenderer>
     </hot-column>
   </hot-table>
   插槽數(shù)據(jù)會(huì)被自動(dòng)注入到渲染組件的$data對(duì)象中
     3.3 還可以通過(guò)配置項(xiàng)columns實(shí)現(xiàn)類似于插槽的操作
   columns: [
     {
    renderer(instance, td, row, col, prop, value) {
      const img = document.createElement('img')
      img.src = value

      td.innerText = ''
      td.appendChild(img)

      return td
    }
     }
   ]

4. 注意點(diǎn)

4.1 表頭數(shù)據(jù)只能進(jìn)行列合并,不能進(jìn)行行合并

4.2 獲取hot-table數(shù)據(jù)this.$refs.hotTable.hotInstance.getData() // 這個(gè)方法拿到的只是每個(gè)單元格里面的數(shù)據(jù)
所以這兒如果使用的是簡(jiǎn)單類型的表格郑气,并且數(shù)據(jù)還是對(duì)象數(shù)組類型的幅垮,可以采用這種方法:
采用事先定義好的columns,然后使用this.$set(this.hotSettings, 'data', this.dataList)就可以在dataList中拿到實(shí)時(shí)變化的數(shù)據(jù)

4.3 如果一個(gè)單元格要區(qū)分單擊事件和雙擊事件:
可以使用afterOnCellMouseDown(單元格點(diǎn)擊回調(diào))回調(diào)方法尾组,再利用 節(jié)流 方法來(lái)分別執(zhí)行
例子:

hotSettings: {
     afterOnCellMouseDown: (event, val) => {
       // event.button 判斷是左鍵點(diǎn)擊
        if (event.button === 0) {
          this.indexCount += 1 // indexCount是data中聲明的變量忙芒,用來(lái)記錄點(diǎn)擊了幾次
          if (this.indexCount % 2 === 0) {
            // 點(diǎn)擊次數(shù)為雙數(shù)
            this.preTime = this.newTime // preTime是data中聲明的變量示弓,用來(lái)記錄上一次點(diǎn)擊的時(shí)間
            this.newTime = Date.now() // preTime是data中聲明的變量,用來(lái)記錄當(dāng)前點(diǎn)擊的時(shí)間
          } else {
            this.newTime = Date.now()
          }
          // event事件 val坐標(biāo)位置
          console.log('val', val)
          this.debouncedTip(event, val) // debouncedTip是data中聲明的變量呵萨,用來(lái)綁定節(jié)流函數(shù)返回的結(jié)果(閉包)
        }
      }, // 單元格點(diǎn)擊回調(diào)
   }
   在created中:
   const throttle = (fn, wait) => {
    let timer = null
    return (event, val) => {
      if (!this.preTime) {
        this.preTime = 0
      }
      console.log('nowTime - preTime', this.newTime, this.preTime)
      if (!timer) {
        timer = setTimeout(() => {
          if (this.newTime - this.preTime > wait) {
            fn(event, val)
          } // wait是在debouncedTip設(shè)置的節(jié)流時(shí)間奏属,如果this.newTime - this.preTime < wait則判斷定位單擊
          timer = null
        }, 300)
      }
    }

    } // 節(jié)流函數(shù)
    this.debouncedTip = throttle((event, val) => { 
      // 要執(zhí)行的操作
    }, 300)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市潮峦,隨后出現(xiàn)的幾起案子囱皿,更是在濱河造成了極大的恐慌,老刑警劉巖忱嘹,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铆帽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡德谅,警方通過(guò)查閱死者的電腦和手機(jī)爹橱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)窄做,“玉大人愧驱,你說(shuō)我怎么就攤上這事⊥终担” “怎么了组砚?”我有些...
    開(kāi)封第一講書人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)掏颊。 經(jīng)常有香客問(wèn)我糟红,道長(zhǎng),這世上最難降的妖魔是什么乌叶? 我笑而不...
    開(kāi)封第一講書人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任盆偿,我火速辦了婚禮,結(jié)果婚禮上准浴,老公的妹妹穿的比我還像新娘事扭。我一直安慰自己,他們只是感情好乐横,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布求橄。 她就那樣靜靜地躺著,像睡著了一般葡公。 火紅的嫁衣襯著肌膚如雪罐农。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,806評(píng)論 1 290
  • 那天催什,我揣著相機(jī)與錄音涵亏,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛溯乒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播豹爹,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼裆悄,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了臂聋?” 一聲冷哼從身側(cè)響起光稼,我...
    開(kāi)封第一講書人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎孩等,沒(méi)想到半個(gè)月后艾君,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肄方,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年冰垄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片权她。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡虹茶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出隅要,到底是詐尸還是另有隱情蝴罪,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布步清,位于F島的核電站要门,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏廓啊。R本人自食惡果不足惜欢搜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谴轮。 院中可真熱鬧狂巢,春花似錦、人聲如沸书聚。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)雌续。三九已至斩个,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驯杜,已是汗流浹背受啥。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人滚局。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓居暖,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親藤肢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子太闺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容