虚拟列表
唔~,好久没有更新博文了,一年前的这个时候用 Vue 实现过一版虚拟列表,不过现在已经忘光光了,故写一篇博文帮忙回忆与巩固一下虚拟列表的知识。
前言本文对虚拟列表出现的原因与解决的问题不再介绍,着重讲解虚拟列表实现的思路以及原理。
技术栈
React
Vite
TS
预览链接
Demo预览链接:react-virtual-list
Github仓库地址:react-virtual-list-demo
卡片快速预览:
问题分析基本思路
虚拟列表的基本结构:
容器层(container):整个虚拟列表的包裹层,滚动事件是在这个包裹层出发的。
幻影层(phantom):容器层的子元素,用于撑开整个容器,获得原生的滚动条展示,不渲染内容。
内容层(content):容器层的子元素,用于渲染列表内容,列表元素动态变化。
虚拟列表的滚动效果实现:首先我们知道,虚拟列表的视口的渲染元素是动态增减的,那么其平滑的滚动效果是如何出现的?这里有一个误区需要注意,虚拟列表的滚动效果就是原生的滚动效果,虚拟列表并不参与scrollTop属性的设置,而是通过CSS的transform属性 ...
LeetCode 算法笔记 Part3
本文主要记录了博主的 Leetcode 算法刷题记录,方便以后查询复习。
图论岛屿数量LeetCode 原题链接:200. 岛屿数量
深度优先遍历,基本思路为,遇到一个岛就把这个岛给沉没掉,然后统计数加 1。
12345678910111213141516171819202122232425262728/**
* @param {character[][]} grid
* @return {number}
*/
const numIslands = (grid) => {
const m = grid.length,
n = grid[0].length;
const dfs = (i, j) => {
if (i < 0 || i > m - 1 || j < 0 || j > n - 1 || grid[i][j] === "0") {
return;
}
grid[i][j] = "0";
dfs(i + 1, j);
dfs( ...
LeetCode 算法笔记 Part2
本文主要记录了博主的 Leetcode 算法刷题记录,方便以后查询复习。
链表相交链表LeetCode 原题链接:160. 相交链表
哈希表存储遍历的节点,然后进行操作。第二种方法技巧性比较强,利用路径长度相同会回到相交的点的做法来求解。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
const ...
LeetCode 算法笔记 Part1
本文主要记录了博主的 Leetcode 算法刷题记录,方便以后查询复习。
哈希表两数之和LeetCode 原题链接:1. 两数之和
这道题首先考虑的是通过两层for循环遍历查询,但这样有很多无意义的查找。因此我们可以采用哈希表来减少查找的时间复杂度,此时查找顺序是往后而不是往前。注意使用Map对象来减少查询之前数据的时间复杂度,这里不能使用WeakMap,因为WeakMap只能使用对象作为键。
12345678910111213141516171819202122232425262728293031323334/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
const twoSum = (nums, target) => {
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
if (nums[i] + nums ...
JS手写题大汇总
本文主要记录了关于前端面试常考的手写代码题,常看常复习。
JS 基础篇深入了解 JS 这门语言的运行逻辑与机制,尝试实现其内部的方法。
ES5 实现继承使用 ES5 的语法实现继承,有几个注意点:
使用Object.create方法,构造以父类的prototype为原型的新对象,防止对子类原型对象的修改影响到父类的原型对象。
注意静态方法的继承,使用Object.setPrototypeOf将父类设置为子类的原型。
123456789101112131415161718192021function Person(name, age) {
this.name = name;
this.age = age;
}
Person.say = () => {
console.log("I'm a person!");
};
function Man(name, age, address) {
Person.call(this, name, age);
this.address = address;
}
Man.speak = () = ...
TypeSript笔记
之前 TS 笔记由于放在长文章后面阅读体验不太好,故单独抽离出来一篇文章。
本文主要记录了 TS 的学习知识与笔记。
基本类型TS 有以下几种数据类型:
基础类型:包括boolean(布尔值)、number(数字)、string(字符串)、null(空值)、undefined(未定义值)、bigint(大整型)和symbol(符号)等。这些类型和 JavaScript 的基本类型基本一致,只是 TS 在编译时会检查变量的类型是否匹配。例如:
1234567let isDone: boolean = false; // 声明一个布尔类型的变量
let age: number = 18; // 声明一个数字类型的变量
let name: string = "Alice"; // 声明一个字符串类型的变量
let x: null = null; // 声明一个空值类型的变量
let y: undefined = undefined; // 声明一个未定义值类型的变量
let a: bigint = 2172141653n; // 定义一个大整型变量
let z: s ...
Intersection Observer
早就想好好总结一下 Intersection Observer 这个 API,苦于一直没有时间,今天就来好好总结一下这个 API。
本篇文章将介绍现代 WebAPI Intersection Observer(元素交集观察器)。
背景交叉观察器 API(Intersection Observer API)提供了一种异步检测目标元素与祖先元素或顶级文档的视口相交情况变化的方法。过去,要检测一个元素是否可见或者两个元素是否相交并不容易,很多解决办法不可靠或性能很差。然而,随着互联网的发展,这种需求却与日俱增,比如,下面这些情况都需要用到相交检测:
在页面滚动时“懒加载”图像或其他内容。
实现“无限滚动”网站,在滚动过程中加载和显示越来越多的内容,这样用户就不必翻页了。
报告广告的可见度,以便计算广告收入。
根据用户是否能看到结果来决定是否执行任务或动画进程。
交叉观察器 API 可令代码注册一个回调函数,当特定元素进入或退出与另一元素(或视口)的交集时,或者当两个元素之间的交集发生指定变化时,该函数就会被执行。这样,网站就不再需要在主线程上做任何事情来监视这种元素交集,浏览器也可以 ...
数据结构与算法笔记
本篇文章将介绍数据结构与算法的基本概念(前端版)。
去年这个时间我在写数据结构与算法的博文,今年还在写,令人感叹。
基础算法的基本概念算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出算法的五大特性:
有限性(Finiteness):一个算法必须保证执行有限步之后结束
确切性(Definiteness): 一个算法的每一步骤必须有确切的定义
输入(Input):一个算法有零个或多个输入,以刻画运算对象的初始情况,所谓零个输入是指算法本身给定了初始条件
输出(Output):一个算法有一个或多个输出。没有输出的算法毫无意义
可行性(Effectiveness):算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步骤,即每个计算步骤都可以在有限时间内完成(也称之为有效性
算法的复杂度时间复杂度是指执行一个算法所需要的计算工作量,它反映了算法的执行效率和数据规模的关系。我们通常用大 O 符号来表示时间复杂度,例如$O(n)、O(logn) ...
React笔记
基础语法基础与规范
JSX注意事项。
JSX必须有一个根节点,如果没有,可以用幽灵节点<></>代替。
所有标签必须闭合,成对闭合或者自闭和都可以。
JSX采用小驼峰命名法,对于class要转化成className,for需要转化成htmlFor,以防止js关键字冲突。
JSX支持换行,如果需要换行需要加上(),防止bug出现。
注释在模板中的书写方式:{/* 苏苏苏 */}。1234567891011import "./app.css";
const showTitle = true;
function App() {
return (
<div className="App">
{/* 苏苏苏 */}
<div className={showTitle ? "title" : ""}>this is a div</div>
</div>
);
}
export d ...
Vue3笔记
本文主要记录了关于 Vue3 的相关笔记,主要记录 Vue3 及其生态的使用与技巧,不定时更新。
基础创建一个 app 实例并挂载1234567891011import { createApp } from "vue";
// 从一个单文件组件中导入根组件
import App from "./App.vue";
const app = createApp(App);
//
app.config.errorHandler = (err) => {
/* 处理错误 */
};
// 挂在到跟组件 #app 容器里面
app.mount("#app");
应用根组件的内容将会被渲染在容器元素里面。容器元素自己将不会被视为应用的一部分。.mount() 方法应该始终在整个应用配置和资源注册完成后被调用。同时请注意,不同于其他资源注册方法,它的返回值是根组件实例而非应用实例。这几个方法的返回值都是应用实例本身,也就是通过 createApp() 方法创建的对象。这样可以方便地链式调用这些方法,而不需要每次都写 app. ...
Vue2笔记
本文主要记录了关于 Vue2 的相关笔记,主要记录 Vue2 的一些基础概念与知识,帮助理解 Vue3。
Vue 的核心特性数据驱动(MVVM)数据驱动(MVVM):MVVM表示的是Model-View-ViewModel
MVVM 模型由以下三个部分组成:
View:表示当前页面所渲染的 DOM 结构,负责将数据模型转化为 UI 展现出来。View 层通常是由 HTML 和 CSS 来编写的,也可以使用模板语言或组件化的方式来构建。
Model:表示当前页面渲染时所依赖的数据源,可以在 Model 层中定义数据修改和操作的业务逻辑。Model 层通常是由 Javascript 对象或数组来表示的,也可以使用 Vuex 等状态管理工具来管理。
ViewModel:表示 Vue 的实例,它是 MVVM 的核心。ViewModel 负责连接 View 和 Model,保证视图和数据的一致性,这种轻量级的架构让前端开发更加高效、便捷。ViewModel 层通常是由 Vue 的选项和方法来定义的,也可以使用组合式 API 等新特性来增强。
MVVM 模型的工作原理是这样的:
当用户在 ...
前端知识笔记
本文主要记录了关于前端面试常考与常问的知识笔记,内容较多,不间断更新。
CSS
CSS中盒模型有传统的content-box与border-box,二者区别在于前者的width与height设置的是content-box,而后者设置的是border-box,注意背景图之类的属性显示依然相同,默认的background-origin属性就是padding-box,即背景图从padding-box开始显示,注意这个属性不要与background-color混淆,background-color默认全部显示。
CSS优先级
ID选择器的个数。
类选择器,属性选择器,伪类选择器的个数。
标签选择器,伪元素选择器的个数。
使用rem的移动端适配方案
核心思路为:
设置网页元素的width属性为rem单位。
通过js获取客户viewport宽度,并除以初始设置宽度,得到放大比例scale。
修改html元素的font-size,达到等比例适配效果。
1234567891011121314151617181920212223242526272829303132333435363738 ...