浅谈Javascript虚拟列表(virtaul list)改造成虚拟表格(virtaul table)的技术

news2024/9/21 19:09:45

前端加载百万条数据列表,如果采用真实的DOM插入100万个div(或li)标签,肯定是非常卡顿的。这就不得不使用虚拟列表技术方案,但是虚拟列表技术方案网上有很详细的实现方法,今天我就来谈谈根据网上的方案,把虚拟列表改造成虚拟表格的过程。

我就直接列出代码:

index.html,里面需要引入hyperHTML-min.js,我也提供了。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>virtual table</title>
		<style>
			.list-container {
				overflow: auto;
				border: 1px solid black;
				height: 500px;
				width: 700px;
				box-sizing: border-box;
			}
			.list-container-inner{
				
			}
			.list-container-inner .box{
				
			}
			.list-container-inner .box .layer1{
				display: table;
				width: 100%;
				height:100%;
				font-size:0;line-height: 0;margin: 0;padding: 0;
			}
			.list-container-inner .box .layer1 .row-box{
				overflow: hidden;
			}
			.list-container-inner .box .layer1 .row{
				box-sizing: border-box;
				height:calc(100% + 2px);
				position: relative;
			}
			.list-container-inner .box .layer1 .row .cell-box{
				box-sizing: border-box;
				position: absolute;
				height: 100%;
				overflow: hidden;
			}
			.list-container-inner .box .layer1 .cell{
				font-size:12px;
				line-height: 12px;
				
			}
/* 			.list-container-inner .box>div>div:first-child{
				border-left: 0px solid red;
			}
			.list-container-inner .box>div>div:last-child{
				border-right: 0px solid red;
			} */

			.list-container-inner .box .layer1>div>div:active{
				border: 0px solid red;
			}
			.wh100{
				width: calc(100% + 1px);
				padding-right: 1px;
				box-sizing: border-box;
				height: 100%;
			}
		</style>
		<script src="./hyperHTML-min.js"></script>
	</head>
	<body>
		<div id="root"></div>
		<!-- 外部容器用来固定列表容器的高度,同时生成滚动条 -->
		<div class="list-container">
			<!-- 内部容器用来装元素,高度是所有元素高度的和 -->
			<div class="list-container-inner">
				<div class="box">
					<div class="layer1"></div>
					<div class="layer2"></div>
				</div>
			</div>
		</div>

		<script>
			
			/** --------- 一些基本变量 -------- */
			const itemHeight = 60
			const columnWidth = 100
			const width = 700
			const height = 500
			const random = (min, max) => {
				return Math.floor(Math.random() * (max - min)) + min;
			}
			const getRandomColor = () => {
				let colors = [
					'red',
					'blue',
					'yellow',
					'orange',
					'brown',
					'purple',
					'pink',
					'green',
					'gray',
					'mauve'
				]
				return colors[random(0,10)]
			}

			/** --------- 生成数据 -------- */
			const getRandomHeight = () => {
				// 返回 [60, 150] 之间的随机数
				return Math.floor(Math.random() * (80 - itemHeight + 1) + itemHeight)
			}
			const getRandomWidth = () => {
				// 返回 [60, 150] 之间的随机数
				return Math.floor(Math.random() * (220 - columnWidth + 1) + columnWidth)
			}
			const columns = () => {
				const data = []
				for (let i = 0; i < 50; i++) {
					data.push({
						content:i,
						width:getRandomWidth(),
						color: getRandomColor()
					})
				}
				return data
			}
			const _columns = columns()
			const initData = () => {
				const data = []
				for (let i = 0; i < 500000; i++) {
					data.push({
						content: _columns,
						rowIndex:i,
						height: getRandomHeight(),
						color: i % 2 ? 'blue' : 'red'
					})
				}
				return data
			}
			const data = initData()
			
			const cacheWidthMap = {}
			const cacheHeightMap = {}
			const outerContainer = document.querySelector('.list-container')

			const scrollCallback = () => {
				//
				 let contentWidth = 0
				 let paddingLeft = 0
				 let upperWidth = 0
				 let startColIndex
				 let endColIndex
				 //
				let contentHeight = 0
				let paddingTop = 0
				let upperHeight = 0
				let startIndex
				let endIndex
				const innerContainer = document.querySelector('.list-container-inner')
				const scrollTop = Math.max(outerContainer.scrollTop, 0)
				const scrollLeft = Math.max(outerContainer.scrollLeft, 0)
				
				for (let i = 0; i < (data[0] ? (data[0].content || []) : []).length; i++) {
					const cacheWidth = cacheWidthMap[i]
					const usedWidth = cacheWidth === undefined ? columnWidth : cacheWidth
					contentWidth += usedWidth;
					if (contentWidth >= scrollLeft && startColIndex === undefined) {
						startColIndex = i
						paddingLeft = contentWidth - usedWidth
					}
					if (contentWidth > scrollLeft + width && endColIndex === undefined) {
						endColIndex = i
						upperWidth = contentWidth
					}
				}
				// 遍历所有的元素,获取当前元素的高度、列表总高度、startIndex、endIndex
				for (let i = 0; i < data.length; i++) {
					// 初始化的时候因为元素还没有渲染,无法获取元素的高度
					// 所以用元素的最小高度itemHeight来进行计算,保证渲染的元素个数能占满列表
					const cacheHeight = cacheHeightMap[i]
					const usedHeight = cacheHeight === undefined ? itemHeight : cacheHeight
					contentHeight += usedHeight
					if (contentHeight >= scrollTop && startIndex === undefined) {
						startIndex = i
						paddingTop = contentHeight - usedHeight
					}
					if (contentHeight > scrollTop + height && endIndex === undefined) {
						endIndex = i
						// console.log(endIndex,startIndex == endIndex, contentHeight, scrollTop + height) 
						upperHeight = contentHeight
					}
				}
				
				if(endColIndex === undefined) {
					endColIndex = (data[0] ? (data[0].content || []) : []).length - 1
					upperWidth = contentWidth
				}
				// 应对列表所有元素没有占满整个容器的情况
				if (endIndex === undefined) {
					endIndex = data.length - 1
					upperHeight = contentHeight
				}
				
				const paddingRight = contentWidth - upperWidth
				// innerContainer.setAttribute('style', `padding-left: ${paddingLeft}px; padding-bottom: ${paddingRight}px`)

				// 未渲染的元素的高度由padding-top和padding-bottom代替,保证滚动条位置正确
				// 这里如果把设置pading的操作放在渲染元素之后,部分浏览器滚动到最后一个元素时会有问题
				const paddingBottom = contentHeight - upperHeight
				innerContainer.setAttribute('style', `padding-left: ${paddingLeft}px; padding-right: ${paddingRight}px;padding-top: ${paddingTop}px; padding-bottom: ${paddingBottom}px`)

				// 从data取出要渲染的元素并渲染到容器中
				const viewData = data.slice(startIndex, endIndex + 1).map((item,index) => {
					let _item = {...item, content: item.content.slice(startColIndex, endColIndex + 1)}
					_item.content = _item.content.map((item,index) => {
						if(index==0) {
							item.left = 0
						} else {
							item.left = _item.content[index - 1].left + _item.content[index - 1].width
						}
						return item
					})
					return _item
				})
									// ${itemData.content.map(column => `<div class="cell-box" style="width:${column.width}px;left:${column.left}px;"><div class="wh100 cell" style="background:${getRandomColor()}">第${itemData.rowIndex}行,第${column.content}列</div></div>`)}
				innerContainer.querySelector('.box').style.width = (viewData[0] ? viewData[0].content : []).reduce(function(accumulator, column) {return accumulator + column.width;}, 0)+ 'px'
				innerContainer.querySelector('.box').style.height = viewData.map(item => item.height).reduce(function(accumulator, currentValue) {return accumulator + currentValue;}, 0) + 'px'
				function update(render, state) {
					render`
						${state.viewData.map(itemData => hyperHTML.wire(itemData)`
							<section class="row-box" style="height: ${itemData.height}px;background: ${itemData.color}">
								<div class="row">
${itemData.content.map(column => `<div class="cell-box" style="width:${column.width}px;left:${column.left}px;"><div class="wh100 cell" style="background:${getRandomColor()}">第${itemData.rowIndex}行,第${column.content}列</div></div>`)}
								</div>
							</section>	
						`)}
					`;
				}
				const render = hyperHTML.bind(innerContainer.querySelector('.box .layer1'))
				update(render, {
					viewData:viewData
				})
				// 存储已经渲染出来的元素的高度,供后面使用
				const children = innerContainer.querySelector('.box .layer1').children
				const columnChildren = innerContainer.querySelector('.box .layer1 .row').children
				let widthFlag = startColIndex
				for (const child of columnChildren) {
					cacheWidthMap[widthFlag] = child.clientHeight
					widthFlag++
				}
				let flag = startIndex
				for (const child of children) {
					cacheHeightMap[flag] = child.clientHeight
					flag++
				}
			}

			// 首屏渲染
			scrollCallback()
			// 监听外部容器的滚动事件
			outerContainer.addEventListener('scroll', scrollCallback)
		</script>

	</body>
