学习笔记

学习笔记

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.scrollWidth0)
// 滚动到页面右侧

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、开始比较之前,先了解一些基本的知识,比如说如何获取某个元素的尺寸大小、滚动条滚动距离及偏移位置距离; img

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、知道如何获取元素尺寸、偏移距离后,接下来一个问题就是:如何判断某个元素进入或者即将进入可视窗口区域?下面也通过一张图来说明问题。

img

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);

五、参考:

1、jQuery.lazyload详解

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

6、Lazyload 延迟加载效果

7、图片延迟加载(lazyload)的实现原理

总结:懒加载的原理,界面初始化时,显示上面的图片。下面的图片没有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

https://lernajs.io/

主要功能:将多个依赖包完美的组合在一个引用中。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}/>
第二, 用它的onChange方法获得file onChange(e){ const file = e.target.files[0] if(file) dispatch({ type:'upload', file }) e.target.value = '' // 上传之后还原 } 第三,样式调整 为了不使用简陋的原生html上传按钮, 用style={{display:’none’}}隐藏原生input,

然后再自己写一个美丽的上传按钮,它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的大版本目标是什么。

  • 关键的是,写下十件事情,然后选择最重要的三件事情(大事),把这部分做完。自己很多情况下主次不分。一定丢弃自己两年内没有穿的衣服,两年内没有看过的书籍资料,敢于放弃才能获取新的东西,这样自己才能提高。这部分东西不是财富,而是累赘。
  • 你有多聪明也不是主要原因,决定因素是你的自信程度。一个人把精力集中在自己所能做的,知道的和拥有的东西上的那一天起,他的成功就已经拉开了序幕。——如果是自己不知道的部分,又是必须知道的事情,那么就尝试知道这部分。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值