四川建设银行手机银行下载官方网站下载安装wordpress和自己写

当前位置: 首页 > news >正文

四川建设银行手机银行下载官方网站下载安装,wordpress和自己写,新都区建设局网站,河南省建设信息网站1、场景描述 在项目开发中#xff0c;遇到在表格中一次性加载完的需求#xff0c;且加载数量不少#xff0c;有几百几千条#xff0c;并且每条都可能有自己的下拉框#xff0c;输入框来做编辑功能#xff0c;此时普通的el-table肯定会导致浏览器卡死#xff0c;那么怎么…1、场景描述 在项目开发中遇到在表格中一次性加载完的需求且加载数量不少有几百几千条并且每条都可能有自己的下拉框输入框来做编辑功能此时普通的el-table肯定会导致浏览器卡死那么怎么办呢 2、解决方案 当然很多童鞋肯定会想到利用插件其实我本人是不咋喜欢插件的能自己写就自己写毕竟插件可能也有bug或者啥的万一出现了作者不去改咋办所以我总结了下面几个解决方法 提示本篇博客基本都用的tsx vue3 composition-api体验版 来写的噢用vue2或者vue3模板语法写会更简单噢照葫芦画瓢逻辑都是一样的我这里就不写了想了解相关的vue3知识我另一篇博客上有噢~ Vue3知识点学习 1、滚动触底分页良 当纵向滚动条触底的时候加载新的数据到当前表格中逻辑如下 table.scrollTop table.clientHeight table.scrollHeight
当上述成立时候触发加载table为表格dom, 但是如果数据很多的话每次滚动都会将新的tr加入到表格中那表格tr dom总数还是会依次递增dom一多照样卡死 2、滚动区间分页良 如果你没有表格编辑功能全是展示数据的话那么这个解决方案已经完全可以了 比如你当前表格可显示区域能够展示十条数据那么首次进来时显示数据的区间为 [0, 9]每次表格滚动时都动态的去获取当前展示的区间其实这种方式是比较好的为啥呢因为不管你几千几万条数据我同一时刻就只有10行完全不会因为tr数量过多导致浏览器渲染卡顿当然这可视区域能展示多少条数据是有你表格可视高度和单行tr高度一起决定的 const selectWrap table.querySelector(.el-tablebody-wrapper);const selectRow table.querySelector(table tr);展示tr数量 Math.ceil(selectWrap.clientHeight / selectRow.clientHeight) tsx页面 setup() {return () (el-tabledata{visibleResult.value} // 可视区域的数据/el-table) } ts逻辑 /** 表格上展示的数据 */const visibleResult computed(() {return result.value.filter((_item, index) {if (index curStartIndex.value) {return false;} else if (index curEndIndex.value) {return false;} else {return true;}});}) 那么如何去控制这个滚动区间呢这个方法很多监听滚动条的scroll当向下滚动或向上滚动我们都可以监听到然后改变curStartIndex和curEndIndex的值就可以改变啦这样的话光是只看数据倒是解决了但是要是表格要实现编辑效果咋办每行数据有十几个下拉框和输入框你要知道el-select dom层级很高像这种el-select数量一多就算你当前展示区域没有多少条数据也会导致渲染卡顿的所以就有下面的优化版方案 3、滚动区间分页 表格编辑优 当前表格可视区域有30条数据每条数据有10个el-select和5个el-input当然可能有童鞋会说el-select dom层级高那我就自己写select鸭但是你自己写的未必有el-select好看且功能相当。此时首次加载就很卡顿了原因就是el-select多了那么我首先想的是这些el-select又不是直接要用为啥不在我点击这个单元格时候再弹出下拉呢不点击单元格时候就直接展示文本效果el-select没有值时展示 请选择, 有值时展示你选择的值 例图如下 滚动区间分页 不管你有多少条数据我始终首次只加载这么十多个trtr数量不变变化的是每次的区间取值大家会发现下面有个tr id为 virtual-scroll那这是干什么 的呢其实核心思路是 显示区的高度 已经滚动过的高度 虚拟滚动条高度 总的数据高度table-wrapper.clientHeight table-wrapper.scrollTop virtual-scroll.height data.lentth * tr.clientHeight 是不是发现和方案1类似但是区别不同的是虚拟条高度可是一来就会被计算出来的因为开始时候scrollTop为0 那么 虚拟条高度 就是 总的数据高度 - 显示区高度 tsx: 通过自定义指令来监听表格的滚动返回值触发loadMore方法来决定显示区展示数据的区间 setup() {return () (el-tabledata{visibleResult.value} // 可视区域的数据{…{ directives: [{ name: load-more, value: methods.loadMore }] }}/el-table) } ts: 逻辑 /** 表格上展示的数据 /const visibleResult computed(() {return result.value.filter((_item, index) {if (index curStartIndex.value) {return false;} else if (index curEndIndex.value) {return false;} else {return true;}});})const methods {/** 懒加载回调* param startIndex 区段位置开始索引* param endIndex 区段位置结束索引*/loadMore(startIndex: number, endIndex: number) {curStartIndex.value startIndexcurEndIndex.value endIndex}, } 那上面是实现滚动区间的代码那说的表格编辑相关在哪里呢下面即是 表格编辑 当我们表格中有很多下拉框和输入框时其实拖垮性能的多半是el-select那解决方法是将渲染input和select的逻辑提出来input不做处理select当前单元格rowcolumn索引和focusCell的值一致时说明单元格被聚焦了就显示el-select否则直接展示文本 关键方法及属性讲解 inputChange输入框回调 selectChange下拉框选择回调 selectPerofrmance下拉框当前值渲染 domPropsInnerHTML 等同于v-html但是jsx中不能用v-html decorateHeader表格各列数据我都是动态配置的后续我会出一期博客来讲解vue3tsx下如何封装表格 然后效果大致如下总结下就是同一时间最多只会存在一个el-select既然el-select dom减少了那么表格渲染速度就自然而然快了 上面例图中被黄色圈中的就是聚焦没有被聚焦的都展示文本源码讲解如下 const focusCell refstring(0,0) // 表格数据第0行第0列 你在el-table 里有 cell-click 这个事件它会将当前row column全都回调回去那么你就会知道你当前点击单元格的索引值, 我们将索引值生成 在同一时间focusCell只会有一条数据所以我们直接用字符串来存储就好 el-tableon-cell-click{methods.cellClick}/el-tableconst methods {cellClick(row, column) {if (focusCell.value ! \({row.index},\){column.index}) {focusCell.value \({row.index},\){column.index}}} } 那么关键来了下拉框单元格聚焦的时候我们才显示下拉框其他时候展示文本输入框类型单元格聚焦的时候不做处理代码该如何写呢 setup() {return () {/** 输入框类型渲染 */const inputDomRender (scope, item) (el-inputvalue{scope.row[item.prop]}on-input{e methods.inputChange(e, scope, item)}/)/** 下拉框类型渲染 */const selectDomRender (scope, item) ((focusCell.value \({scope.row.autoIndex},\){scope.column.index} ? el-selectvalue-keyidvalue{scope.row[item.prop]}onChange{e methods.selectChange(e, scope, item)}{item.selects.map(item1 {return el-optionkey{item1.id}label{item1.label}value{item1.id}/el-option})}/el-select : divdomPropsInnerHTML{methods.selectPerofrmance(scope.row[item.prop], item.prop)}/div))return el-tableon-cell-click{methods.cellClick}{decorateHeader.map((item: TableLabel) {return el-table-columnwidth{item.width}label{item.label}align{item.align ? item.align : center}prop{item.prop}scopedSlots{{default: scope {return div{item.mode ! input ? selectDomRender(scope, item) : inputDomRender(scope, item)}/div}}}/el-table-column})}/el-table} }自此上述两步优化其实就能使我们一次性加载几千条可编辑数据不会卡顿了 3、v-load-more自定义指令 源码 import {VNodeDirective } from vue let timeout; /** 设置表格滚动区间 */ const setRowScrollArea (topNum, showRowNum, binding) {if (timeout) {clearTimeout(timeout);}timeout setTimeout(() {binding.value.call(null, topNum, topNum showRowNum);}); }; const loadMore {bind(el: Element, _binding) {setTimeout(() {// 创建虚拟滚动条const selectWrap el.querySelector(.el-tablebody-wrapper);const selectTbody selectWrap.querySelector(table tbody);const createElementTR document.createElement(tr);createElementTR.id virtual-scrollselectTbody.append(createElementTR); // 先行将虚拟滚动条加入进来})},componentUpdated(el: Element, binding: VNodeDirective, vnode, oldVnode) {setTimeout(() {const dataSize vnode.data.attrs[data-size];const oldDataSize oldVnode.data.attrs[data-size];// 当数量相同时表明当前未发生更新减少后续操作if (dataSize oldDataSize) {return;}const selectWrap el.querySelector(.el-tablebody-wrapper);const selectTbody selectWrap.querySelector(table tbody);const selectRow selectWrap.querySelector(table tr);// 当一行都没有说明无数据渲染但一般逻辑都不会进入这里if (!selectRow) {return;}const rowHeight selectRow.clientHeight;// 能够在当前显示区的展示条数本项目就是11条const showRowNum Math.round(selectWrap.clientHeight / rowHeight);const createElementTRHeight (dataSize - showRowNum) * rowHeight;const createElementTR selectTbody.querySelector(#virtual-scroll)// 监听滚动后事件selectWrap.addEventListener(scroll, function() {let topPx this.scrollTop;let topNum Math.round(topPx / rowHeight);const minTopNum dataSize - showRowNum;if (topNum minTopNum) {topNum minTopNum;}if (topNum 0) {topNum 0;topPx 0;}selectTbody.setAttribute(style, transform: translateY(\({topPx}px));// 本来触底的话应该设置为0但是触底后 就没有滚动条了createElementTR.setAttribute(style, height: \){createElementTRHeight - topPx 0 ? createElementTRHeight - topPx : rowHeight}px;);setRowScrollArea(topNum, showRowNum, binding);})});} }export default loadMore不太了解自定义指令是啥的可以参考我另一篇博客 vue学习6自定义指令详解及常见自定义指令 4、有趣拓展 1、我想在上述表格中对指定列实现高亮搜索怎么做 当有值时滚动到指定位置无值时不动那首先在加载数据时要先写下面代码 // 先让他触发滚动才能让virtual-scroll高度生成 table.$el.querySelector(.el-tablebody-wrapper).scrollTo({ top: 1, behavior: smooth })输入框执行逻辑如下防抖肯定是要的然后搜索的列是 originName当发现有搜索到值时找到第一个被匹配到的行索引然后去计算表格应该滚动到哪个高度位置然后滚动 /*** 滚动定位到表格指定位置* param flag 是否能执行滚动的标志* returns/scrollToTable: () \(debounce(function() {// 当没有值时不进行搜索if (dialogSearchKey.value) {const vmEl table.value.\)el;const selectWrap vmEl.querySelector(.el-table__body-wrapper)if (vmEl) {const autoIndex result.value.find((item: TableDataItem) {return item.originName.indexOf(dialogSearchKey.value) ! -1})?.autoIndex ?? -1if (autoIndex ! -1) {scrollToIndex(selectWrap, autoIndex)}}}}, 500, false),/** 表格滚动到指定索引值行* param selectWrap 表格dom* param autoIndex 索引*/scrollToIndex(selectWrap, autoIndex) {const showNum 12 // 当显示条数小于次数时不进行滚动操作const topPx autoIndex * columnHeight.valueif (autoIndex showNum) {selectWrap.scrollTo({ top: topPx, behavior: smooth })}} 然后高亮被搜索文字源码如下 setup() {return () {return el-tableon-cell-click{methods.cellClick}{decorateHeader.map((item: TableLabel) {return el-table-columnwidth{item.width}label{item.label}align{item.align ? item.align : center}prop{item.prop}scopedSlots{{default: scope {return divdivclassmultilinedomPropsInnerHTML{methods.textRender(scope.row[item.prop], item.prop)}//div}}}/el-table-column})}/el-table} }props.heightLight  为输入框的搜索关键词 /*** 文字渲染* param word 被渲染的文字* param prop 属性名* returns 替换后的渲染文字*/textRender(word: string, prop: string): string {const reg new RegExp(\({props.heightLight}, ig)// 有搜索关键词 是否有该子字符串if (props.heightLight word.indexOf(props.heightLight) ! -1) {return word.replace(reg, font colorred\)/font)// 正常返回的列} else {return word}} 2、前端实现表格导出excel 需要依赖如下 import * as XLSX2 from xlsx; import XLSX from xlsx-style; 存在需要对依赖源码进行打补丁的地方 1、/node_modules/xlsx-style/dist/cpexcel.js 错误源码var cpt require(./cpt able); 应修改为var cpt cptable;2、/node_modules/xlsx-style/dist/ods.js 错误源码return require(../ xlsx).utils; 应修改为return require(./ xlsx).utils; 变量名讲解 // props.headerDisplay 导出excel头部 {autoIndex: 序号,originName: 视频文件, }// exportData 导出文件数据格式 [{autoIndex: 1,originName: xxx},{autoIndex: 2,originName: xxx} ]// headProp 导出excel头部属性名数组 [autoIndex, originName] 导出excel源码  exportTransfer(exportData, header) {nextTick(() {const newData [props.headerDisplay, …exportData] // 封装组合后的数据const headProp header.map(item item.prop) // 头部属性数组// 把json转为worksheet对象 后续用这种方法const wb XLSX2.utils.json_to_sheet(newData, { header: headProp, skipHeader: true })// returnconst widthList header.map(item item.width ? Number(item.width) : 150)// 举例一共有14列(包括序号不包括操作栏)wb[!cols] [] // 先初始化列数组配置for (let i 0; i 14; i) {wb[!cols][i] {wpx: widthList[i]}}// 样式的文档地址// https://www.npmjs.com/package/xlsx-stylefor (const key in wb) {if (key.indexOf(!) -1) { // 非excel配置类带!都是配置类这里对非配置类进行样式修改wb[key].s {font: { // 字体设置sz: 13,bold: false,color: { // 只有DEFG第一行标题行才是红色其余皆是黑色rgb: new RegExp(/^[DEFG]1{1}\(/).test(key) ? D9001B : 000000 // 十六进制不带#, 除去文件类型, 视频来源, 视频版权, 视频分类 这四栏标题行标红外其他都是黑色}},alignment: { // 文字居中horizontal: center,vertical: center,wrapText: 1 // 换行},border: { // 设置边框top: { style: thin },bottom: { style: thin },left: { style: thin },right: { style: thin }}}}}const filedata sheet2blob(wb)openDownloadDialog(filedata, xxx)})},/*** 将一个sheet转成最终的excel文件的blob对象然后利用URL.createObjectURL下载* param sheet excel对象* param sheetName* returns*/sheet2blob(sheet, sheetName?: string) {const s2ab (s) {const buf new ArrayBuffer(s.length);const view new Uint8Array(buf);for (let i 0; i ! s.length; i) {view[i] s.charCodeAt(i) 0xFF;}return buf;}sheetName sheetName || sheet1;const workbook {SheetNames: [sheetName],Sheets: {}};workbook.Sheets[sheetName] sheet; // 生成excel的配置项const wopts {bookType: xlsx, // 要生成的文件类型bookSST: false, // 是否生成Shared String Table官方解释是如果开启生成速度会下降但在低版本IOS设备上有更好的兼容性type: binary};const wbout XLSX.write(workbook, wopts);const blob new Blob([s2ab(wbout)], { // 字符串转ArrayBuffertype: application/octet-stream});return blob;},/*** 创建excel地址并下载到本地* param url 文件blob二进制路径* param saveName 文件名*/openDownloadDialog(url, saveName) {if (typeof url object url instanceof Blob) {url URL.createObjectURL(url); // 创建blob地址}const aLink document.createElement(a);aLink.href url;aLink.download \){saveName}.xlsx; // HTML5新增的属性指定保存文件名let event;if (window.MouseEvent) {event new MouseEvent(click);} else {event document.createEvent(MouseEvents); // 事件抛出event.initMouseEvent(click, true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);}aLink.dispatchEvent(event); // 事件派发} 有不理解的或有更好想法的可以底下评论喔~