1.preact��Դ��
2.详解|天猫搜索前端技术历代记
3.Preact(React)核心原理详解
4.preact源码解析,码p码从preact中理解react原理
5.å¦ä½ç¼è¯ReactNative示ä¾ç¨åºExamples
6.畅谈React material-ui的码p码样式方案
preact��Դ��
在掌握了 React 技能后,我尝试过不少小项目,码p码但总感觉这些项目只是码p码自娱自乐,对于找工作并没有太大帮助,码p码让我感到有些迷茫。码p码扫描网站 源码于是码p码,我决定尝试做点开源项目,码p码既能锻炼自己写 React 组件的码p码能力,又能让自己有所收获。码p码我和女票都很喜欢**,码p码因此产生了制作一个播放器的码p码想法。经过一番努力,码p码我开发了一个名为“qier-player”的码p码 h5 播放器。
qier-player 目前已实现在线播放器的码p码基本功能,包括暂停、播放、全屏、音量调节、进度条拖拽和倍速等。接下来,我打算添加快捷键和一些性能优化。如果你对播放器有需求,但又不想自己从头开始编写,或者觉得现有的播放器功能不足、不够美观,那么 qier-player 就是你的不二之选。
以下是这个开源组件的源代码,欢迎 star 和提建议!~
介绍:qier-player 是一个基于 React 编写的在线视频播放器组件,界面简洁,操作流畅,具有大部分视频播放器的基础功能。支持视频清晰度的切换,提供了原画、4K、2K、P、P、P 的视频源接口。
演示官网(tip: 演示的视频没有放cdn,下载比较慢,比较卡,local源码介绍需要等它加载完)
示例快速开始安装使用近期更新记录1.0.4 (--)1.0.3 (--)
如果你觉得这个项目对你有所帮助,不妨赏个 star,也可以点个 watch。版本迭代会第一时间通知到你 ^-^
详解|天猫搜索前端技术历代记
天猫搜索前端技术的发展历程,从上古时代的PC搜索,到逐步演进的H5搜索,再到MV*时代的Preact应用,直至引入Weex技术与搭建时代的探索,直至智能时代的展望,每一步都承载着技术的革新与业务的革新。
PC时代的搜索前端采用KISSY和MUI3作为主要技术方案,适应了3G/2G时代的网络环境和用户习惯。然而,随着智能手机的普及与流量成本的下降,流量需求激增,导致原有的技术方案显得力不从心。因此,H5搜索时代应运而生,采用Zepto和MUI4,引入前端模板,优化模块化方案与页面渲染策略,解决PC搜索时代的问题,同时引入前后端分离的wormhole app,降低模板维护成本。
进入MV*时代,随着组织架构调整,搜索前端资源投入集中在核心功能与跨平台适应性上,如H5搜索凑单页、领券弹层等。引入Preact和MUI5,优化模块化方案,采用自动化工具转换技术,实现一份源码同时复用在Weex和Web上,提升了开发效率与代码复用性。
Weex时代,为应对流量场景下的动态化需求,以及客户端迭代的挑战,引入Native内嵌Weex坑位技术方案,结合模板下发的Oreo平台,采用Prax解决方案,实现在Web和Weex间的技术兼容性与性能优化。
搭建时代,自动源码屋面对共建与规模化的需求,长颈鹿项目应运而生,通过千叶平台提供模块化搭建能力,为品牌商与行业提供定制化页面,实现模块化、自动化搭建,有效提升运营效率与用户体验。同时,无界模块定投方案解决了多场景间的交叉展示问题,进一步优化了模块化搭建的灵活性与适应性。
深度搭建时代,引入Rax1.0,针对Web进行优化,模块化划分明确,实现交互、展示与数据模块的分离,以实现更高效、更灵活的页面构建与内容复用。此外,团队正尝试基于机器学习的智能UI生成技术,以期实现UI零成本构建,推动前端技术与业务的深度融合。
智能时代,展望未来,前端技术将融合更先进的AI与数据驱动策略,实现自动化的界面生成、内容产出与用户行为分析,从而构建更为个性化、智能化的用户体验,推动业务创新与技术迭代。
Preact(React)核心原理详解
本文作者:字节跳动 - 宝丁
在前端领域,React 是一个广为人知的前端开发框架,它革新了全栈 Web 开发的体验。React 引入了诸如 JSX、虚拟 DOM、组件化与合成事件等概念。然而,探究其源码时,庞大且晦涩的代码体系往往让这一过程变得艰难。为了解答这个挑战,本文将聚焦 Preact,一个轻量级的cpu加密源码 React 替代方案,其体积仅为 3KB。Preact 的设计初衷是提升性能,简化复杂性。我们将从以下几个角度深入探讨 Preact 的核心原理。
一、Preact 是什么?
Preact 是一个功能与 React 类似的轻量级前端框架。它的名字中的“P”意味着“Performance”,强调了提高性能的初衷。Preact 旨在提供 React 的核心功能,同时以更简洁的代码实现。
二、Preact 与 React 的区别
1. 事件系统:React 内置了事件合成系统,主要使用 `onChange` 方法处理表单组件的值更新。相比之下,Preact 直接利用浏览器原生的事件系统,使用 `onInput` 方法,因此在体积上更加精简。
2. DOM 规范描述:在描述 DOM 类名时,React 要求使用 `className`。Preact 支持使用 `class` 直接描述 DOM 类名,使其更贴近原生 DOM 规范。
三、Preact 的工作流程
1. JSX:JSX 是 Preact 的模板语法,它允许用类似 HTML 的结构描述 DOM。经过转换,JSX 被编译为函数调用,进而生成原生 DOM 结构。
2. Virtual DOM:Preact 采用 Virtual DOM 技术,将 DOM 更新操作最小化。它通过比较虚拟 DOM 和实际 DOM,仅对发生变化的部分进行更新。
四、Diff 算法详解
1. Diff 儿童节点:比较新旧儿童节点,匹配相同的 key,进行差异比较,对未匹配的节点进行处理。
2. Diff 阶段:根据节点类型(Fragment、Component、DOM node)进行不同处理,如更新组件状态、创建新 DOM 节点或更新现有 DOM 节点。
3. Diff 属性:比较新旧 DOM 节点属性,ds源码分析仅更新变化的部分。
五、结合实际组件
通过一个简单的 Clock 组件,直观展示 Preact 的渲染流程,帮助理解 Preact 的工作原理。
六、Preact Hooks
Preact Hooks 是 React Hooks 的替代方案,提供了性能优化的组件状态管理机制。分为三类:MemoHook、ReducerHook 和 EffectHook,分别用于性能优化、状态管理与副作用操作。
七、结束语
本文深入介绍了 Preact 的核心原理,包括框架设计、与 React 的比较、工作流程、Diff 算法、实际应用以及 Hooks 机制。通过 Preact,前端开发者可以更高效地构建应用,同时理解其与 React 的异同。希望本文能够帮助大家更深入地掌握 Preact 的使用方法与性能优化策略。
preact源码解析,从preact中理解react原理
基于preact.3.4版本进行分析,完整注释请参阅链接。阅读源码建议采用跳跃式阅读,遇到难以理解的部分先跳过,待熟悉整体架构后再深入阅读。如果觉得有价值,不妨为项目点个star。 一直对研究react源码抱有兴趣,但每次都半途而废,主要原因是react项目体积庞大,代码颗粒化且执行流程复杂,需要投入大量精力。因此,转向研究preact,一个号称浓缩版react,体积仅有3KB。市面上已有对preact源码的解析,但大多存在版本过旧和分析重点不突出的问题,如为什么存在_nextDom?value为何不在diffProps中处理?这些都是解析代码中的关键点和收益点。一. 文件结构
二. 渲染原理 简单demo展示如何将App组件渲染至真实DOM中。 vnode表示节点描述对象。在打包阶段,babel的transform-react-jsx插件会将jsx语法编译为JS语法,即转换为React.createElement(type, props, children)形式。preact中需配置此插件,使React.createElement对应为h函数,编译后的jsx语法如下:h(App,null)。 执行render函数后,先调用h函数,然后通过createVNode返回虚拟节点。最终,h(App,null)的执行结果为{ type:App,props:null,key:null,ref:null},该虚拟节点将被用于渲染真实DOM。 首次渲染时,旧虚拟节点基本为空。diff函数比较虚拟节点与真实DOM,创建挂载完成,执行commitRoot函数,该函数执行组件的did生命周期和setState回调。2. diff
diff过程包含diff、diffElementNodes、diffChildren、diffProps四个函数。diff主要处理函数型虚拟节点,非函数型节点调用diffElementNodes处理。判断虚拟节点是否存在_component属性,若无则实例化,执行组件生命周期,调用render方法,保存子节点至_children属性,进而调用diffChildren。 diffElementNodes处理HTML型虚拟节点,创建真实DOM节点,查找复用,若无则创建文本或元素节点。diffProps处理节点属性,如样式、事件监听等。diffChildren比较子节点并添加至当前DOM节点。 分析diff执行流程,render函数后调用diff比较虚拟节点,执行App组件生命周期和render方法,保存返回的虚拟节点至_children属性,调用diffChildren比较子节点。整体虚拟节点树如下: diffChildren遍历子节点,查找DOM节点,比较虚拟节点,返回真实DOM,追加至parentDOM或子节点后。三. 组件
1. component
Component构造函数设置状态、强制渲染、定义render函数和enqueueRender函数。 强制渲染通过设置_force标记,加入渲染队列并执行。_force为真时,diff渲染不会触发某些生命周期。 render函数默认为Fragment组件,返回子节点。 enqueueRender将待渲染组件加入队列,延迟执行process函数。process排序组件,渲染最外层组件,调用renderComponent渲染,更新DOM后执行所有组件的did生命周期和setState回调。2. context
使用案例展示跨组件传递数据。createContext创建context,包含Provider和Consumer组件。Provider组件跨组件传递数据,Consumer组件接收数据。 源码简单,createContext后返回context对象,包含Consumer与Provider组件。Consumer组件设置contextType属性,渲染时执行子节点,等同于类组件。 Provider组件创建函数,渲染到Provider组件时调用getChildContext获取ctx对象,diff时传递至子孙节点组件。组件设置contextType,通过sub函数订阅Provider组件值更新,值更新时渲染订阅组件。四. 解惑疑点
理解代码意图。支持Promise时,使用Promise处理,否则使用setTimeout。了解Promise.prototype.then.bind(Promise.resolve())最终执行的Promise.resolve().then。 虚拟节点用Fragment包装的原因是,避免直接调用diffElementNodes,以确保子节点正确关联至父节点DOM。 hydrate与render的区别在于,hydrate仅处理事件,不处理其他props,适用于服务器端渲染的HTML,客户端渲染使用hydrate提高首次渲染速度。 props中value与checked单独处理,diffProps不处理,处理在diffChildren中,找到原因。 在props中设置value为空的原因是,遵循W3C规定,不设置value时,文本内容作为value。为避免MVVM问题,需在子节点渲染后设置value为空,再处理元素value。 组件异常处理机制中,_processingException和_pendingError变量用于标记组件异常处理状态,确保不会重复跳过异常组件。 diffProps中事件处理机制,为避免重复添加事件监听器,只在事件函数变化时修改dom._listeners,触发事件时仅执行保存的监听函数,移除监听在onChange设置为空时执行。 理解_nextDom的使用,确保子节点与父节点关联,避免在函数型节点渲染时进行不必要的关联操作。å¦ä½ç¼è¯ReactNative示ä¾ç¨åºExamples
ããç¼è¯ç¤ºä¾ç¨åºéè¦å°æ´ä¸ªé¡¹ç®å¯¼å ¥å°androidStudioä¸ï¼androidStudioå¯¼å ¥é¡¹ç®æ¶éæ©react-native/ReactAndroidç®å½ã
ããç±äºé¡¹ç®ä¾èµndkå æ¤å¦æè¦ç¼è¯Examplesè¿éè¦å®è£ é ç½®ndkç®å½ï¼ä¸è½½ndkåæ¯ä¸ä¸ªèªè§£åç¨åºï¼ä¼éæ¾ndkçç®å½ã
ããç¶åéè¦è®¾ç½®ç¯å¢åéæè å¨react-nativeæ ¹ç®å½ä¸æ°å»ºlocal.propertiesæ件ï¼æ件å 容å¦ä¸ï¼
ããsdk.dir=c:\ä½ çsdkç®å½
ããndk.dir=c:\ä½ çndkç®å½
ãã设置è¦ä¹åå°±å¯ä»¥ç¼è¯äºï¼å¯¼å ¥åç¼è¯çè¿ç¨æ¯è¾æ²æï¼è¯·ç»§ç»çä¸æã
ããå¨ç¼è¯AwesomeProject项ç®æ¶ï¼æ²¡æç¨å°ndkï¼å®é ä¸è¿éçndké»è®¤æ åµä¸å¹¶æ²¡æç¨å°ï¼åªæ¯gradleç设置éændkå æ¤å¿ é¡»é ç½®ndkæè½å¯¼å ¥é¡¹ç®ã
ããndkæ¯å¨ç¼è¯æ ¸å¿åºæ¯æç¨å°ï¼æ ¸å¿åºä½äºreact-native/ReactAndroidï¼å¯¼å ¥æ´ä¸ªé¡¹ç®æ¶ä»¥libå½¢å¼åå¨ãæ¥çExamplesç®å½ä¸UIExplorerï¼ä¼åç°å¨build.gradleæ¯ä»¥å¨çº¿çæ¹å¼å¯¼å ¥æ ¸å¿åºçãéè¿æºç çæ¹å¼å¯¼å ¥è¢«æ³¨éæäºã
ããdependencies {
ããcompile fileTree(dir: 'libs', include: ['*.jar'])
ããcompile 'com.android.support:appcompat-v7:.0.1'
ãã// Depend on pre-built React Nativecompile 'com.facebook.react:react-native:0..+'
ãã// Depend on React Native source.
ãã// This is useful for testing your changes when working on React Native.
ãã// compile project(':ReactAndroid')
ãã}
ããç±æ¤å¯ç¥ï¼ç¼è¯UIExplorer并ä¸éè¦ndkï¼å¦æä½ ä¸æ³è®¾ç½®ndkï¼æ2个åæ³
ãã1.æ·è´AwesomeProject项ç®ä¸çbuild.gradleï¼settings.gradleå°UIExplorerçandroidç®å½ï¼å¨å¯¼å ¥é¡¹ç®æ¶éæ©UIExplorer/androidå°±å¯ä»¥äºï¼è¿æ ·androidStudioä¼å¯¼å ¥å个项ç®ï¼å¦åä¼å¯¼å ¥æ´ä¸ªé¡¹ç®ã
ãã2.ç¨androidStudioæ°å»ºä¸ä¸ªååç项ç®ï¼ç¶åæUIExplorerç®å½ä¸çæ件æ·è´å°æ°å»ºç项ç®ä¸ã
ããç¼è¯å¥½ä¹åå¯å¨æå¡å¨ç«¯ï¼å°react-nativeç®å½ä¸æ§è¡:
ããnpm install
ããnode packager\packager.js
ããwindowsä¸å¦æåºç°é误éè¦æ ¹æ®é误æ示修æ¹ä»£ç blogs.com/zhaojietec/p/.html
ããä¸è¿éè¦æ³¨æçæ¯ï¼ç®å为æ¢ï¼UIExplorerå¨Androidä¸æä¸ä¸ªbugï¼IOSä¸æ²¡æé®é¢ï¼éè¿googleå¯ä»¥æ¾å°äºè§£å³åæ³ã/facebook/react-native/issues/
ããåå æ¯ï¼js代ç åandroidåç代ç ä¸åæ¥ï¼éè¿build.gradleå¯ä»¥çå°androidä¸çå¼ç¨çreactNativeæ ¸å¿åºä¸ºï¼èjs代ç çæ¬å·²ç»æ´æ°å°äºã
ãã解å³çåæ³æ2个ï¼ä¸ä¸ªæ¯ä½¿ç¨gitå·¥å ·(å¦smartGit)ï¼å°js代ç æ¢å¤å°ä¹åççæ¬ï¼å¦ä¸ä¸ªåæ³æ¯éæ°ç¼è¯reactNativeçæ ¸å¿åºï¼ç¼è¯æ ¸å¿åºéè¦ndkï¼å¨macä¸æ²¡æé®é¢ï¼å¨windowsç¼è¯ä¼åºéãç¼è¯reactNativeæ ¸å¿åºï¼å¯¹UIExplorerä¸æ³¨éæçä¾èµé¡¹è¿è¡ä¿®æ¹å³å¯ï¼ç¼è¯é度è¾æ ¢ éè¦å¨çº¿ä¸è½½ç¬¬ä¸æ¹ä¾èµåºã
ããdependencies {
ããcompile fileTree(dir: 'libs', include: ['*.jar'])
ããcompile 'com.android.support:appcompat-v7:.0.1'
ãã// Depend on pre-built React Native//compile 'com.facebook.react:react-native:0..+'
ãã// Depend on React Native source.
ãã// This is useful for testing your changes when working on React Native.
ããcompile project(':ReactAndroid')
ãã}
ããç±äºwindowsä¸æ æ³ç¼è¯ï¼æ以è¿éæä¾ç¼è¯å¥½çaaræ件ï¼ä¿®æ¹UIExplorer build.gradleä¸çä¾èµé¡¹å°±å¯ä»¥äºãè³äºå¦ä½å¼å ¥aaræ件ï¼å¯ä»¥èªè¡æç´¢ãå½ç¶macä¸åæ ·ä¹å¯ä»¥ç¨è¿ä¸ªaarï¼å¯ä»¥çå»ä¸å°éº»ç¦ã
畅谈React material-ui的样式方案
Google 在 年提出了 material design 的设计理念,极具颠覆性,在国外非常受欢迎。各类前端框架也都出现了material design风格的组件库,其中 React 最受欢迎的 material design 风格组件库非 material-ui 莫属。mui-org/material-ui 这个开源库目前收获了 star,npm 的周下载量达到了 万,数据摆在那儿,也不需要继续“吹捧” material-ui 了。本文主要是带大家一起领略一下 material-ui 的样式方案。
material-ui 将自己的样式方案独立发布成一个 npm 包,叫 @material-ui/styles。它拥抱了CSS-in-JS,据他们的文档,也尝试过使用 LESS 等其他方案,但发现有明显的局限性,最后拥抱了 CSS-in-JS。官方文档宣称material-ui 样式方案有以下优点。
使用 @material-ui/styles 的样式方案主要支持三种形式的API,但底层的代码和逻辑是一致的。下面是代码示范,通过 makeStyles API,传入一个描述CSS的对象(下面简称css对象),就能得到一个自定义的Hook,通常命名为 useStyles。在函数式组件内调用这个Hook,得到一个对象,通常命名为classes。最后,将classes 对象的“对应值” 赋给 组件的 className 属性,就成功定制了这个组件的样式。细节:classes对象的 root 属性 对应的就是 css对象的 root 属性。下面是代码示范:
使用 styled API 就能采用类似于 styled-components 的语法,当然还是有区别的 —— styled-components 用的是 es6 tagged template literals 而 material-ui styled API 返回函数的参数是css对象。使用 Higher-order component API 接收一个 css 对象返回一个高阶组件函数。material-ui 的 Higher-order component API 不仅能用于函数组件也能用于类组件,但在 Hook 大行其道后这个 API 慢慢退出舞台了。接下来都只使用 makeStyles API 做后面的代码示范。
material-ui 上述的API 在底层都会生成一些“随机的html class 名称” 以及 相应的 css 规则。以 上面的 makeStyles demo 为例,会生成以下 css 规则插入到 html head。自定义样式按钮 对应的 html 片段如下。小结:上述这三种形式的API都能定制化组件的样式。查看源码就能发现其实 styled 和 withStyles 底层都调用了makeStyles API。
在底层原理是动态生成 css 规则插入到 html 中。这三个API的使用方法中,最关键的都是两部分:查看 css 对象的构成和使用。接下来将细聊 css 对象的构成和使用。嵌套选择器:上面的代码可以得到以下效果。实际生成的 css 规则如下。
根据传入值动态调整:上述的 css 对象并不一定是单纯的简单对象。可以将函数传递给makeStyles (“插值”),这样一来根据组件的属性可以变换生成的样式的值。 此函数可以运用于样式规则的级别,也可以放在 CSS 属性级别。例1和例2展示了如何根据组件属性动态调整样式。
覆盖样式 —— classes 属性:接下来换个角度,假如你使用 material-ui 样式方案创作了一些组件(提供了默认的样式)并作为公用组件分享给其他模块使用,如何让调用端可自定义这些组件的样式呢?上面提到的根据传入值动态调整 是一种解决方案,但很明显这是一种只允许微调的方案;而且这个方案的实现通常比较繁琐。假如以下是我们设计的一个组件代码。那么我在 Parent 中如何自定义这个 Nested 组件的 span 样式呢?我们可以利用classes属性 覆盖样式。上面的代码中,我们往 useStyles 这个hook中传入 props 作为参数 (其实是为了将 classes 传进去)。而在 Parent 的代码中,我们给 Nested 传入 classes 属性(这个命名是个规范,必须遵守)。最终的效果生成的 html 中 span 的 class 值是 ‘makeStyles-label-2 my-label’ —— 注意 my-label 的顺序在后面,因此它的样式会覆盖前面 makeStyles-label-2 的样式。
总结:你所在前端项目使用的样式方案还是 LESS, SASS 甚至是 css 吗?material-ui 样式解决方案是不是对你有所冲击或者启示呢?欢迎留言评论。如果觉得文章质量不错,请积极地点赞、喜欢、收藏三连!p.s. material-ui 样式方案中还有其他内容,如主题、JSS 插件等,个人感觉难度比较小,文档也易懂,(或者过于生僻,很少使用),本文就不做介绍了,如果有读者强烈要求写某个部分,我再继续补充。