</html>

 hyperHTML-min.js

/*! (c) Andrea Giammarchi (ISC) */var hyperHTML=function(N){"use strict";var t={};try{t.WeakMap=WeakMap}catch(e){t.WeakMap=function(t,e){var n=e.defineProperty,r=e.hasOwnProperty,i=a.prototype;return i.delete=function(e){return this.has(e)&&delete e[this._]},i.get=function(e){return this.has(e)?e[this._]:void 0},i.has=function(e){return r.call(e,this._)},i.set=function(e,t){return n(e,this._,{configurable:!0,value:t}),this},a;function a(e){n(this,"_",{value:"_@ungap/weakmap"+t++}),e&&e.forEach(o,this)}function o(e){this.set(e[0],e[1])}}(Math.random(),Object)}var s=t.WeakMap,i={};try{i.WeakSet=WeakSet}catch(e){!function(e,t){var n=r.prototype;function r(){t(this,"_",{value:"_@ungap/weakmap"+e++})}n.add=function(e){return this.has(e)||t(e,this._,{value:!0,configurable:!0}),this},n.has=function(e){return this.hasOwnProperty.call(e,this._)},n.delete=function(e){return this.has(e)&&delete e[this._]},i.WeakSet=r}(Math.random(),Object.defineProperty)}function m(e,t,n,r,i,a){for(var o=("selectedIndex"in t),u=o;r<i;){var c,l=e(n[r],1);t.insertBefore(l,a),o&&u&&l.selected&&(u=!u,c=t.selectedIndex,t.selectedIndex=c<0?r:f.call(t.querySelectorAll("option"),l)),r++}}function y(e,t){return e==t}function b(e){return e}function w(e,t,n,r,i,a,o){var u=a-i;if(u<1)return-1;for(;u<=n-t;){for(var c=t,l=i;c<n&&l<a&&o(e[c],r[l]);)c++,l++;if(l===a)return t;t=c+1}return-1}function x(e,t,n,r,i){return n<r?e(t[n],0):0<n?e(t[n-1],-0).nextSibling:i}function E(e,t,n,r){for(;n<r;)a(e(t[n++],-1))}function C(e,t,n,r,i,a,o,u,c,l,s,f,h){!function(e,t,n,r,i,a,o,u,c){for(var l=[],s=e.length,f=o,h=0;h<s;)switch(e[h++]){case 0:i++,f++;break;case 1:l.push(r[i]),m(t,n,r,i++,i,f<u?t(a[f],0):c);break;case-1:f++}for(h=0;h<s;)switch(e[h++]){case 0:o++;break;case-1:-1<l.indexOf(a[o])?o++:E(t,a,o++,o)}}(function(e,t,n,r,i,a,o){var u,c,l,s,f,h,d=n+a,v=[];e:for(m=0;m<=d;m++){if(50<m)return null;for(h=m-1,s=m?v[m-1]:[0,0],f=v[m]=[],u=-m;u<=m;u+=2){for(c=(l=u===-m||u!==m&&s[h+u-1]<s[h+u+1]?s[h+u+1]:s[h+u-1]+1)-u;l<a&&c<n&&o(r[i+l],e[t+c]);)l++,c++;if(l===a&&c===n)break e;f[m+u]=l}}for(var p=Array(m/2+d/2),g=p.length-1,m=v.length-1;0<=m;m--){for(;0<l&&0<c&&o(r[i+l-1],e[t+c-1]);)p[g--]=0,l--,c--;if(!m)break;h=m-1,s=m?v[m-1]:[0,0],(u=l-c)===-m||u!==m&&s[h+u-1]<s[h+u+1]?(c--,p[g--]=1):(l--,p[g--]=-1)}return p}(n,r,a,o,u,l,f)||function(e,t,n,r,i,a,o,u){var c=0,l=r<u?r:u,s=Array(l++),f=Array(l);f[0]=-1;for(var h=1;h<l;h++)f[h]=o;for(var d=i.slice(a,o),v=t;v<n;v++){var p,g=d.indexOf(e[v]);-1<g&&(-1<(c=k(f,l,p=g+a))&&(f[c]=p,s[c]={newi:v,oldi:p,prev:s[c-1]}))}for(c=--l,--o;f[c]>o;)--c;l=u+r-c;var m=Array(l),y=s[c];for(--n;y;){for(var b=y.newi,w=y.oldi;b<n;)m[--l]=1,--n;for(;w<o;)m[--l]=-1,--o;m[--l]=0,--n,--o,y=y.prev}for(;t<=n;)m[--l]=1,--n;for(;a<=o;)m[--l]=-1,--o;return m}(n,r,i,a,o,u,c,l),e,t,n,r,o,u,s,h)}var e=i.WeakSet,f=[].indexOf,k=function(e,t,n){for(var r=1,i=t;r<i;){var a=(r+i)/2>>>0;n<e[a]?i=a:r=1+a}return r},a=function(e){return(e.remove||function(){var e=this.parentNode;e&&e.removeChild(this)}).call(e)};function l(e,t,n,r){for(var i=(r=r||{}).compare||y,a=r.node||b,o=null==r.before?null:a(r.before,0),u=t.length,c=u,l=0,s=n.length,f=0;l<c&&f<s&&i(t[l],n[f]);)l++,f++;for(;l<c&&f<s&&i(t[c-1],n[s-1]);)c--,s--;var h=l===c,d=f===s;if(h&&d)return n;if(h&&f<s)return m(a,e,n,f,s,x(a,t,l,u,o)),n;if(d&&l<c)return E(a,t,l,c),n;var v=c-l,p=s-f,g=-1;if(v<p){if(-1<(g=w(n,f,s,t,l,c,i)))return m(a,e,n,f,g,a(t[l],0)),m(a,e,n,g+v,s,x(a,t,c,u,o)),n}else if(p<v&&-1<(g=w(t,l,c,n,f,s,i)))return E(a,t,l,g),E(a,t,g+p,c),n;return v<2||p<2?(m(a,e,n,f,s,a(t[l],0)),E(a,t,l,c)):v==p&&function(e,t,n,r,i,a){for(;r<i&&a(n[r],e[t-1]);)r++,t--;return 0===t}(n,s,t,l,c,i)?m(a,e,n,f,s,x(a,t,c,u,o)):C(a,e,n,f,s,p,t,l,c,v,u,i,o),n}var n,r={};function o(e,t){t=t||{};var n=N.createEvent("CustomEvent");return n.initCustomEvent(e,!!t.bubbles,!!t.cancelable,t.detail),n}r.CustomEvent="function"==typeof CustomEvent?CustomEvent:(o[n="prototype"]=new o("").constructor[n],o);var u=r.CustomEvent,c={};try{c.Map=Map}catch(e){c.Map=function(){var n=0,i=[],a=[];return{delete:function(e){var t=r(e);return t&&(i.splice(n,1),a.splice(n,1)),t},forEach:function(n,r){i.forEach(function(e,t){n.call(r,a[t],e,this)},this)},get:function(e){return r(e)?a[n]:void 0},has:r,set:function(e,t){return a[r(e)?n:i.push(e)-1]=t,this}};function r(e){return-1<(n=i.indexOf(e))}}}var h=c.Map;function d(){return this}function v(e,t){var n="_"+e+"$";return{get:function(){return this[n]||p(this,n,t.call(this,e))},set:function(e){p(this,n,e)}}}var p=function(e,t,n){return Object.defineProperty(e,t,{configurable:!0,value:"function"==typeof n?function(){return e._wire$=n.apply(this,arguments)}:n})[t]};Object.defineProperties(d.prototype,{ELEMENT_NODE:{value:1},nodeType:{value:-1}});var g,A,S,O,T,M,_={},j={},L=[],P=j.hasOwnProperty,D=0,W={attributes:_,define:function(e,t){e.indexOf("-")<0?(e in j||(D=L.push(e)),j[e]=t):_[e]=t},invoke:function(e,t){for(var n=0;n<D;n++){var r=L[n];if(P.call(e,r))return j[r](e[r],t)}}},$=Array.isArray||(A=(g={}.toString).call([]),function(e){return g.call(e)===A}),R=(S=N,O="fragment",M="content"in H(T="template")?function(e){var t=H(T);return t.innerHTML=e,t.content}:function(e){var t,n=H(O),r=H(T);return F(n,/^[^\S]*?<(col(?:group)?|t(?:head|body|foot|r|d|h))/i.test(e)?(t=RegExp.$1,r.innerHTML="<table>"+e+"</table>",r.querySelectorAll(t)):(r.innerHTML=e,r.childNodes)),n},function(e,t){return("svg"===t?function(e){var t=H(O),n=H("div");return n.innerHTML='<svg xmlns="http://www.w3.org/2000/svg">'+e+"</svg>",F(t,n.firstChild.childNodes),t}:M)(e)});function F(e,t){for(var n=t.length;n--;)e.appendChild(t[0])}function H(e){return e===O?S.createDocumentFragment():S.createElementNS("http://www.w3.org/1999/xhtml",e)}var I,z,V,Z,G,q,B,J,K,Q,U=(z="appendChild",V="cloneNode",Z="createTextNode",q=(G="importNode")in(I=N),(B=I.createDocumentFragment())[z](I[Z]("g")),B[z](I[Z]("")),(q?I[G](B,!0):B[V](!0)).childNodes.length<2?function e(t,n){for(var r=t[V](),i=t.childNodes||[],a=i.length,o=0;n&&o<a;o++)r[z](e(i[o],n));return r}:q?I[G]:function(e,t){return e[V](!!t)}),X="".trim||function(){return String(this).replace(/^\s+|\s+/g,"")},Y="-"+Math.random().toFixed(6)+"%",ee=!1;try{J=N.createElement("template"),Q="tabindex",(K="content")in J&&(J.innerHTML="<p "+Q+'="'+Y+'"></p>',J[K].childNodes[0].getAttribute(Q)==Y)||(Y="_dt: "+Y.slice(1,-1)+";",ee=!0)}catch(e){}var te="\x3c!--"+Y+"--\x3e",ne=8,re=1,ie=3,ae=/^(?:style|textarea)$/i,oe=/^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i;var ue=" \\f\\n\\r\\t",ce="[^"+ue+"\\/>\"'=]+",le="["+ue+"]+"+ce,se="<([A-Za-z]+[A-Za-z0-9:._-]*)((?:",fe="(?:\\s*=\\s*(?:'[^']*?'|\"[^\"]*?\"|<[^>]*?>|"+ce.replace("\\/","")+"))?)",he=new RegExp(se+le+fe+"+)(["+ue+"]*/?>)","g"),de=new RegExp(se+le+fe+"*)(["+ue+"]*/>)","g"),ve=new RegExp("("+le+"\\s*=\\s*)(['\"]?)"+te+"\\2","gi");function pe(e,t,n,r){return"<"+t+n.replace(ve,ge)+r}function ge(e,t,n){return t+(n||'"')+Y+(n||'"')}function me(e,t,n){return oe.test(t)?e:"<"+t+n+"></"+t+">"}var ye=ee?function(e,t){var n=t.join(" ");return t.slice.call(e,0).sort(function(e,t){return n.indexOf(e.name)<=n.indexOf(t.name)?-1:1})}:function(e,t){return t.slice.call(e,0)};function be(e,t,n,r){for(var i=e.childNodes,a=i.length,o=0;o<a;){var u=i[o];switch(u.nodeType){case re:var c=r.concat(o);!function(e,t,n,r){var i,a=e.attributes,o=[],u=[],c=ye(a,n),l=c.length,s=0;for(;s<l;){var f=c[s++],h=f.value===Y;if(h||1<(i=f.value.split(te)).length){var d=f.name;if(o.indexOf(d)<0){o.push(d);var v=n.shift().replace(h?/^(?:|[\S\s]*?\s)(\S+?)\s*=\s*('|")?$/:new RegExp("^(?:|[\\S\\s]*?\\s)("+d+")\\s*=\\s*('|\")[\\S\\s]*","i"),"$1"),p=a[v]||a[v.toLowerCase()];if(h)t.push(we(p,r,v,null));else{for(var g=i.length-2;g--;)n.shift();t.push(we(p,r,v,i))}}u.push(f)}}l=u.length;var m=(s=0)<l&&ee&&!("ownerSVGElement"in e);for(;s<l;){var y=u[s++];m&&(y.value=""),e.removeAttribute(y.name)}var b=e.nodeName;if(/^script$/i.test(b)){var w=N.createElement(b);for(l=a.length,s=0;s<l;)w.setAttributeNode(a[s++].cloneNode(!0));w.textContent=e.textContent,e.parentNode.replaceChild(w,e)}}(u,t,n,c),be(u,t,n,c);break;case ne:var l=u.textContent;if(l===Y)n.shift(),t.push(ae.test(e.nodeName)?Ne(e,r):{type:"any",node:u,path:r.concat(o)});else switch(l.slice(0,2)){case"/*":if("*/"!==l.slice(-2))break;case"馃懟":e.removeChild(u),o--,a--}break;case ie:ae.test(e.nodeName)&&X.call(u.textContent)===te&&(n.shift(),t.push(Ne(e,r)))}o++}}function we(e,t,n,r){return{type:"attr",node:e,path:t,name:n,sparse:r}}function Ne(e,t){return{type:"text",node:e,path:t}}var xe,Ee=(xe=new s,{get:function(e){return xe.get(e)},set:function(e,t){return xe.set(e,t),t}});function Ce(o,f){var e=(o.convert||function(e){return e.join(te).replace(de,me).replace(he,pe)})(f),t=o.transform;t&&(e=t(e));var n=R(e,o.type);Se(n);var u=[];return be(n,u,f.slice(0),[]),{content:n,updates:function(c){for(var l=[],s=u.length,e=0,t=0;e<s;){var n=u[e++],r=function(e,t){for(var n=t.length,r=0;r<n;)e=e.childNodes[t[r++]];return e}(c,n.path);switch(n.type){case"any":l.push({fn:o.any(r,[]),sparse:!1});break;case"attr":var i=n.sparse,a=o.attribute(r,n.name,n.node);null===i?l.push({fn:a,sparse:!1}):(t+=i.length-2,l.push({fn:a,sparse:!0,values:i}));break;case"text":l.push({fn:o.text(r),sparse:!1}),r.textContent=""}}return s+=t,function(){var e=arguments.length;if(s!==e-1)throw new Error(e-1+" values instead of "+s+"\n"+f.join("${value}"));for(var t=1,n=1;t<e;){var r=l[t-n];if(r.sparse){var i=r.values,a=i[0],o=1,u=i.length;for(n+=u-2;o<u;)a+=arguments[t++]+i[o++];r.fn(a)}else r.fn(arguments[t++])}return c}}}}var ke=[];function Ae(i){var a=ke,o=Se;return function(e){var t,n,r;return a!==e&&(t=i,n=a=e,r=Ee.get(n)||Ee.set(n,Ce(t,n)),o=r.updates(U.call(N,r.content,!0))),o.apply(null,arguments)}}function Se(e){for(var t=e.childNodes,n=t.length;n--;){var r=t[n];1!==r.nodeType&&0===X.call(r.textContent).length&&e.removeChild(r)}}var Oe,Te,Me=(Oe=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,Te=/([^A-Z])([A-Z]+)/g,function(e,t){return"ownerSVGElement"in e?function(e,t){var n;return(n=t?t.cloneNode(!0):(e.setAttribute("style","--hyper:style;"),e.getAttributeNode("style"))).value="",e.setAttributeNode(n),je(n,!0)}(e,t):je(e.style,!1)});function _e(e,t,n){return t+"-"+n.toLowerCase()}function je(a,o){var u,c;return function(e){var t,n,r,i;switch(typeof e){case"object":if(e){if("object"===u){if(!o&&c!==e)for(n in c)n in e||(a[n]="")}else o?a.value="":a.cssText="";for(n in t=o?{}:a,e)r="number"!=typeof(i=e[n])||Oe.test(n)?i:i+"px",!o&&/^--/.test(n)?t.setProperty(n,r):t[n]=r;u="object",o?a.value=function(e){var t,n=[];for(t in e)n.push(t.replace(Te,_e),":",e[t],";");return n.join("")}(c=t):c=e;break}default:c!=e&&(u="string",c=e,o?a.value=e||"":a.cssText=e||"")}}}var Le,Pe,De=(Le=[].slice,(Pe=We.prototype).ELEMENT_NODE=1,Pe.nodeType=111,Pe.remove=function(e){var t,n=this.childNodes,r=this.firstChild,i=this.lastChild;return this._=null,e&&2===n.length?i.parentNode.removeChild(i):((t=this.ownerDocument.createRange()).setStartBefore(e?n[1]:r),t.setEndAfter(i),t.deleteContents()),r},Pe.valueOf=function(e){var t=this._,n=null==t;if(n&&(t=this._=this.ownerDocument.createDocumentFragment()),n||e)for(var r=this.childNodes,i=0,a=r.length;i<a;i++)t.appendChild(r[i]);return t},We);function We(e){var t=this.childNodes=Le.call(e,0);this.firstChild=t[0],this.lastChild=t[t.length-1],this.ownerDocument=t[0].ownerDocument,this._=null}function $e(e){return{html:e}}function Re(e,t){switch(e.nodeType){case Ke:return 1/t<0?t?e.remove(!0):e.lastChild:t?e.valueOf(!0):e.firstChild;case Je:return Re(e.render(),t);default:return e}}function Fe(e,t){t(e.placeholder),"text"in e?Promise.resolve(e.text).then(String).then(t):"any"in e?Promise.resolve(e.any).then(t):"html"in e?Promise.resolve(e.html).then($e).then(t):Promise.resolve(W.invoke(e,t)).then(t)}function He(e){return null!=e&&"then"in e}var Ie,ze,Ve,Ze,Ge,qe="ownerSVGElement",Be="connected",Je=d.prototype.nodeType,Ke=De.prototype.nodeType,Qe=(ze=(Ie={Event:u,WeakSet:e}).Event,Ve=Ie.WeakSet,Ze=!0,Ge=null,function(e){return Ze&&(Ze=!Ze,Ge=new Ve,function(t){var i=new Ve,a=new Ve;try{new MutationObserver(u).observe(t,{subtree:!0,childList:!0})}catch(e){var n=0,r=[],o=function(e){r.push(e),clearTimeout(n),n=setTimeout(function(){u(r.splice(n=0,r.length))},0)};t.addEventListener("DOMNodeRemoved",function(e){o({addedNodes:[],removedNodes:[e.target]})},!0),t.addEventListener("DOMNodeInserted",function(e){o({addedNodes:[e.target],removedNodes:[]})},!0)}function u(e){for(var t,n=e.length,r=0;r<n;r++)c((t=e[r]).removedNodes,"disconnected",a,i),c(t.addedNodes,"connected",i,a)}function c(e,t,n,r){for(var i,a=new ze(t),o=e.length,u=0;u<o;1===(i=e[u++]).nodeType&&function e(t,n,r,i,a){Ge.has(t)&&!i.has(t)&&(a.delete(t),i.add(t),t.dispatchEvent(n));for(var o=t.children||[],u=o.length,c=0;c<u;e(o[c++],n,r,i,a));}(i,a,t,n,r));}}(e.ownerDocument)),Ge.add(e),e}),Ue=/^(?:form|list)$/i,Xe=[].slice;function Ye(e){return this.type=e,Ae(this)}var et=!(Ye.prototype={attribute:function(n,r,e){var i,t=qe in n;if("style"===r)return Me(n,e,t);if("."===r.slice(0,1))return l=n,s=r.slice(1),t?function(t){try{l[s]=t}catch(e){l.setAttribute(s,t)}}:function(e){l[s]=e};if("?"===r.slice(0,1))return o=n,u=r.slice(1),function(e){c!==!!e&&((c=!!e)?o.setAttribute(u,""):o.removeAttribute(u))};if(/^on/.test(r)){var a=r.slice(2);return a===Be||"disconnected"===a?Qe(n):r.toLowerCase()in n&&(a=a.toLowerCase()),function(e){i!==e&&(i&&n.removeEventListener(a,i,!1),(i=e)&&n.addEventListener(a,e,!1))}}if("data"===r||!t&&r in n&&!Ue.test(r))return function(e){i!==e&&(i=e,n[r]!==e&&null==e?(n[r]="",n.removeAttribute(r)):n[r]=e)};if(r in W.attributes)return function(e){var t=W.attributes[r](n,e);i!==t&&(null==(i=t)?n.removeAttribute(r):n.setAttribute(r,t))};var o,u,c,l,s,f=!1,h=e.cloneNode(!0);return function(e){i!==e&&(i=e,h.value!==e&&(null==e?(f&&(f=!1,n.removeAttributeNode(h)),h.value=e):(h.value=e,f||(f=!0,n.setAttributeNode(h)))))}},any:function(r,i){var a,o={node:Re,before:r},u=qe in r?"svg":"html",c=!1;return function e(t){switch(typeof t){case"string":case"number":case"boolean":c?a!==t&&(a=t,i[0].textContent=t):(c=!0,a=t,i=l(r.parentNode,i,[(n=t,r.ownerDocument.createTextNode(n))],o));break;case"function":e(t(r));break;case"object":case"undefined":if(null==t){c=!1,i=l(r.parentNode,i,[],o);break}default:if(c=!1,$(a=t))if(0===t.length)i.length&&(i=l(r.parentNode,i,[],o));else switch(typeof t[0]){case"string":case"number":case"boolean":e({html:t});break;case"object":if($(t[0])&&(t=t.concat.apply([],t)),He(t[0])){Promise.all(t).then(e);break}default:i=l(r.parentNode,i,t,o)}else"ELEMENT_NODE"in t?i=l(r.parentNode,i,11===t.nodeType?Xe.call(t.childNodes):[t],o):He(t)?t.then(e):"placeholder"in t?Fe(t,e):"text"in t?e(String(t.text)):"any"in t?e(t.any):"html"in t?i=l(r.parentNode,i,Xe.call(R([].concat(t.html).join(""),u).childNodes),o):"length"in t?e(Xe.call(t)):e(W.invoke(t,e))}var n}},text:function(r){var i;return function e(t){var n;i!==t&&("object"==(n=typeof(i=t))&&t?He(t)?t.then(e):"placeholder"in t?Fe(t,e):"text"in t?e(String(t.text)):"any"in t?e(t.any):"html"in t?e([].concat(t.html).join("")):"length"in t?e(Xe.call(t).join("")):e(W.invoke(t,e)):"function"==n?e(t(r)):r.textContent=null==t?"":t)}}}),tt=function(e){var t,r,i,a,n=(t=(N.defaultView.navigator||{}).userAgent,/(Firefox|Safari)\/(\d+)/.test(t)&&!/(Chrom[eium]+|Android)\/(\d+)/.test(t)),o=!("raw"in e)||e.propertyIsEnumerable("raw")||!Object.isFrozen(e.raw);return n||o?(r={},i=function(e){for(var t=".",n=0;n<e.length;n++)t+=e[n].length+"."+e[n];return r[t]||(r[t]=e)},tt=o?i:(a=new s,function(e){return a.get(e)||(n=i(t=e),a.set(t,n),n);var t,n})):et=!0,nt(e)};function nt(e){return et?e:tt(e)}function rt(e){for(var t=arguments.length,n=[nt(e)],r=1;r<t;)n.push(arguments[r++]);return n}var it=new s,at=function(t){var n,r,i;return function(){var e=rt.apply(null,arguments);return i!==e[0]?(i=e[0],r=new Ye(t),n=ut(r.apply(r,e))):r.apply(r,e),n}},ot=function(e,t){var n=t.indexOf(":"),r=it.get(e),i=t;return-1<n&&(i=t.slice(n+1),t=t.slice(0,n)||"html"),r||it.set(e,r={}),r[i]||(r[i]=at(t))},ut=function(e){var t=e.childNodes,n=t.length;return 1===n?t[0]:n?new De(t):e},ct=new s;function lt(){var e=ct.get(this),t=rt.apply(null,arguments);return e&&e.template===t[0]?e.tagger.apply(null,t):function(e){var t=new Ye(qe in this?"svg":"html");ct.set(this,{tagger:t,template:e}),this.textContent="",this.appendChild(t.apply(null,arguments))}.apply(this,t),this}var st,ft,ht,dt,vt=W.define,pt=Ye.prototype;function gt(e){return arguments.length<2?null==e?at("html"):"string"==typeof e?gt.wire(null,e):"raw"in e?at("html")(e):"nodeType"in e?gt.bind(e):ot(e,"html"):("raw"in e?at("html"):gt.wire).apply(null,arguments)}return gt.Component=d,gt.bind=function(e){return lt.bind(e)},gt.define=vt,gt.diff=l,(gt.hyper=gt).observe=Qe,gt.tagger=pt,gt.wire=function(e,t){return null==e?at(t||"html"):ot(e,t||"html")},gt._={WeakMap:s,WeakSet:e},st=at,ft=new s,ht=Object.create,dt=function(e,t){var n={w:null,p:null};return t.set(e,n),n},Object.defineProperties(d,{for:{configurable:!0,value:function(e,t){return function(e,t,n,r){var i,a,o,u=t.get(e)||dt(e,t);switch(typeof r){case"object":case"function":var c=u.w||(u.w=new s);return c.get(r)||(i=c,a=r,o=new e(n),i.set(a,o),o);default:var l=u.p||(u.p=ht(null));return l[r]||(l[r]=new e(n))}}(this,ft.get(e)||(n=e,r=new h,ft.set(n,r),r),e,null==t?"default":t);var n,r}}}),Object.defineProperties(d.prototype,{handleEvent:{value:function(e){var t=e.currentTarget;this["getAttribute"in t&&t.getAttribute("data-call")||"on"+e.type](e)}},html:v("html",st),svg:v("svg",st),state:v("state",function(){return this.defaultState}),defaultState:{get:function(){return{}}},dispatch:{value:function(e,t){var n=this._wire$;if(n){var r=new u(e,{bubbles:!0,cancelable:!0,detail:t});return r.component=this,(n.dispatchEvent?n:n.firstChild).dispatchEvent(r)}return!1}},setState:{value:function(e,t){var n=this.state,r="function"==typeof e?e.call(this,n):e;for(var i in r)n[i]=r[i];return!1!==t&&this.render(),this}}}),gt}(document);

