JS前端輕松導(dǎo)出Excel的通用方法詳解
背景
在項(xiàng)目開發(fā)中,我們經(jīng)常遇到需要將數(shù)據(jù)導(dǎo)出為Excel文件的情況。然而,這個(gè)過程可能相對(duì)復(fù)雜和繁瑣,特別是對(duì)于大量數(shù)據(jù)和復(fù)雜表格結(jié)構(gòu)的情況。因此,我們需要一個(gè)通用方法,能夠在各種場景下靈活使用,實(shí)現(xiàn)簡單高效的數(shù)據(jù)導(dǎo)出操作
安裝依賴:
npm install file-saver --save npm install script-loader --save-dev npm install xlsx --save
如果項(xiàng)目用的不是 npm 用 yarn 或 pnpm 一樣的操作
在src下創(chuàng)建目錄 vendor
目錄下創(chuàng)建兩個(gè)文件
Blob.js
/* eslint-disable */
(function (view) {
"use strict";
view.URL = view.URL || view.webkitURL;
if (view.Blob && view.URL) {
try {
new Blob;
return;
} catch (e) { }
}
// Internally we use a BlobBuilder implementation to base Blob off of
// in order to support older browsers that only have BlobBuilder
var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function (view) {
var
get_class = function (object) {
return Object.prototype.toString.call(object).match(/^[object\s(.*)]$/)[1];
}
, FakeBlobBuilder = function BlobBuilder() {
this.data = [];
}
, FakeBlob = function Blob(data, type, encoding) {
this.data = data;
this.size = data.length;
this.type = type;
this.encoding = encoding;
}
, FBB_proto = FakeBlobBuilder.prototype
, FB_proto = FakeBlob.prototype
, FileReaderSync = view.FileReaderSync
, FileException = function (type) {
this.code = this[this.name = type];
}
, file_ex_codes = (
"NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
+ "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
).split(" ")
, file_ex_code = file_ex_codes.length
, real_URL = view.URL || view.webkitURL || view
, real_create_object_URL = real_URL.createObjectURL
, real_revoke_object_URL = real_URL.revokeObjectURL
, URL = real_URL
, btoa = view.btoa
, atob = view.atob
, ArrayBuffer = view.ArrayBuffer
, Uint8Array = view.Uint8Array
;
FakeBlob.fake = FB_proto.fake = true;
while (file_ex_code--) {
FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
}
if (!real_URL.createObjectURL) {
URL = view.URL = {};
}
URL.createObjectURL = function (blob) {
var
type = blob.type
, data_URI_header
;
if (type === null) {
type = "application/octet-stream";
}
if (blob instanceof FakeBlob) {
data_URI_header = "data:" + type;
if (blob.encoding === "base64") {
return data_URI_header + ";base64," + blob.data;
} else if (blob.encoding === "URI") {
return data_URI_header + "," + decodeURIComponent(blob.data);
} if (btoa) {
return data_URI_header + ";base64," + btoa(blob.data);
} else {
return data_URI_header + "," + encodeURIComponent(blob.data);
}
} else if (real_create_object_URL) {
return real_create_object_URL.call(real_URL, blob);
}
};
URL.revokeObjectURL = function (object_URL) {
if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
real_revoke_object_URL.call(real_URL, object_URL);
}
};
FBB_proto.append = function (data/*, endings*/) {
var bb = this.data;
// decode data to a binary string
if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
var
str = ""
, buf = new Uint8Array(data)
, i = 0
, buf_len = buf.length
;
for (; i < buf_len; i++) {
str += String.fromCharCode(buf[i]);
}
bb.push(str);
} else if (get_class(data) === "Blob" || get_class(data) === "File") {
if (FileReaderSync) {
var fr = new FileReaderSync;
bb.push(fr.readAsBinaryString(data));
} else {
// async FileReader won't work as BlobBuilder is sync
throw new FileException("NOT_READABLE_ERR");
}
} else if (data instanceof FakeBlob) {
if (data.encoding === "base64" && atob) {
bb.push(atob(data.data));
} else if (data.encoding === "URI") {
bb.push(decodeURIComponent(data.data));
} else if (data.encoding === "raw") {
bb.push(data.data);
}
} else {
if (typeof data !== "string") {
data += ""; // convert unsupported types to strings
}
// decode UTF-16 to binary string
bb.push(unescape(encodeURIComponent(data)));
}
};
FBB_proto.getBlob = function (type) {
if (!arguments.length) {
type = null;
}
return new FakeBlob(this.data.join(""), type, "raw");
};
FBB_proto.toString = function () {
return "[object BlobBuilder]";
};
FB_proto.slice = function (start, end, type) {
var args = arguments.length;
if (args < 3) {
type = null;
}
return new FakeBlob(
this.data.slice(start, args > 1 ? end : this.data.length)
, type
, this.encoding
);
};
FB_proto.toString = function () {
return "[object Blob]";
};
FB_proto.close = function () {
this.size = this.data.length = 0;
};
return FakeBlobBuilder;
}(view));
view.Blob = function Blob(blobParts, options) {
var type = options ? (options.type || "") : "";
var builder = new BlobBuilder();
if (blobParts) {
for (var i = 0, len = blobParts.length; i < len; i++) {
builder.append(blobParts[i]);
}
}
return builder.getBlob(type);
};
}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));Export2Excel.js
/* eslint-disable */
import {saveAs} from 'file-saver'
import * as XLSX from 'xlsx'
import XLSXS from "xlsx-style"
require('script-loader!file-saver');
require('./Blob');//這里是你的Blob.js的地址
require('script-loader!xlsx/dist/xlsx.core.min');
/**
*
* @param {*} table
* @returns
* 將HTML表格轉(zhuǎn)換為二維數(shù)組
* 函數(shù)支持處理表格中的單元格合并、行列跨度以及特定數(shù)據(jù)類型轉(zhuǎn)換
*/
function generateArray(table) {
let out = [];
let rows = table.querySelectorAll('tr');
let ranges = [];
for (let R = 0; R < rows.length; ++R) {
let outRow = [];
let row = rows[R];
let columns = row.querySelectorAll('td');
for (let C = 0; C < columns.length; ++C) {
let cell = columns[C];
let colspan = cell.getAttribute('colspan');
let rowspan = cell.getAttribute('rowspan');
let cellValue = cell.innerText;
if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
//Skip ranges
ranges.forEach(function (range) {
if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e
.c) {
for (let i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
}
});
//Handle Row Span
if (rowspan || colspan) {
rowspan = rowspan || 1;
colspan = colspan || 1;
ranges.push({
s: {
r: R,
c: outRow.length
},
e: {
r: R + rowspan - 1,
c: outRow.length + colspan - 1
}
});
}
;
//Handle Value
outRow.push(cellValue !== "" ? cellValue : null);
//Handle Colspan
if (colspan)
for (let k = 0; k < colspan - 1; ++k) outRow.push(null);
}
out.push(outRow);
}
return [out, ranges];
};
function datenum(v, date1904) {
if (date1904) v += 1462;
let epoch = Date.parse(v);
return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
}
/**
*
* @param {*} data
* @param {*} opts
* @returns
* 用于將二維數(shù)組轉(zhuǎn)換為Excel工作表對(duì)象的JavaScript函數(shù)
* 使用了XLSX.js庫提供的工具方法來編碼單元格引用和工作表范圍,可生成可供Excel處理的工作表數(shù)據(jù)
* 支持將一些數(shù)據(jù)類型轉(zhuǎn)換為Excel支持的數(shù)據(jù)類型,例如將日期對(duì)象轉(zhuǎn)換為數(shù)字類型,并設(shè)置相應(yīng)的格式。
*/
function sheet_from_array_of_arrays(data, opts) {
let ws = {};
let range = {
s: {
c: 10000000,
r: 10000000
},
e: {
c: 0,
r: 0
}
};
for (let R = 0; R != data.length; ++R) {
for (let C = 0; C != data[R].length; ++C) {
if (range.s.r > R) range.s.r = R;
if (range.s.c > C) range.s.c = C;
if (range.e.r < R) range.e.r = R;
if (range.e.c < C) range.e.c = C;
let cell = {
v: data[R][C]
};
if (cell.v == null) continue;
let cell_ref = XLSX.utils.encode_cell({
c: C,
r: R
});
if (typeof cell.v === 'number') cell.t = 'n';
else if (typeof cell.v === 'boolean') cell.t = 'b';
else if (cell.v instanceof Date) {
cell.t = 'n';
cell.z = XLSX.SSF._table[14];
cell.v = datenum(cell.v);
} else cell.t = 's';
ws[cell_ref] = cell;
}
}
if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
return ws;
}
function Workbook() {
if (!(this instanceof Workbook)) return new Workbook();
this.SheetNames = [];
this.Sheets = {};
}
function s2ab(s) {
let buf = new ArrayBuffer(s.length);
let view = new Uint8Array(buf);
for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
export function export_table_to_excel(id) {
let theTable = document.getElementById(id);
let oo = generateArray(theTable);
let ranges = oo[1];
/* original data */
let data = oo[0];
let ws_name = "SheetJS";
let wb = new Workbook(),
ws = sheet_from_array_of_arrays(data);
/* add ranges to worksheet */
// ws['!cols'] = ['apple', 'banan'];
ws['!merges'] = ranges;
/* add worksheet to workbook */
wb.SheetNames.push(ws_name);
wb.Sheets[ws_name] = ws;
let wbout = XLSX.write(wb, {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
});
saveAs(new Blob([s2ab(wbout)], {
type: "application/octet-stream"
}), "test.xlsx")
}
export function export_json_to_excelhb({
multiHeader = [], // 第一行表頭
multiHeader2 = [], // 第二行表頭
header = [], // 第三行表頭
data,//傳遞的數(shù)據(jù)
filename, //文件名
merges = [], // 合并
autoWidth = true,//用于設(shè)置列寬的
bookType = 'xlsx'
} = {}) {
/* original data */
filename = filename || '列表';
data = [...data]
for (let i = header.length - 1; i > -1; i--) {
data.unshift(header[i])
}
for (let i = multiHeader2.length - 1; i > -1; i--) {
data.unshift(multiHeader2[i])
}
for (let i = multiHeader.length - 1; i > -1; i--) {
data.unshift(multiHeader[i])
}
let ws_name = "SheetJS";
let wb = new Workbook(),
ws = sheet_from_array_of_arrays(data);
// 設(shè)置單元格公共樣式
let borderAll = { //單元格外側(cè)框線
top: {
style: 'thin',
},
bottom: {
style: 'thin',
},
left: {
style: 'thin',
},
right: {
style: 'thin',
}
};
for (let key in ws) {
// 單元格公共樣式設(shè)置
if (ws[key] instanceof Object) {
ws[key].s = {
border: borderAll,
alignment: {
horizontal: 'center', //水平居中對(duì)齊
vertical: 'center',//垂直居中
wrapText: 1,//自動(dòng)換行
},
// fill: { //背景色
// fgColor: { rgb: 'dbf3f2' }
// },
font: {
sz: 10,//單元格中字體的樣式與顏色設(shè)置
color: {
rgb: '000000'
}
},
bold: true,
numFmt: 0
}
}
//給特定格子(帶'1'的,即首行 標(biāo)題)添加樣式,下面同理
// if (key.replace(/[^0-9]/ig, '') === '1') {
// ws[key].s = {
// ...ws[key].s,
// fill: { //背景色
// fgColor: { rgb: 'd4e6fd' }
// },
// font: {//覆蓋字體
// name: '等線',
// sz: 10,
// // bold: true
// },
// }
// }
if (key === 'A1') {
ws[key].s = {
...ws[key].s,
fill: { //背景色
fgColor: {rgb: 'd4e6fd'}
},
}
}
// if (key === 'B2' || key === 'C2' || key === 'D2' || key === 'E2' || key === 'F2' || key === 'G2') {
// ws[key].s = {
// ...ws[key].s,
// fill: { //背景色
// fgColor: { rgb: 'fbedd7' }
// }
// }
// }
}
if (merges.length > 0) {
if (!ws['!merges']) ws['!merges'] = [];
merges.forEach(item => {
ws['!merges'].push(XLSX.utils.decode_range(
XLSX.utils.encode_cell(item.s) + ':' + XLSX.utils.encode_cell(item.e)
));
// 設(shè)置單元格的樣式
ws[XLSX.utils.encode_cell(item.s)].s = item.style;
});
}
// ws['I2'] = ws['H2'] = ws['G2'] = ws['F2'] = ws['E2'] = ws['D2'] = ws['C2'] = ws['B2'] = ws['A2']//用于第二行的單元格的樣式設(shè)置(如果是合并的第一行,就是1)
// if (merges.length > 0) {
// if (!ws['!merges']) ws['!merges'] = [];
// merges.forEach(item => {
// console.log(item);
// ws['!merges'].push(XLSX.utils.decode_range(item))
// })
// }
if (autoWidth) {
let colWidths = [];
// 計(jì)算每一列的所有單元格寬度
// 先遍歷行
data.forEach((row) => {
// 列序號(hào)
let index = 0
// 遍歷列
for (const key in row) {
if (colWidths[index] == null) colWidths[index] = []
switch (typeof row[key]) {
case 'string':
case 'number':
case 'boolean':
colWidths[index].push(getCellWidth(row[key]))
break
case 'object':
case 'function':
colWidths[index].push(0)
break
}
index++
}
})
ws['!cols'] = [];
// 第三行表頭的設(shè)置
colWidths.forEach((widths, index) => {
// 計(jì)算列頭的寬度
// widths.push(getCellWidth(header[index]))
// 設(shè)置最大值為列寬
ws['!cols'].push({
wch: Math.max(...widths)
})
})
}
/* add worksheet to workbook */
wb.SheetNames.push(ws_name);
wb.Sheets[ws_name] = ws;
let wbout = XLSXS.write(wb, {
bookType: bookType,
bookSST: false,
type: 'binary'
});
saveAs(new Blob([s2ab(wbout)], {
type: "application/octet-stream"
}), `${filename}.${bookType}`);
}
export function getCellWidth(value) {
if (value == null) {
return 10
} else if (value.toString().charCodeAt(0) > 255) {
// 判斷是否包含中文
let length = value.toString().length * 2
if (length > 60) {
length = length - 40
//這里的寬度可以自己設(shè)定,在前面設(shè)置wrapText: 1可以在單元格內(nèi)換行
}
return length
} else {
return value.toString().length * 1.2
}
}import {saveAs} from 'file-saver'
import * as XLSX from 'xlsx'
import XLSXS from "xlsx-style"
`file-saver`庫中導(dǎo)入`saveAs`函數(shù),用于保存文件。
`xlsx`庫中導(dǎo)入所有的功能,并將其作為`XLSX`對(duì)象進(jìn)行引用。
`xlsx-style`庫導(dǎo)入是支持樣式的,并將其命名為`XLSXS`。require('script-loader!file-saver');
require('./Blob');//這里是你的Blob.js的地址
require('script-loader!xlsx/dist/xlsx.core.min');
這部分代碼使用`require`和`script-loader`來加載和引入所需的腳本文件。
其中,通過`script-loader!file-saver`來加載`file-saver`庫所需要的腳本,
`require('./Blob')`用于加載自定義的`Blob.js`文件,
`script-loader!xlsx/dist/xlsx.core.min`用于加載`xlsx`庫的核心腳本。上述代碼片段中的具體路徑和文件名可能因你的項(xiàng)目結(jié)構(gòu)而有所不同,你需要根據(jù)實(shí)際情況進(jìn)行調(diào)整。
通過以上步驟,你可以在項(xiàng)目中使用saveAs()函數(shù)將文件保存到本地,以及使用XLSX和XLSXS對(duì)象進(jìn)行 Excel 文件的處理和操作。
代碼實(shí)現(xiàn)
Blob.js 和Export2Excel.js 兩個(gè)文件網(wǎng)上有很多,根據(jù)個(gè)人項(xiàng)目有細(xì)微不同,基本大同小異, 但是在項(xiàng)目有非常多的數(shù)據(jù)圖表以及各種不同類型的表格。不做封裝通用方法,代碼重復(fù)量便會(huì)增多并且不易維護(hù)
因此,我基于Export2Excel中做了一個(gè)通用方法,代碼如下:
創(chuàng)建 vendor/exportExcel.js 文件
// 導(dǎo)出Excel通用方法
async function exportExcel(multiHeader, multiHeader2, filterVal, tableData, tabulationTitle, indexNumber) {
// 導(dǎo)出標(biāo)題
const EXPORT_FILENAME = tabulationTitle;
// 單元格樣式1 dbf3f2
const style1 = {
fill: {patternType: 'solid', fgColor: {rgb: 'dbf3f2'}},
border: {top: {style: 'thin'}, left: {style: 'thin'}, bottom: {style: 'thin'}, right: {style: 'thin'}},
alignment: {horizontal: 'center', vertical: 'center', wrapText: 1}
};
// 單元格樣式2 fbedd7
const style2 = {
fill: {patternType: 'solid', fgColor: {rgb: 'fbedd7'}},
border: {top: {style: 'thin'}, left: {style: 'thin'}, bottom: {style: 'thin'}, right: {style: 'thin'}},
alignment: {horizontal: 'center', vertical: 'center', wrapText: 1}
};
// 進(jìn)行所有表頭的單元格合并
let headerList = [];
let titleList = [];
let styleNumber = 1; // 初始為1 1級(jí)表頭樣式判斷
let headerStyle = style2;
let rowIndex = 1;
let colIndex = 1;
let isOdd = true;
let count = 0;
const indexNumber2 = indexNumber + 1
// 一級(jí)表頭合并與顏色賦值
if (multiHeader[0] && multiHeader[0].length > 0) {
multiHeader[0].forEach((group, index) => {
if (rowIndex < multiHeader[0].length) {
headerList.push({s: {r: 0, c: rowIndex}, e: {r: 0, c: rowIndex + indexNumber}, style: headerStyle});
rowIndex += indexNumber2;
}
// 修改樣式值
if (styleNumber === 1) {
styleNumber = 2 // 修改樣式值
headerStyle = style1
} else {
styleNumber = 1 // 修改樣式值
headerStyle = style2
}
});
}
if (multiHeader2[0] && multiHeader2[0].length > 0) {
multiHeader2[0].forEach((group, index) => {
if (colIndex < multiHeader2[0].length) {
titleList.push({s: {r: 1, c: colIndex}, e: {r: 1, c: colIndex}, style: isOdd ? style2 : style1});
colIndex += 1;
count++;
}
if (count % indexNumber2 === 0) {
isOdd = !isOdd;
}
});
}
// 進(jìn)行所有表頭的單元格合并
const merges = [
// 將A1和A2合并,并設(shè)置背景色1
{
s: {r: 0, c: 0},
e: {r: 1, c: 0},
style: {
fill: {patternType: 'solid', fgColor: {rgb: 'd4e6fd'}},
border: {top: {style: 'thin'}, left: {style: 'thin'}, bottom: {style: 'thin'}, right: {style: 'thin'}},
alignment: {horizontal: 'center', vertical: 'center', wrapText: 1}
}
},
...headerList,
...titleList // 二級(jí)表頭
];
const data = tableData.map((v) => filterVal.map((j) => v[j]));
await import('/src/vendor/Export2Excel.js').then((excel) => {
excel.export_json_to_excelhb({
multiHeader, // 這里是第一行的表頭
multiHeader2, // 這里是第二行的表頭
data,
filename: EXPORT_FILENAME,
merges
});
});
}
export default {exportExcel}上面給出的代碼是一個(gè)導(dǎo)出Excel通用方法的示例。讓我們逐步解析其中的關(guān)鍵邏輯:
- 首先,在函數(shù)的參數(shù)中,我們傳入了一些必要的參數(shù),如多級(jí)表頭(
multiHeader和multiHeader2)、數(shù)據(jù)過濾列(filterVal)、表格數(shù)據(jù)(tableData)、表格標(biāo)題(tabulationTitle)和索引號(hào)(indexNumber)。這些參數(shù)會(huì)作為函數(shù)的輸入,用于生成Excel文件。 - 接下來,我們定義了一些常量,如導(dǎo)出文件名稱(
EXPORT_FILENAME)和兩種不同樣式的單元格樣式(style1和style2)。這些樣式可以用于美化導(dǎo)出的Excel表格,使其更加具有可讀性和專業(yè)感。 - 在進(jìn)行表頭的合并和樣式設(shè)置之后,我們使用
import語法引入了名為Export2Excel.js的庫文件。這個(gè)庫文件是用于實(shí)現(xiàn)數(shù)據(jù)導(dǎo)出到Excel的核心工具,我們可以調(diào)用其中的export_json_to_excelhb方法來實(shí)現(xiàn)導(dǎo)出功能。 - 最后,我們將整理好的數(shù)據(jù)、需要導(dǎo)出的文件名、表頭樣式和單元格合并信息作為參數(shù),調(diào)用
export_json_to_excelhb方法實(shí)現(xiàn)導(dǎo)出操作。
導(dǎo)出示例
main.js引入全局
import Excel from './vendor/exportExcel' Vue.prototype.$Excel = Excel;
// 調(diào)用導(dǎo)出Excel通用方法
async exportExcelDemo() {
let multiHeader = []; // 第一行的表頭
let multiHeader2 = [] // 第二行的表頭
let filterVal = [] // 對(duì)應(yīng)字段
multiHeader = [[this.areaNameText, '游戲廳', '', '', '游戲廳', '', '', '網(wǎng)咖', '', '',]]
multiHeader2 = [['', this.current, this.text, '同比去年', this.current, this.text, '同比去年', this.current, this.text, '同比去年',]];
filterVal = ['areaName',
'sumValue03', 'momPerCent', 'yoyPerCent',
'sumValue032', 'momPerCent2', 'yoyPerCent2',
'sumValue033', 'momPerCent3', 'yoyPerCent3',
];
const tabulationTitle = '導(dǎo)出表格'; // 導(dǎo)出標(biāo)題
const indexNumber = this.activeDate === 'day' ? 6 : 7 // 根據(jù)業(yè)務(wù)需求進(jìn)行調(diào)整 需要的字段數(shù)據(jù)也不同
await this.$Excel.exportExcel(multiHeader, multiHeader2, filterVal, tableData, tabulationTitle,indexNumber);
}
// 調(diào)用示例
this.exportExcelDemo();應(yīng)用場景
這個(gè)通用的導(dǎo)出Excel方法適用于多種前端開發(fā)場景,比如:
- 在數(shù)據(jù)可視化項(xiàng)目中,將圖表數(shù)據(jù)導(dǎo)出為Excel文件,以便進(jìn)一步分析和處理。
- 在數(shù)據(jù)管理系統(tǒng)中,將查詢到的數(shù)據(jù)導(dǎo)出為Excel表格,方便用戶離線使用和分享。
- 在電子商務(wù)平臺(tái)中,將商品信息、銷售報(bào)表等導(dǎo)出為Excel文件,方便商家進(jìn)行業(yè)務(wù)分析和統(tǒng)計(jì)。
總結(jié)
通過這個(gè)通用的導(dǎo)出Excel方法,我們能夠輕松地處理各種數(shù)據(jù)導(dǎo)出需求,并且能夠適應(yīng)不同的表格結(jié)構(gòu)和數(shù)據(jù)量。只需簡單配置參數(shù),就能生成美觀、便于閱讀和處理的Excel文件。
希望這篇文章能夠?qū)Υ蠹以谇岸碎_發(fā)中的數(shù)據(jù)導(dǎo)出需求有所幫助。
以上就是JS前端輕松導(dǎo)出Excel的通用方法詳解的詳細(xì)內(nèi)容,更多關(guān)于JS導(dǎo)出Excel通用方法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
在layui中使用form表單監(jiān)聽ajax異步驗(yàn)證注冊(cè)的實(shí)例
今天小編就為大家分享一篇在layui中使用form表單監(jiān)聽ajax異步驗(yàn)證注冊(cè)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-09-09
JavaScript Map實(shí)現(xiàn)原理與底層結(jié)構(gòu)詳解
哈希表(也稱為哈希表)是一種基于鍵直接訪問內(nèi)存存儲(chǔ)位置的數(shù)據(jù)結(jié)構(gòu)。也就是說,它通過計(jì)算一個(gè)鍵值函數(shù)來加速查找,該函數(shù)將要查詢的數(shù)據(jù)映射到表中的某個(gè)位置。該映射函數(shù)稱為散列函數(shù),記錄數(shù)組稱為散列表2022-09-09
Javascript圖像處理—圖像形態(tài)學(xué)(膨脹與腐蝕)
上一篇文章,我們講解了圖像處理中的閾值函數(shù),這一篇文章我們來做膨脹和腐蝕函數(shù)2013-01-01
Bootstrap Table快速完美搭建后臺(tái)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Bootstrap Table快速完美搭建后臺(tái)管理系統(tǒng)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09
js+for循環(huán)實(shí)現(xiàn)字符串自動(dòng)轉(zhuǎn)義的代碼(把后面的字符替換前面的字符)
這段代碼是從網(wǎng)上看到的一段不錯(cuò)的代碼,用for命令實(shí)現(xiàn)字符串的轉(zhuǎn)移,而且使用的是for循環(huán)直接將后面的字符替換成前面的字符,這個(gè)邏輯以前沒試過2020-12-12
js實(shí)現(xiàn)從右向左緩緩浮出網(wǎng)頁浮動(dòng)層廣告的方法
這篇文章主要介紹了js實(shí)現(xiàn)從右向左緩緩浮出網(wǎng)頁浮動(dòng)層廣告的方法,可實(shí)現(xiàn)右側(cè)浮動(dòng)廣告的定時(shí)彈出及點(diǎn)擊展開、折疊等功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-05-05
postMessage消息通信Promise化的方法實(shí)現(xiàn)
postMessage Api 想必大家都不陌生,WebWorker 通信會(huì)用到,iframe 窗口之間通信也會(huì)用到,那么我們能不能將 postMessage 進(jìn)行一次轉(zhuǎn)化,把他變成類似 Promise 的使用方式,所以本文給大家介紹了postMessage消息通信Promise化的方法實(shí)現(xiàn),需要的朋友可以參考下2024-03-03
javascript 帶有滾動(dòng)條的表格,標(biāo)題固定,帶排序功能.
帶有滾動(dòng)條的表格,標(biāo)題固定,帶排序功能. 雖然經(jīng)測試有點(diǎn)問題,但編程思路很清晰,需要的朋友可以參考下。2009-11-11
JS圖片定時(shí)翻滾效果實(shí)現(xiàn)方法
這篇文章主要介紹了JS圖片定時(shí)翻滾效果實(shí)現(xiàn)方法,涉及javascript結(jié)合時(shí)間函數(shù)實(shí)現(xiàn)頁面元素動(dòng)態(tài)切換的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06

