tanabalu / tanabalu.github.io

Blog
https://hbuecx.com/?from=github
1 stars 0 forks source link

留言板 | 白山 #88

Open tanabalu opened 2 years ago

tanabalu commented 2 years ago

https://hbuecx.com/post/message/?

温故而知新。

tanabalu commented 2 years ago

哈哈哈,开通留言板啦

tanabalu commented 2 years ago

六种断点方式

tanabalu commented 2 years ago

【编码】一个很有趣的代码校验的写法,这里的 switch(false) 很有灵性啊!这种写法也值得被推广到更多的校验场景里。

function validate(password: string): string {
  let error = '';

  switch (false) {
    case password.length >= 8:
      error = '密码长度不能小于8位';
      break;
    case password.length <= 16:
      error = '密码长度不能大于16位';
      break;
    case /[0-9]/.test(password):
      error = '密码中必须含有数字';
      break;
    case /[a-z]/.test(password):
      error = '密码中必须含有小写字母';
      break;
    case /[A-Z]/.test(password):
      error = '密码中必须含有大写字母';
      break;
    // ……
  }

  return error;
}
tanabalu commented 2 years ago

【写作】拟人化、加上形容词

+ 落叶它静静地铺满了整条街
- 落叶铺满了整条街
tanabalu commented 2 years ago

【写作】在写论点时要附带有论据

+ 作为朋友,你一直是我追随学习的人,想起高中有段时间想做第一个早读的人,但无论多早你都先坐在了教室。看着你跟哥哥低头交谈……
- 作为朋友,你一直都是我追随学习的人。看看你跟哥哥低头交谈……
tanabalu commented 2 years ago

Markdown diff 语法的用法:

