element-plus源码学习后,我了解到多种多样的写法

news2024/11/26 4:22:43

文章封面来自于深圳湾桥,很漂亮!

本文是阅读源码之后,学习到一些新写法,平常业务开发也可以用起来。在我看来,阅读源码,不但能知道该框架的底层原理,出现bug时,可以快速排查和修复,更重要的是,阅读源码就像向优秀的人学习,掌握我们不曾了解的新知识点,看看别人是如何编写出漂亮的,可复用的代码。

操作符!.

onMounted(() => {
  // 组合在一起,!. 就是“强制执行方法,然后再访问它的返回值”。
  const items = breadcrumb.value!.querySelectorAll(`.${ns.e('item')}`)
  if (items.length) {
    items[items.length - 1].setAttribute('aria-current', 'page')
  }
})

element-plus: 只有控制到页面上行为的函数就存在于vue文件中,其他逻辑处理函数,都在ts文件中

取值和监听值变化,不使用watch

const checkedValue = computed<CascaderValue>({
  get() {
    return cloneDeep(props.modelValue) as CascaderValue
  },
  set(val) {
    emit(UPDATE_MODEL_EVENT, val)
    emit(CHANGE_EVENT, val)
    if (props.validateEvent) {
      formItem?.validate('change').catch((err) => debugWarn(err))
    }
  },
})

方法调用后面加!

// 透传
  const carouselContext = inject(carouselContextKey)!

在 JavaScript 中,方法调用后面加上感叹号 ! 通常是用来强制执行(Force execution)这个方法。以数组作为例子:- 使用数组方法时不加感叹号,它只会返回方法的结果,但不会改变数组自身:

let arr = [1, 2, 3];
let newArr = arr.map(x => x * 2);

// newArr [2, 4, 6]
// arr 还是 [1, 2, 3], 数组本身没有变化

而加上感叹号后,会修改数组自身:

let arr = [1, 2, 3];
arr.map!(x => x * 2);

// arr 变为 [2, 4, 6]
// 数组自身被修改了

这是因为,数组的 map 等方法本身是不会修改原数组的,而加上感叹号后则会强制修改数组自身。

其他数组方法同理,比如 filter、forEach、sort 等,不加感叹号只返回结果,加感叹号则修改原数组。

总的来说,感叹号 ! 被用于强制执行某个不会产生副作用的方法,产生副作用(side effect),修改调用者自身。

这一点和 Haskell 中的特写运算符(Bang pattern)! 类似,也用于产生 computations with effects。

使用感叹号需要小心,可能会影响程序的可预测性和数据不变性,但对于需要改变源数据的场景,使用感叹号可以使代码更加简洁。

透传使用symbol

provide(
      CASCADER_PANEL_INJECTION_KEY, // 透传下去,使用Symbol作为唯一值
      reactive({
        config,
        expandingNode,
        checkedNodes,
        isHoverMenu,
        initialLoaded,
        renderLabelFn,
        lazyLoad,
        expandNode,
        handleCheckChange,
      })
    )


export const CASCADER_PANEL_INJECTION_KEY: InjectionKey<ElCascaderPanelContext> =
  Symbol()



强制执行,会影响最终值

获取组件实例,调用组件自定义事件

const { emit } = getCurrentInstance()!

const model = computed({
    get() {
      return isGroup.value
        ? checkboxGroup?.modelValue?.value
        : props.modelValue ?? selfModel.value
    },

    set(val: unknown) {
      if (isGroup.value && isArray(val)) {
        isLimitExceeded.value =
          checkboxGroup?.max?.value !== undefined &&
          val.length > checkboxGroup?.max.value
        isLimitExceeded.value === false && checkboxGroup?.changeEvent?.(val)
      } else {
        emit(UPDATE_MODEL_EVENT, val)
        selfModel.value = val
      }
    },
  })

  1. getCurrentInstance() 函数可以在 setup() 中获取到当前组件实例。

  2. 但是直接调用 getCurrentInstance() 会返回一个可选型(maybe)的实例,可能为 null。

  3. 为了确保获取到实例,使用 ! 非空断言运算符,强制转换为非空实例。

  4. 所以 getCurrentInstance()! 确保了返回的实例不会是 null。

  5. 然后使用 ES6 解构赋值语法,从实例中取出 emit 方法。

  6. emit 方法用于在组件内部触发自定义事件。

  7. 这种方式避免了代码中出现隐式的 this,使代码更清晰可读。

  8. 是 Vue 3 Composition API 中常用的一种实例访问模式,用于在 setup() 中获取实例属性和方法。

unref与ref

