随手记第一弹

406 阅读8分钟

引言

当谈到前端开发时, 无论是初学者还是经验丰富的开发者, 都能够感受到这个领域的迅速发展和变化。前端技术不断演进, 新的框架和工具层出不穷, 这使得我们需要不断学习和掌握新的知识点。然而, 有时候我们会遇到一些零散的小知识点, 它们虽然看似微小, 但却能为我们的工作和学习带来巨大的帮助。

在本专栏中, 我将总结一些我平时 随手 记录小知识点。这些小的知识点有的是平常项目中遇到的, 有的则是看了一些大佬们分享的博客后摘抄、总结的; 尽管它们可能篇幅较小, 但它们的实际应用价值却是不可忽视的。我会选择一些具有代表性的知识点, 并提供简洁明了的解释和示例, 以便大家能够轻松理解和应用。

最后如果, 如果你对本专栏的知识感兴趣, 欢迎👏🏻👏🏻 点击订阅!!! 无论你是新手还是有经验的开发者, 都希望这些小知识点能够对你有所启发和帮助!!!

一、禁用 Google 翻译功能

Google 翻译功能想必大家都用过吧, 但是呢? 如果我们想要让指定的区域禁止翻译, 我们可以怎么设置呢?

其实方法很简单, 只需将 class=notranslate 添加到任何 HTML 元素中, 就可以防止该元素被翻译了, 如下代码所示:

<div class="notranslate">我不会被翻译</div>

这里我们可以参考 GitHub, 它针对代码块, 其实也是通过该方式来禁用谷歌翻功能的!!!

image

二、展开运行符对 null 以及 undefined 的处理

缘由: 在小组周会上, 小伙伴分享的一个关于 展开运行符(...) 的小细节

对于 展开运行符(...) 想必大家都不陌生吧, 如下代码演示: 通过该语法我们能够将数组或者对象在语法层面上进行展开, 有点类似于浅拷贝

const arr1 = [0, 1, 2];
const arr2 = [3, 4, 5];
const arr = [...arr2, ...arr1]; // arr 现在为 [3, 4, 5, 0, 1, 2]

const obj1 = { foo: 'bar', x: 42 };
const obj2 = { foo: 'baz', y: 13 };
const mergedObj = { ...obj1, ...obj2 }; // 合并后的对象 { foo: "baz", x: 42, y: 13 }

上面演示了 展开运行符(...) 的一个常规用法, 下面我们来看下在不同情况下, 展开运行符(...) 对于 nullundefined 的不同处理, 是的你没有听错, 这里也分两种情况: 数组和对象

  1. 在对象中, 对 nullundefined 使用 展开运行符(...), 是不会做任何处理, 也不会报错
const obj1 = null;
const obj2 = undefined;
const mergedObj = { ...obj1, ...obj2 }; // 合并后的对象 {}
  1. 在数组中, 对 nullundefined 使用 展开运行符(...) 会报错, 因为这里对操作数是有要求的, 必须是个 可迭代对象
const arr1 = null;
const arr2 = undefined;
const arr = [...arr2, ...arr1]; // VM226:3 Uncaught TypeError: arr2 is not iterable

傻傻的我还在写这样的代码 {...(obj || {})} 😭😭😭😭

三、分享一道有意思的题

缘由: 来自 飞叶大大 在一个微信群里的一个分享

题目: 如果一个数大于 0, 返回 1; 等于 0, 返回 0; 小于 0, 返回 -1; 请问如何用一句代码实现?

实现代码:

function getSign(val) {
  return (val > 0) - (val < 0)
}

实现思路还是挺有意思的, 虽然在实际开发中并没有什么卵用, 这里这样涉及了布尔值在操作符 - 下的一个隐式转换:

  • true - false = 1
  • false - true = -1
  • false - false = 0

四、光标吸底

《在 Koa 中基于 gpt-3.5 模型实现一个最基本的流式问答 DEMO》 一文中介绍了前后端如何实现 gpt 流式问答, 后面实践过程中遇到滚动条吸底问题, 要实现的效果如下, 在不断进行流式输出中, 需要保证滚动条一直在底部, 也就是要让光标一直出现在视口

Kapture 2023-07-09 at 20

这里其实使用了一个比较取巧的办法, 主要代码如下, viewRef.current 为展示区域 dom, cursorRef.current 则是光标 dom, 在每次追加内容后都会执行下面这个方法, 只要滚动条和底部的距离小于 50 则让光标滚动到视口, 从而实现滚动条吸底效果, 同时如果将滚动条手动向上进行滚动一大段(大于 50), 则不会进行吸底

// 设置光标位置
const setCursor = useCallback(() => {
  const { current: viewDom }  = viewRef;
  const offset =
    viewDom.scrollHeight -
    viewDom.scrollTop -
    viewDom.clientHeight;

  // 如果当前滚动条在底部(<50) 则需要将光标滚动到视口
  if (offset < 50) {
    cursorRef.current.scrollIntoView({ behavior: 'smooth' });
  }
}, []);

完整代码 点击 查看

五、React Ref 彩蛋

前段时间有幸看到 卡颂大大 的一篇关于 React 中的隐藏彩蛋功能 的介绍, 其中里面讲到一个关于 React Ref 的一个彩蛋, 故记录如下:

我们都知道 ReactRef 除了支持使用 useRef 声明的变量, 还支持一个函数, 特殊的是该函数还允许类似 useEffect 一样返回一个函数, 当 Dom 被销毁时将会执行该函数

