学习笔记
1、自定义滚动条(与CSDN上相同, 2022-06-07)
1.1 设置滚动条的经过显示
设置常规的滚动条:使用 overflow:auto。父元素需要设置一个高度,设置相对定位,这样子元素的高度大于父元素高度才能显示滚动条。如果父元素的高度完全由子元素撑开,界面上不会出现滚动条。设置overflow:auto 失效的主要问题:可能是这个div没有设置高度 100% 然后父元素清除浮动 (float:none; position: relative;)
设置鼠标经过显示的滚动条:预设值盒子是 overflow: hidden。鼠标经过盒子,设置盒子 overflow: auto。这样鼠标不经过时不会显示滚动条。缺点:如果盒子内部有文字,盒子的宽度变化可能造成文字的重新排版,视觉上不好看(内部文字可以使用一个固定宽度实现-但是这样在适配屏幕宽度时不合适——适配屏幕必然会导致文字的重新排版)。
实际工作中,用这两种实现比较多(实现界面滚动)完全自定义滚动条情况不多。
div {
overflow: hidden;
}
div:hover {
overflow: auto;
}
设置界面可以滚动但是不显示滚动条:
方法一:设置滚动条的样式(在webkit内核的浏览器比较适合)这样可以同时设置滚动条的宽度和颜色
div::-webkit-scrollbar {
width: 0;
}
方法二:右侧元素设置宽度或者定位,将左侧元素的滚动条遮挡。这样的方法不入流,在移动端兼容不好实现。
div {
float: right;
width: 32%
}
div {
float: left;
width: 70%;
}
使用JS方法控制滚动条的显示隐藏(使用jquery)
<body>
<div id='wrapper'>
...
...
</div>
</body>
body{
overflow: hidden; /* 隐藏原有的滚动条 */
}
#wrapper{
width: 1940px;
/* 宽度,通常浏览页面是1920px ,根据实际状况做调整,通常滚动条为20px,大于20即可隐藏 */
height: 1000px;
overflow-y: scroll; /* 创建新的滚动条*/
padding-right: 20px; /* 滚动条右边距 */
}
var topValue = 0
interval = null;// 定时器
jQuery('#wrapper').scroll(function(){
if(interval == null){// 未发起时,启动定时器,1秒1执行
interval = setInterval(function(){
// 判断是否滚动
if(jQuery('#wrapper').scrollTop()== topValue){
clearInterval(interval);
interval = null;
// 没有滚动,则隐藏,padding边距,根据开发状况修改,此处是为了,不影响之前的css,width同理,通常是1940px,达到滚动条隐藏效果
jQuery("#wrapper").css({width:'1940px',padding:'0px 20px 0px 0px'})
}
}, 1000);
}
topValue = jQuery('#wrapper').scrollTop();
//滚动,则显示,padding边距,根据开发状况修改,此处是为了,不影响之前的css,width同理,通常是1940px,达到滚动条隐藏效果
jQuery("#wrapper").css({width:'1920px',padding:'0px 0px 0px 0px'})
});
1.2 滚动条的样式设置
改变浏览器默认的滚动条的颜色和样式,使用伪元素改变某个DIV上面的滚动条
::-webkit-scrollbar //滚动条整体部分
::-webkit-scrollbar-button //滚动条两端的按钮
::-webkit-scrollbar-track // 外层轨道
::-webkit-scrollbar-track-piece //内层轨道,滚动条中间部分(除去)
::-webkit-scrollbar-thumb //滚动条里面可以拖动的那个
::-webkit-scrollbar-corner //边角
::-webkit-resizer ///定义右下角拖动块的样式
http://www.xuanfengge.com/demo/201311/scroll/css3-scroll.html
这是不同颜色滚动条的demo
/*定义滚动条高宽及背景:高宽分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar {
width:16px;
height:16px;
background-color:#F5F5F5;
}
/*定义滚动条轨道:内阴影+圆角*/
::-webkit-scrollbar-track {
-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.3);
border-radius:10px;
background-color:#F5F5F5;
}
/*定义滑块:内阴影+圆角*/
::-webkit-scrollbar-thumb {
border-radius:10px;
-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,.3);
background-color:#555;
}
:horizontal//适用于任何水平方向上的滚动条
:vertical//适用于任何垂直方向的滚动条
:decrement//适用于按钮和轨道碎片。表示递减的按钮或轨道碎片,例如可以使区域向上或者向右移动的区域和按钮
:increment//适用于按钮和轨道碎片。表示递增的按钮或轨道碎片,例如可以使区域向下或者向左移动的区域和按钮
:start//适用于按钮和轨道碎片。表示对象(按钮轨道碎片)是否放在滑块的前面
:end //适用于按钮和轨道碎片。表示对象(按钮轨道碎片)是否放在滑块的后面
:double-button//适用于按钮和轨道碎片。判断轨道结束的位置是否是一对按钮。也就是轨道碎片紧挨着一对在一起的按钮。
:single-button//适用于按钮和轨道碎片。判断轨道结束的位置是否是一个按钮。也就是轨道碎片紧挨着一个单独的按钮。
:no-button//表示轨道结束的位置没有按钮。
:corner-present//表示滚动条的角落是否存在。
:window-inactive//适用于所有滚动条,表示包含滚动条的区域,焦点不在该窗口的时候。
IE 早期浏览器设置:https://www.cnblogs.com/koleyang/p/5484922.html
5、内存泄漏
传统内存泄漏:闭包造成了内部变量无法释放,造成内存泄漏(某些变量和函数始终占用内存,GC无法清空内存,内存泄漏)
React 内存泄漏:通常是 setTimeout 或者 setInterval 中实行函数,或者 setState 等异步操作,造成组件卸载时,还有未执行的代码,造成的内存泄漏。
解决:在 componentWillUNmount 中清理定时器和属性,避免无效 setState 等。
6、界面中插入txt文件
两种情况:界面中直接插入可以编辑的字符串(markdown或者txt文本),直接在前端进行读取;或者上传文件到服务器,然后读取服务器中的内容。其中的第二种情况是问题7解决。
这里使用JS的方法
<input type="file" accept="img/jpg, txt/plain" onChange={this.handleUpload}></input>
这里可以选择上传文件的文件类型,在HTML标签中进行设定,这样避免上传一些不合法的文件或者CSRF攻击。这个属性在FF和chrome中有效。文件类型的验证最好在上传后或者JS代码进行二次验证。
值 | 描述 |
---|---|
audio/* | 接受所有的声音文件。 |
video/* | 接受所有的视频文件。 |
image/* | 接受所有的图像文件。 |
MIME_type | 一个有效的 MIME 类型,不带参数。 |
可以查看文章:
https://blog.csdn.net/u013379933/article/details/77119796 http://www.iana.org/assignments/media-types/
function handleUpload(event) {
const file = event.target.files[0];
// 获取上传的文件数组的第一个文件
if (file.size) {
// 首先判断文件是否有内容
let reader = new FileReader();
reader.readAsText(file);
// 按照text文件进行读取文件
reader.onload = (resultFile) => {
let pointsTxt = resultFile.target.result;
console.log(pointsTxt);
// 继续处理,显示在界面上或者其他方式
};
}
}
// arrow function in ES6
handleUpload = (event) => {
const file = event.target.files[0]; // if update several files, use for-in circle to get
if (file.size) {
let reader = new FileReader();
reader.readAsText(file);
reader.onload = (result) => {
let resultText = result.target.result;
console.log(resultText);
};
}
}
这里的关键就是FileReader,可以查看标准的解释
https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader
6.1 FileReader 对象说明
1、作用:可以使用 JS 异步读取本地文件
// 创建对象
let reader = new FileReader();
// 获取本地文件两种情况:input 元素对应的 FileList 对象;拖放操作生成的 DataTransfer 对象;
const file = event.target.files[0];
// 将本地文件放在对象中(传入的对象是一个Blob对象)
reader.readAsText(file);
// 读取过程是异步的,所以有不同的状态码(类似于Ajax)
属性(只读)
FileReader.error
// 出错时的属性
FileReader.readyState
// 上传过程属性,012
FileReader.result
// 上传结果
常用事件
onabort 中断上传事件
onerror 错误上传事件
onload 上传完成事件(最常用)
onprogress 上传过程中事件
方法:将Blob对象按照不同的方式进行读取;在事件 FileReader.onload = function(event){ event.targte.result } 中进行获取转化后的文本。
这里将一个 markdown 文件以四种方式进行上传(同样,使用zipjs进行压缩需要考虑不同类型的编码形式,解码时需要对应的解码形式。不同的文件使用不同的解码形式)
FileReader.readAsArrayBuffer()
开始读取指定的Blob中的内容, 一旦完成, result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象。ArrayBuffer 类型化数组,类型化数组是JavaScript操作二进制数据的一个接口。最初为了满足JavaScript与显卡之间大量的、实时的数据交换,它们之间的数据通信必须是二进制的,而不能是传统的文本格式的背景下诞生的。
FileReader.readAsBinaryString()
开始读取指定的Blob中的内容。result 属性中将包含所读取文件的原始二进制数据。
FileReader.readAsDataURL()
开始读取指定的 BLOB中的内容。result 属性中将包含一个 data URL格式的字符串以表示所读取文件的内容。
通常使用这个模式处理图片上传,例子:https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/readAsDataURL#javascript
FileReader.readAsText()
开始读取指定的 Blob 中的内容。result 属性中将包含一个字符串以表示所读取的文件内容。这是最常用的txt上传数据类型。
通常使用这模式上传简单文本文件(txt markdown 文件等)
7、文件上传到服务器
参考这篇博客 阮一峰的5个方案
https://blog.csdn.net/weixin_41697143/article/details/86219954
8、上传文件按钮很难看的修改方案
基本思路:使用一个DIV进行包裹,然后设置input的样式是 opacity:0,设置这个按钮位于原始按钮上面,点击这个按钮仍然可以触发上传。(如果是下拉菜单中,需要避免事件向上冒泡的其他后果)。
.a-upload {
padding: 4px 10px;
height: 20px;
line-height: 20px;
position: relative;
cursor: pointer;
color: #888;
background: #fafafa;
border: 1px solid #ddd;
border-radius: 4px;
overflow: hidden;
display: inline-block;
*display: inline;
*zoom: 1
}
.a-upload input {
position: absolute;
font-size: 100px;
right: 0;
top: 0;
opacity: 0;
filter: alpha(opacity=0);
cursor: pointer;
}
.a-upload:hover {
color: #444;
background: #eee;
border-color: #ccc;
text-decoration: none;
}
9、界面滚动问题
React setState 是异步操作,如果需要获取界面上 DOM 的尺寸,需要在回调函数中获取。直接获取不到正确的尺寸。
this.setState({
commentsList: res.data.commentsList
}, () => {
this.commentRightPanelRef.current.scrollTo(0, 10000);
});
界面滚动的 API
ScrollTo 表示滚动到指定的坐标(100, 100), ScrollBy 表示滚动多少坐标,向左滚动100px,向右滚动 100px。scroll 主要使用与滚动的结果确定(滚动到底部,上部,中部等等),scrollBy主要适应于用户点击按钮,界面向下滚动100px。
window.scroll(0,document.body.scrollHeight)
// 滚动到页面最底部
window.scrollBy(document.body.scrollWidth,0)
// 滚动到页面右侧
window.scrollTo(document.body.scrollWidth/2,document.body.scrollHeight/2)
// 滚动到水平和垂直居中位置
10、懒加载
图片懒加载
https://www.cnblogs.com/flyromance/p/5042187.html
界面懒加载(列表)
1.引用
<script src="http://a.tbcdn.cn/apps/baron/js/??lib/tmm/tmm.js,lib/lazyload/lazyload.js?20121015"></script>
2.对于要懒加载的图片进行如下属性设置。
其中src为未加载时的图片,dataimg为实际要加载的图片。
3.执行lazyload.init();
4.分tab的懒加载。判断tab把下面的图片有没加载过。根据loaded属性判断,还要对非当前tab所属的图片进行class lazy去掉。对已加载的loaded为true的图片,不加lazy属性
5.注意lazyload.init()的执行时机,如果在dom ready阶段执行,会下载所有图片,不能实现懒加载。要在winow.onload完成这个阶段去执行。
lazyload.js代码解读:
/**
* 基于jQuery或者zeptoJS的惰性加载
*/
var lazyload = {
init : function(opt){
var that = this;
var op = {
anim: true,
extend_height:400
};
// 合并对象,已有的{anim:true}+用户自定义对象。也就是op = op + opt
$.extend(op,opt);
// 调用lazyload.img.init(op)函数
that.img.init(op);
},
img : {
init : function(n){
var that = this;
// 要加载的图片是不是在指定窗口内
function inViewport( el ) {
// 当前窗口的顶部
var top = window.pageYOffset
// 当前窗口的底部
var btm = window.pageYOffset + window.innerHeight
// 元素所在整体页面内的y轴位置
var elTop = $(el).offset().top;
// 判断元素,是否在当前窗口,或者当前窗口延伸400像素内
return elTop >= top && elTop - n.extend_height <= btm
}
// 滚动事件里判断,加载图片
$(window).bind('scroll', function() {
$('img.lazy').each(function(index,node) {
var $this = $(this)
if(!$this.attr('dataimg')){
return
}
if ( !inViewport(this) ) return
act($this)
})
}).trigger('scroll')
// 展示图片
function act(_self){
// 已经加载过了,则中断后续代码
if (_self.attr('loaded')) return;
var img = new Image(), original = _self.attr('dataimg')
// 图片请求完成后的事件,把dataimg指定的图片,放到src里面,浏览器显示
img.onload = function() {
_self.attr('src', original).removeClass('lazy');
n.anim && _self.css({ opacity: .2 }).animate({ opacity: 1 }, 280);
}
// 当你设置img.src的时候,浏览器就在发送图片请求了
original && (img.src = original);
_self.attr('loaded', true);
}
}
}
};
添加用例
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>懒加载实例</title>
<style type="text/css">
/*一定要有预先高度*/
img{
width: 600px;
height: 260px;
}
</style>
</head>
<body>
<div>
<img class="samLazyImg" src="http://a.tbcdn.cn/mw/webapp/fav/img/grey.gif" dataimg="http://yangege.b0.upaiyun.com/11de79502d0af.jpg!v1sell" alt="" />
</div>
<div>
<img class="samLazyImg" src="http://a.tbcdn.cn/mw/webapp/fav/img/grey.gif" dataimg="http://yangege.b0.upaiyun.com/33f99f823ed3d.jpg!v1sell" alt="" />
</div>
<div>
<img class="samLazyImg" src="http://a.tbcdn.cn/mw/webapp/fav/img/grey.gif" dataimg="http://yangege.b0.upaiyun.com/680120973b82.jpg!v1sell" alt="" />
</div>
<div>
<img class="samLazyImg" src="http://a.tbcdn.cn/mw/webapp/fav/img/grey.gif" dataimg="http://yangege.b0.upaiyun.com/67f87ba08cf0.jpg!v1sell" />
</div>
<div>
<img class="samLazyImg" src="http://a.tbcdn.cn/mw/webapp/fav/img/grey.gif" dataimg="http://yangege.b0.upaiyun.com/22ec075a17c33.jpg!v1sell" alt="" />
</div>
<div>
<img class="samLazyImg" src="http://a.tbcdn.cn/mw/webapp/fav/img/grey.gif" dataimg="http://yangege.b0.upaiyun.com/2e4a699680788.jpg!v1sell" alt="" />
</div>
<div>
<img class="samLazyImg" src="http://a.tbcdn.cn/mw/webapp/fav/img/grey.gif" dataimg="http://yangege.b0.upaiyun.com/c2f4043a4991.jpg!v1sell" alt="" />
</div>
<div>
<img class="samLazyImg" src="http://a.tbcdn.cn/mw/webapp/fav/img/grey.gif" dataimg="http://yangege.b0.upaiyun.com/33f996b4386ab.jpg!v1sell" alt="" />
</div>
</body>
<script src="jquery-2.1.4.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
var lazyload = {
init : function(opt){
var that = this,
op = {
anim: true,
extend_height:0,
selectorName:"img",
realSrcAtr:"dataimg"
};
// 合并对象,已有的{anim:true}+用户自定义对象。也就是op = op + opt
$.extend(op,opt);
// 调用lazyload.img.init(op)函数
that.img.init(op);
},
img : {
init : function(n){
var that = this,
selectorName = n.selectorName,
realSrcAtr = n.realSrcAtr,
anim = n.anim;
// console.log(n);
// 要加载的图片是不是在指定窗口内
function inViewport( el ) {
// 当前窗口的顶部
var top = window.pageYOffset,
// 当前窗口的底部
btm = window.pageYOffset + window.innerHeight,
// 元素所在整体页面内的y轴位置
elTop = $(el).offset().top;
// 判断元素,是否在当前窗口,或者当前窗口延伸400像素内
return elTop >= top && elTop - n.extend_height <= btm;
}
// 滚动事件里判断,加载图片
$(window).on('scroll', function() {
$(selectorName).each(function(index,node) {
var $this = $(this);
if(!$this.attr(realSrcAtr) || !inViewport(this)){
return;
}
act($this);
})
}).trigger('scroll');
// 展示图片
function act(_self){
// 已经加载过了,则中断后续代码
if (_self.attr('lazyImgLoaded')) return;
var img = new Image(),
original = _self.attr('dataimg');
// 图片请求完成后的事件,把dataimg指定的图片,放到src里面,浏览器显示
img.onload = function() {
_self.attr('src', original);
anim && _self.css({ opacity: .2 }).animate({ opacity: 1 }, 280);
};
// 当你设置img.src的时候,浏览器就在发送图片请求了
original && (img.src = original);
_self.attr('lazyImgLoaded', true);
}
}
}
};
/*
* selectorName,要懒加载的选择器名称
* extend_height 扩展高度
* anim 是否开启动画
* realSrcAtr 图片真正地址*/
lazyload.init({
anim:false,
selectorName:".samLazyImg"
});
</script>
</html>
10.1 滚动加载图片(懒加载)实现原理
一、什么是图片滚动加载?
通俗的讲就是:当访问一个页面的时候,先把img元素或是其他元素的背景图片路径替换成一张大小为1*1px图片的路径(这样就只需请求一次),只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来。这就是图片懒加载。
二、为什要使用这个技术?
比如一个页面中有很多图片,如淘宝、京东首页等等,如果一上来就发送这么多请求,页面加载就会很漫长,如果js文件都放在了文档的底部,恰巧页面的头部又依赖这个js文件,那就不好办了。更为要命的是:一上来就发送百八十个请求,服务器可能就吃不消了(又不是只有一两个人在访问这个页面)。
因此优点就很明显了:不仅可以减轻服务器的压力,而且可以让加载好的页面更快地呈现在用户面前(用户体验好)。
三、怎么实现?
关键点如下:
1、页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片(也就没有请求咯,也就提高性能咯),一旦通过javascript设置了图片路径,浏览器才会送请求。有点按需分配的意思,你不想看,就不给你看,你想看了就给你看~
2、如何获取正真的路径,这个简单,现在正真的路径存在元素的“data-url”(这个名字起个自己认识好记的就行)属性里,要用的时候就取出来,再设置;
3、开始比较之前,先了解一些基本的知识,比如说如何获取某个元素的尺寸大小、滚动条滚动距离及偏移位置距离;
1)屏幕可视窗口大小:对应于图中1、2位置处
原生方法:window.innerHeight 标准浏览器及IE9+ || document.documentElement.clientHeight 标准浏览器及低版本IE标准模式 ||
document.body.clientHeight 低版本混杂模式
jQuery方法: $(window).height()
2)浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离:也就是图中3、4处对应的位置;
原生方法:window.pagYoffset——IE9+及标准浏览器 || document.documentElement.scrollTop 兼容ie低版本的标准模式 ||
document.body.scrollTop 兼容混杂模式;
jQuery方法:$(document).scrollTop();
3)获取元素的尺寸:对应于图中5、6位置处;左边jquery方法,右边原生方法
$(o).width() = o.style.width;
$(o).innerWidth() = o.style.width+o.style.padding;
$(o).outerWidth() = o.offsetWidth = o.style.width+o.style.padding+o.style.border;
$(o).outerWidth(true) = o.style.width+o.style.padding+o.style.border+o.style.margin;
注意:要使用原生的style.xxx方法获取属性,这个元素必须已经有内嵌的样式,如
如果原先是通过外部或内部样式表定义css样式,必须使用o.currentStyle[xxx] || document.defaultView.getComputedStyle(0)[xxx]来获取样式值
4)获取元素的位置信息:对应与图中7、8位置处
1)返回元素相对于文档document顶部、左边的距离;
jQuery:(o).offset().top元素距离文档顶的距离,(o).offset().left元素距离文档左边缘的距离
原生:getoffsetTop(),高程上有具体说明,这边就忽略了;
顺便提一下返回元素相对于第一个以定位的父元素的偏移距离,注意与上面偏移距的区别;
jQuery:position()返回一个对象,(o).position().left = style.left,(o).position().top = style.top;
4、知道如何获取元素尺寸、偏移距离后,接下来一个问题就是:如何判断某个元素进入或者即将进入可视窗口区域?下面也通过一张图来说明问题。
1)外面最大的框为实际页面的大小,中间浅蓝色的框代表父元素的大小,对象1~8代表元素位于页面上的实际位置;以水平方向来做如下说明!
2)对象8左边界相对于页面左边界的偏移距离(offsetLeft)大于父元素右边界相对于页面左边界的距离,此时可判读元素位于父元素之外;
3)对象7左边界跨过了父元素右边界,此时:对象7左边界相对于页面左边界的偏移距离(offsetLeft)小于 父元素右边界相对于
页面左边界的距离,因此对象7就进入了父元素可视区;
4)在对象6的位置处,对象5的右边界与页面左边界的距离 大于 父元素左边界与页面左边界的距离;
5)在对象5位置处时,对象5的右边界与页面左边界的距离 小于 父元素左边界与页面左边界的距离;此时,可判断元素处于父元素可视区外;
6)因此水平方向必须买足两个条件,才能说明元素位于父元素的可视区内;同理垂直方向也必须满足两个条件;具体见下文的源码;
四、扩展为jquery插件
使用方法:$("selector").scrollLoad({ 参数在代码中有说明 }
(function($) {
$.fn.scrollLoading = function(options) {
var defaults = {
// 在html标签中存放的属性名称;
attr: "data-url",
// 父元素默认为window
container: window,
callback: $.noop
};
// 不管有没有传入参数,先合并再说;
var params = $.extend({}, defaults, options || {});
// 把父元素转为jquery对象;
var container = $(params.container);
// 新建一个数组,然后调用each方法,用于存储每个dom对象相关的数据;
params.cache = [];
$(this).each(function() {
// 取出jquery对象中每个dom对象的节点类型,取出每个dom对象上设置的图片路径
var node = this.nodeName.toLowerCase(), url = $(this).attr(params["attr"]);
//重组,把每个dom对象上的属性存为一个对象;
var data = {
obj: $(this),
tag: node,
url: url
};
// 把这个对象加到一个数组中;
params.cache.push(data);
});
var callback = function(call) {
if ($.isFunction(params.callback)) {
params.callback.call(call);
}
};
//每次触发滚动事件时,对每个dom元素与container元素进行位置判断,如果满足条件,就把路径赋予这个dom元素!
var loading = function() {
// 获取父元素的高度
var contHeight = container.outerHeight();
var contWidth = container.outerWidth();
// 获取父元素相对于文档页顶部的距离,这边要注意了,分为以下两种情况;
if (container.get(0) === window) {
// 第一种情况父元素为window,获取浏览器滚动条已滚动的距离;$(window)没有offset()方法;
var contop = $(window).scrollTop();
var conleft = $(window).scrollLeft();
} else {
// 第二种情况父元素为非window元素,获取它的滚动条滚动的距离;
var contop = container.offset().top;
var conleft = container.offset().left;
}
$.each(params.cache, function(i, data) {
var o = data.obj, tag = data.tag, url = data.url, post, posb, posl, posr;
if (o) {
//对象顶部与文档顶部之间的距离,如果它小于父元素底部与文档顶部的距离,则说明垂直方向上已经进入可视区域了;
post = o.offset().top - (contop + contHeight);
//对象底部与文档顶部之间的距离,如果它大于父元素顶部与文档顶部的距离,则说明垂直方向上已经进入可视区域了;
posb = o.offset().top + o.height() - contop;
// 水平方向上同理;
posl = o.offset().left - (conleft + contWidth);
posr = o.offset().left + o.width() - conleft;
// 只有当这个对象是可视的,并且这四个条件都满足时,才能给这个对象赋予图片路径;
if ( o.is(':visible') && (post < 0 && posb > 0) && (posl < 0 && posr > 0) ) {
if (url) {
//在浏览器窗口内
if (tag === "img") {
//设置图片src
callback(o.attr("src", url));
} else {
// 设置除img之外元素的背景url
callback(o.css("background-image", "url("+ url +")"));
}
} else {
// 无地址,直接触发回调
callback(o);
}
// 给对象设置完图片路径之后,把params.cache中的对象给清除掉;对象再进入可视区,就不再进行重复设置了;
data.obj = null;
}
}
});
};
//加载完毕即执行
loading();
//滚动执行
container.bind("scroll", loading);
};
})(jQuery);
五、参考:
2、张大大:http://www.zhangxinxu.com/wordpress/?p=1259
3、Jquery图片延迟加载插件jquery.lazyload. http://www.daxueit.com/article/3944.html 4、jQuery.lazyload实现延时加载详解步骤 http://www.daxueit.com/article/21.html 5、jquery lazyload延迟加载技术的实现原理分析 http://www.daxueit.com/article/3777.html
总结:懒加载的原理,界面初始化时,显示上面的图片。下面的图片没有src属性,所以暂时不发送请求显示图片。等界面向下滚动时,获取当前滚动的位置和图片的位置,使用js将图片的其他属性中的src加入到src路径中,此时发出请求,界面加载图片。通常的库是JQ,原生的JS实现也需要掌握。
11、文件拖动
http://www.w3school.com.cn/html5/html_5_draganddrop.asp
12、文档碎片-Fragment
Fragment 这里的Fragment不是React中的Fragment,是DOM中的 Fragment 对象。这是一个DOM元素,不包括完整的DOM树结构。
https://developer.mozilla.org/zh-CN/docs/Web/API/DocumentFragment
let fragment = document.createDocumentFragment();
主要作用:
用于复制粘贴是DOM碎片的临时存储;
用于界面增删大量文本的中转。
例如:界面中依次添加100个节点,那么直接appendChild 就会频繁重绘界面,造成性能浪费。此时可以使用这个Fragment暂时存放,然后统一渲染到页面节点上,提高10%——30%的性能。
**文档片段**接口,表示一个没有父级文件的最小文档对象。它被作为一个轻量版的 Document
使用,用于存储已排好版的或尚未打理好格式的XML片段。最大的区别是因为 DocumentFragment 不是真实DOM树的一部分,它的变化不会触发 DOM 树的(重新渲染) ,且不会导致性能等问题。
13、恢复删除的分支
删除分支 git branch -d fix-bug
强制删除分支 git branch -D fix-bug
恢复误删的分支原理:任何一个分支中,只要提交就会创建一个hash值对应。删除分支仅仅删除一个指针,实际上还存在这个提交。注意:如果一个分支上有未提交的代码,那么这个分支删除后,未提交的代码不会找回来。
# 列出删除分支的最后提交
git reflog
git branch fix-bug hash
# 从某次提交中复原分支fix-bug
15、lerna.js
主要功能:将多个依赖包完美的组合在一个引用中。Lerna is a tool that optimizes the workflow around managing multi-package repositories with git and npm.
16、软件设计原则 GRASP
https://blog.csdn.net/weixin_41697143/article/details/88773925
17、React中的fetch
第一,使用原生input的type=”file”
<input type="file" name="file" onChange={this.onChange} style={{display:'none'}} ref={this.inputRef}/>
然后再自己写一个美丽的上传按钮,它onClick的时候, 调用原生input的引用,手动触发click, 像这样:
this.inputRef.click() 就相当于点击了原生按钮
第四,设置好body 用上刚才的file变量, 创建一个FormData,
append上去, 这里的formData就是fetch的body
const formData = new FormData()
formData.append('file', file)
// 最后 执行fetch 记得改content-type
"Content-Type": "multipart/form-data",
fetch(url,{
method :"POST",
body: formData,
headers:{
"Content-Type": "multipart/form-data"
}
})
18、浏览器消耗性能分析
火狐浏览器消耗内存最小,chrome 消耗内存较大性能好,Safari 在苹果电脑上最兼容。
2022-06
- CSS自定义滚动条(鼠标经过显示滚动条等,设置父盒子和子盒子的高度,父盒子固定,子盒子较大,然后就显示了滚动条;或者鼠标经过改变overflow)
- React 内存溢出(什么情况溢出,怎么避免)
- 如何实现拖拽上传文件(设置一个DIV监听事件,监听 dragEnter dragOver dragLeave 拖拽事件,然后改变 div 的样式表示可以释放)监听 onDrop 释放事件,通过事件对象获取拖拽的文件,然后调用 FileReader 读到 JS 中并上传文件。FileReader 对象处理读取文件和上传文件。不同的文件类型,使用不同的编码方式解析。普通文本文件,使用 fileReader.readAsText 进行解析,结果是字符串。如果是多媒体文件,那么是二进制文件流,使用 readAsArrayBuffer 解析,例如 mp3 文件。如果是图片文件,也是二进制文件流,使用 readAsDataUrl 解析文件,结果是二进制数据。
- 百度文库:实现不能复制的技术,可能是先实现节点,然后 htmltocanvas 转换成canvas避免了浏览器节点打开复制文本内容。
-
如果dom结构变化了,也就是层级变化了,那么自组件必然重新卸载重新渲染。如果 dom结构不变,仅仅改变props,这样组件会receive props,然后执行will update函数,就是组件的更新。这个问题需要注意。可能 react-dnd 内部组件重新渲染和这个问题也是有关的。
-
那就是只有在你真的愿意的情况下,我才帮得了你。就像一个赏心悦目的大房子,真的是住的舒服(比现在的小破地方舒服多了),那么自己在室内锻炼就有地方了。梦想相册中的梦想,问问自己现在是否还要这么大的动力;自信罐罐需要再写起来,很多事情每天坚持做很重要(健身,阅读等)不管顺境还是逆境,这些事情都要坚持去做。如果迷茫或者懈怠时,看看经典书籍。看一下整体7的大版本目标是什么。
- 关键的是,写下十件事情,然后选择最重要的三件事情(大事),把这部分做完。自己很多情况下主次不分。一定丢弃自己两年内没有穿的衣服,两年内没有看过的书籍资料,敢于放弃才能获取新的东西,这样自己才能提高。这部分东西不是财富,而是累赘。
- 你有多聪明也不是主要原因,决定因素是你的自信程度。一个人把精力集中在自己所能做的,知道的和拥有的东西上的那一天起,他的成功就已经拉开了序幕。——如果是自己不知道的部分,又是必须知道的事情,那么就尝试知道这部分。