JSX为什么要用React认为渲染逻辑天生就是和其他UI逻辑耦合的,比如在UI中,需要绑定和处理事件,需要在状态发生时通知UI某些时刻会发生变化,需要在UI中展示准备好的数据。React不是将标记和逻辑人为地分离到单独的文件中,而是通过将两者存储在称为“组件”的松散耦合单元中来实现关注点分离。React不强制使用JSX,但大多数时候,将JSX和UI放在JavaScript代码中在视觉上很有帮助。它还使React显示更有帮助的错误和警告消息。注意事项由于JSX在语法上比HTML更接近JavaScript,因此ReactDOM使用camelCase(小驼峰命名法)来定义属性名称,而不是使用HTML属性名称的命名约定。比如JSX中class变成className,tabindex变成tabIndex。JSX防止注入攻击:ReactDOM在渲染之前默认对所有输入内容进行转义。它确保您没有明确自己编写的内容永远不会注入到您的应用程序中。所有内容在呈现之前都转换为字符串。这样可以有效防止XSS(cross-site-scripting,跨站脚本)攻击。你可以使用babel(@babel/preset-react)将JSX翻译成调用React.createElement()的函数调用,而无需借助webpackloader等处理器下面两种写法是完全等价的constelement=(你好,世界!)constelement=React.createElement('h1',/*type*/{className:'greeting'},/*props*/'Hello,world!'/*children*/);ReactElement常用字段和XSS截图下面是产品的上面代码createElement,本质上是一个ReactObject(extendsObject):key:组件的key,主要用在virtualdom中,比较diff和moveelementprops:组件属性,从父组件派生或者HOC,或者类似的外部传递ref:currentdomreferencetype:componenttype_owner:是ReactComponent,创建react组件的组件,null值为null`$$typeof`:earlyReact(0.13)version[veryeasy](http://danlec.com/blog/xss-via-a-spoofed-react-element)被XSS攻击,为了解决这个问题,字段名是使用$$typeof,值使用SymbolReact如何解决这个问题,有两种方式:(参考文档why-do-react-elements-have-typeof-property)-编码时:React等新兴代码库会进行转义(客户端)-数据传输时:由于JSON不支持$$属性名,这个属性会被过滤掉(服务器端)ObjectvsReactObject如何区分一个对象是不是react对象?React提供了isValidElement方法/***验证对象是否为ReactElement。*参见https://reactjs.org/docs/react-api.html#isvalidelement*@param{?object}object*@return{boolean}如果`object`是ReactElement则为真。*@final*/exportfunctionisValidElement(object){return(typeofobject==='object'&&object!==null&&object.$$typeof===REACT_ELEMENT_TYPE);}Fiber节点代码中声明如下functionFiberNode(tag:WorkTag,pendingProps:mixed,key:null|string,mode:TypeOfMode,){//实例//静态数据存储的属性//定义协调算法中使用的纤程类型,以确定需要完成的工作。如前所述,工作取决于React元素的类型。函数createFiberFromTypeAndProps将React元素映射到相应的fiber节点类型this.tag=tag;this.key=键;this.elementType=null;//定义与此纤程关联的函数或类。对于类组件,它指向构造函数,对于DOM元素,它指定HTML标记。我经常使用这个字段来了解光纤节点与哪些元素相关。this.type=null;//持有对组件、DOM节点或与纤程节点关联的其他React元素类型的类实例的引用。一般来说,我们可以说这个属性用于保存与纤程相关的局部状态。this.stateNode=null;//Fiber//Fiber关系相关属性,用于生成FiberTree结构this.return=null;this.child=null;this.sibling=null;这个.index=0;this.ref=null;//动态数据&状态相关属性//newprops,新变化带来的新props,即nextPropsthis.pendingProps=pendingProps;//prevprops,用于在上次渲染过程中创建输出Fiberpropsthis.memoizedProps=null;//状态更新、回调和DOM更新的队列,Fiber对应的组件,产生的更新都会放在这个队列中this.updateQueue=null;//当前屏幕UI对应的状态,upFiber状态通过input更新一次this.memoizedState=null;//存储Fiber依赖的上下文的列表,eventsthis.dependencies=null;//conCurrentMode和strictMode//共存模式表示本子树默认是否异步渲染//Fiber在第一次创建的时候会继承父Fiberthis.mode=mode;//Effects//当前Fiber阶段需要执行的任务,包括:placeholder、update、delete等this.flags=NoFlags;this.subtreeFlags=NoFlags;这个。删除=空;//优先级调度相关属性this.lanes=NoLanes;this.childLanes=NoLanes;//currenttree和workinginprgoresstree关联的属性//在FIbertree的更新过程中,每个Fiber都有对应的Fiber//我们称之为current<==>workInProgress//rendering完成后会指向对方this.alternate=null;//profiler记录的相关时间if(enableProfilerTimer){//this.actualDuration真实渲染时长(毫秒级)//this.actualStartTime渲染开始时间//this.selfBaseDuration//this.treeBaseDuration子树渲染时长//注意:以下是为了避免v8性能悬崖。}//Debuggingrelatedif(__DEV__){//这不是直接使用的,但对内部调试很方便:}}类型转换(重点)React中的每个组件都有一个UI表示,我们可以调用返回的视图或模板来自render方法下面是示例代码在JSX到ReactElement模板通过JSX编译器之后,您将得到一堆React元素。这实际上是从React组件的render方法返回的,而不是HTML。由于我们不需要使用JSX,我们可以覆盖组件的渲染方法ClickCounterclassClickCounter{...render(){return[React.createElement('button',{key:'1',onClick:this.onClick},'Updatecounter'),React.createElement('span',{key:'2'},this.state.count)]}}React.createElement中调用render会创建两个数据结构,如下所示:[{$$typeof:Symbol(react.element),type:'button',key:"1",props:{children:'更新计数器',onClick:()=>{...}},{$$typeof:Symbol(react.element),type:'span',key:"2",props:{children:0}}]可以看到ReactObject中的$$typeof属性,它是ReactElement的唯一标识。然后将props描述的元素属性传递给React.createElement函数。ClickCounter的React元素没有任何props或keys:{$$typeof:Symbol(react.element),key:null,props:{},ref:null,type:ClickCounter}ReactElementtoFiberNodes从render方法中返回reconciliation中每个React元素的数据都会被合并到Fiber树中。每个ReactElement都有对应的FiberNode用于存储组件状态和DOM的可变数据结构。与React元素不同,Fibers不会在每个渲染器上重新创建(可重用)。在React中,框架根据React元素的类型执行不同的活动。在我们的示例应用程序中,对于类组件,ClickCounter调用生命周期方法和渲染方法,对于跨度宿主组件(DOM节点),它执行DOM突变。因此,每个React元素都会转化为对应类型的Fiber节点,它描述了需要完成的工作。您可以将Fiber视为一种数据结构,它代表一些要完成的工作,或者换句话说,一个工作单元。Fiber的架构还提供了一种方便的方式来跟踪、安排、暂停和中止工作。第一次将React元素转换为Fiber时,React使用元素中的数据在createFiberFromTypeAndProps函数中创建Fiber。在随后的更新中,React重用了Fiber并且仅使用来自相应React元素的数据更新必要的属性。具有相同键的React元素不再从render方法返回,React可能还需要根据props移动或删除层次结构中的节点。React为每一个React元素创建一个Fiber节点,我们可以通过ReactElementTree生成FiberTree。在我们的示例应用程序中,它看起来像这样:所有Fiber节点节点都通过一个链表连接起来:child、sibling和return。上一篇内容:React18技术概览-基础篇https://segmentfault.com/a/11...下一篇预览:源码实现