WS的博客日志

奔赴山海,保持热爱

Observer观察器

  • IntersectionObserver

    ​ 过去,相交检测通常要用到事件监听,并且需要频繁调用 Element.getBoundingClientRect() 方法以获取相关元素的边界信息。事件监听和调用 Element.getBoundingClientRect() 都是在主线程上运行,因此频繁触发、调用可能会造成性能问题。这种检测方法极其怪异且不优雅。

    ​ Intersection Observer API 会注册一个回调函数,每当被监视的元素进入或者退出另外一个元素时 (或者 viewport ),或者两个元素的相交部分大小发生变化时,该回调方法会被触发执行。这样,我们网站的主线程不需要再为了监听元素相交而辛苦劳作,浏览器会自行优化元素相交管理。

    应用场景:

    • 图片懒加载——当图片滚动到可见时才进行加载
  • 内容无限滚动——也就是用户滚动到接近内容底部时直接加载更多,而无需用户操作翻页,给用户一种网页可以无限滚动的错觉

    • 检测广告的曝光情况——为了计算广告收益,需要知道广告元素的曝光情况
    • 在用户看见某个区域时执行任务或播放动画
  • MutationObserver

    监听一个普通 JS 对象的变化,我们会用 Object.defineProperty 或者 Proxy。

    监听元素属性和子节点变化,比如可以用来做去不掉的水印。MutationObserver 可以监听对元素的属性的修改、对它的子节点的增删改

  • ResizeObserver

    窗口我们可以用 addEventListener 监听 resize 事件。

    监听元素大小变化。使用 ResizeObserver 监听大小的改变,当 width、height 被修改时会触发回调

  • PerformanceObserver

    PerformanceObserver 用于监听记录 performance 数据的行为。一旦记录了就会触发回调,这样我们就可以在回调里把这些数据上报

  • ReportingObserver

    可以保证更全面的了解网页 app 的运行情况。ReportingObserver 可以监听过时的 api、浏览器干预等报告等的打印,在回调里上报,这些是错误监听无法监听到但对了解网页运行情况很有用的数据

跨平台调试

  • Vconsole

  • Eruda

  • window下调试 iOS-Safari

    实现真机调试主要是使用了 remotedebug-ios-webkit-adapter

    1
    2
    3
    4
    安装scoopeWindows 命令行安装工具

    Set-ExecutionPolicy RemoteSigned -scope CurrentUser
    iex (new-object net.webclient).downloadstring('https://get.scoop.sh')
    1
    2
    3
    4
    5
    scoop bucket add extras
    scoop install ios-webkit-debug-proxy
    npm install -g vs-libimobile

    npm install remotedebug-ios-webkit-adapter -g
    1. 进入 iPhone 中的 设置 > Safari 浏览器 > 高级 > Web 检查器,开启该选项。
    2. 打开 iTunes 并连接 iPhone,在 iPhone 弹框中选择信任该电脑。
    3. 打开命令行,执行以下命令,启动适配器:
    1
    remotedebug_ios_webkit_adapter --port=9000
    1. 在 iPhone 中打开 Safari 浏览器,打开待调试页面。
    2. 打开 Chrome 浏览器,进入 chrome://inspect/#devices 页面,在 Discover network targets 选项添加 localhost:9000 配置。刷新页面,这时页面中会出现 ‘Remote Target’ 列表,该列表展示了 iPhone 中打开的页面,点击 inspect,即可进行调试。(科学上网/edge)
阅读全文 »

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,因其简洁、易读、易于解析的特点,在前后端数据交互、API 设计、配置文件等领域广泛应用。下面是使用 JSON 传输数据的优缺点:

