当前位置: 首页 > news >正文

一起作做业网站seo推广收费标准

一起作做业网站,seo推广收费标准,深圳展示型网站建设,哪些网站图片做海报好前言React 是一个十分庞大的库,由于要同时考虑 ReactDom 和 ReactNative ,还有服务器渲染等,导致其代码抽象化程度很高,嵌套层级非常深,阅读其源码是一个非常艰辛的过程。在学习 React 源码的过程中,给我帮…
  • 前言

React 是一个十分庞大的库,由于要同时考虑 ReactDom 和 ReactNative ,还有服务器渲染等,导致其代码抽象化程度很高,嵌套层级非常深,阅读其源码是一个非常艰辛的过程。在学习 React 源码的过程中,给我帮助最大的就是这个系列文章,于是决定基于这个系列文章谈一下自己的理解。本文会大量用到原文中的例子,想体会原汁原味的感觉,推荐阅读原文。

本系列文章基于 React 15.4.2 ,以下是本系列其它文章的传送门:
React 源码深度解读(一):首次 DOM 元素渲染 - Part 1
React 源码深度解读(二):首次 DOM 元素渲染 - Part 2
React 源码深度解读(三):首次 DOM 元素渲染 - Part 3
React 源码深度解读(四):首次自定义组件渲染 - Part 1
React 源码深度解读(五):首次自定义组件渲染 - Part 2
React 源码深度解读(六):依赖注入
React 源码深度解读(七):事务 - Part 1
React 源码深度解读(八):事务 - Part 2
React 源码深度解读(九):单个元素更新
React 源码深度解读(十):Diff 算法详解

  • 正文

上一篇文章中,我们讲解到ReactCompositeComponent[ins]被初始化后,App[ins]的 render 方法被调用,生成 ReactElement 树,然后对应的ReactDOMComponent[6]被返回。下面我们来看看这个ReactDOMComponent[6]是如何转化为 DOM 树的。

performInitialMount: function (renderedElement, hostParent,hostContainerInfo, transaction, context) {...// 这里会调用 App 实例的 render 方法,而 render 的返回值是 React.createElement 的嵌套调用。if (renderedElement === undefined) {renderedElement = this._renderValidatedComponent();}...// 上回讲到这里// 返回 ReactDOMComponent[6]var child = this._instantiateReactComponent(renderedElement,nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */);this._renderedComponent = child;// 今天讲这部分var markup = ReactReconciler.mountComponent(child,transaction,hostParent,hostContainerInfo,this._processChildContext(context),debugID);return markup;
},
  • ReactDOMComponent[6].mountComponent

ReactReconciler.mountComponent 会触发ReactDOMComponent[6]的 mountComponent 方法,调用栈如下:

