2、localStorage、sessionStorage,IE8+才支持,容量一般在5MB左右。
3、WebSQL,IE不支持。好处是结构跟关系型数据库一样,而且没有容量限制;缺点是慢。
4、IndexDB,IE10+才支持,已被废弃的一种特性(废弃的意思是你可以继续使用,但是浏览器厂商已经不再维护这个特性了,即使有BUG也没人管了)。
把看到的区域当画布,创建足够能展现界面的Dom就够了。比如一个屏幕的高度一般是800像素左右,假设一条记录占用的高度是20像素,我们只用创建40个对象即可。
接下来就是对这40个对象进行数据填充,通过滚动条调整填充数据的起始下标。
10W条记录,IE下有些卡
<style type="text/css">
.panel{
overflow:scroll
width:200px
height:80%
}
.panel .scroll{
}
.item{
width:500px
height:20px
}
.odd{
background-color:#ccc
}
.items{
overflow:hidden
position:absolute
}
.red{
color:red
}
.green{
color:green
}
</style>
<script>
window.console = window.console || { log: function() {} }
function absolutePoint(element) {
var result = [element.offsetLeft, element.offsetTop]
element = element.offsetParent
while (element) {
result[0] += element.offsetLeft
result[1] += element.offsetTop
element = element.offsetParent
}
return result
}
function ListView(options){
options = options || {}
var self = this,
$C = function(tagName) { return document.createElement(tagName)}, // 创建节点
p,
height,
item_height, // 项高
view_count, // 可见项条数
parent = options.parent || document.body, // 容器
height, // 面板历史高度
div_panel = $C("div"),
div_scroll = $C("div"),
div_items = $C("div"),
div_items_list = [$C("div")],
freed = [div_panel, div_scroll, div_items]// 可释放的对象
div_panel.className = "panel"
parent.appendChild(div_panel)
div_items.className = "items"
document.body.appendChild(div_items)
div_scroll.className = "scroll"
div_panel.appendChild(div_scroll)
div_panel.onscroll = function() {
doChange()
}
div_panel.onresize = function() {
doChange()
}
div_items_list[0].className = "item"
div_items.appendChild(div_items_list[0])
div_scroll.style.width = div_items_list[0].clientWidth + "px"
item_height = div_items_list[0].clientHeight
p = absolutePoint(div_panel)
with(div_items.style) {
left = p[0] + "px"
top = p[1] + "px"
width = div_panel.clientWidth
height = div_panel.clientHeight
}
/**
* 界面改变
*/
function doChange() {
if (!item_height) return
var i, div
if (height != div_panel.clientHeight) {
height = div_panel.clientHeight
view_count = parseInt(height / item_height)
for (i = div_items_list.lengthi <view_counti++) {
div = $C("div")
div.className = "item" + (i % 2 == 0 ? "" : " odd")
div_items.appendChild(div)
div_items_list.push(div)
}
for (i = 0i <div_items_list.lengthi++) {
div_items_list[i].style.display = i <view_count ? "" : "none"
}
div_scroll.style.height = div_panel.clientHeight + options.count - view_count + "px"
console.log(["view_count", view_count])
}
div_items.scrollLeft = div_panel.scrollLeft
if (!options.ondrawitem) return
i = Math.min(view_count, div_items_list.length)
while(i--) {
// 重新绘制
options.ondrawitem(i + div_panel.scrollTop, div_items_list[i])
}
}
doChange()
this.doChange = doChange
/**
* 释放Dom对象
*/
this.dispose = function() {
var i = freed.length
while(i--) {
freed[i].parentNode.removeChild(freed[i])
}
i = freed.length
while(i--) {
div_items_list[i].parentNode.removeChild(div_items_list[i])
}
}
}
function format(template, json) {
if (!json) return template
return template &&template.replace(/\$\{(.+?)\}/g, function() {
return json[arguments[1]]
})
}
window.onload = function() {
var i = 100000, data = new Array(i)
while(i--) {
data[i] = { index: i, random: Math.random(), key: (+new Date()).toString(36) }
}
var listview = new ListView({
count: data.length,
ondrawitem: function(i, div) {
div.innerHTML = format(" <em>${index} </em> <span class=\"red\">${random} </span> <span class=\"green\">${key} </span>", data[i])
}
})
}
</script>
为什么页面会卡顿呢,以60Hz为例,即一秒钟的动画就是由60张静态图片连在一起。60fps是动画播放比较理想、比较基础的要求,windows系统有个刷新频率也是这个意思。60fps就要求一帧的时间为1s/60=16.67ms。浏览器显示页面的时候,要处理js逻辑,还要做渲染,每个执行片段的时间不能超过16.67ms。实际上,浏览器内核自身支撑体系运行也需要消耗一些时间,所以留给我们的时间差不多只有10ms。并且在处理js计算时,浏览器不会响应用户的操作,所以就造成了页面“假死”。 Web Work,就是为JavaScript创造多线程环境,允许主线程创建Web Worker线程,将一些任务分配给后台运行。在主线程运行的同事,Work线程在后台运行,两者互不干扰。等到Work线程完成计算任务再把结果返回给主线程。这样的好处是,一些密集或者高延迟的计算任务,被Work线程给分担了,这样主线程就会很流程。 Worker线程一旦创建成功,就会始终运行,不会被主线程上的活动打断取消。这样有利于随时响应主线程的通信。但是,这也造成了Worker比较耗费资源,不应该过度使用,所以一旦使用完毕,就应该关闭。 1.同源限制:分配给Worker线程运行的脚本文件,必须与主线程的脚本文件同源。 2.DOM限制:Work线程所在的全局对象和主线程不一样,所以无法读取主线程所在网页的DOM对象,也无法使用document,window,parent这些对象。但是可以使用navigator和location。 3.通信联系:Worker线程和主线程不在同一个上下文环境,他们不能直接通信,必须通过消息完成。 4.脚本限制:Worker线程不能执行alert和confirm方法,但是可以使用XMLHttpRequest对象发出的AJAX请求。 5.文件限制:Work线程不能读取本地文件,它所加载的脚本必须来自网络。