原理 我就不过多赘述,主要就是说以下优点和缺点:

1、在27万条数据以内,背景填充没有问题。超过27万的div的背景不能正确填充div绘制的范围,导致看上去上下间有问题,有一条白色的水平线条。曾做过如下方法解决:

 a 、我已经把font-size改为0了,不能解决。

b、把padding-top padding-bottom 改为 真实的元素占位,不能解决。因为我以为这情况回事padding导致。

c、也把div从 position static 改为 absolute 定位来解决,发现也与这个无关。

d、设置过background相关的参数,不能解决。

通过审查解决,是背景不能填充,确定是背景的问题。如果是在firfox,低于27万就出现这种问题了。

上图是垂直方向的问题,水平方向也会这种问题,我就不截图了。

2、超过27万以后的数据在chrome浏览器中,当滚动时候,出现渲染不准确问题,比如说border都设置为1px,但是看上去并不一致,outline也一样。而且有时候应该隐藏outline的时候,还是出现一些颜色在边上,不知道是不是显卡问题,但是浏览器渲染div又不用显卡。

3、这种方案,从百万数据中找到 屏幕可视数据的算法是非常棒的!经过有以上问题,但是性能非常好,别说100万,200万也就秒渲染,只是渲染后有一些问题。

4、padding填充内部实现内部内容高度的增高大约只支持到 55.92w条左右,超过这个数,将无法显示,因为chrome浏览器似乎支持的最大padding-bottom的值是33551640px,所以如果有需要超过这个值的需求,padding撑起内部内容高度实现滚动条是不可取的,必须自定义滚动条支持超过55.9万条的数据。