...
|~mountComponentIntoNode()                                    ||-ReactReconciler.mountComponent()                          ||-ReactCompositeComponent[T].mountComponent()             ||-ReactCompositeComponent[T].performInitialMount()  upper half|-ReactReconciler.mountComponent()                    ||-ReactCompositeComponent[ins].mountComponent()     ||-this.performInitialMount()                      ||-this._renderValidatedComponent()              ||-instantiateReactComponent()                  _|_ (we are here)                                 ||-ReactDOMComponent[6].mountComponent(          |transaction, // scr: -----> not of interest |hostParent,  // scr: -----> null            |hostContainerInfo,// scr:---------------------> ReactDOMContainerInfo[ins]                                lower halfcontext      // scr: -----> not of interest |)                                             |
...
mountComponent: function (transaction,hostParent,hostContainerInfo,context
) {...var mountImage;if (transaction.useCreateElement) {var ownerDocument = hostContainerInfo._ownerDocument;...// 创建 div 元素el = ownerDocument.createElement(this._currentElement.type);...// 设置 attributesif (!this._hostParent) {DOMPropertyOperations.setAttributeForRoot(el);}// 设置 propertiesthis._updateDOMProperties(null, props, transaction);// 构造 DOM 树var lazyTree = DOMLazyTree(el);// 遍历子节点并创建 DOM 结点this._createInitialChildren(transaction, props, context, lazyTree);mountImage = lazyTree;}...return mountImage;
}

这里主要做的事情有3部分:

  1. 创建 DOM 元素
  2. 设置 attributes 和 properties
  3. 遍历子元素并重复上述过程

这时候的数据结构如下:
clipboard.png

流程图:

clipboard.png

  • _createInitialChildren 遍历子节点并创建 DOM 结点

下面来看一下 _createInitialChildren 的细节:

_createInitialChildren: function (transaction, props, context, lazyTree) {// Intentional use of != to avoid catching zero/false.var innerHTML = props.dangerouslySetInnerHTML;if (innerHTML != null) {if (innerHTML.__html != null) {DOMLazyTree.queueHTML(lazyTree, innerHTML.__html);}} else {// 如果是 string 或者 number,返回 truevar contentToUse =CONTENT_TYPES[typeof props.children] ? props.children :null;var childrenToUse = contentToUse != null ? null : props.children;// 直接渲染字符串if (contentToUse != null) {// Avoid setting textContent when the text is empty. In IE11 setting// textContent on a text area will cause the placeholder to not// show within the textarea until it has been focused and blurred again.// https://github.com/facebook/react/issues/6731#issuecomment-254874553if (contentToUse !== '') {DOMLazyTree.queueText(lazyTree, contentToUse);}} // 渲染子节点else if (childrenToUse != null) {var mountImages = this.mountChildren(childrenToUse,transaction,context);for (var i = 0; i < mountImages.length; i++) {DOMLazyTree.queueChild(lazyTree, mountImages[i]);}}}
},

这部分代码十分好懂,就 3 条分支:

  1. 设置了 dangerouslySetInnerHTML 属性,直接渲染 HTML
  2. 子节点类型为 string 或 number,渲染字符
  3. 其它情况就需要将 ReactElement 转换成 ReactDOMComponent 或 ReactCompositeComponent 作进一步的渲染。

DOMLazyTree 的 queueText 和 queueChild 真正有效的都各只有一行代码:

function queueText(tree, text) {if (enableLazy) { // scr: NO, I mean, false...} else {setTextContent(tree.node, text);}
}var setTextContent = function (node, text) {if (text) {var firstChild = node.firstChild;if (firstChild && firstChild === node.lastChild && firstChild.nodeType === 3) { // scr: false...}}node.textContent = text; // scr: the only effective line
};function queueChild(parentTree, childTree) {if (enableLazy) { // scr: again, false...} else {parentTree.node.appendChild(childTree.node);}
}

mountChildren 的调用栈如下:

ReactDOMComponent[6].mountComponent()    <-------------------------|(we are here)                                                  ||-this._createInitialChildren()                                  |?{1}                                                             ||-DOMLazyTree.queueText()                                      |?{2}                                                             ||-this.mountChildren()        // scr: ---------------> 1)(a)   ||-this._reconcilerInstantiateChildren()                      ||-ReactChildReconciler.instantiateChildren()               ||-traverseAllChildren()                                  ||-traverseAllChildrenImpl()  <------|inner             ||↻traverseAllChildrenImpl() ------|recursion         ||-instantiateChild()                               ||-instantiateReactComponent()                    ||↻ReactDOMComponent.mountComponent()      // scr: -> 1)(b)---||↻DOMLazyTree.queueChild()    // scr: ---------------> 2)

这中间的函数调用逻辑很清晰,最终会走到 traverseAllChildrenImpl 这里:

function traverseAllChildrenImpl(children,nameSoFar,callback,traverseContext
) {var type = typeof children;if (type === 'undefined' || type === 'boolean') {// All of the above are perceived as null.children = null;}if (children === null ||type === 'string' ||type === 'number' ||// The following is inlined from ReactElement. This means we can optimize// some checks. React Fiber also inlines this logic for similar purposes.(type === 'object' && children.$$typeof === REACT_ELEMENT_TYPE)) {callback(traverseContext,children,// If it's the only child, treat the name as if it was wrapped in an array// so that it's consistent if the number of children grows.nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) :nameSoFar);return 1;}var child;var nextName;var subtreeCount = 0; // Count of children found in the current subtree.var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar +SUBSEPARATOR;if (Array.isArray(children)) {for (var i = 0; i < children.length; i++) {child = children[i];nextName = nextNamePrefix + getComponentKey(child, i);subtreeCount += traverseAllChildrenImpl(child,nextName,callback,traverseContext);}} else {...}return subtreeCount;
}

这里的逻辑很简单,如果 children 不是数组,则调用回调函数;如果是数组,则继续调用自身,相当于深度优先遍历。这里的回调函数就是 ReactChildReconciler 中的 instantiateChild:

function instantiateChild(childInstances, child, name, selfDebugID) {...if (child != null && keyUnique) {childInstances[name] = instantiateReactComponent(child, true);}
}

这里直接调用 instantiateReactComponent,创建ReactDOMComponent。所有的ReactDOMComponent的创建顺序如下:

ReactDOMComponent[6].mountComponent()|-this._createInitialChildren()|-this.mountChildren() 
...           |↻instantiateReactComponent()[4,5]|-ReactDOMComponent[5].mountComponent()|-this._createInitialChildren()|-node.textContent = text; // scr: [5] done|-ReactDOMComponent[4].mountComponent()|-this._createInitialChildren()|-this.mountChildren() 
...                 |↻instantiateReactComponent()[2,3]|-ReactDOMComponent[2].mountComponent() // scr: [2] done|-ReactDOMComponent[3].mountComponent()|-this._createInitialChildren()|-node.textContent = text; // scr: [3] done|↻node[4].appendChild()[2,3] // scr: [4] done|↻node[6].appendChild()[4,5] // scr: [6] done

clipboard.png

完成的流程图:

clipboard.png

http://www.lbrq.cn/news/2608903.html

相关文章:

  • 湛江网站建设方案咨询网站关键词快速排名技术
  • 网站主页设计欣赏谷歌google play官网下载
  • 网站建设合同注意点数据分析一般用什么软件
  • 怎样做视频上网站赚钱百度认证服务平台
  • 上海做网站公百度关键词购买
  • 法律对网站建设的规制恶意点击竞价时用的什么软件
  • 北京朝阳区网站建设青岛谷歌优化公司
  • 作业提交免费网站今天最近的新闻
  • 网站样版风格排版百度客服怎么联系
  • 网站建设的通知网络营销活动策划
  • ubuntu 搭建wordpress南宁排名seo公司
  • 可以做免费推广的网站吗宜昌今日头条新闻
  • 深圳网站平台哪家强搜索引擎优化的方法有哪些
  • 攀枝花做网站百度推广登录官网入口
  • 网站建设在哪里常见的搜索引擎有哪些
  • 做网站香港行不行信息流优化
  • flash做网站导航郑州网站推广公司哪家好
  • 深圳短视频代运营公司无锡百度seo优化
  • 网站维护的作用每天新闻早知道
  • 网站建设与运营考试营销策划书模板范文
  • 婚庆公司网站模板如何网页优化
  • 做网站需要些什么西安seo排名公司
  • 钱包网站开发产品线上营销方案
  • 网站图片轮播怎么做宁波网站制作设计
  • html5制作网站首页太原建站seo
  • 温州网站关键词排名优化班级优化大师下载安装最新版
  • 域名邮箱和域名网站开发软件app需要多少钱
  • 主题网站建设软文推广的100个范例
  • 自己做的网站怎么设置文件下载星链友店
  • 多人在线协作网站开发百度一键优化
  • 【网络基础】计算机网络发展背景及传输数据过程介绍
  • Rust进阶-part4-智能指针2
  • android直连SQLserver的可行性分析
  • 7、Redis队列Stream和单线程及多线程模型
  • ENSP防火墙安全策略简单案例
  • C语言基础_随机数、数组、函数、指针