【sgExcelGrid】自定义组件:简单模拟Excel表格拖拽、选中单元格、横行、纵列、拖拽圈选等操作

特性:

  1. 可以自定义拖拽过表格
  2. 可以点击某个表格,拖拽右下角小正方形进行任意方向选取单元格
  3. 支持选中某一行、列
  4. 支持监听@selectedGrids、@selectedDatas事件获取选中项的DOM对象和数据数组
  5. 支持props自定义显示label字段别名

 sgExcelGrid源码

<template><div :class="$options.name"><div class="ruler-corner"></div><div class="horizontal-ruler" :style="{ left: `${-rulerPosition.x}px` }"><divclass="tick":hoverGrid="hoverGrid.x === A_Z[i]"@click="(hoverGrid = { x: A_Z[i] }), (mousedownGrid = {})"v-for="(a, i) in A_Z.slice(0, colCount_)":key="i">{{ a }}</div></div><div class="vertical-ruler" :style="{ top: `${-rulerPosition.y}px` }"><divclass="tick":hoverGrid="hoverGrid.y === i"@click="(hoverGrid = { y: i }), (mousedownGrid = {})"v-for="(a, i) in Math.ceil(pageSize / colCount_)":key="i">{{ i + 1 }}</div></div><div class="grids-scroll" ref="scrollContainer"><div class="grids" ref="dragContainer" :selectedGrids="selectedGrids.length > 0"><divclass="grid":hoverGridX="selectedGrids.length == 0 && hoverGrid.x === gridsData[i].x":hoverGridY="selectedGrids.length == 0 && hoverGrid.y === gridsData[i].y":mousedownGrid="mousedownGrid.x === gridsData[i].x && mousedownGrid.y === gridsData[i].y":dragMove="isMouseDragMove":type="a.strong ? 'primary' : ''"v-for="(a, i) in data":key="i"@mouseover="hoverGrid = gridsData[i]"@mouseout="hoverGrid = {}"@click="clickGrid(i)"><span :title="a[label]">{{ a[label] }}</span><i class="el-icon-close" @click="del(a)" /><divclass="position-text":title="`点击复制`"@click="$g.copy($g.stripHTML(getPositionText(gridsData[i])), true)"v-html="getPositionText(gridsData[i])"></div><div class="drag-select-btn" @mousedown.stop="clickResizeHandle"></div></div></div></div><!-- 拖拽 --><sgDragMoveTile :data="dragMoveTileData" @scroll="scroll" /></div>
</template>
<script>
import sgDragMoveTile from "@/vue/components/admin/sgDragMoveTile";
export default {name: "sgExcelGrid",components: {sgDragMoveTile,},data() {return {A_Z: [...Array(26)].map((v, i) => String.fromCharCode(i + 65)),hoverGrid: {}, //移入的宫格标记mousedownGrid: {}, //点击的宫格标记gridsData: [], //记录网格宫格状态selectedGrids: [], //被选中的网格宫格DOMselectedDatas: [], //被选中的网格宫格数据rulerPosition: { x: 0, y: 0 },dragMoveTileData: {},gridWidth: 200,gridHeight: 100,colCount_: 8,pageSize_: 100,isMouseDragMove: false, //鼠标拖拽选中移动label: `label`, //显示文本字段名};},props: ["value","props","data","pageSize", //每页显示多少个宫格"colCount", //列数],computed: {},watch: {props: {handler(newValue, oldValue) {if (newValue && Object.keys(newValue).length) {newValue.label && (this.label = newValue.label);}},deep: true, //深度监听immediate: true, //立即执行},pageSize: {handler(newValue, oldValue) {//console.log('深度监听:', newValue, oldValue);newValue && (this.pageSize_ = newValue);},deep: true, //深度监听immediate: true, //立即执行},data: {handler(newValue, oldValue) {this.init_gridsData();},deep: true, //深度监听immediate: true, //立即执行},colCount: {handler(newValue, oldValue) {//console.log('深度监听:', newValue, oldValue);newValue && (this.colCount_ = newValue);this.$nextTick(() => {this.$el.style.setProperty("--gridWidth", `${this.gridWidth}px`); //js往css传递局部参数this.$el.style.setProperty("--gridHeight", `${this.gridHeight}px`); //js往css传递局部参数this.$el.style.setProperty("--gridsWidth",`${this.colCount_ * this.gridWidth}px`); //js往css传递局部参数});},deep: true, //深度监听immediate: true, //立即执行},selectedGrids: {handler(newValue, oldValue) {this.$emit(`selectedGrids`, newValue || []);},deep: true, //深度监听// immediate: true, //立即执行},selectedDatas: {handler(newValue, oldValue) {this.$emit(`selectedDatas`, newValue || []);},deep: true, //深度监听// immediate: true, //立即执行},},created() {},mounted() {this.init_grid_view();this.addEvents();},destroyed() {this.removeEvents();},methods: {clickGrid(i) {(this.mousedownGrid = this.gridsData[i]),(this.hoverGrid = {}),this.resetSelectGrid();this.selectedGrids = [this.gridsData[i]];this.selectedDatas = [this.data[i]];},clickResizeHandle(e) {this.originRect = e.target.parentNode.getBoundingClientRect();this.originRect.bottomRightX = this.originRect.x + this.originRect.width; //右下角坐标.xthis.originRect.bottomRightY = this.originRect.y + this.originRect.height; //右下角坐标.ythis.__addWindowEvents();},__addWindowEvents() {this.__removeWindowEvents();addEventListener("mousemove", this.mousemove_window);addEventListener("mouseup", this.mouseup_window);},__removeWindowEvents() {removeEventListener("mousemove", this.mousemove_window);removeEventListener("mouseup", this.mouseup_window);},mousemove_window(e) {this.isMouseDragMove = true;let { x, y } = e;let minWidth = 0,minHeight = 0,maxWidth = innerWidth,maxHeight = innerHeight;x < 0 && (x = 0),y < 0 && (y = 0),x > maxWidth && (x = maxWidth),y > maxHeight && (y = maxHeight);let style = {};style.x = this.originRect.x;style.y = this.originRect.y;style.width = x - this.originRect.x;style.width <= minWidth &&((style.width = Math.abs(style.width)),((style.x = this.originRect.x - style.width),(style.width = style.width + this.originRect.width)));style.height = y - this.originRect.y;style.height <= minHeight &&((style.height = Math.abs(style.height)),((style.y = this.originRect.y - style.height),(style.height = style.height + this.originRect.height)));style.width > maxWidth && (style.width = maxWidth);style.height > maxHeight && (style.height = maxHeight);this.calcRectGrid(style);},mouseup_window(e) {this.isMouseDragMove = false;this.__removeWindowEvents();},resetAllGridStatus() {this.resetSelectGrid();this.mousedownGrid = {};},resetSelectGrid(d) {this.selectedGrids = [];this.selectedDatas = [];let grids = this.$refs.dragContainer.querySelectorAll(`.grid`);grids.forEach((v) => {v.removeAttribute("selected-left");v.removeAttribute("selected-top");v.removeAttribute("selected-right");v.removeAttribute("selected-bottom");v.removeAttribute("selected");});},// 计算是否选中格子calcRectGrid(rect) {this.resetSelectGrid();this.selectedGrids = this.getSelectedDoms({targetDoms: this.$refs.dragContainer.querySelectorAll(`.grid`),rect,});this.selectedGrids.forEach((grid) => {let grid_rect = grid.getBoundingClientRect();let gridRectScreenWidth = grid_rect.x + grid_rect.width;let gridRectScreenHeight = grid_rect.y + grid_rect.height;grid_rect.x <= rect.x &&rect.x < gridRectScreenWidth &&grid.setAttribute("selected-left", true);grid_rect.y <= rect.y &&rect.y < gridRectScreenHeight &&grid.setAttribute("selected-top", true);let rectScreenWidth = rect.x + rect.width;let rectScreenHeight = rect.y + rect.height;grid_rect.x < rectScreenWidth &&rectScreenWidth <= grid_rect.x + grid_rect.width &&grid.setAttribute("selected-right", true);grid_rect.y < rectScreenHeight &&rectScreenHeight <= grid_rect.y + grid_rect.height &&grid.setAttribute("selected-bottom", true);grid.setAttribute("selected", true);});},// 获取被选中的DOMgetSelectedDoms({ targetDoms, rect } = {}) {this.selectedDatas = [];return [...targetDoms].filter((targetDom, i) => {if (this.$g.isCrash(targetDom, rect)) {this.selectedDatas.push(this.data[i]);return targetDom;}}); // 获取被圈选的内容},// ----------------------------------------del(d) {this.$emit(`del`, d);},addEvents(d) {this.removeEvents();this.__removeWindowEvents();addEventListener("resize", this.resize);},removeEvents(d) {removeEventListener("resize", this.resize);},getPositionText(gridData) {return `<span>第${gridData.y + 1}行</span>&nbsp;<span>第${gridData.x}列</span>`;},init_grid_view() {this.resize();this.$nextTick(() => {this.init_sgDragMoveTile();});},init_gridsData(d) {this.gridsData = [...Array(this.pageSize_)].map((v, i) => ({x: this.A_Z[i % this.colCount_],y: Math.floor(i / this.colCount_),}));this.$nextTick(() => {this.resetAllGridStatus();});},init_sgDragMoveTile() {this.dragMoveTileData = {scrollContainer: this.$refs.scrollContainer,dragContainer: this.$refs.dragContainer,};},resize(d) {this.rulerPosition = {x: 0,y: 0,};},scroll(e) {this.rulerPosition = {x: e.target.scrollLeft,y: e.target.scrollTop,};},},
};
</script>
<style lang="scss" scoped>
.sgExcelGrid {/*禁止选中文本*/user-select: none;overflow: hidden;$tickDis: 40px;$gridWidth: var(--gridWidth);$gridHeight: var(--gridHeight);$gridsWidth: var(--gridsWidth);$scrollbarWidth: 14px;width: 100%;height: 100%;position: relative;.ruler-corner {position: absolute;z-index: 2;left: 0;top: 0;width: $tickDis;height: $tickDis;box-sizing: border-box;border: 1px solid #ebeef5;border-right: none;border-bottom: none;background-color: #eff2f755;/*遮罩模糊*/backdrop-filter: blur(5px);}.horizontal-ruler {position: absolute;z-index: 1;left: 0;top: 0;margin-left: $tickDis;display: flex;flex-wrap: nowrap;border-top: 1px solid #ebeef5;border-left: 1px solid #ebeef5;/*遮罩模糊*/backdrop-filter: blur(5px);// box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);.tick {display: flex;justify-content: center;align-items: center;flex-shrink: 0;width: $gridWidth;height: $tickDis;box-sizing: border-box;border-top: 1px solid transparent;border-left: 1px solid transparent;border-bottom: 1px solid #ebeef5;border-right: 1px solid #ebeef5;font-family: DIN-Black;background-color: #eff2f755;&[hoverGrid] {border-left: 1px solid #409eff;border-right: 1px solid #409eff;background-color: #b3d8ff99;color: #409eff;}}}.vertical-ruler {position: absolute;z-index: 1;left: 0;top: 0;margin-top: $tickDis;display: flex;flex-wrap: wrap;flex-direction: column;border-top: 1px solid #ebeef5;border-left: 1px solid #ebeef5;/*遮罩模糊*/backdrop-filter: blur(5px);// box-shadow: 2px 0 12px 0 rgba(0, 0, 0, 0.1);.tick {display: flex;justify-content: center;align-items: center;flex-shrink: 0;width: $tickDis;height: $gridHeight;box-sizing: border-box;border-top: 1px solid transparent;border-left: 1px solid transparent;border-bottom: 1px solid #ebeef5;border-right: 1px solid #ebeef5;font-family: DIN-Black;background-color: #eff2f7;background-color: #eff2f755;&[hoverGrid] {border-top: 1px solid #409eff;border-bottom: 1px solid #409eff;background-color: #b3d8ff99;color: #409eff;}}}.grids-scroll {width: calc(100% - #{$tickDis});height: calc(100vh - 310px);box-sizing: border-box;overflow: auto;position: relative;margin: $tickDis 0 0 $tickDis;.grids {width: calc(#{$gridsWidth} + #{$scrollbarWidth});min-height: calc(#{$gridHeight} + #{$scrollbarWidth});overflow: auto;display: flex;flex-wrap: wrap;align-content: flex-start;box-sizing: border-box;border-top: 1px solid #ebeef5;border-left: 1px solid #ebeef5;.grid {display: flex;justify-content: center;align-items: center;width: $gridWidth;height: $gridHeight;padding: 20px;box-sizing: border-box;border-top: 1px solid transparent;border-left: 1px solid transparent;border-bottom: 1px solid #ebeef5;border-right: 1px solid #ebeef5;word-wrap: break-word;word-break: break-all;white-space: break-spaces;position: relative;span {/*多行省略号*/overflow: hidden;word-break: break-all;white-space: break-spaces;display: -webkit-box;-webkit-box-orient: vertical;max-height: min-content;-webkit-line-clamp: 3;line-height: 1.2;}// 坐标文本.position-text {position: absolute;height: 22px;z-index: 1;left: 0px;top: 0px;display: none;flex-wrap: nowrap;white-space: nowrap;align-items: center;color: white;background-color: #00000055;box-sizing: border-box;padding: 0 5px;border-radius: 0 0 8px 0;>>> span {font-size: 12px !important;}cursor: cell;&:hover {background-color: #409eff;color: white;}}// 删除i.el-icon-close {z-index: 1;display: none;position: absolute;right: 0;top: 0;font-size: 12px !important;justify-content: center;align-items: center;color: white;background-color: #409eff;box-sizing: border-box;padding: 5px;border-radius: 0 0 0 8px;cursor: pointer;&:hover {background-color: #f56c6c;}}// 拖拽选区.drag-select-btn {position: absolute;height: 9px;width: 9px;z-index: 1;right: -4.5px;bottom: -4.5px;display: none;box-sizing: border-box;border: 2px solid white;background-color: #f56c6c;cursor: crosshair;}&:nth-of-type(2n) {background-color: #eff2f755;}&[hoverGridX] {border-left: 1px solid #409eff;border-right: 1px solid #409eff;background-color: #f2f8fe;}&[hoverGridY] {border-top: 1px solid #409eff;border-bottom: 1px solid #409eff;background-color: #f2f8fe;}&[mousedownGrid] {border: 1px solid #f56c6c;background-color: #f56c6c22;.drag-select-btn {display: block;}}&[selected] {// border: 1px solid #f56c6c;border-top: 1px solid transparent;border-left: 1px solid transparent;border-right: 1px solid #f56c6c22;border-bottom: 1px solid #f56c6c22;background-color: #f56c6c22;.position-text {background-color: #f56c6c66;color: white;&:hover {background-color: #f56c6c;}}i.el-icon-close {background-color: #f56c6c66;&:hover {background-color: #f56c6c;}}.drag-select-btn {display: none;}&:hover:not([dragMove]) {border: 1px solid #f56c6c;background-color: #f56c6c66 !important;}}&[selected-left] {border-left: 1px solid #f56c6c;}&[selected-top] {border-top: 1px solid #f56c6c;}&[selected-right] {border-right: 1px solid #f56c6c;}&[selected-bottom] {border-bottom: 1px solid #f56c6c;}&[mousedownGridX] {border-left: 1px solid #f56c6c;border-right: 1px solid #f56c6c;background-color: #f56c6c22;}&[mousedownGridY] {border-top: 1px solid #f56c6c;border-bottom: 1px solid #f56c6c;background-color: #f56c6c22;}&[dragMove] {}&:hover:not([mousedownGrid]):not([dragMove]) {background-color: #b3d8ff99;i,.position-text {display: flex;}}}&[selectedGrids] {.grid {&:hover:not([mousedownGrid]):not([dragMove]):not([selected]) {border: 1px solid #409eff;}}}}}
}
</style>

应用

<template><sgExcelGrid:props="{ label: `MC` }":data="gridDatas":pageSize="pageSize"@del="delGrid"@selectedDatas="selectedDatas"/>
</template>
<script>
import sgExcelGrid from "@/vue/components/admin/sgExcelGrid";
export default {components: {sgExcelGrid,},data() {return {gridDatas: [{ ID: 1, value: 1, MC: "显示文本1" },{ ID: 2, value: 2, MC: "显示文本2" },{ ID: 3, value: 3, MC: "显示文本3" },{ ID: 4, value: 4, MC: "显示文本4" },{ ID: 5, value: 5, MC: "显示文本5" },],pageSize: 100, //每页显示多少个单元格rectSelectIDS: [], //选中的ID数组};},props: ["value"],computed: {},watch: {},created() {},mounted() {},destroyed() {},methods: {selectedDatas(d) {this.rectSelectIDS = d.map((v) => v.ID); //获取选中项ID数组},delGrid(d) {//删除单元格},},
};
</script>

基于【sgDragMoveTile】自定义组件:拖拽瓦片图、地图、大图,滚动条对应同步滚动_用鼠标拖拽(drag)内容div”,滚动条对应同步滚动 vue-CSDN博客文章浏览阅读140次。【代码】【sgDragMoveTile】自定义组件:拖拽瓦片图、地图、大图,滚动条对应同步滚动。_用鼠标拖拽(drag)内容div”,滚动条对应同步滚动 vuehttps://blog.csdn.net/qq_37860634/article/details/133292981

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/733780.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Swift 入门学习:集合(Collection)类型趣谈-下

概览 集合的概念在任何编程语言中都占有重要的位置&#xff0c;正所谓&#xff1a;“古来聚散地&#xff0c;宿昔长荆棘&#xff1b;游人聚散中&#xff0c;一片湖光里”。把那一片片、一瓣瓣、一粒粒“可耐”的小精灵全部收拢、吸纳的井然有序、条条有理&#xff0c;怎能不让…

React Three Fiber快速入门

https://threejs-journey.com/lessons/what-are-react-and-react-three-fiber#学习笔记 1.基础知识 resize 填充模版 构建第一个场景 we didn’t have to create a scenewe didn’t have to create the webglrenderthe scene is being rendered on each framethe default…

ubuntu23.10安装搜狗拼音

1.添加fcitx仓库 sudo add-apt-repository ppa:fcitx-team/nightly 更新: sudo apt-get update 安装fcitx sudo apt-get install fcitx fcitx安装成功 切换输入系统为fcitx

【C语言】tcp_transmit_skb

一、__tcp_transmit_skb讲解 这个函数 __tcp_transmit_skb() 是 Linux 内核中 TCP/IP 协议栈的一部分&#xff0c;负责处理传输控制协议&#xff08;TCP&#xff09;数据包的发送。具体来说&#xff0c;这个函数将 TCP 头部添加到一个没有任何头部信息的 socket buffer (sk_bu…

Diddler抓包工具——学习笔记

F12抓包 302【重定向】&#xff1a;当你发送了一个请求之后&#xff0c;那么这个请求重定向到了另外的资源 跳转和重定向的区别&#xff1a; 跳转是会把数据传到新的地址 重定向不会把新的数据传到新的地址 使用F12抓包时一定要打开Preserve Log开关&#xff0c;作用是保留…

万用表数据导出变化曲线图——pycharm实现视频数据导出变化曲线图

万用表数据导出变化曲线图——pycharm实现视频数据导出变化曲线图 一、效果展示二、环境配置三、代码构思四、代码展示五、代码、python环境包链接 一、效果展示 图1.1 效果展示 &#xff08;左图&#xff1a;万用表视频截图&#xff1b;右图&#xff1a;表中数据变化曲线图&am…

Springboot整合Mybaits启动过程

Springboot整合Mybaits启动过程 1.前言2.MybatisAutoConfiguration3.SqlSessionFactoryBean3.1 XMLConfigBuilder.parse()3.1.1 XMLMapperBuilder.parse()3.1.1.1 XMLStatementBuilder.parse() 4.SqlSession4.1 Executor 1.前言 直接加载mybatis配置文件&#xff0c;然后创建S…

Matlab|【EI复现】电动汽车集群并网的分布式鲁棒优化调度模型

目录 1 内容简介 2 关键知识点 2.1 三类电动汽车模型 3 程序结果 4 下载链接 1 内容简介 电动汽车的数据模型种类繁多&#xff0c;但是用到比较高阶数学方法的并不多&#xff0c;本次分享的程序是下图所示的文章。 采用分布鲁棒优化模型&#xff0c;用到鲁棒对等转换&…

MyBatis3源码深度解析(七)JDBC单连接事务

文章目录 前言2.7 JDBC单连接事务2.7.1 事务的开启与提交2.7.2 事务隔离级别2.7.2.1 并发访问问题&#xff08;1&#xff09;脏读&#xff08;2&#xff09;不可重复读&#xff08;3&#xff09;幻读 2.7.2.2 事务隔离级别&#xff08;1&#xff09;TRANSACTION_NONE&#xff1…

ChatGPT 串接到 Discord - 团队协作好助理

ChatGPT 串接到 Discord - 团队协作好助理 ChatGPT 是由 OpenAI 开发的一个强大的语言模型&#xff0c;本篇文章教你如何串接 Discord Bot &#xff0c;协助团队在工作上更加高效并促进沟通与协作。使 ChatGPT 发挥出最大的功效&#xff0c;进一步提升工作效率和团队协作能力。…

Redis 内存的优化

目录 前言 Redis 的内存碎片问题 判断Redis 内存碎片 如何清理内存碎片&#xff1f; 前言 我想讲一下怎么提高Redis 内存的利用率&#xff0c;redis 的数据是保存在内存中。对内存的利用率低&#xff0c;意味着存的数据很少&#xff0c;并不意味着就没有内存了&#xff0c…

【解读】OWASP大语言模型应用程序十大风险

OWASP大型语言模型应用程序前十名项目旨在教育开发人员、设计师、架构师、经理和组织在部署和管理大型语言模型&#xff08;LLM&#xff09;时的潜在安全风险。该项目提供了LLM应用程序中常见的十大最关键漏洞的列表&#xff0c;强调了它们的潜在影响、易利用性和在现实应用程序…

利用华为CodeArts持续交付项目演示流程

软件开发生产线&#xff08;CodeArts&#xff09;是面向开发者提供的一站式云端平台&#xff0c;即开即用&#xff0c;随时随地在云端交付软件全生命周期&#xff0c;覆盖需求下发、代码提交、代码检查、代码编译、验证、部署、发布&#xff0c;打通软件交付的完整路径&#xf…

力扣---腐烂的橘子

题目&#xff1a; bfs思路&#xff1a; 感觉bfs还是很容易想到的&#xff0c;首先定义一个双端队列&#xff08;队列也是可以的~&#xff09;&#xff0c;如果值为2&#xff0c;则入队列&#xff0c;我这里将队列中的元素定义为pair<int,int>。第一个int记录在数组中的位…

day15_集合_ArrayList

今日内容 零、 复习昨日 一、集合框架体系 二、Collection 三、泛型 四、迭代 五、List(ArrayList、LinkedList) 零、 复习昨日 日期解析的方法签名(字符串–>日期) Date parse(String s) 日期格式化的方法签名(日期–>字符串) String format(Date date) 运行时异常有哪些…

19、电源管理入门之微内核中的电源管理

目录 1. QNX电源管理框架 2. QNX客户端API库 3. QNX代码分析 4. Fuchsia中的电源管理 5. Minix中的电源管理 6. Harmony OS中的电源管理 之前介绍的电源管理机制基本都是在Linux中实现的,可以看到很复杂,各种框架,明明一个操作非要转来转去,而且在内核里面实现,跟内…

【HarmonyOS】ArkTS-联合类型

目录 联合类型实例 联合类型 联合类型是一种灵活的数据类型&#xff0c;它修饰的变量可以存储不同类型的数据。 语法&#xff1a;let 变量: 类型1 | 类型2 | 类型3 值 基于联合类型&#xff0c;变量可存不同类型数据 实例 // 需求&#xff1a;定义一个变量&#xff0c;存放…

Spring web开发(入门)

1、我们在执行程序时&#xff0c;运行的需要是这个界面 2、简单的web接口&#xff08;127.0.0.1表示本机IP&#xff09; package com.example.demo;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestCont…

【OD】算法二

开源项目热度榜单 某个开源社区希望将最近热度比较高的开源项目出一个榜单&#xff0c;推荐给社区里面的开发者。对于每个开源项目&#xff0c;开发者可以进行关注(watch)、收藏(star)、fork、提issue、提交合并请求(MR)等。 数据库里面统计了每个开源项目关注、收藏、fork、…

垃圾回收:JavaScript内存管理的利器

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…