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

网站没有百度快照佛山网页设计模板

网站没有百度快照,佛山网页设计模板,装修免费预约平台,上海市建设工程 安全质量网站如今的前端#xff0c;框架横行#xff0c;出去面试问到框架是常有的事。我比较常用React#xff0c; 这里就写了一篇 React 基础原理的内容#xff0c; 面试基本上也就问这些#xff0c; 分享给大家。React 是什么React是一个专注于构建用户界面的 Javascript Library.一… 如今的前端框架横行出去面试问到框架是常有的事。 我比较常用React 这里就写了一篇 React 基础原理的内容 面试基本上也就问这些 分享给大家。React 是什么React是一个专注于构建用户界面的 Javascript Library.一、React做了什么Virtual Dom模型生命周期管理setState机制Diff算法React patch、事件系统React的 Virtual Dom模型virtual dom 实际上是对实际Dom的一个抽象是一个js对象。react所有的表层操作实际上是在操作Virtual dom。经过 Diff 算法会计算出 Virtual DOM 的差异然后将这些差异进行实际的DOM操作更新页面。二、React  总体架构三、几点要了解的知识JSX 如何生成ElementElement 如何生成DOM1JSX 如何生成Element先看一个例子 Counter :App.js 就做了一件事情就是把 Counter 组件挂在 #root 上.Counter 组件里面定义了自己的 state, 这是个默认的 property 还有一个 handleclick 事件和 一个 render 函数。看到 render 这个函数里竟然在 JS 里面写了 html !  这是一种 JSX 语法。React 为了方便 View 层组件化承载了构建 html 结构化页面的职责。这里也简单的举个例子将 html 语法直接加入到 javascript 代码中再通过翻译器转换到纯 javascript 后由浏览器执行。这里调用了 React 和 createElement 方法这个方法就是用于创建虚拟元素 Virtual Dom 的。React 把真实的 DOM 树转换成 Javascript 对象树也就是 Virtual Dom。每次数据更新后重新计算 Virtual Dom 并和上一次生成的 virtual dom 做对比对发生变化的部分做批量更新。而 React 是通过创建与更新虚拟元素 Virtual Element 来管理整个Virtual Dom 的。 虚拟元素可以理解为真实元素的对应它的构建与更新都是在内存中完成的并不会真正渲染到 dom 中去。回到我们的计数器 counter 组件注意下 a 标签 createElement 的返回结果 这里 CreateElement 只是做了简单的参数修正返回一个 ReactElemet 实例对象。Virtual element 彼此嵌套和混合就得到了一颗 virtual dom 的树2Element 如何生成DOM现在我们有了由 ReactElement 组成的 Virtual Dom 树接下来我们要怎么我们构建好的 Virtual dom tree 渲染到真正的 DOM 里面呢这时可以利用 ReactDOM.render 方法传入一个 reactElement 和一个 作为容器的 DOM 节点。看进去 ReactDOM.render 的源码里面有两个比较关键的步骤:第一步是 instantiateReactComponent。这个函数创建一个 ReactComponent 的实例并返回也可以看到 ReactDOM.render 最后返回的也是这个实例。instantiateReactComponent 方法是初始化组件的入口函数它通过判断 node 的类型来区分不同组件的入口。当 node 为空的时候初始化空组件。当 node 为对象类型 type 字段标记为是字符串初始化 DOM 标签。否则初始化自定义组件。当 node 为字符串或者数字时初始化文本组件。虽然 Component 有多种类型但是它们具有基本的数据结构ReactComponent 类。注意到这里的 setState, 这也是重点之一。创建了 Component 实例后调用 component 的 mountComponent 方法注意到这里是会被批量 mount 的这样组件就开始进入渲染到 DOM 的流程了。四、React生命周期React 组件基本由三个部分组成属性 props状态 state生命周期方法React 组件可以接受参数props, 也有自身状态 state。一旦接受到的参数 props 或自身状态 state 有所改变React 组件就会执行相应的生命周期方法。React 生命周期的全局图首次挂载组件时按顺序执行componentWillMount、rendercomponentDidMount卸载组件时执行 componentDidUnmount当组件接收到更新状态重新渲染组件时执行componentWillReceivePropsshouldComponentUpdatecomponentWillUpdaterender  componentDidUpdate更新策略通过 updateComponent 更新组件首先判读上下文是否改变前后元素是否一致如果不一致且组件的 componentWillReceiveProps 存在则执行。然后进行 state 的合并。调用 shouldComponentUpdate 判断是否需要进行组件更新如果存在 componentWillUpdate 则执行。后面的流程跟 mountComponent 相似这里就不赘述了。五、setState机制为避免篇幅过长这部分可移步我的专题文章六、Diff算法Diff算法用于计算出两个virtual dom的差异是React中开销最大的地方。传统diff算法通过循环递归对比差异算法复杂度为 O(n3)。React diff算法制定了三条策略将算法复杂度从 O(n3)降低到O(n)。1. UI中的DOM节点跨节点的操作特别少可以忽略不计。2. 拥有相同类的组件会拥有相似的DOM结构。拥有不同类的组件会生成不同的DOM结构。3. 同一层级的子节点可以根据唯一的ID来区分。1. Tree Diff对于策略一React 对树进行了分层比较两棵树只会对同一层次的节点进行比较。只会对相同层级的 DOM 节点进行比较当发现节点已经不存在时则该节点及其子节点会被完全删除不会用于进一步的比较。如果出现了 DOM 节点跨层级的移动操作。如上图这样A节点就会被直接销毁了。Diif 的执行情况是create A - create C - create D - delete A2. Element Diff当节点处于同一层级时diff 提供了 3 种节点操作插入、移动和删除。对于同一层的同组子节点添加唯一 key 进行区分。通过 diff 对比后发现新旧集合的节点都是相同的节点因此无需进行节点删除和创建只需要将旧集合中节点的位置更新为新集合中节点的位置.七、原理解析几个概念对新集合中的节点进行循环遍历新旧集合中是否存在相同节点nextIndex: 新集合中当前节点的位置lastIndex: 访问过的节点在旧集合中最右的位置(最大位置)If (child._mountIndex lastIndex)对新集合中的节点进行循环遍历通过 key 值判断新旧集合中是否存在相同节点如果存在则进行移动操作。在移动操作的过程中有两个指针需要注意一个是 nextIndex表示新集合中当前节点的位置也就是遍历新集合时当前节点的坐标。另一个是 lastIndex表示访问过的节点在旧集合中最右的位置更新流程1( 如果新集合中当前访问的节点比 lastIndex 大证明当前访问节点在旧集合中比上一个节点的位置靠后则该节点不会影响其他节点的位置即不进行移动操作。只有当前访问节点比 lastIndex 小的时候才需要进行移动操作。)首先我们开遍历新集合中的节点, 当前 lastIndex 0, nextIndex 0拿到了 B.此时在旧集合中也发现了 BB 在旧集合中的 mountIndex 为 1 比当前 lastIndex 0 要大不满足 child._mountIndex lastIndex对 B 不进行移动操作更新 lastIndex 1, 访问过的节点在旧集合中最右的位置也就是 B 在旧集合中的位置nextIndex 进入下一步。2当前 lastIndex 1, nextIndex 1拿到了 A在旧集合中也发现了 AA 在旧集合中的 mountIndex 为 0 比当前 lastIndex 1 要小满足 child._mountIndex lastIndex对 A 进行移动操作此时 lastIndex 依然 1, A 的 _mountIndex 更新为 nextIndex 1, nextIndex, 进入下一步.3这里A 变成了蓝色表示对 A 进行了移动操作。当前 lastIndex 1, nextIndex 2拿到了 D在旧集合中也发现了 DD 在旧集合中的 mountIndex 为 3 比当前 lastIndex 1 要大不满足 child._mountIndex lastIndex不进行移动操作此时 lastIndex 3, D 的 _mountIndex 更新为 nextIndex 2, nextIndex, 进入下一步.4当前 lastIndex 3, nextIndex 3拿到了 C在旧集合中也发现了 CC 在旧集合中的 mountIndex 为 2 比当前 lastIndex 3 要小满足 child._mountIndex lastIndex要进行移动此时 lastIndex不变为 3, C 的 _mountIndex 更新为 nextIndex 3.5由于 C 已经是最后一个节点因此 diff 操作完成.这样最后要进行移动操作的只有 A C。另一种情况刚刚说的例子是新旧集合中都是相同节点但是位置不同。那如果新集合中有新加入的节点且旧集合存在需要删除的节点那 diff 又是怎么进行的呢比如1首先依旧我们开遍历新集合中的节点, 当前 lastIndex 0, nextIndex 0拿到了 B此时在旧集合中也发现了 BB 在旧集合中的 mountIndex 为 1 比当前 lastIndex 0 要大不满足 child._mountIndex lastIndex对 B 不进行移动操作更新 lastIndex 1, 访问过的节点在旧集合中最右的位置也就是 B 在旧集合中的位置nextIndex 进入下一步。2当前 lastIndex 1, nextIndex 1拿到了 E发现旧集合中并不存在 E此时创建新节点 EnextIndex进入下一步3当前 lastIndex 1, nextIndex 2拿到了 C在旧集合中也发现了 CC 在旧集合中的 mountIndex 为 2 比当前 lastIndex 1 要大不满足 child._mountIndex lastIndex不进行移动此时 lastIndex 更新为 2, nextIndex 进入下一步4当前 lastIndex 2, nextIndex 3拿到了 A在旧集合中也发现了 AA 在旧集合中的 mountIndex 为 0 比当前 lastIndex 2 要小不满足 child._mountIndex lastIndex进行移动此时 lastIndex 不变, nextIndex 进入下一步5当完成新集合中所有节点的差异化对比后还需要对旧集合进行循环遍历判断是否勋在新集合中没有但旧集合中存在的节点。此时发现了 D 满足这样的情况因此删除 D。Diff 操作完成。整个过程还是很繁琐的 明白过程即可。二、性能优化由于react中性能主要耗费在于update阶段的diff算法因此性能优化也主要针对diff算法。1减少diff算法触发次数减少diff算法触发次数实际上就是减少update流程的次数。正常进入update流程有三种方式1、setStatesetState机制在正常运行时由于批更新策略已经降低了update过程的触发次数。因此setState优化主要在于非批更新阶段中(timeout/Promise回调)减少setState的触发次数。常见的业务场景即处理接口回调时无论数据处理多么复杂保证最后只调用一次setState。2、父组件render父组件的render必然会触发子组件进入update阶段(无论props是否更新)。此时最常用的优化方案即为shouldComponentUpdate方法。最常见的方式为进行this.props和this.state的浅比较来判断组件是否需要更新。或者直接使用PureComponent原理一致。需要注意的是父组件的render函数如果写的不规范将会导致上述的策略失效。// Bad case// 每次父组件触发render 将导致传入的handleClick参数都是一个全新的匿名函数引用。// 如果this.list 一直都是undefined每次传入的默认值[]都是一个全新的Array。// hitSlop的属性值每次render都会生成一个新对象class Father extends Component { onClick() {} render() {return Child handleClick{() this.onClick()} list{this.list || []} hitSlop{{ top: 10, left: 10}}/ }}// Good case// 在构造函数中绑定函数给变量赋值// render中用到的常量提取成模块变量或静态成员const hitSlop {top: 10, left: 10};class Father extends Component { constructor(props) {super(props);this.onClick this.onClick.bind(this);this.list []; } onClick() {} render() {return Child handleClick{this.onClick} list{this.list} hitSlop{hitSlop} / }}3、forceUpdateforceUpdate方法调用后将会直接进入componentWillUpdate阶段无法拦截因此在实际项目中应该弃用。其他优化策略   1.  shouldComponentUpdate     使用shouldComponentUpdate钩子根据具体的业务状态减少不必要的props变化导致的渲染。如一个不用于渲染的props导致的update。另外 也要尽量避免在shouldComponentUpdate 中做一些比较复杂的操作 比如超大数据的pick操作等。2. 合理设计state不需要渲染的state尽量使用实例成员变量。     不需要渲染的 props合理使用 context机制或公共模块(比如一个单例服务)变量来替换。2正确使用 diff算法不使用跨层级移动节点的操作。对于条件渲染多个节点时尽量采用隐藏等方式切换节点而不是替换节点。尽量避免将后面的子节点移动到前面的操作当节点数量较多时会产生一定的性能问题。看个具体的例子这时一个 List 组件里面有标题包含 ListItem 子组件的members列表和一个按钮,绑定了一个 onclick 事件.然后我加了一个插件可以显示出各个组件的渲染情况。现在我们来点击改变标题 看看会发生些什么。奇怪的事情发生了为什么我只改了标题  为什么不相关的 ListItem 组件也会重新渲染呢我们可以回到组件生命周期看看为什么。还记得这个组件更新的生命周期流程图嘛这里的重点在于这个 shouldComponentUpdate。只有这个方法返回 true 的时候才会进行更新组件的操作。我们进步一来看看源码。可以看到这里原来如果组件没有定义 shouldComponentUpdate 方法也是默认认为需要更新的。当然我们的 ListItem 组件是没有定义这个 shouldComponentUpdate 方法的。然后我们使用PureComponent :其原理为重新实现了 shouldComponentUpdate 生命周期方法让当前传入的 props 和 state 之前做浅比较如果返回 false 那么组件就不会更新了。这里也放上一张官网的例图根据渲染流程首先会判断shouldComponentUpdate(SCU)是否需要更新。如果需要更新则调用组件的render生成新的虚拟DOM然后再与旧的虚拟DOM对比(vDOMEq)。如果对比一致就不更新如果对比不同则根据最小粒度改变去更新DOM如果SCU不需要更新则直接保持不变同时其子元素也保持不变。相似的APi还有React.memo回到组件再次回到我们的组件中 这次点击按钮 把第二条数据换掉奇怪的事情发生了为什么我只改了第二个 listItem, 还是全部 10 个都重新渲染了呢原因在于 shallow compare , 浅比较。前面说到我们不能直接修改 this.state 的值所以我们把this.state.members 拷贝出来再修改第二个人的信息。很明显因为对象的比较是引用地址显然是不相等的。因此 shoudComponentUpdate 方法都返回了 false, 组件就进行了更新。那么我们怎么能避免这种情况的发生呢其中一个方法是做深比较但是如果对象或数组层级比较深和复制那么这个代价就太昂贵了。我们就可以用到 Immutable.js 来解决这个问题进一步提高组件的渲染性能。 Immutable Data 就是一旦被创建就是不能再更改的数据。首先我们定义了一个 Immutable 的 List 对象List 对应于原生 JS 的 Array对 Immutable 对象进行修改、添加或删除操作都会返回一个新的 Immutable 对象所以这里 bbb 不等于 aaa。但是同时为了避免深拷贝吧所有节点都复制一遍带来的性能消耗Immutable 使用了结构共享即如果对象树中一个节点发生变化只修改这个节点和受它影响的父节点其他节点则进行共享。结果也是我们预期的那样。性能分析用好火焰图 该优化的时候再优化。八、Hooks  及其后续更新为避免篇幅过长这部分可移步我的专题文章最后
http://www.zqtcl.cn/news/954683/

