目前使用的Vue做的项目,就讲下 Handsontable 在Vue中的使用吧
npm install @handsontable/vue handsontable
<template>
<hot-table :data="data" :rowHeaders="true" :colHeaders="true"></hot-table>
</template>
<script>
import { HotTable } from '@handsontable/vue';
export default {
data: function() {
return {
data: [
["", "Ford", "Volvo", "Toyota", "Honda"],
["2016", 10, 11, 12, 13],
["2017", 20, 11, 14, 13],
["2018", 30, 15, 12, 13]
],
};
},
components: {
HotTable
}
}
</script>
<style src="../node_modules/handsontable/dist/handsontable.full.css"></style>
到这里有些小伙伴会说,诶,我这里没有获取到许可证,导致表格下面会有一行提示并且控制台警告了,那么我们就生成个 licenseKey 吧,(本文仅作为技术测试范畴,商业用途请购买正版 https://handsontable.com/pricing)
// Warning!
The license key for Handsontable is missing. Use your purchased key to activate the product. Alternatively, you can activate Handsontable to use for non-commercial purposes by passing the key: 'non-commercial-and-evaluation'. Read more about it in the documentation or contact us at [email protected].
<script>
function generateKey() {
function random(min, max) {
let n = max - min + 1
return Math.ceil((Math.random() * n)) - 1 + min
}
function randomString(length) {
let r = ''
for (let i = 0; i < length; i++) {
r += random(0, 15).toString(16)
}
return r
}
function calcFF(x) {
/*
计算所有可能 取一种 概率准 效率高
当 y ∈ [0, 100)
则 (100x + y) % 97 = 1
y % 97 = 97 - 100x % 97 + 1
y % 97 = 98 - 100x % 97
y = a * 97 + (98 - 100x % 97)
∵ y ∈ [0, 100) , 98 - 100x % 97 ∈ [2, 98]
∴ 当 98 - 100x % 97 <= 2 时 a ∈ [0, 1]
当 98 > 98 - 100x % 97 > 2 时 a = 0
当 98 - 100x % 97 = 98 时 a ∈ [-1, 0]
∵ y < 100
∴ 当 98 - 100x % 97 <= 2 的时候 y的最小值为 98 - 100x % 97
当 98 > 98 - 100x % 97 > 2 的时候 y的最小值也为 98 - 100x % 97
当 98 - 100x % 97 = 98 的时候 y的最小值为 1
∴ 当 98 > 98 - 100x % 97 的时候 y的最小值为 98 - 100x % 97
当 98 = 98 - 100x % 97 的时候 y的最小值为 1
当 y ∈ [100, 255]
则 (1000x + y) % 97 = 1
y % 97 = 97 - 1000x % 97 + 1
y % 97 = 98 - 1000x % 97
y = a * 97 + (98 - 1000x % 97)
∵ y ∈ [100, 255] , 98 - 1000x % 97 ∈ [2, 98]
∴ 98 - 1000x % 97 < 3 时 a = 2
3 <= 98 - 1000x % 97 <= 61 时 a ∈ [1, 2]
∵ y 的最大值肯定 > 100
∴ 当 98 - 1000x % 97 < 3 时 y 的最大值为 98 - 1000x % 97 + 97 * 2
当 98 - 1000x % 97 > 61 时 y 的最大值为 98 - 1000x % 97 + 97 * 1
当 3 <= 98 - 1000x % 97 <= 61 时 y 的最大值为 98 - 1000x % 97 + 97 * 2
∴ 当 98 - 1000x % 97 <= 61 时 y 的最大值为 98 - 1000x % 97 + 97 * 2
当 98 - 1000x % 97 > 61 时 y 的最大值为 98 - 1000x % 97 + 97 * 1
*/
let min, max, ys = [],
y
if (98 - 100 * x % 97 === 98) {
min = 1
} else {
min = 98 - 100 * x % 97
}
if (98 - 1000 * x % 97 > 61) {
max = 98 - 1000 * x % 97 + 97 * 1
} else {
max = 98 - 1000 * x % 97 + 97 * 2
}
let i = 0
do {
ys.push(max - i * 97)
i++
} while (max - i * 97 >= 100)
if (min + 97 < 100) {
ys.push(min + 97)
}
ys.push(min)
y = ys[random(0, ys.length - 1)]
return y.toString(16).padStart(2, '0')
}
function calcFF_2(x) {
/*
//这个方法概率不准 因为只是简单的假设y 并没有由x推导 效率高
若要使 0 <= y < 100
则 (100x + y) % 97 = 1
y % 97 = 97 - 100x % 97 + 1
y % 97 = 98 - 100x % 97
y = a * 97 + (98 - 100x % 97)
∵ y ∈ [0, 100) , 98 - 100x % 97 ∈ [2, 98]
∴ 当 98 - 100x % 97 <= 2 时 a ∈ [0, 1]
当 98 > 98 - 100x % 97 > 2 时 a = 0
当 98 - 100x % 97 = 98 时 a ∈ [-1, 0]
若要使 100 <= y <= 255
则 (1000x + y) % 97 = 1
y % 97 = 97 - 1000x % 97 + 1
y % 97 = 98 - 1000x % 97
y = a * 97 + (98 - 1000x % 97)
∵ y ∈ [100, 255] , 98 - 1000x % 97 ∈ [2, 98]
∴ 98 - 1000x % 97 < 3 时 a = 2
3 <= 98 - 1000x % 97 <= 61 时 a ∈ [1, 2]
*/
let y = 0
if (random(0, 255) < 100) {
let z = 98 - 100 * x % 97
if (z <= 2) {
y = random(0, 1) * 97 + z
} else if (z == 98) {
y = random(-1, 0) * 97 + z
} else {
y = z
}
} else {
let z = 98 - 1000 * x % 97
if (z < 3) {
y = 2 * 97 + z
} else if (z > 61) {
y = 97 + z
} else {
y = random(1, 2) * 97 + z
}
}
return y.toString(16).padStart(2, '0')
}
function calcFF_3(x) {
/*
取所有可能一个个随机试 效率最差 但是实现最简单 效率低100倍
*/
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
251, 252, 253, 254, 255
]
let y
do {
let i = random(0, arr.length - 1)
y = arr.splice(i, 1)[0]
} while (((y > 100 ? (1000 * x) : (100 * x)) + y) % 97 !== 1)
return y.toString(16).padStart(2, '0')
}
function build(day = 365) {
//根据验证需求 day需小于 45000
//随机生成的 1-6 9-14 17-18 位 除了第二位为时间因数 其他数字可自定义 成为用户信息标识符
for (let i = 0; i < 3; i++) {
if (i === 0) {
//第 1-6 位任意 第二位为时间校验码的因数
v = randomString(6)
//第 1-6 位与第 7-8 位 各自转成十进制再转成字符串相连转整数 需要能被97除余1
//取 7-8 位
v += calcFF(parseInt(v.substr(0, 6), 16))
} else if (i === 1) {
//第 9-14 位随机生成
v += randomString(6)
//第 7-14 位与第 15-16 位 各自转成十进制再转成字符串相连转整数 需要能被97除余1
//取 15-16 位
v += calcFF(parseInt(v.substr(6, 8), 16))
} else {
//第 17-18 位随机生成
v += randomString(2)
//第 19-23 位时间校验码
//当前时间戳的天数 + 有效天数 乘以第2位校验因数 如果为0 就乘以9 转16进制
let n = (parseInt((new Date()) / 8.64e7) + day) * (parseInt(v.substr(1, 1), 16) || 9)
if (n > parseInt('fffff', 16)) {
//如果时间校验码超过五位 为错误
//理论上不可能 就算有效期至100年以后因数取最大都不会超过这个数
return ""
}
v += n.toString(16).padStart(5, '0')
//第 15-23 位与第 24-25 位各自转成十进制再转成字符串相连转整数 需要能被97除余1
//取 24-25 位
v += calcFF(parseInt(v.substr(14, 9), 16))
}
}
let r = []
for (let i = 0; i < 5; i++) {
r.push(v.substr(i * 5, 5))
}
return r.join('-')
}
function _checkKeySchema(v) {
//验证有效性
let p = 0;
if (v.length !== 25) {
return false;
}
for (let item of [
[0, 6, 6],
[6, 8, 14],
[14, 9, 23]
]) {
if (parseInt(parseInt(v.substr(item[0], item[1]), 16) + String(parseInt(v.substr(item[2], 2), 16)).padStart(
2, '0')) % 97 !== 1) {
return false
}
}
return true
}
function _extractTime(v) {
//获取有效期时间戳
return parseInt(v.substr(18, 5), 16) / (parseInt(v.substr(1, 1), 16) || 9)
}
function vaild(k) {
//验证函数
let v = k.replace(/\-/g, '')
let keyGenTime = _extractTime(v)
if (keyGenTime > 45000 || keyGenTime !== parseInt(keyGenTime, 10)) {
return false
}
let releaseTime = Math.floor((new Date()) / 8.64e7)
if (releaseTime > keyGenTime + 1) {
return false
}
return _checkKeySchema(v)
}
return build()
}
for (let i = 0; i < 10; i++) {
console.log('licenseKey-' + (i + 1) + ': ', generateKey())
}
</script>
<template>
<div>
<hot-table
:data="dataObject"
:columns="columns"
:stretchH="stretchH"
:autoWrapRow="autoWrapRow"
:width="width"
:manualRowResize="manualRowResize"
:manualColumnResize="manualColumnResize"
:rowHeaders="rowHeaders"
:colHeaders="colHeaders"
:manualRowMove="manualRowMove"
:manualColumnMove="manualColumnMove"
:contextMenu="contextMenu"
:filters="filters"
:dropdownMenu="dropdownMenu"
:hiddenRows="hiddenRows"
:licenseKey="licenseKey"
></hot-table>
</div>
</template>
<script>
import { HotTable } from "@handsontable/vue";
export default {
data: function() {
return {
dataObject: [
{
id: 1,
flag: "EUR",
currencyCode: "EUR",
currency: "Euro",
level: 0.9033,
units: "EUR / USD",
asOf: "08/19/2019",
onedChng: 0.0026
},
{
id: 2,
flag: "JPY",
currencyCode: "JPY",
currency: "Japanese Yen",
level: 124.387,
units: "JPY / USD",
asOf: "08/19/2019",
onedChng: 0.0001
},
{
id: 3,
flag: "GBP",
currencyCode: "GBP",
currency: "Pound Sterling",
level: 0.6396,
units: "GBP / USD",
asOf: "08/19/2019",
onedChng: 0.0
},
{
id: 4,
flag: "CHF",
currencyCode: "CHF",
currency: "Swiss Franc",
level: 0.9775,
units: "CHF / USD",
asOf: "08/19/2019",
onedChng: 0.0008
},
{
id: 5,
flag: "CAD",
currencyCode: "CAD",
currency: "Canadian Dollar",
level: 1.3097,
units: "CAD / USD",
asOf: "08/19/2019",
onedChng: -0.0005
},
{
id: 6,
flag: "AUD",
currencyCode: "AUD",
currency: "Australian Dollar",
level: 1.3589,
units: "AUD / USD",
asOf: "08/19/2019",
onedChng: 0.002
},
{
id: 7,
flag: "NZD",
currencyCode: "NZD",
currency: "New Zealand Dollar",
level: 1.5218,
units: "NZD / USD",
asOf: "08/19/2019",
onedChng: -0.0036
},
{
id: 8,
flag: "SEK",
currencyCode: "SEK",
currency: "Swedish Krona",
level: 8.528,
units: "SEK / USD",
asOf: "08/19/2019",
onedChng: 0.0016
},
{
id: 9,
flag: "NOK",
currencyCode: "NOK",
currency: "Norwegian Krone",
level: 8.2433,
units: "NOK / USD",
asOf: "08/19/2019",
onedChng: 0.0008
},
{
id: 10,
flag: "BRL",
currencyCode: "BRL",
currency: "Brazilian Real",
level: 3.4806,
units: "BRL / USD",
asOf: "08/19/2019",
onedChng: -0.0009
},
{
id: 11,
flag: "CNY",
currencyCode: "CNY",
currency: "Chinese Yuan",
level: 6.3961,
units: "CNY / USD",
asOf: "08/19/2019",
onedChng: 0.0004
},
{
id: 12,
flag: "RUB",
currencyCode: "RUB",
currency: "Russian Rouble",
level: 65.598,
units: "RUB / USD",
asOf: "08/19/2019",
onedChng: 0.0059
},
{
id: 13,
flag: "INR",
currencyCode: "INR",
currency: "Indian Rupee",
level: 65.3724,
units: "INR / USD",
asOf: "08/19/2019",
onedChng: 0.0026
},
{
id: 14,
flag: "TRY",
currencyCode: "TRY",
currency: "New Turkish Lira",
level: 2.8689,
units: "TRY / USD",
asOf: "08/19/2019",
onedChng: 0.0092
},
{
id: 15,
flag: "THB",
currencyCode: "THB",
currency: "Thai Baht",
level: 35.5029,
units: "THB / USD",
asOf: "08/19/2019",
onedChng: 0.0044
},
{
id: 16,
flag: "IDR",
currencyCode: "IDR",
currency: "Indonesian Rupiah",
level: 13.83,
units: "IDR / USD",
asOf: "08/19/2019",
onedChng: -0.0009
},
{
id: 17,
flag: "MYR",
currencyCode: "MYR",
currency: "Malaysian Ringgit",
level: 4.0949,
units: "MYR / USD",
asOf: "08/19/2019",
onedChng: 0.001
},
{
id: 18,
flag: "MXN",
currencyCode: "MXN",
currency: "Mexican New Peso",
level: 16.4309,
units: "MXN / USD",
asOf: "08/19/2019",
onedChng: 0.0017
},
{
id: 19,
flag: "ARS",
currencyCode: "ARS",
currency: "Argentinian Peso",
level: 9.2534,
units: "ARS / USD",
asOf: "08/19/2019",
onedChng: 0.0011
},
{
id: 20,
flag: "DKK",
currencyCode: "DKK",
currency: "Danish Krone",
level: 6.7417,
units: "DKK / USD",
asOf: "08/19/2019",
onedChng: 0.0025
},
{
id: 21,
flag: "ILS",
currencyCode: "ILS",
currency: "Israeli New Sheqel",
level: 3.8262,
units: "ILS / USD",
asOf: "08/19/2019",
onedChng: 0.0084
},
{
id: 22,
flag: "PHP",
currencyCode: "PHP",
currency: "Philippine Peso",
level: 46.3108,
units: "PHP / USD",
asOf: "08/19/2019",
onedChng: 0.0012
}
],
currencyCodes: [
"EUR",
"JPY",
"GBP",
"CHF",
"CAD",
"AUD",
"NZD",
"SEK",
"NOK",
"BRL",
"CNY",
"RUB",
"INR",
"TRY",
"THB",
"IDR",
"MYR",
"MXN",
"ARS",
"DKK",
"ILS",
"PHP"
],
columns: [
{
data: "id",
type: "numeric",
width: 40
},
{
data: "flag",
renderer: this.flagRenderer
},
{
data: "currencyCode",
type: "text"
},
{
data: "currency",
type: "text"
},
{
data: "level",
type: "numeric",
numericFormat: {
pattern: "0.0000"
}
},
{
data: "units",
type: "text"
},
{
data: "asOf",
type: "date",
dateFormat: "MM/DD/YYYY"
},
{
data: "onedChng",
type: "numeric",
numericFormat: {
pattern: "0.00%"
}
}
],
stretchH: "all",
width: 1366,
autoWrapRow: true,
height: 800,
manualRowResize: true,
manualColumnResize: true,
rowHeaders: true,
colHeaders: [
"ID",
"Country",
"Code",
"Currency",
"Level",
"Units",
"Date",
"Change"
],
manualRowMove: true,
manualColumnMove: true,
contextMenu: true,
filters: true,
dropdownMenu: true,
hiddenRows: {
},
licenseKey: "4d522-5237a-55f42-6653a-d1494"
};
},
components: {
HotTable
},
methods: {
flagRenderer(instance, td, row, col, prop, value, cellProperties) {
var currencyCode = value;
while (td.firstChild) {
td.removeChild(td.firstChild);
}
if (this.currencyCodes.indexOf(currencyCode) > -1) {
var flagElement = document.createElement("DIV");
flagElement.className = "flag " + currencyCode.toLowerCase();
td.appendChild(flagElement);
} else {
var textNode = document.createTextNode(value === null ? "" : value);
td.appendChild(textNode);
}
}
}
};
</script>
<style lang="scss" scoped>
@import "../../node_modules/handsontable/dist/handsontable.full.css";
</style>
Handsontable官方网站
handsontable 授权码生成 带备注