总结,如果实际需求中碰不到超过10万条的数据,这种方式处理10万条的数据,还是很优秀的,但是我想要他支持百万,可超过27万就出现了不可解决的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1535938.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【软考高项】十六、信息系统工程之安全工程

1、基础概念 定义&#xff1a;建造一个信息安全系统&#xff0c;它是整个信息系统工程的一部分&#xff0c;而且最好是与业务应用信息系统工程同步进行&#xff0c;主要围绕“信息安全”内容 信息安全系统三维空间&#xff1a; 包括安全机制、网络参考模型和安全服务 X轴是…

23 OpenCV 直方图比较

文章目录 直方图比较的目的相关性计算 (CV_COMP_CORREL)卡方计算 (CV_COMP_CHISQR)十字计算(CV_COMP_INTERSECT)巴氏距离计算 (CV_COMP_BHATTACHARYYA )compareHist 直方图比较算子示例 直方图比较的目的 直方图比较的目的是衡量两幅图像之间的相似度或差异度。通过计算图像的颜…

如何在 Windows 中恢复永久删除的文件

即使您从电脑或笔记本电脑中永久删除文件或文档&#xff0c;您也可以轻松恢复它们。因此&#xff0c;在本文的帮助下&#xff0c;我们将了解一些轻松恢复丢失数据的最佳和最值得信赖的方法。 生活中&#xff0c;难免会发生错误。这就是我们作为个人学习和成长的方式。这些错误…