相关文章:

  • 盐城建设厅网站设计备案网站创建服务
  • wp如何做双语网站个人网站首页内容
  • 网络推广网站排行榜百度怎么搜索网址打开网页
  • 网站制作和如何推广深圳西乡
  • 男生女生做污事网站免费西安企业展厅设计公司
  • 做网络写手最好进那个网站网页建站需要多少钱
  • 网站打开不对摄影设计说明200字
  • 无锡网站制作公司排名网站开发与应用 大作业作业
  • 网站建设中搜索引擎wordpress 不在首页显示文章
  • 先做网站先备案嘉兴网站建设推广
  • 建设法律法规文本查询网站Html手机浏览网站变形
  • 怎么拥有个人网站wordpress做的网站
  • wordpress建什么站江苏网站建设效果
  • 建设网站网站多少钱东莞网站建设 光龙
  • 天津和平做网站哪家好搞笑网站建设目的和意义
  • 一般做网站带宽选择多大的wordpress页面侧菜单
  • 海淀青岛网站建设友情链接适用网站
  • 青海建设厅官方网站资阳seo
  • 网站个人备案 企业备案深圳高端网站建设网页设计
  • 网站广东省备案国产最好的a级suv88814
  • 没有公司怎么做网站西安市市政建设网站
  • 北京网站制作net2006装饰网站建设策划书
  • 建立什么网站中小学图书馆网站建设
  • 襄阳网站建设外包任县附近网站建设价格
  • led灯网站建设案例有没有什么东西可以做网站
  • 网站可视化设计企业网络管理系统
  • 优惠券怎做网站南宁网站公司
  • 灌南县规划局网站理想嘉苑规划建设那些公司做网站好
  • 大型网站开发的主流语言wordpress 连接flickr
  • 制作一个网站流程怎样做网站运营