优点:
  1. 简洁、易读:JSON 格式的数据非常简洁易读,使用起来非常方便。可以轻松地通过文本编辑器或浏览器插件进行查看、编辑、调试。
  2. 易于解析:JSON 数据可以使用多种编程语言解析,支持主流的编程语言,如JavaScript、Java、Python、C#等,因此JSON数据格式具有良好的跨平台和可扩展性。
  3. 结构化数据:JSON数据是一种结构化的数据格式,具有良好的扩展性和兼容性,可以非常容易地扩展、更新、维护和重用。
  4. 跨域请求:JSON 支持跨域请求,允许在不同域名之间安全地传输数据。这使得使用 JSON 传输数据成为一个非常有用的选择。
缺点:
  1. 不适合传输大文件:JSON 是基于文本的格式,传输大文件时会占用较多的带宽和时间。
  2. 缺乏标准:虽然 JSON 是一种非常流行的数据交换格式,但是没有官方标准或规范,因此可能存在不同实现之间的差异性。
  3. 不支持注释:JSON格式不支持注释,因此无法在数据中添加注释,这可能会导致在一些场景下的不便利。
  4. 安全性:JSON 格式虽然支持跨域请求,但是如果没有正确地处理跨域请求,可能会导致安全问题。
JSON.parse(JSON.stringify())的缺点
  1. 如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式;
  2. 如果obj里有RegExp(正则表达式的缩写)、Error对象,则序列化的结果将只得到空对象;
  3. 如果obj里有函数、undefined,则序列化的结果会把函数或 undefined丢失;
  4. 如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
  5. JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
  6. 如果对象中存在循环引用的情况也无法正确实现深拷贝(可利用map结构辅助过滤);

综上所述,JSON 是一种非常便捷、灵活和可扩展的数据交换格式,独立于计算机各类语言,但在使用时需要注意其缺点,以确保数据的安全性和完整性。

闭包(Closure)是 JavaScript 中一个重要的概念,它允许函数访问其词法作用域(lexical scope)之外的变量。闭包是由函数和对其周围状态(词法环境)的引用共同构成的。换句话说,闭包让函数可以“记住”并访问它被创建时的作用域,即使这个函数在其作用域之外执行。

闭包的基本概念

闭包的核心在于函数可以访问其外部函数的变量,即使外部函数已经执行完毕并从调用栈中移除。以下是一个简单的例子来说明闭包的概念:

1
2
3
4
5
6
7
8
9
10
11
12
function outerFunction() {
let outerVariable = 'I am outside!';

function innerFunction() {
console.log(outerVariable); // 访问外部函数的变量
}

return innerFunction;
}

const closure = outerFunction();
closure(); // 输出: I am outside!

在这个例子中,innerFunction 是一个闭包,因为它可以访问 outerFunction 中的变量 outerVariable,即使 outerFunction 已经执行完毕。