OSError: We couldn‘t connect to ‘https://huggingface.co‘ to load this file

想折腾bert的同学&#xff0c;应该也遇到这个问题。 一、报错信息分析 完整报错信息&#xff1a;OSError: We couldnt connect to https://huggingface.co to load this file, couldnt find it in the cached files and it looks like google/mt5-small is not the path to a…

比堆垛机方案省电65% 实施快50% 四向车系统柔性化建设进程异军突起

对物流企业来说&#xff0c;供应链的数智化升级并非“赶时髦”&#xff0c;它需要找到一个既懂物流行业&#xff0c;又有数字化技术作基础的仓储方案提供商。而河北沃克基于AI底层技术、软硬一体化产品体系和技术创新行业经验双轮驱动的业务团队等“技术产品人才”三位一体优势…

杭州克鲁斯机器人控制信号线缆故障维修攻略,快来了解一下!

克鲁斯机器人作为工业自动化的重要组成部分&#xff0c;其稳定运行对于生产效率至关重要。克鲁斯机器人控制信号线缆作为机器人与外部控制设备之间的桥梁&#xff0c;承担着传输指令和反馈信号的重要任务。 一、克鲁斯机器人控制信号线缆故障识别与诊断 故障现象&#xff1a;当…

人工智能时代的引领者:AI提示工程激发大语言模型的无限潜能