unref 和 ref 都可以用来获取响应式对象的值,但是有以下几点关键区别:

  1. unref 是一个函数,ref 是创建ref对象的方法。unref直接返回值,ref会创建一个响应式的引用对象。

  2. unref 获取值,ref 创建值的引用。unref目的是获取值,ref是创建一个值的响应式引用。

  3. unref 参数可以是基础值或响应式对象,ref只接受基础值创建引用。unref的参数可以是基础类型的值,也可以是ref或reactive对象,它会返回对象的值或对象本身。ref只接受基础类型的值来创建一个响应式的引用对象。

  4. unref 使用场景是在组件逻辑中获取值,ref创建应用于模板的响应式引用。unref常用于组件逻辑中,需要获取响应式对象的原始值时使用。ref更多地在模板中使用,创建一个可以响应式跟踪的引用。

unref直接返回的值,不需要用.value访问

rAF & cAF

requestAnimationFrame 和 cancelAnimationFrame 是浏览器用来实现高性能动画的 API。它可以把每一帧的代码编排到浏览器的一次重绘中,避免频繁的重绘导致性能问题。

这两个函数在频繁重绘调用,可以减轻浏览器负担

比如:定时器

const isClient = typeof window !== "undefined";

export const rAF = (fn: () => void) =>
  isClient
    ? window.requestAnimationFrame(fn)
    : (setTimeout(fn, 16) as unknown as number)

export const cAF = (handle: number) =>
  isClient ? window.cancelAnimationFrame(handle) : clearTimeout(handle)

(event.target as HTMLElement).closest

const handleMouseDown = (event: MouseEvent) => {
  const target = (event.target as HTMLElement).closest('td')
  if (!target) return
  focusWithClick = true
}

const handleMouseUp = (event: MouseEvent) => {
  const target = (event.target as HTMLElement).closest('td')
  if (!target) return
  focusWithClick = false
}

closest() 方法会沿着 DOM 树向上寻找匹配的选择器的第一个祖先元素,在这里是查找最近的 元素。所以整个代码的作用就是:- 获取点击事件的目标元素

  • 将其转化为 HTMLElement 类型
  • 在其祖先元素中查找最近的 td元素
  • 并返回这个 td 元素这样可以方便地通过点击事件获取到对应的 td 元素进行后续操作。

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

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

相关文章

如何使用unittest批量管理Python接口自动化测试用例?

我们日常项目中的接口测试案例肯定不止一个&#xff0c;当案例越来越多时我们如何管理这些批量案例&#xff1f;如何保证案例不重复&#xff1f;如果案例非常多&#xff08;成百上千&#xff0c;甚至更多&#xff09;时如何保证案例执行的效率&#xff1f;如何做&#xff08;批…

如何记住表格列宽,供下次调用,来提升用户操作体验?

如何让系统记住用户每次拖动表格后的列宽&#xff0c;下次表格初始化就可以直接用该列宽&#xff0c;来显示表格的每一个列。每个用户的使用习惯不一样&#xff0c;和使用的功能不一样&#xff0c;即使是同一套系统&#xff0c;只要用户不同&#xff0c;就有可能需要不同的列宽…

【全局异常】返回值通过【枚举】的形式返回

&#x1f4da;目录 需求创建抽象类创建业务枚举使用枚举升级简单的方式实现:使用注解方式实现: 需求 后台程序发生异常&#xff0c;通过全局的异常类使用枚举的方式把错误信息返回给前端。 全局异常类处理方式&#xff1a; 改造前使用 改造后使用枚举传递&#xff1a; 创建抽象…

高楼电脑端+黑金手机端个人引导页HTML源码

https://wwwf.lanzout.com/ipAfg12n5y4f 二、黑金主题网址导航 https://wwwf.lanzout.com/ieSVB12n5y2d

C语言文件操作【超详解】

目录 1.为什么使用文件 2.什么是文件 2.1程序文件 2.2数据文件 2.3文件名 3.文件的打开和关闭 3.1文件指针 3.2文件的打开和关闭 3.2.1fopen函数 3.2.2fclose函数 4.文件的顺序读写 4.1顺序读写函数介绍 4.1.1 fputc、fgetc和fputs、fgets 4.1.2fprintf、fscanf&…

装饰(Decorator)模式

目录 动机使用场景参与者协作效果实现相关模式应用和思考类图 装饰模式是对象结构型模式&#xff0c;动态地给一个对象添加一些额外的职责。就增加的功能来说装饰器模式相比生成子类更为灵活。 动机 有时候需要给某个对象而不是整个类添加一些功能&#xff0c;使用继承也可以&…

【SDOF振荡器的非线性-非弹性多轴时间响应分析】用于SDOF振荡器非线性非弹性时程分析的鲁棒性分析研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

经典指针笔试题你会了嘛

作者简介&#xff1a;დ旧言~&#xff0c;目前大一&#xff0c;现在学习Java&#xff0c;c&#xff0c;Python等 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 望小伙伴们点赞&#x1f44d;收藏✨加关注哟&#x1f495;&#x1f495; 指针和数组笔试题 &…

【Linux】多线程 之 POSIX信号量