阅读全文 »

  • Autoprefixer自动添加浏览器前缀插件,属于后处理程序,不像 Sass 以及 Stylus 之类的预处理器。它适用于普通的 CSS,可以实现css3代码自动补全。也可以轻松跟 Sass,LESS及Stylus集成,在CSS编译前或编译后运行。

  • ant-design table树结构折叠图标火狐浏览器内显示错误

    1
    2
    3
    4
    5
    6
    // 这种写法仅火狐识别
    @-moz-document url-prefix() {
    .surely-table-row-expand-icon::before {
    height: 2px;
    }
    }
  • Chromium
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    /*滚动条整体粗细样式*/
    ::-webkit-scrollbar {
    /*高宽分别对应横竖滚动条的尺寸*/
    width: 8px;
    height: 8px;
    }

    /*滚动条里面小方块*/
    ::-webkit-scrollbar-thumb {
    border-radius: 10px !important;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2) !important;
    /* 颜色 */
    /* background:#b6b6b6!important; */
    /* 线性渐变背景 */
    background-image: linear-gradient(
    45deg,
    #ffbd61 25%,
    #ffbd61 25%,
    #ff8800 25%,
    #ff8800 50%,
    #ffbd61 50%,
    #ffbd61 75%,
    #ff8800 75%,
    #ff8800 100%
    ) !important;
    }

    ::-webkit-scrollbar-thumb:hover {
    background: #1175c2 !important;
    }

    /*滚动条轨道*/
    ::-webkit-scrollbar-track {
    border-radius: 10px !important;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2) !important;
    background: #ededed !important;
    }

    /*滚动条角落*/
    ::-webkit-scrollbar-corner {
    background: #000;
    }
    Firefox

    scrollbar-width

    scrollbar-color

    IE

    scrollbar-base-color

    scrollbar-track-color

    scrollbar-arrow-color

    scrollbar-3dlight-color

    scrollbar-shadow-color

    scrollbar-highlight-color

  • AngularError: Zone.js has detected that ZoneAwarePromise (window|global).Promise has been overwritten. Most likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)

    原因:Zone.js检测到ZoneAwarePromise(window | global).Promise已被覆盖。 最可能的原因是在Zone.js之后加载了Promise polyfill(加载zone.js时不需要填充Promise api。如果必须加载,则在加载zone.js之前执行。)

    解决:

    1. 改的方向就是在zone.js之前加载它,把polyfill.ts里import ‘zone.js/dist/zone’的这一行提到main.ts里
  1. 在polyfill.ts里import ‘zone.js/dist/zone’这一行前面,引入import ‘core-js/es/promise’

  • background 渐变色、图片叠加
    1
    2
    // 使用,间隔 需要渐变色置后
    background: url(static/images/xxx.png) no-repeat center center, linear-gradient(105deg, #F8FCFF 0%, #C4CBD5 100%);
  • 断线边框动画
    1
    <div class="box"></div>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    @keyframes run {
    0%,
    100% {
    clip: rect(0px, 220px, 2px, 0px);
    /*初始和结束状态:上边线条*/
    }

    25% {
    clip: rect(0px, 2px, 220px, 0px);
    /*左边线条*/
    }

    50% {
    clip: rect(218px, 220px, 220px, 0px);
    /*底边线条*/
    }

    75% {
    clip: rect(0px, 220px, 220px, 218px);
    /*右边线条*/
    }
    }
    .box {
    height: 200px;
    width: 200px;
    background: rgba(10, 150, 220, 1);
    margin: 50px auto;
    position: relative;

    &::after,
    &::before {
    content: '';
    position: absolute;
    width: 220px;
    height: 220px;
    box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.5);
    /*内阴影 inset*/
    left: 0;
    top: 0;
    margin: -10px;

    // 设计CLIP:
    // clip:rect(上边起始的距离 , 自左道右的距离, 自上到下的距离, 左边起始的距离)

    /* 开始0% : 裁剪保留上边部分*/
    /* clip: rect(0px, 220px, 2px, 0px); */
    /* 25% : 裁剪保留左边部分*/
    /* clip: rect(0px, 2px, 220px, 0px); */
    /* 50% : 裁剪保留底边部分*/
    /* clip: rect(218px, 220px, 220px, 0px); */
    /* 75% : 裁剪保留右边部分 */
    /* clip: rect(0px, 220px, 220px, 218px); */
    /* 结束100% : 回到原点 裁剪保留上边部分*/
    /* clip: rect(0px, 220px, 2px, 0px); */

    animation: run 6s linear infinite;
    /*应用动画run 匀速运动 重复执行*/
    }

    &::before {
    animation-delay: 3s;
    /*让before 比after 慢3秒,总时间6秒,这样就形成对角线动画效果*/
    }
    }
  • 滚动显示
    1
    <div class="clip-txt">稍等~稍等等~~稍等~~~~马上出现! -done!</div>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @keyframes clipTxt {
    0% {
    clip: rect(0px, 0px, 30px, 0);
    }
    100% {
    clip: rect(0px, 200px, 30px, 0);
    }
    }
    .clip-txt {
    width: 200px;
    height: 30px;
    background: rgba(0, 0, 0, 0.2);
    animation: clipTxt 5s infinite;
    }
0%