文章目录 一、AI提示工程的概念与定义二、AI提示工程的应用领域三、AI提示工程的技术创新与突破四、AI提示工程的未来发展趋势《AI提示工程实战&#xff1a;从零开始利用提示工程学习应用大语言模型》亮点内容简介作者简介目录 一、AI提示工程的概念与定义 在当今日新月异的科…

【Python】为什么能用 tuple 的地方就不用 list

元组(tuple)和列表(list)的区别 相对于 list 而言&#xff0c;tuple 内的元素是不可变的&#xff0c;也就是tuple 不可对元素进行增删tuple是静态的固定大小的&#xff0c;而list是动态分配存储空间&#xff0c;自动扩容的。 内存比较 代码 listtest [1,2,3,4] tupletest …

洛谷_P2678 [NOIP2015 提高组] 跳石头_python写法

P2678 [NOIP2015 提高组] 跳石头 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) d, n, m map(int,input().split())data [0] for i in range(n):value int(input())data.append(value) data.append(d)def check(mid):now 0cnt 0for i in range(1,n2):if abs(data[now]-da…

十分钟快速入门 Python

本文以 Eric Matthes 的《Python编程&#xff1a;从入门到实践》为基础&#xff0c;以有一定其他语言经验的程序员视角&#xff0c;对书中内容提炼总结&#xff0c;化繁为简&#xff0c;将这本书的精髓融合成一篇10分钟能读完的文章。 读完本篇文章后&#xff0c;可对 Python …

Redis相关操作高阶篇--集群搭建

Redis相关操作大全一篇全搞定-CSDN博客 Redis集群 是一个由多个主从节点群组成的分布式服务器群&#xff0c;它具有复制、高可用和分片特性。Redis集群不需要seninel哨兵也能完成节点移除和故障转移的功能。需要将每个节点 设置成集群模式&#xff0c;这种集群模式没有中心节…

产品经理杂谈

像游戏一样设计联赛 1、通过互联网规模化&#xff0c;然后分析数据&#xff0c;哪里好&#xff0c;哪里不好&#xff0c;大家都喜欢你的产品了&#xff0c;然后反哺更大规模 2、产品分类 toC 工具 内容 游戏 社交 电商 交易 toB 内部办公类 – 提高企业内部效率&#xff0c;…

34 vue 项目默认暴露出去的 public 文件夹 和 CopyWebpackPlugin

前言 这里说一下 vue.config.js 中的一些 public 文件夹是怎么暴露出去的? 我们常见的 CopyWebpackPlugin 是怎么工作的 ? 这个 也是需要 一点一点积累的, 因为 各种插件 有很多, 不过 我们仅仅需要 明白常见的这些事干什么的即可 当然 以下内容会涉及到一部分vue-cli,…

一篇文章带你了解知乎热门话题的撰写技巧

在当今信息高速发展的时代&#xff0c;人们越来越依赖网络获取知识。而知乎作为一个知识分享和知识传播的平台&#xff0c;吸引了大量用户的关注和参与。那么&#xff0c;如何在知乎上撰写一篇引人注目的文章呢&#xff1f;接下来&#xff0c;腾轩科技传媒探讨一下知乎文章的撰…

【测试开发学习历程】MySQL数据类型 + MySQL表创建与操作

前言&#xff1a; 半夜梦到自己没有写今天的博客&#xff0c;结果惊醒起来看一看。 得&#xff0c;真的没写。QWQ 可谓垂死病中惊坐起了。 看看发博的时间6&#xff1a;16&#xff0c;而不是什么整点的&#xff0c;就知道我4点就起来了&#xff0c;不是定时发布&#xff01…

python网络爬虫实战教学——requests的使用(1)

文章目录 专栏导读1、前言2、get请求3、抓取网页4、抓取二进制数据5、请求头 专栏导读 ✍ 作者简介&#xff1a;i阿极&#xff0c;CSDN 数据分析领域优质创作者&#xff0c;专注于分享python数据分析领域知识。 ✍ 本文录入于《python网络爬虫实战教学》&#xff0c;本专栏针对…

11 html 学习/作业

<!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body><a href"./index.html">首页</a><a href"https://www.baidu.com/">百度</a><a h…

asp.net mvc 重新引导视图路径,改变视图路径

asp.net mvc 重新引导视图路径&#xff0c;改变视图路径 使用指定的控制器上下文和母版视图名称来查找指定的视图 通过本文学习&#xff0c;你可以根据该技法&#xff0c;去实现&#xff0c;站点自定义皮肤&#xff0c;手机站和电脑站&#xff0c;其他设备站点&#xff0c;在不…

【复杂网络建模】——建模工具Matlab入门

目录 一、认识MATLAB 二、认识工具箱 三、基本操作和函数 3.1 算术操作符 3.2 数学函数 3.3 矩阵操作 3.4 索引和切片 3.5 逻辑操作 3.6 控制流程 3.7 数据输入输出 四、变量和数据类型 4.1 数值类型 4.2 整型 4.3 复数 4.4 字符串 4.5 逻辑类型 4.6 结构体&a…

【合合TextIn】深度解析智能文档处理技术与应用

目录 一、智能文档处理介绍 二、文档格式解析 三、图像增强技术解析 四、传统文字识别OCR技术解析 五、深度学习OCR技术解析 六、深度学习版面分析技术解析 七、文档分类 八、信息抽取 九、系统集成&#xff1a;将IDP处理后的数据集成到企业系统 结论 一、智能文档处…