文章目录 1. 概念2. 信号量的工作机制3. 认识接口sem_init ——初始化信号量sem_destroy——销毁信号量sem_wait ——申请信号量sem_post ——释放信号量 4. 基于环形队列的生产消费模型原理解析代码代码解析ringqueue类构造析构push ——生产pop ——消费 代码实现Ringqueue.h…

精通Skia引擎,发挥应用程序中高性能图形的潜力

Skia是由Google开发的一个开源的2D图形库。它提供了丰富的图形绘制、图像处理和渲染功能&#xff0c;适用于多个平台&#xff0c;包括操作系统、浏览器和移动设备等。Skia主要用于处理2D图形的绘制、文字渲染、图像处理和用户界面的呈现。 特点和功能&#xff1a; 高性能&…

基于Javaweb实现ATM机系统开发实战(十一)存储交易记录

首先创建一个业务接口&#xff1a; package com.atm.service;import com.atm.pojo.RunMessage;//交易记录的业务接口 public interface RunMessageService{//添加交易记录public void addRunMessage(RunMessage runMessage) throws Exception ; }再完成业务接口的实现类&#…

iNav开源代码之FAILSAFE

iNav开源代码之FAILSAFE 1. 源由2. FAILSAFE类别3. FAILSAFE配置4. FAILSAFE阶段&状态机5. 参考资料 1. 源由 最近因为炸机&#xff0c;百思不得其解。 关于炸鸡的过程&#xff0c;就不再展开&#xff0c;都是“泪”啊&#xff01;想进一步了解的&#xff0c;请参阅前面的…

科普一下Elasticsearch中BM25算法的使用

首先还是先了解几个概念&#xff0c;Elasticsearch是一个开源的分布式搜索和分析引擎&#xff0c;它使用一系列算法来计算文档的相关性分数&#xff08;relevance score&#xff09;。这些算法用于确定查询与文档的匹配程度&#xff0c;以便按相关性对搜索结果进行排序。以下是…

【C++】多线程编程一(初识并发和多线程)

目录 一、并发和并行的概念 1.并发 2.并行 3.并发和并行的区别 二、并发的途径 多进程并发 多线程并发 三、C11相关多线程编程的头文件 一、并发和并行的概念 1.并发 并发&#xff1a;指同一时刻只能有一条指令执行&#xff0c;但是多个进程指令被快速地轮换执行&#…

C语言--文件操作

文章目录 前言文件文件名 文件的打开和关闭文件指针文件的打开和关闭 文件的顺序读写fgetc、fputcfgets、fputsfprintf、fsanffread、fwrite 文件的随机读写fseekftellrewind 文本文件和二进制文件文件读取结束的判定feof 文件缓冲区 前言 在我们写完一个程序之后&#xff0c;…

【数据结构】树二叉树的概念以及堆的详解

⭐️ 往期相关文章 ✨链接1&#xff1a;【数据结构】顺序表 ✨链接2&#xff1a;【数据结构】单链表 ✨链接3&#xff1a;【数据结构】双向带头循环链表 ✨链接4&#xff1a;【数据结构】栈和队列 ⭐️ 树的概念 百度百科的解释&#xff1a;树是一种非线性的数据结构&#xf…

Jmeter四种关联方法讲解

目录 方法一&#xff0c;从前一个请求中取&#xff0c;用正则表达式提取器。 二、json path extractor 三、json extractor 四、XPath Extractor 方法一&#xff0c;从前一个请求中取&#xff0c;用正则表达式提取器。 具体方法&#xff0c;在需要获得数据的请求上右击添加…

【09】STM32·HAL库-新建HAL库版本MDK工程 | 下载STM32固件库

目录 1&#xff0c;新建工程前的准备工作&#xff08;了解&#xff09;1.1下载相关STM32Cube 官方固件包&#xff08;F1/F4/F7/H7&#xff09; 2&#xff0c;新建HAL库版本MDK工程步骤&#xff08;熟悉&#xff09;2.1新建工程文件夹2.1.1Drivers文件夹2.1.2Middlewares文件夹2…

基数排序(Radix_Sort)

基数排序 (Radix Sort)-20230715 前言 基数排序适用于多关键字排序&#xff0c;与前述的比较排序不同&#xff0c;实现基数排序不需要对关键字进行比较和移动。简而言之&#xff0c;基数排序是一类借助多关键字排序的思想对单逻辑关键字实现排序的方法。 多关键字排序 先看…

SwiftUI 原生或利用 Vision 检测限定高度的 Text 视图能否完整显示文本的方法

功能需求 在 SwiftUI 开发中,为了节省空间我们往往会为内容很长的文本视图(Text)限定一个高度,然后让用户决定是否展开显示其完整内容。 如上图所示,为了节省空间我们对 Text 视图高度做了限制,然后根据文本长度自动显示或隐藏展开按钮,用户点击该按钮即可展开显示完整…