Live Note

Remain optimistic

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<style>
.container {
width: 200px; /* 固定宽度,触发溢出 */
overflow: hidden; /* 隐藏溢出内容 */
white-space: nowrap; /* 禁止换行 */
}

.text {
display: inline-block;
width: 100%; /* 占满容器 */
direction: rtl; /* 文本方向从右到左 */
text-overflow: ellipsis; /* 显示省略号 */
overflow: hidden;
text-align: left; /* 强制左对齐,保持视觉上的正常阅读方向 */
}
</style>
<div class="container">
<span class="text">短文本不会被省略</span>
</div>

<div class="container">
<span class="text">这是一段很长的文本,左侧会被省略</span>
</div>

在 TypeScript 的类型系统中,逆变(Contravariance)协变(Covariance)双变(Bivariance)不变(Invariance) 是描述类型兼容性和子类型关系的重要概念。这些术语来源于类型理论,主要用于处理函数类型、泛型和接口的赋值规则。理解这些概念不仅能帮助我们编写更安全的代码,还能让我们更好地设计类型系统。本文将逐一讲解这四种变型,辅以代码示例,让你轻松掌握它们的含义与应用。

Read more »

AJAX:实现原理与技术背景

在现代 Web 开发中,AJAX(Asynchronous JavaScript and XML,异步 JavaScript 和 XML)是一种不可或缺的技术。它通过异步通信实现了网页的无刷新更新,极大地提升了用户体验。那么,AJAX 是如何实现的?它的出现又有着怎样的背景?

从静态到动态的 Web 进化

Web 1.0 的局限性

在互联网早期,网页主要依赖同步请求模型。当用户点击链接或提交表单时,浏览器会向服务器发送请求,然后等待服务器返回全新的 HTML 页面。这一过程会导致整个页面刷新,用户不得不面对短暂的空白和等待。对于简单的静态网站,这种模式尚可接受,但随着 Web 应用复杂性的增加,例如实时聊天、动态表单验证等需求,这种方式的弊端愈发明显——用户体验差、交互效率低。

动态 Web 的需求

进入 21 世纪,互联网用户对 Web 应用的要求日益提高。人们希望网页能像桌面应用程序一样,提供流畅的交互和实时更新。例如,在输入搜索关键词时实时显示建议,或在聊天应用中即时刷新消息。这些需求推动了 Web 技术向动态化、异步化的方向发展。

技术基础的成熟

AJAX 并非凭空出现,它建立在一系列已有技术之上:

  • JavaScript:作为客户端脚本语言,负责处理用户交互和动态更新页面内容。
  • XMLHttpRequest(XHR):浏览器内置对象,允许在后台与服务器通信。
  • DOM(文档对象模型):提供操作页面结构的接口,使数据能够无缝嵌入。
  • XML:最初用于数据交换(后来 JSON 逐渐取而代之)。

这些技术的成熟为 AJAX 的诞生奠定了基础。尤其是 XMLHttpRequest,最早由微软在 Internet Explorer 5 中引入,随后被其他浏览器标准化,成为 AJAX 的核心组件。

Read more »

在 TypeScript 的类型系统中,Top Type(顶层类型)Bottom Type(底层类型) 是两个非常重要的概念。它们分别代表了类型范围的“最顶层”和“最底层”,理解它们对于掌握 TypeScript 的类型系统至关重要。

Read more »

Subtype Polymorphism

通过类继承和方法重写,子类可以提供与父类方法相同的接口,但实现不同的行为。

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
class Animal {
makeSound(): void {
console.log("Some generic animal sound")
}
}

class Dog extends Animal {
makeSound(): void {
console.log("Woof!")
}
}

class Cat extends Animal {
makeSound(): void {
console.log("Meow!")
}
}

function makeAnimalSound(animal: Animal): void {
animal.makeSound()
}

const dog = new Dog()
const cat = new Cat()

makeAnimalSound(dog) // Woof!
makeAnimalSound(cat) // Meow!

key points:

  • 类型兼容性:TypeScript 的类型系统允许子类实例赋值给父类类型的变量(向上转型)。
  • 运行时行为:实际执行的方法取决于对象的运行时类型,而不是声明时的类型。
Read more »

