1.2023新春版:React+Antd开发Chrome插件教程(Manifest V3)
2.Ant Design Vue 3.0 的组件组件那些正经事儿
3.没写过复杂 React 组件?来实现下 AntD 的 Space 组件吧
4.读读antd源码之通用组件
5.antd 中 Form 表单的使用
6.ä¸çå°±ä¼çè¶
å®ç¨å°ç»ä»¶ä¹LoadingButton
2023新春版:React+Antd开发Chrome插件教程(Manifest V3)
在深入探讨Chrome浏览器插件开发时,随着技术的源码更新与演变,开发者需要紧跟趋势并采用最新的组件组件开发规范以确保应用的兼容性、安全性和性能。源码本文旨在介绍并指导React与Antd在Manifest V3环境下的组件组件Chrome插件开发流程,以适应年及以后的源码安徽全网推广源码开发环境。 随着Manifest V3的组件组件引入,Chrome插件开发迎来了新的源码变革。此版本旨在增强隐私保护、组件组件提升安全性能、源码优化跨平台兼容性及简化开发流程。组件组件具体来说,源码其改进包括:隐私保护:插件在运行时仅在必要时请求权限,组件组件减少对用户数据的源码访问。
安全措施:限制外部资源的组件组件访问,特别是禁止引入外部JavaScript,以减少安全风险。
性能优化:确保插件能够在各种设备上流畅运行,适应多插件环境下。
开发友好:降低开发门槛,提供更直观、高效的开发体验。
增强功能:持续提升插件的能力,丰富功能实现。
为了适应Manifest V3,开发者需从多个角度进行调整和优化,包括但不限于服务工作者的引入、网络请求管理、资源访问控制以及使用现代JavaScript特性如Promises和async/await。 本文将分步骤指导如何搭建和配置基于React和Antd的Chrome插件项目,包括初始化项目、精简配置、实现基础功能、配置Webpack以满足Chrome插件构建需求、支持CSS预处理器(如Sass、Less和Stylus)以及优化构建过程等。通过遵循这些步骤,开发者能够高效地开发出符合最新标准的Chrome插件,确保应用的视频解析api源码稳定性和兼容性。 具体操作包括使用create-react-app创建项目、删除不必要的文件以精简配置、配置manifest.json以符合Manifest V3规范、规划目录结构以支持不同类型的脚本文件、配置Webpack以生成符合Chrome插件要求的输出文件、设置国内镜像源以提高构建速度、暴露Webpack配置以自定义构建过程、支持CSS预处理语言(如Sass、Less和Stylus)以增强样式灵活性、设置路径别名以简化导入路径、禁用构建生成source map文件以保护源代码安全以及配置多入口以适应不同脚本文件的需求。 在构建过程中,开发者需要确保遵循Chrome插件的官方指南,合理规划目录结构、配置文件和构建流程,以确保最终生成的插件能够正常运行在各种浏览器环境中,并在功能、性能和安全性方面达到预期标准。Ant Design Vue 3.0 的那些正经事儿
Ant Design Vue 3.0 的发布并非仓促之举,它标志着一个重要的里程碑,旨在提供更深入的源码重构、增强的功能特性、优化的易用性和性能提升。以下是3.0版本的主要亮点:
1. **源码重构与提升**:从 TypeScript 和 Composition API 开始,大部分组件已切换至这种架构,以提升类型提示和管理复杂度。虽然Vue 3在TS支持上有所增强,但组件库的泛型组件和属性类型复用仍面临挑战。团队鼓励对TS技术熟练者加入,共同改进。
2. **功能同步更新**:3.0引入了AntD 4.x的多项功能,如自定义时间库、虚拟滚动、暗黑主题、无障碍辅助和RTL支持,以及CSS Variables。
3. **易用性优化**:在Table、TreeSelect等组件的趋势跟踪指标源码自定义渲染API上,3.0简化了配置,引入统一的`v-slot`命名,减少了配置膨胀和未来扩展的风险。
4. **性能改进**:FormItem的渲染优化、TreeNode的废弃以及Tree和TreeSelect的虚拟滚动功能,旨在提升组件的性能和大数据渲染能力。
尽管Table暂未支持虚拟滚动,但团队计划推出专门的产品解决大数据问题,预计在接下来的1-2个月推出。
升级Ant Design Vue 3.0,你可以期待更简洁的代码、更好的性能,以及与社区的持续互动。如果你对这些改变感兴趣,别错过月日的Vue专场会议,详细内容可通过关注公众号获取。
没写过复杂 React 组件?来实现下 AntD 的 Space 组件吧
React 开发者在日常工作中经常编写组件,但这些大多为业务组件,复杂度并不高。
组件通常通过传入 props 并使用 hooks 组织逻辑来渲染视图,偶尔会用到 context 跨层传递数据。
相对复杂的组件是怎样的呢?antd 组件库中就有许多。
今天,我们将实现antd组件库中的一个组件——Space组件。
首先,我们来了解一下Space组件的使用方法:
Space是一个布局组件,用于设置组件的间距,还可以设置多个组件的对齐方式。
例如,我们可以使用Space组件来包裹三个盒子,设置方向为水平,渲染结果如下:
当然,我们也可以设置为垂直:
水平和垂直的间距可以通过size属性设置,如large、middle、small或任意数值。
多个子节点可以设置对齐方式,如start、asp网站源码恶搞end、center或baseline。
此外,当子节点过多时,可以设置换行。
Space组件还可以单独设置行列的间距。
最后,它还可以设置split分割线部分。
此外,你也可以不直接设置size,而是通过ConfigProvider修改context中的默认值。
Space组件会读取context中的size值,这样如果有多个Space组件,就不需要每个都设置,只需要添加一个ConfigProvider即可。
这就是Space组件的全部用法,简单回顾一下几个参数和用法:
Space组件的使用方法很简单,但功能非常强大。
接下来,我们来探讨一下这样的布局组件是如何实现的。
首先,我们来看一下它最终的DOM结构:
每个box都包裹了一层div,并设置了ant-space-item类。
split部分包裹了一层span,并设置了ant-space-item-split类。
最外层包裹了一层div,并设置了ant-space类。
这些看起来很简单,但实现起来却有很多细节。
下面我们来写一下Space组件的实现代码:
首先,我们声明组件props的类型。
需要注意的是,style是React.CSSProperties类型,即可以设置各种CSS样式。
split是React.ReactNode类型,即可以传入jsx。
其余参数的类型根据其取值而定。
Space组件会对所有子组件包裹一层div,查看php页面源码因此需要遍历传入的children并做出修改。
props传入的children需要转换为数组,可以使用React.Children.toArray方法。
虽然children已经是数组了,但为什么还要使用React.Children.toArray转换一下呢?
因为toArray可以对children进行扁平化处理。
更重要的是,直接调用children.sort()会报错,而toArray之后就不会了。
因此,我们会使用React.Children.forEach、React.Children.map等方法操作children,而不是直接操作。
但这里我们有一些特殊的需求,比如空节点不过滤掉,依然保留。
因此,我们使用React.Children.forEach自己实现toArray:
这部分比较容易理解,就是使用React.Children.forEach遍历jsx节点,对每个节点进行判断,如果是数组或fragment就递归处理,否则push到数组中。
保不保留空节点可以根据keepEmpty的option来控制。
这样,children就可以遍历渲染item了,这部分是这样的:
我们单独封装了一个Item组件。
然后,我们遍历childNodes并渲染这个Item组件。
最后,我们将所有的Item组件放在最外层的div中:
这样就可以分别控制整体布局和Item布局了。
具体的布局还是通过className和样式来实现的:
className通过props计算而来,使用了classnames包,这是react生态中常用的包,根据props动态生成className基本都会使用这个包。
这个前缀是动态获取的,最终就是ant-space的前缀。
这些class的样式都定义好了:
整个容器使用inline-flex,然后根据不同的参数设置align-items和flex-direction的值。
最后一个direction的css可能大家没用过,是设置文本方向的。
这样,就通过props动态给最外层div添加了相应的className,设置了对应的样式。
但还有一部分样式没有设置,也就是间距。
其实这部分可以使用gap设置,当然,也可以使用margin,但处理起来比较麻烦。
不过,antd这种组件自然要做得兼容性好一点,所以两种都支持,支持gap就使用gap,否则使用margin。
问题来了,antd是如何检测浏览器是否支持gap样式的呢?
antd创建一个div,设置样式,并添加到body下,然后查看scrollHeight的值,最后删除这个元素。
这样就可以判断是否支持gap、column等样式,因为不支持的话高度会是0。
然后antd提供了一个这样的hook:
第一次会检测并设置state的值,之后直接返回这个检测结果。
这样组件里就可以使用这个hook来判断是否支持gap,从而设置不同的样式了。
最后,这个组件还会从ConfigProvider中取值,我们之前见过:
所以,我们再处理一下这部分:
使用useContext读取context中的值,并设置为props的解构默认值,这样如果传入了props.size就使用传入的值,否则使用context中的值。
这里给Item子组件传递数据也是通过context,因为Item组件不一定会在哪一层。
使用createContext创建context对象:
把计算出的size和其他一些值通过Provider设置到spaceContext中:
这样子组件就能拿到spaceContext中的值了。
这里使用了useMemo,很多同学不会用,其实很容易理解:
props变化会触发组件重新渲染,但有时候props并不需要变化却每次都变,这样就可以通过useMemo来避免它不必要的更新。
useCallback也是同样的道理。
计算size时封装了一个getNumberSize方法,为字符串枚举值设置了一些固定的数值:
至此,这个组件我们就完成了,当然,Item组件还没展开讲。
先来欣赏一下这个Space组件的全部源码:
回顾一下要点:
思路理得差不多了,再来看一下Item的实现:
这部分比较简单,直接上全部代码了:
通过useContext从SpaceContext中取出Space组件里设置的值。
根据是否支持gap来分别使用gap或margin、padding的样式来设置间距。
每个元素都用div包裹一下,设置className。
如果不是最后一个元素并且有split部分,就渲染split部分,用span包裹。
这块还是比较清晰的。
最后,还有ConfigProvider的部分没有看:
这部分就是创建一个context,并初始化一些值:
有没有感觉antd里用context简直太多了!
确实。
为什么?
因为你不能保证组件和子组件隔着几层。
比如Form和FormItem:
比如ConfigProvider和各种组件(这里是Space):
还有刚讲过的Space和Item。
它们能用props传数据吗?
不能,因为不知道隔几层。
所以antd里基本都是用context传数据的。
你会你在antd里会见到大量的用createContext创建context,通过Provider修改context值,通过Consumer或useContext读取context值的这类逻辑。
最后,我们来测试一下自己实现的这个Space组件吧:
测试代码如下:
这部分不用解释了。就是ConfigProvider包裹了两个Space组件,这两个Space组件没有设置size值。
设置了direction、align、split、wrap等参数。
渲染结果是正确的:
就这样,我们自己实现了antd的Space组件!
完整代码在github:github.com/QuarkGluonPl...
总结:
一直写业务代码,可能很少写一些复杂的组件,而antd里就有很多复杂组件,我们挑Space组件来写了下。
这是一个布局组件,可以通过参数设置水平、垂直间距、对齐方式、分割线部分等。
实现这个组件的时候,我们用到了很多东西:
很多同学不会封装布局组件,其实就是对整体和每个item都包裹一层,分别设置不同的class,实现不同的间距等的设置。
想一下,这些东西以后写业务组件是不是也可以用上呢?
读读antd源码之通用组件
ui组件库在ui开发框架中扮演着类似模具的角色,极大地提升了生产效率。无论是设计风格、基础功能还是操作交互,ui组件库都进行了高度统一,为项目开发提供了开箱即用的便捷。在React领域,中后台项目常用到的ui组件库,非Ant Design(antd)莫属。
本文将分享antd组件库的源码,探讨我们习以为常的功能背后的逻辑处理。在阅读过程中,将遵循《阅读前端源码的思路》,文章将直接分享重点,忽略具体细节。
一个没有设计理念的ui组件库,都不好意思称作ui组件库。官方文档中,第一个栏目就是“设计”,可见设计是ui组件库的灵魂,它包含了自身的价值观和模式,并遵循一系列规范。本文将先分享阅读的第1个,通用组件的源码。
通用组件包含三个:Button、Icon、Typography。关于这些组件,我们可以从官方文档中看到一些值得思考的功能。例如,Button的点击动作反馈,Icon的内部图标封装,Typography的文本处理或功能封装等。
antd的组件源码相对混乱,但我们可以从中找到一些有趣的点。例如,Button组件中关于按钮文字是两个汉字时插入空格的逻辑,以及内容劫持的过程。Wave组件的实现主要涉及到transition和animation,其中onClick方法的关键在于updateCSS方法,它动态添加样式,并添加transition和animation。
Icon组件则被搬到了@ant-design/icons库中实现,主要是一些样式、事件和图标引用的处理。Typography组件则提供了一系列文本样式的内容,其中文本拷贝使用了copy-to-clipboard库,文本溢出处理则通过Ellipsis组件实现。
本文对antd源码之通用组件的探讨就到这里,希望能帮助你更好地理解这些组件的内部逻辑。
antd 中 Form 表单的使用
本文主要介绍在使用 Ant Design (antd) 中的 Form 表单组件时的常见问题以及对源码的研究分析。
在创建 Form 组件时,会通过 `useForm` 钩子生成对应的 FormStore 类对象,并返回一个 FormInstance 对象。FormStore 的 store 对象则作为表单数据的唯一数据源,包含所有已命名表单组件的值。
使用 `useForm` 获得的 FormInstance 对象能够与表单组件内的 Input 组件互动。当输入框内容发生变化时,通过 `form.getFieldsValue(true)` 或 `onFinish` 事件,可以获取输入的 id 或 name 值。实现机制上,antd 选择在创建表单元素时定义并传入 `value` 和 `onChange` 属性,这样在组件值发生变化时,可以同步更新 store。
当遇到特定问题,如如何获取表单值、如何传递 FormInstance 对象给子组件、如何监听表单值的变化等,可以利用 antd 提供的 `Form.useFormInstance` 方法简化传值,`Form.useWatch` 方法获取表单值并触发组件刷新。监听表单值变化时,需注意区分与获取表单值的差别,避免复杂的逻辑编写。
在使用 Form.Item 时,有时会遇到其不支持传入数组子组件的问题,这是因为 Form.Item 会重置子组件的属性,包括 `value` 和 `onChange`。为解决此需求,可以将子组件数组封装成一个单个组件,并代理其属性,使 Form.Item 看似一个具有 `value` 和 `onChange` 的表单组件。
以上内容是通过分析 antd 中 Form 表单组件的源码,以及在实际开发中遇到的问题,总结出的关键点与解决方案。通过了解这些细节,可以更有效地使用 Form 表单组件,避免常见错误,提高开发效率。
ä¸çå°±ä¼çè¶ å®ç¨å°ç»ä»¶ä¹LoadingButton
ç»ä»¶èæ¯
å¨å¹³æ¶çå·¥ä½ä¸ï¼ç»å¸¸ä¼éå°ä¸ä¸ªåºæ¯ï¼
ç¹å»æé®æ¶è¯·æ±ä¸äºæ¥å£æ°æ®ï¼è为äºé¿å ç¨æ·éå¤çç¹å»æ们é常ä¼ä¸ºè¿äºæé®æ·»å loadingãè¿ä¸ªæ·»å loadingçåè½æ¬èº«æ¶é常ç®åçï¼åªè¦æ们å®ä¹ä¸ä¸ªåé使ç¨å¨Buttonç»ä»¶ä¸å³å¯ï¼ä½å¨ååå°ç®¡ç类项ç®æ¶ï¼è¿æ ·çæé®å¯è½ä¼æé常é常å¤ï¼å¯è½ä¸ä¸ªç»ä»¶ä¸ï¼å¾å¤åéé½æ¯xxx_loadingï¼èæ¶èååä¸å¤ä¼é ãæ¥ä¸æ¥ï¼æ们对Buttonç»ä»¶åä¸ä¸ªç®åçå°è£ æ¥è§£å³è¿ä¸ªèæ¶èååä¸å¤ä¼é çloadingé®é¢
çµææ¥æºæ们å¨ä½¿ç¨AntdçModal对è¯æ¡æ¶ï¼å½æ们çonOk为å¼æ¥å½æ°æ¶ï¼æ¤æ¶Modalçç¡®å®æé®ä¼èªå¨æ·»å loadingææï¼å¨å½æ°æ§è¡å®æåå ³éå¼¹çªï¼å°±åè¿æ ·ï¼æ¤æ¶ï¼ä»£ç å¦ä¸ï¼
asyncFunc(){ returnnewPromise(resolve=>{ setTimeout(()=>{ resolve()},)})},handleTestModal(){ constthat=thisthis.$confirm({ title:'æµè¯å¼æ¥å½æ°',content:'å¼æ¥å½æ°å»¶è¿ä¸¤ç§ç»æ',asynconOk(){ awaitthat.asyncFunc()}})},çå°è¿ç§ææåï¼å°±æ³å°ï¼å¦æå¯ä»¥å°è£ ä¸ä¸ªButtonç»ä»¶ï¼å°éè¦æ§è¡çå½æ°ä¼ å ¥ï¼ç»ä»¶ä¸èªå¨æ ¹æ®å½æ°æ§è¡æ åµæ·»å loadingææå²ä¸æ¯é常çæ¹ä¾¿ã
å®ç°LoadingButtonå®ä¹ç»ä»¶åæ°è¿è¾¹å°±å®ä¹å 个大家ä¼å¸¸ç¨å°çåæ°ï¼text(æé®æå)ãtype(æé®ç±»å)ãasyncFunc(æé®ç¹å»æ¶æ§è¡çå¼æ¥å½æ°)ãdelay(loading延è¿)ï¼å¦å¤ï¼è¿éè¦ä¸ä¸ªç»ä»¶å é¨çloadingåéæ¥æ§å¶æ们Buttonç»ä»¶çç¶æï¼ä»£ç å¦ä¸ï¼
exportdefault{ data(){ return{ loading:false}},props:{ text:{ type:String,default:'ç¡®å®'},type:{ type:String,default:'primary'},delay:{ type:Number,default:0},asyncFunc:{ type:Function,default:()=>{ }}},}使ç¨antdä¸çButtonç»ä»¶è¿è¡äºæ¬¡å°è£å¨æ们çèªå®ä¹LoadingButtonç»ä»¶ä¸ï¼å°ä¸é¢å®ä¹çåæ°ä½¿ç¨èµ·æ¥ï¼å¹¶ç»å®ä¸ä¸ªclickäºä»¶ï¼ä»£ç å¦ä¸ï¼
<template><Button:type="type":loading="loading"@click="handleClick">{ { text}}</Button></template><script>import{ Button}from'ant-design-vue'exportdefault{ components:{ Button},methods:{ handleClick(){ }}}</script>å¤æå¼æ¥å½æ°asyncFuncè¿ä¸é¨å为æ´ä¸ªç»ä»¶æéè¦çä¸ä¸ªé¨åï¼å³æ们å¦ä½å»å¤æä¼ å ¥çå½æ°æ¯å¼æ¥å½æ°ï¼å½æä»¬ä¼ å ¥çasyncFuncå½æ°æ¯å¼æ¥å½æ°æ¶ï¼ç»ä»¶æéè¦æ·»å loadingçå¨ç»ï¼é£ä¹æ们åºè¯¥å¦ä½å»å¤æä¸ä¸ªå½æ°æ¯å¦ä¸ºå¼æ¥å½æ°å¢ï¼
åèantdæ¯å¦ä½å®ç°çï¼ä¸é¢æ们åä»ç»äºantdçModal对è¯æ¡ä¸æ类似çé»è¾ï¼é£ä¹ä¸å¦¨å»é 读ä¸ä¸è¿é¨åç¸å ³çæºç ï¼çä¸antdçå®ç°æ¹å¼ï¼
//components/modal/ActionButton.jsxonClick(){ const{ actionFn,closeModal}=this;if(actionFn){ letret;if(actionFn.length){ ret=actionFn(closeModal);}else{ ret=actionFn();if(!ret){ closeModal();}}if(ret&&ret.then){ this.setState({ loading:true});ret.then((...args)=>{ //It'sunnecessarytosetloading=false,fortheModalwillbeunmountedafterclose.//this.setState({ loading:false});closeModal(...args);},e=>{ //Emiterrorwhencatchpromisereject//eslint-disable-next-lineno-consoleconsole.error(e);//See:/post/