如下代码所示, Ref 为函数 measuredRef, 在函数中我们创建了一个 ResizeObserver 实例, 用来来监听 Dom 尺寸变更, 同时该函数返回一个销毁 ResizeObserver 实例的方法 A, 当 DOM 被销毁时也会对应执行方法 A 来销毁 ResizeObserver 实例

function MeasureExample() {
  const [entry, setEntry] = useState();
  
  const measuredRef = useCallback((node) => {
    const observer = new ResizeObserver(([entry]) => {
      setEntry(entry)
    })
    observer.observe(node)

    // 解绑事件
    return () => observer.disconnect()
  }, [])

  return (
    <div ref={measuredRef}>Hello</div>
  );
}

当前 React 文档中 Ref 的部分还未提及这个功能改动。可能在未来的某个小版本中, 会上线这个功能;

六、CSS 隔行变色

已知 nth-child 选择器可匹配作为其父元素的第 n 个子元素, 这里的 n 可以是数字、关键字(oddeven)、公式(如 an + b)

这里通过关键词 oddeven 或者公式, 就能够实现隔行样式:

<style> 
  // 基数
  p:nth-child(odd) {
    background: #f4f4f4;
  }

  // 偶数
  p:nth-child(even) {
    background: #ccc;
  }

  /**
  上面样式等价于:
  // 基数
  p:nth-child(2n + 1) {
    background: #f4f4f4;
  }

  // 偶数
  p:nth-child(2n) {
    background: #ccc;
  }
  **/
</style>
<body>
  <p>The first paragraph.</p>
  <p>The second paragraph.</p>
  <p>The third paragraph.</p>
  <p>The fourth paragraph.</p>
  <p>The fifth paragraph.</p>
</body>

image

七、企微链接默认使用系统浏览器打开

在企业微信里, 我们如果打开一个链接, 默认情况下会用内置的浏览器进行打开, 但大部分情况下我们并不想这样, 那么我们该怎么配置才能让一个链接默认使用系统浏览器进行打开呢?

  1. 通过 control + command + shift + dctrl + win + shift + d 开启企业微信 Debug 模式

image

  1. 打开 Debug 模式后, 系统右上角会多出一个调试的选项, 然后打开「浏览器、webView 相关」->「系统浏览器打开网页」

image

  1. 最后再次通过 control + command + shift + dctrl + win + shift + d 关闭企业微信 Debug 模式

image

八、Node 项目路径别名配置

在前端项目中我们一般都会为项目配置路径别名, 而别名配置一般都是在打包工具里进行配置的, 那么请问在 Node 项目中我们要如何为我们的项目配置别名呢?

  1. 对于 CommonJS 项目默认是不支持配置路径别名的, 但是可以通过 module-alias 工具来实现, 具体使用方式可查阅官方文档

  2. 对于 ES Module 项目, 默认是支持设置路径别名的, 配置方式也很简单只需要在 package.json 新增 imports 配置即可:

{
  "type": "module", // 开启, ES Module
  "imports": {
    "#src/*": "./src/*.js",
    "#app/*": "./src/app/*.js",
    "#utils/*": "./src/utils/*.js",
    "#logger": "./src/logger/index.js",
    "#graphql": "./src/app/graphql/index.js",
    "#middleware": "./src/app/middleware/index.js"
  },
}

ES Module 项目中使用路径别名

import { importFiles } from '#utils/fs';
import logger from '#logger';

九、CSS 滚动穿透(渗透)设置

如下图, 默认情况下当子元素滚动到底部后, 如果我们继续滚动会触发父元素的滚动, 这里姑且理解为滚动穿透现象

Kapture 2023-07-10 at 19

那么如果我们想要禁止滚动穿透现象呢? 也就是当子元素滚动到底部后, 继续滚动禁止触发父元素的滚动, 这里实现方式其实很简单, 只需要为子元素设置一行 CSS 代码即可:

overscroll-behavior: contain;

补充: overscroll-behavioroverscroll-behavior-xoverscroll-behavior-y 属性的合并写法, 可以控制浏览器过度滚动时的一个表现(也就是用来约定当元素滚动到边界时如何进行处理), 具体使用可查阅 MDN

十、遮罩同层级的元素, 层级问题

有代码如下, 代码中通过 ::before 实现了一个遮罩层, 但是呢文字 展开 也被遮罩层盖住了

<style>
 .wrapper {
    height: 300px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
  }

  .wrapper::before {
    content: "";
    inset: 0;
    position: absolute;
    background-color: rgba($color: #000, $alpha: 45%);
  }

  .wrapper span {
    background-color: aqua;
  }
</style>
<div class="wrapper">
  <span>展开</span>
</div>

image

这里的问题涉及到 层叠上下文 的知识, 如果好奇可以自行百度, 后面博主应该也会专门写一篇文章进行讲解, 这里先直接给出解决办法: 为文字层设置 position: relative

<style>
 .wrapper {
    height: 300px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
  }

  .wrapper::before {
    content: "";
    inset: 0;
    position: absolute;
    background-color: rgba($color: #000, $alpha: 45%);
  }
  .wrapper span {
+   position: relative;
    background-color: aqua;
  }
</style>
<div class="wrapper">
  <span>展开</span>
</div>

image

本文到此结束, 欢迎👏🏻订阅本栏目, 敬请期待下一弹...

Group 3143