React Fast Refresh 是 React 官方推荐的 HMR 解决方案,旨在提供快速、可靠的热更新体验,同时保留组件的本地状态(例如 useStateuseRef 的值)。它由 Facebook 团队开发,广泛集成到现代构建工具(如 Vite 和 Next.js)中。

背景与目标

传统 HMR 的问题

  • 在传统的 HMR 实现中,当模块更新时,整个组件树可能会被重新渲染,导致本地状态丢失。
  • 对于 React 组件,状态丢失会影响开发体验,例如表单输入值或动画状态被重置。

React Fast Refresh 的目标

  • 提供快速的模块更新。
  • 保留 React 组件的本地状态。
  • 只重新渲染受影响的组件,而不是整个应用。

核心原理

React Fast Refresh 通过在编译时注入特定的运行时代码,并在运行时与 React 协调器(React Reconciler)协作,实现高效的热更新。

Read more »

Vite 为什么快?

Vite 的速度优势主要来源于其基于原生 ESM(ES Modules)的开发模式和高效的构建过程

原生 ESM 的开发服务器

传统打包工具(如 Webpack)的问题

  • Webpack 在开发模式下会将所有模块打包成一个或多个 bundle 文件,即使只修改了一个文件,也需要重新打包整个 bundle。
  • 这种打包过程涉及大量的文件读取、解析、转换和写入操作,随着项目规模增加,启动时间和热更新时间会显著变慢。

Vite 的解决方案

  • Vite 利用现代浏览器对 原生 ES Modules(ESM) 的支持,在开发模式下不进行打包,而是直接通过 HTTP 请求按需加载模块。
  • 浏览器支持 <script type="module">,可以动态加载 ESM 模块,Vite 的开发服务器将源码直接以 ESM 格式提供给浏览器。
  • 启动速度快:
    • Vite 的开发服务器启动时,只需要初始化一个简单的 HTTP 服务器,无需预先打包整个项目。
    • 文件按需加载,只有访问到的模块才会被处理(例如解析和转换),大大减少了初始启动时间。
  • 按需编译:
    • Vite 使用 Esbuild(一个极快的 JavaScript/TS 编译器)对 TypeScript、JSX 等非标准 ESM 文件进行预编译,生成浏览器可识别的 ESM 格式。
    • Esbuild 的性能比传统工具(如 Babel)快 10-100 倍,因为它是基于 Go 语言实现的,充分利用了多核 CPU。
Read more »

Delete Service Worker on Safari

To delete a service worker on Safari, you can follow these steps:

  1. Open Safari Developer Console (Press Command + Option + C)
  2. Copy and paste the following JavaScript code into the console:
1
2
3
4
5
6
7
navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (let registration of registrations) {
registration.unregister().then(function () {
console.log("Service Worker Unregistered:", registration.scope)
})
}
})

This code will:

  1. Get all registered service workers using navigator.serviceWorker.getRegistrations()
  2. Loop through each registration
  3. Unregister each service worker using the unregister() method
  4. Log a confirmation message with the scope of the unregistered service worker

You can verify that the service worker has been successfully removed by:

  1. Opening Safari Developer Tools
  2. Going to the Application tab
  3. Checking the Service Workers section - it should now be empty

Note: After unregistering the service worker, you might need to close all tabs and restart Safari for the changes to take full effect.

Introduction

I’ve recorded an MP4 demo to showcase the results. In the video, you’ll see the Markdown content being displayed
character by character, with dynamic rendering and automatic scrolling.

Demo MP4

In this article, I’ll walk you through a simple yet powerful demo of implementing stream output in JavaScript. This
demo
mimics the behavior of ChatGPT-like applications, where responses are displayed in a streaming fashion, and the
content
is dynamically rendered as Markdown. The best part? It’s incredibly simple to implement, and I’ll provide the full
source code and an MP4 demo to showcase the results.

Read more »

In modern web development, enhancing user experience by highlighting specific text within a larger body of content is a common requirement. Whether it’s for search results, annotations, or emphasizing key information, a Highlight Text component can be incredibly useful. In this article, we’ll walk through the process of building a simple yet effective Highlight Text component using React.

Here is the Example captured:

Highlight Text Component Example

Read more »