```diff
+ new
- delete
tanabalu commented 2 years ago

【阅读】在阅读论述型内容时,不仅要关注他的论点,同时,论据也非常重要。

从论据与论点的关系中,去发现作者的逻辑组织方式,培养自己更好的逻辑思维。假想一下,当有一天你对他人提起这个论点时却找不到论据,这样的论点在你这里是站不住脚的。

另外,终有一天,当你怀疑你自己的时候,这些论据也能帮助你重回正轨。

tanabalu commented 2 years ago

【Debug】“AuthProvider”表示值,但在此处用作类型。是否指“类型 AuthProvider”

问题在于:该文件是 ts 后缀的文件,无法解析 dom ,需要将文件后缀改为 tsx ,然后警告就消除了。

ssort ReactNade)frce Mreact: any

tanabalu commented 2 years ago

【编码】使用svg连线

tanabalu commented 1 year ago

【杂记】本来想在快报的头栏里加入更多个人的元素的,为此我还思虑良久。但在刚刚,一个念头点醒了我,快报是一个公共的透出信息的平台,大家去看它是为了获取更多的信息,增长见识,绝大多数人对编者是个什么样的人不感兴趣。那么,加入个人元素的方向本身就存在着错误。

作为一个技术周刊,真正的着力点应该在于让读者获得更多内容,更加专业,更加平易近人才是真正需要做的事情。

tanabalu commented 1 year ago

macos系统升级后,git会失效,需要执行 xcode-select --install 命令来重装 git。

tanabalu commented 1 year ago

【编码】前端异常捕获方案:

  1. window.onerror 捕获语法异常
  2. 可以重写 setTimeoutsetInterval 等异步方法,用同步的写法包裹 try 来捕获异步函数中发生的错误
  3. window.addEventListener (‘unhandledrejection’,・・・); 捕获未处理的异步 reject
  4. window.addEventListener (‘error’, …) 捕获资源异常
  5. 重写 fetch , XMLHttpRequest 来捕获接口状态
  6. ReactErrorBoundary 异常捕获组件
tanabalu commented 1 year ago

昨晚做了一个梦,梦见我在一座看似是一辆车的诊所里,诊所里的有一张桌子,桌子旁边坐着一个男医生,站着一个女医生。 我说:“我来拿药。” 男医生指了指女医生说道:“上次是她给你看的病,不知道你要拿什么药。不过我看你没什么病,就是嗓子有点问题。” 我深以为然,下了车,离开了。

tanabalu commented 1 year ago

【编码】发现一个性能优化的技巧:在产品功能上线前几天(7天)先推送资源至客户端(让大多数用户都已经读取过资源),这样基于客户端缓存,产品上线时,可以有效的降低资源加载对首屏展示的影响。

tanabalu commented 1 year ago

【Debug】我在使用 Antd 的 Tree 组件时,它需要在有限的宽度里展示树型结构,当树型结构横向超出宽度时,需要展示滚动条。

当前的问题是,确实可以出现滚动条,但是只有在文案被极致压缩的情况下才会出现滚动条,文案挤压变形根本无法阅读,体验极差。

image

分析:从截图看,问题主要出在文案换行了,那么如果不允许文案换行,这个问题就解决了。

解决方案:给文案增加 white-space: nowrap; 属性后,文案不会换行,而 white-space 属性是可以被继承的,所以无需再文案上加上该属性,只要在该组件外围加上该 css 配置即可。

增加后,文案就不会被挤压变形了: image

tanabalu commented 1 year ago

【编码】Typescript 读取 enum 枚举的 key 值和 value 值

// 假设我一个枚举
enum ENUM_TYPE {
    ALL = 'all',
    SOME = 'some',
    LITTLE = 'little'
}

// 获取枚举的 value
type IValue = `${ENUM_TYPE}`  // 'all' | 'some' | 'little'

// 获取枚举的 key
type IKey = keyof typeof ENUM_TYPE  // 'ALL' | 'SOME' | 'LITTLE'
tanabalu commented 1 year ago

【编码】正则贪婪匹配与懒惰匹配

贪婪匹配:【.*】,默认即为贪婪匹配 懒惰匹配:【.*?】,后面加上?表示懒惰匹配

tanabalu commented 1 year ago

【编码】下面这句代码放到控制台,将会执行alert(1)这段代码,弹出弹窗。

"".constructor.constructor("alert(1)")()

基本原理:首先字符串的constructor是一个字符串的构造函数,而这个构造函数本身就是一个函数,它的constructor构造函数就是 function 的构造函数,所以"".constructor.constructor() 的作用相当于new Function()。很有意思的代码!!

tanabalu commented 1 year ago

【编码】阻止滚动穿透:overscroll-behavior-y: contain;

具体使用见MDN

tanabalu commented 1 year ago

【编码】将searchURL转换为对象

const params = Object.fromEntries(  
  new URLSearchParams(window.location.search)
)

// URL: example.com/path?foo=bar&name=futurestudio&num=1
// { foo: 'bar', name: 'futurestudio', num: '1' }
tanabalu commented 1 year ago

【工具】键帽数字

tanabalu commented 1 year ago

【编码】原来书签栏里也可以执行自定义脚本。参考 Cubox 书签栏快速收藏插件的代码,直接要将这段代码放到书签栏里,点击就可以实现自动收藏文章的功能。

<a href="
javascript:
var url = location.href;
var title = document.title;
var desc = '';
if (document.getSelection) {
  desc = document.getSelection();
};
if (desc.toString().length === 0) {
  let descTag = document.querySelector('[name=description]');
  desc = descTag ? descTag.getAttribute('content') : '';
};
if (desc.length > 500) {
  desc = desc.slice(0, 500) + '...';
};
void(
  open(
    'https://cubox.pro/my/tool/collection?url=' + encodeURIComponent(url) + '&amp;title=' + encodeURIComponent(title) + '&amp;description=' + encodeURIComponent(desc) + '&amp;groupId=' + '&amp;tags=' + '&amp;starTarget=false' + '&amp;editable=false',
    'cubox',
    'toolbar=no,
    resizable=no,
    location=no,
    menubar=no,
    width=300,
    height=100',
  )
);" class="SettingApps_quickCollect__yrNRf"><span class="SettingApps_quickCollectIcon__qTcZP">★</span>快速收藏</a>
tanabalu commented 11 months ago

提取你项目中的所有中文字:

const fs = require('fs');
const path = require('path');

// 定义你的项目路径
const projectPath = './src';

// 定义输出文件路径
const outputPath = './output.txt';

// 定义正则表达式来匹配单行、多行注释
const commentRegex = /\/\/.*|\/\*[\s\S]*?\*\//g;

// 定义正则表达式来匹配包含至少一个中文字符的字符串,同时保留其中的英文和数字
const chineseWithEnglishRegex = /[一-龥]+[一-龥a-zA-Z0-9,.!?()();;::]*|[一-龥a-zA-Z0-9,.!?()();;::]*[一-龥]+/g;

// 定义你希望跳过的文件夹数组
const ignoreDirs = ['.umi', '.umi-production', 'assets', 'services'];

// 将找到的中文句子写入到文件
const output = fs.createWriteStream(outputPath, { encoding: 'utf-8' });

// 搜索指定文件类型
const fileTypes = ['.js', '.jsx', '.ts', '.tsx'];

function findChineseText(filePath) {
  const content = fs.readFileSync(filePath, { encoding: 'utf-8' });
  // 移除注释
  const contentWithoutComments = content.replace(commentRegex, '');
  // 匹配中文和可能的英文单词
  const matches = contentWithoutComments.match(chineseWithEnglishRegex);
  if (matches) {
    output.write(`File: ${filePath}\n${matches.join('\n')}\n\n`);
  }
}

function walkDirectory(directory) {
  // 获取目录名,用于检查是否应该跳过
  const dirName = path.basename(directory);
  if (ignoreDirs.includes(dirName)) {
    return;
  }

  fs.readdirSync(directory, { withFileTypes: true }).forEach((dirent) => {
    const resPath = path.resolve(directory, dirent.name);
    if (dirent.isDirectory()) {
      walkDirectory(resPath);
    } else if (fileTypes.includes(path.extname(dirent.name).toLowerCase())) {
      findChineseText(resPath);
    }
  });
}

walkDirectory(projectPath);

output.end(() => {
  console.log(`完成!所有含中文字符的短语(保留其中的英文单词)已经被写入到 ${outputPath}`);
});
tanabalu commented 11 months ago

爬取网页文章并且将其转换为 Markdown 格式:

  1. 安装依赖
    pip install requests beautifulsoup4 html2text
  2. 编写代码:创建 spider.py 文件:
import requests
from bs4 import BeautifulSoup
import html2text

# 定义获取文章内容的函数
def fetch_article_content(url):
    try:
        # 发送 HTTP GET 请求获取网页内容
        response = requests.get(url)
        response.raise_for_status()  # 如果请求失败,将抛出异常

        # 解析 HTML 内容
        soup = BeautifulSoup(response.text, 'html.parser')

        # 找到类名为 'main-container' 的元素
        main_container = soup.find(class_='main-container')

        if main_container:
            # 使用 html2text 将 HTML 转换为 Markdown
            h2t = html2text.HTML2Text()
            h2t.ignore_links = False  # 将链接转换成 Markdown 链接格式
            h2t.ignore_images = False  # 将图片转换成 Markdown 图片格式
            h2t.ignore_tables = False  # 将表格转换成 Markdown 表格格式
            return h2t.handle(str(main_container))
        else:
            return "Article content not found."

    except requests.HTTPError as e:
        return f"HTTP Error: {e}"
    except Exception as e:
        return f"An error occurred: {e}"

# 目标网页的 URL
url_to_scrape = 'https://hub.baai.ac.cn/view/33417'

# 调用函数并打印结果
markdown_content = fetch_article_content(url_to_scrape)
print(markdown_content)
  1. 执行 spider.py
python spider.py
tanabalu commented 6 months ago

新知识:接口的入参类型、接口的出参类型跟前端渲染对象并不是同一个实体,它们只是长得很相似而已。

以前总有一种执念,总想着最大限度的复用类型定义,就会在 Typescript 中大量的使用 extends 关键字来对原来的类型做增删改查操作,以满足新的类型设计需求。而这个实现方案在处理接口出参数据和前端渲染数据时又是常用,比如:

接口入参:

interface Params {
    id?: string;
    name?: string;
    pageSize: number;
    pageNum: number;
}

接口出参

interface Response {
    id: string;
    name: string;
    description: string;
    gmtCreate: string;
    gmtModify: strring;
}

前端渲染

interface View {
    name: string;
    description: string;
    gmtCreate: string;
    gmtModify: strring;
}

按照过去的习惯,我总会想先构造一个简单类型,然后用 extends 扩展出另外两种类型。但是实际上,它们并不是同一个类型,只是长得有点像而已,过于执着使用基础类型来扩展反而会把代码弄成一团乱麻,要摒弃这个执念!

tanabalu commented 5 months ago

问题:

在对话场景中,下拉新的聊天记录时,如何保障新拉取到的聊天内容后,页面扔停留在下拉前的原始位置?

附加:如果新拉取的聊天记录里有图片或者其他异步渲染的模块,如何保障?