React16源码: React.Children源码实现

洞悉细节!react 16.8.6源码分析-4 children遍历 前言 作为一个前端页面仔和需求粉碎机,在日常的工作中重复雷同的业务需求,能够获得的提高是很有限的。要想跳出此山中,开阔新视野,笔者墙裂建议大家阅读市面上顶尖开源库的源码。这是学习和掌握js语言特性的绝佳机会(前端发展到现在,大型应用高度依赖框架,正常情况下普通开发者是没有机会接触底层的语言特性),同时也是深刻理解框架底层思维的契机。这里笔者选择react第一个开刀,市面上不少关于react源码分析的文章要么过于老旧,要么只截取部分代码或者是伪代码,笔者这里将选取react的16.8.6版本作为示例,从第0行 阅读详情

React.Children


1 ) 概述

  • 这个API用的也比较的少,因为大部分情况下,我们不会单独去操作children
  • 我们在一个组件内部拿到 props 的时候,我们有props.children这么一个属性
  • 大部分情况下,直接把 props.children 把它渲染到我们的jsx 里面就可以了
  • 很少有情况需要去操作一下这个children,但是一旦需要去操作这个children呢
    • 直接使用react点children的API,而不是你直接去操作dom
    • 大部分时候拿到的 children,可能是一个合理的react element,或者是一个数组
  • React提供Children这个API去操作它,一定是有一个合理的原因的

2 )示例演示

import React from 'react'

function ChildrenDemo(props) {
  console.log(props.children)
  console.log(React.Children.map(props.children, c => [c, c]))
  return props.children
}

export default () => (
  <ChildrenDemo>
    <span>1</span>
    <span>2</span>
  </ChildrenDemo>
)
  • 上面这个代码非常简单,创建了一个组件叫 ChildrenDemo
    • 里面有两个 span 作为children,在 props.children 里面,就可以拿到
  • 第一个打印出来的就是 props.children
    • 它就是两个 react element 节点
  • 第二个打印的是 map 的返回值
    • 我们通过react.children.map, 传入这个props.children 和一个callback
    • 这个callback,返回的是一个数组, 这个数组里面,包含两个相同的节点
      • 那这时候打印出来的是4个节点
      • 也就是每个span都被克隆成2份,2个span是4份
      • 前两个children 都是1,后两个都是2
    • 再来改一下 console.log(React.Children.map(props.children, c => [c, [c, c]]))
      • 它会输出六个节点
      • 0, 1, 2,的children是 1
      • 3, 4, 5 的 children 是2
      • 也就是说 react.children的map function返回的是一个数组,它会继续把它展开
      • 里面不管传了多少层嵌套的数组,最终都会展开成一层数组,即: 被拍平
    • 拍平后有几个元素,map中的当前child就会被克隆成几份
  • 这就是 React.Children.map,跟普通原生的数组.map 的一个本质区别

3 )源码分析

定位到 React.js 中

const React = {
  Children: {
    map,
    forEach,
    count,
    toArray,
    only,
  },
  // ... 省略其他
};
  • 这个对象里面有五个函数,跟原生数组操作非常的像
  • 前两个是最重要的,就是map 和 forEach, 它和数组的意义是一样的
  • 但它实际的操作可能跟数组的map和forEach会有一定的区别
  • map是这些方法所有逻辑里面最复杂的一个,而 map 和 forEach 是差不多的
    • 它们唯一的区别是一个有返回一个没有返回
    • map是通过我们传入的一个方法之后,返回的一个新的数组
    • 而forEach 中只在 null 的判断中返回,其实并非真实的返回值

再定位到 ReactChildren.js 中

/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import invariant from 'shared/invariant';
import warning from 'shared/warning';
import {
  getIteratorFn,
  REACT_ELEMENT_TYPE,
  REACT_PORTAL_TYPE,
} from 'shared/ReactSymbols';

import {isValidElement, cloneAndReplaceKey} from './ReactElement';
import ReactDebugCurrentFrame from './ReactDebugCurrentFrame';

const SEPARATOR = '.';
const SUBSEPARATOR = ':';

/**
 * Escape and wrap key so it is safe to use as a reactid
 *
 * @param {string} key to be escaped.
 * @return {string} the escaped key.
 */
function escape(key) {
  const escapeRegex = /[=:]/g;
  const escaperLookup = {
    '=': '=0',
    ':': '=2',
  };
  const escapedString = ('' + key).replace(escapeRegex, function(match) {
    return escaperLookup[match];
  });

  return '$' + escapedString;
}

/**
 * TODO: Test that a single child and an array with one item have the same key
 * pattern.
 */

let didWarnAboutMaps = false;

const userProvidedKeyEscapeRegex = /\/+/g;
function escapeUserProvidedKey(text) {
  return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/');
}

const POOL_SIZE = 10;
const traverseContextPool = [];
function getPooledTraverseContext(
  mapResult,
  keyPrefix,
  mapFunction,
  mapContext,
) {
  if (traverseContextPool.length) {
    const traverseContext = traverseContextPool.pop();
    traverseContext.result = mapResult;
    traverseContext.keyPrefix = keyPrefix;
    traverseContext.func = mapFunction;
    traverseContext.context = mapContext;
    traverseContext.count = 0;
    return traverseContext;
  } else {
    return {
      result: mapResult,
      keyPrefix: keyPrefix,
      func: mapFunction,
      context: mapContext,
      count: 0,
    };
  }
}

function releaseTraverseContext(traverseContext) {
  traverseContext.result = null;
  traverseContext.keyPrefix = null;
  traverseContext.func = null;
  traverseContext.context = null;
  traverseContext.count = 0;
  if (traverseContextPool.length < POOL_SIZE) {
    traverseContextPool.push(traverseContext);
  }
}

/**
 * @param {?*} children Children tree container.
 * @param {!string} nameSoFar Name of the key path so far.
 * @param {!function} callback Callback to invoke with each child found.
 * @param {?*} traverseContext Used to pass information throughout the traversal
 * process.
 * @return {!number} The number of children in this subtree.
 */
function traverseAllChildrenImpl(
  children,
  nameSoFar,
  callback,
  traverseContext,
) {
  const type = typeof children;

  if (type === 'undefined' || type === 'boolean') {
    // All of the above are perceived as null.
    children = null;
  }

  let invokeCallback = false;

  if (children === null) {
    invokeCallback = true;
  } else {
    switch (type) {
      case 'string':
      case 'number':
        invokeCallback = true;
        break;
      case 'object':
        switch (children.$$typeof) {
          case REACT_ELEMENT_TYPE:
          case REACT_PORTAL_TYPE:
            invokeCallback = true;
        }
    }
  }

  if (invokeCallback) {
    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;
  }

  let child;
  let nextName;
  let subtreeCount = 0; // Count of children found in the current subtree.
  const nextNamePrefix =
    nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;

  if (Array.isArray(children)) {
    for (let i = 0; i < children.length; i++) {
      child = children[i];
      nextName = nextNamePrefix + getComponentKey(child, i);
      subtreeCount += traverseAllChildrenImpl(
        child,
        nextName,
        callback,
        traverseContext,
      );
    }
  } else {
    const iteratorFn = getIteratorFn(children);
    if (typeof iteratorFn === 'function') {
      if (__DEV__) {
        // Warn about using Maps as children
        if (iteratorFn === children.entries) {
          warning(
            didWarnAboutMaps,
            'Using Maps as children is unsupported and will likely yield ' +
              'unexpected results. Convert it to a sequence/iterable of keyed ' +
              'ReactElements instead.',
          );
          didWarnAboutMaps = true;
        }
      }

      const iterator = iteratorFn.call(children);
      let step;
      let ii = 0;
      while (!(step = iterator.next()).done) {
        child = step.value;
        nextName = nextNamePrefix + getComponentKey(child, ii++);
        subtreeCount += traverseAllChildrenImpl(
          child,
          nextName,
          callback,
          traverseContext,
        );
      }
    } else if (type === 'object') {
      let addendum = '';
      if (__DEV__) {
        addendum =
          ' If you meant to render a collection of children, use an array ' +
          'instead.' +
          ReactDebugCurrentFrame.getStackAddendum();
      }
      const childrenString = '' + children;
      invariant(
        false,
        'Objects are not valid as a React child (found: %s).%s',
        childrenString === '[object Object]'
          ? 'object with keys {' + Object.keys(children).join(', ') + '}'
          : childrenString,
        addendum,
      );
    }
  }

  return subtreeCount;
}

/**
 * Traverses children that are typically specified as `props.children`, but
 * might also be specified through attributes:
 *
 * - `traverseAllChildren(this.props.children, ...)`
 * - `traverseAllChildren(this.props.leftPanelChildren, ...)`
 *
 * The `traverseContext` is an optional argument that is passed through the
 * entire traversal. It can be used to store accumulations or anything else that
 * the callback might find relevant.
 *
 * @param {?*} children Children tree object.
 * @param {!function} callback To invoke upon traversing each child.
 * @param {?*} traverseContext Context for traversal.
 * @return {!number} The number of children in this subtree.
 */
function traverseAllChildren(children, callback, traverseContext) {
  if (children == null) {
    return 0;
  }

  return traverseAllChildrenImpl(children, '', callback, traverseContext);
}

/**
 * Generate a key string that identifies a component within a set.
 *
 * @param {*} component A component that could contain a manual key.
 * @param {number} index Index that is used if a manual key is not provided.
 * @return {string}
 */
function getComponentKey(component, index) {
  // Do some typechecking here since we call this blindly. We want to ensure
  // that we don't block potential future ES APIs.
  if (
    typeof component === 'object' &&
    component !== null &&
    component.key != null
  ) {
    // Explicit key
    return escape(component.key);
  }
  // Implicit key determined by the index in the set
  return index.toString(36);
}

function forEachSingleChild(bookKeeping, child, name) {
  const {func, context} = bookKeeping;
  func.call(context, child, bookKeeping.count++);
}

/**
 * Iterates through children that are typically specified as `props.children`.
 *
 * See https://reactjs.org/docs/react-api.html#reactchildrenforeach
 *
 * The provided forEachFunc(child, index) will be called for each
 * leaf child.
 *
 * @param {?*} children Children tree container.
 * @param {function(*, int)} forEachFunc
 * @param {*} forEachContext Context for forEachContext.
 */
function forEachChildren(children, forEachFunc, forEachContext) {
  if (children == null) {
    return children;
  }
  const traverseContext = getPooledTraverseContext(
    null,
    null,
    forEachFunc,
    forEachContext,
  );
  traverseAllChildren(children, forEachSingleChild, traverseContext);
  releaseTraverseContext(traverseContext);
}

function mapSingleChildIntoContext(bookKeeping, child, childKey) {
  const {result, keyPrefix, func, context} = bookKeeping;

  let mappedChild = func.call(context, child, bookKeeping.count++);
  if (Array.isArray(mappedChild)) {
    mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, c => c);
  } else if (mappedChild != null) {
    if (isValidElement(mappedChild)) {
      mappedChild = cloneAndReplaceKey(
        mappedChild,
        // Keep both the (mapped) and old keys if they differ, just as
        // traverseAllChildren used to do for objects as children
        keyPrefix +
          (mappedChild.key && (!child || child.key !== mappedChild.key)
            ? escapeUserProvidedKey(mappedChild.key) + '/'
            : '') +
          childKey,
      );
    }
    result.push(mappedChild);
  }
}

function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
  let escapedPrefix = '';
  if (prefix != null) {
    escapedPrefix = escapeUserProvidedKey(prefix) + '/';
  }
  const traverseContext = getPooledTraverseContext(
    array,
    escapedPrefix,
    func,
    context,
  );
  traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
  releaseTraverseContext(traverseContext);
}

/**
 * Maps children that are typically specified as `props.children`.
 *
 * See https://reactjs.org/docs/react-api.html#reactchildrenmap
 *
 * The provided mapFunction(child, key, index) will be called for each
 * leaf child.
 *
 * @param {?*} children Children tree container.
 * @param {function(*, int)} func The map function.
 * @param {*} context Context for mapFunction.
 * @return {object} Object containing the ordered map of results.
 */
function mapChildren(children, func, context) {
  if (children == null) {
    return children;
  }
  const result = [];
  mapIntoWithKeyPrefixInternal(children, result, null, func, context);
  return result;
}

/**
 * Count the number of children that are typically specified as
 * `props.children`.
 *
 * See https://reactjs.org/docs/react-api.html#reactchildrencount
 *
 * @param {?*} children Children tree container.
 * @return {number} The number of children.
 */
function countChildren(children) {
  return traverseAllChildren(children, () => null, null);
}

/**
 * Flatten a children object (typically specified as `props.children`) and
 * return an array with appropriately re-keyed children.
 *
 * See https://reactjs.org/docs/react-api.html#reactchildrentoarray
 */
function toArray(children) {
  const result = [];
  mapIntoWithKeyPrefixInternal(children, result, null, child => child);
  return result;
}

/**
 * Returns the first child in a collection of children and verifies that there
 * is only one child in the collection.
 *
 * See https://reactjs.org/docs/react-api.html#reactchildrenonly
 *
 * The current implementation of this function assumes that a single child gets
 * passed without a wrapper, but the purpose of this helper function is to
 * abstract away the particular structure of children.
 *
 * @param {?object} children Child collection structure.
 * @return {ReactElement} The first and only `ReactElement` contained in the
 * structure.
 */
function onlyChild(children) {
  invariant(
    isValidElement(children),
    'React.Children.only expected to receive a single React element child.',
  );
  return children;
}

export {
  forEachChildren as forEach,
  mapChildren as map,
  countChildren as count,
  onlyChild as only,
  toArray,
};
  • 翻到最下面,看到 mapChildren as map,这边 export 出去的是 map

  • 对应的,我们来看 mapchildren 这个方法

    /**
     * Maps children that are typically specified as `props.children`.
     *
     * See https://reactjs.org/docs/react-api.html#reactchildrenmap
     *
     * The provided mapFunction(child, key, index) will be called for each
     * leaf child.
     *
     * @param {?*} children Children tree container.
     * @param {function(*, int)} func The map function.
     * @param {*} context Context for mapFunction.
     * @return {object} Object containing the ordered map of results.
     */
    function mapChildren(children, func, context) {
      if (children == null) {
        return children;
      }
      const result = [];
      mapIntoWithKeyPrefixInternal(children, result, null, func, context);
      return result;
    }
    
    • 开始会调用一个方法叫 mapIntoWithKeyPrefixInternal

       function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
        let escapedPrefix = '';
        if (prefix != null) {
          escapedPrefix = escapeUserProvidedKey(prefix) + '/';
        }
        const traverseContext = getPooledTraverseContext(
          array,
          escapedPrefix,
          func,
          context,
        );
        traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
        releaseTraverseContext(traverseContext);
      }
      
    • 代码上是先处理了一下 escapedPrefix, 这个倒没什么,后面调用的方法和 forEachChildren 是差不多的

    • 进入这里的 getPooledTraverseContext 方法

    • 它先判断是否已有存在池中是否节点,如果有,则pop一个

    • 并将传入的内容都挂载到这个pop出来的对象上面,用于记录

    • 再经过一系列作用之后,执行到上面的 releaseTraverseContext 就是对对象进行清空

    • 上面的过程涉及到了一个对象池的概念,也就是缓存池,用于节省操作的性能

      • js是单线程语言,对大量对象进行操作,比如挂载和删除,可能会造成内存抖动的问题
      • 可能导致浏览器内的页面性能很差
      • 它设置Pool Size的大小是 10,是一个渐进的过程
      • 一开始是空的,随着对象的创建会进行缓存,接着复用
    • 总体来说,它会做一个非常重要的事情,就是到一个叫做 contextPool 的地方去获取一个 context

    • 接下去所有流程都是在这个函数里面调用了 traverseAllChildren 这个方法

    • 调用完所有的方法之后,它会把这个context再返回到这个 contextPool 里面

    • 调用的 traverseAllChildren 方法没有什么操作,本质上调了 traverseAllChildrenImpl 的方法

      /**
       * Traverses children that are typically specified as `props.children`, but
       * might also be specified through attributes:
       *
       * - `traverseAllChildren(this.props.children, ...)`
       * - `traverseAllChildren(this.props.leftPanelChildren, ...)`
       *
       * The `traverseContext` is an optional argument that is passed through the
       * entire traversal. It can be used to store accumulations or anything else that
       * the callback might find relevant.
       *
       * @param {?*} children Children tree object.
       * @param {!function} callback To invoke upon traversing each child.
       * @param {?*} traverseContext Context for traversal.
       * @return {!number} The number of children in this subtree.
       */
      function traverseAllChildren(children, callback, traverseContext) {
        if (children == null) {
          return 0;
        }
      
        return traverseAllChildrenImpl(children, '', callback, traverseContext);
      }
      
    • 进入 traverseAllChildrenImpl 这个方法会判断我们的children是否是一个数组或者是一个iterator对象

    • 这代表它们是多个节点是可以遍历的, 如果它是多个节点,它会去循环每一个节点

    • 然后对每一个节点再重新调用这个 traverseAllChildrenImpl 这个方法, 也就是递归实现

    • 最终要传入这个 traverseAllChildrenImpl 方法的children,是以单个节点的时候

    • 才会去执行真正的 mapSingleChildIntoContext 方法, 在这个方法里面会调用

    • React.Children.map 传入的第二个参数,也就是那个map function

    • 它会传入上面遍历出来的最终的单个节点,返回想要的map结果的一个数据

    • 拿到一个map数据之后,它会进行一个判断,是否是数组,如果不是数组

    • 它会在result中插入克隆节点,并替换key,防止有相同的key出现

    • 如果是数组的话,又会回过头来去调用这个 mapIntoWithKeyPrefixInternal,到这里完成了一个大的递归

    • 在这么一个递归的过程下去,最终是把里面返回的所有层级的数组都进行了一个展开

    • 展开之后就变成了一个一维数组, 这就是它的一个整体的流程

  • 然后再来对比一下 forEachChildren

    /**
    * Iterates through children that are typically specified as `props.children`.
    *
    * See https://reactjs.org/docs/react-api.html#reactchildrenforeach
    *
    * The provided forEachFunc(child, index) will be called for each
    * leaf child.
    *
    * @param {?*} children Children tree container.
    * @param {function(*, int)} forEachFunc
    * @param {*} forEachContext Context for forEachContext.
    */
    function forEachChildren(children, forEachFunc, forEachContext) {
     if (children == null) {
       return children;
     }
     const traverseContext = getPooledTraverseContext(
       null,
       null,
       forEachFunc,
       forEachContext,
     );
     traverseAllChildren(children, forEachSingleChild, traverseContext);
     releaseTraverseContext(traverseContext);
    }
    
    • 可以看到它最后没有 return,这就是 forEachChildren 跟 mapChildren 的本质区别
  • 关于export 出去的 toArray

    function toArray(children) {
       const result = [];
       mapIntoWithKeyPrefixInternal(children, result, null, child => child);
       return result;
    }
    
    • toArray和 mapChildren 唯一的区别就是 map function
    • 换句话说,它的map function,其实就是 child => child
    • 它其实也会把数组展开,只是说没有map的过程
  • 还有 export 出去的 onlyChild

    function onlyChild(children) {
      invariant(
        isValidElement(children),
        'React.Children.only expected to receive a single React element child.',
      );
      return children;
    }
    
    • 其实就是判断一下这个children是否是单个的合理的 react element 节点
    • 如果是的话,就返回,不是的话,给出提醒
  • 最后 export 出去的 countChildren

    function countChildren(children) {
      return traverseAllChildren(children, () => null, null);
    }
    
    • 内部调用 traverseAllChildren, 本质上还是调用 traverseAllChildrenImpl
    • 最终返回的是统计后的值 subtreeCount
  • 最后还有一个 节点 key 相关的处理,主要核心实现是在 getComponentKey 也是个递归的处理

    • 打印出的每个节点上,都会有一个key,这个key的处理也是比较核心的
    • 参考 ChildrenDemo中的 React.Children.map 中的回调 c => [c, [c,c]] 这里会总计打印出6个节点
      • 可以看到第一个节点是 .0/.0
      • 然后第二个节点是 .0/.1:0
      • 然后第三个节点是 .0/.1:1
      • …
    • 可以按照上述函数和顶层声明的两个变量 SEPARATOR 和 SUBSEPARATOR
    • 理解下这个打印出的结果
AutoDock Vina 对接计算(大批量) AutoDock Vina是一种用于计算生物分子之间相互作用的计算工具,主要用于蛋白质和小分子(通常是潜在药物分子)之间的对接研究。它可以用于虚拟筛选、药物设计和生物分子结合位点的预测等多个应用领域。 阅读详情

相关推荐

STM8开发环境搭建(STVD + COSMIC)

一、STM8开发IDE 1. STVD + COSMIC ST Visual Develop (STVD)只支持汇编开发,C语言开发需要再安装COSMIC,配套起来使用。 2. IAR IAR也可以用来开发STM8 下面介绍STVD + COSMIC的搭建方式 二、环境搭建 1. STVD下载、安装 直接从官网下载:https://www.st.com/en/development-tools/stvd-stm8.html 安装很简单,基本下一步往下点。 2. COSMIC下载、安装 对于stm8可以使用3

a183635870的博客 1万+

理解 React 中的 ReactElement、children 和 ReactNode

childrenReactNode是 React 用来描述 UI 元素的对象,是不可变的。children是一个特殊的属性,用于传递嵌套的内容到组件内部。ReactNode是一个通用的类型,可以包含所有可以被渲染的内容,包括、字符串、数字、数组等。

weixin_51687565的博客 2400

1.3、云计算HCIP融合存储产品及部署

目标:描述Oceanstor V3系列存储产品系统组成及产品定位 描述Oceanstor V3硬件结构及软件架构 掌握存储系统与主机系统之间的连接 一、存储型号 低端型存储:Oceanstor 2200 2600 2800 V3/V5 终端型存储:Oceanstor 5300 5500 5600 5800 6800 V3/V5 高端型存储:Oceanstor 18000 二、Oceanstor V3系列存储系统定位 OceanStor V3系列存储系统是华为根据存储产品应用现状和存储

weixin_43666279的博客 1655

解决 function childrenEqual(a /*: ReactChildren*/, b /*: ReactChildren*/) /*: boolean*/{ 报错

的目标环境未正确设置,可能会导致现代语法未被转译。使用了现代 JavaScript 语法(例如。或 Webpack 配置未正确处理这些语法。和其他现代语法,例如可选链和空值合并运算符。默认情况下,Webpack 不会转译。因此,你需要显式地将。添加到 Babel 的处理范围。如果你无法修改配置,可以尝试降级。该版本可能不会使用现代语法。在 Babel 配置中添加。确保 Babel 支持。到一个较老版本,比如。然后启动前端启动脚本。

菜鸡的博客 492

基于STM32的多普勒雷达测速

基于多普勒雷达传感器,以STM32单片机为主控芯片,根据不同模块检测距离的不同,使用不同多普勒雷达传感器实现对远近距离车辆行驶速度及方向的测量。 1、基础知识 无线电探测和测距,是用无线电(电磁波)方法发现目标并测定其空间位置的装置。随着雷达技术的发展,现代雷达不仅可以对目标进行定位,还可以测量目标的速度、对目标进行成像甚至测量目标的大小和材料特性。所有利用雷达波来检测物体速度的原理,其理论基础皆源自于“多普勒效应”,...

weixin_52801934的博客 6315

射频测试基础知识总结

表示可以辐射到空间的电磁频率,频率范围从300KHz~110GHz之间,射频简称RF,是高频交流变化电磁波的简称,其每秒变化小于1000次被称为低频电流,超过10000次的称为高频电流,而射频就是这种高频电流。为了确保天线接收的信号能够在接收机的最后一级被正确的恢复,一个好的低噪音放大器需要在放大信号的同时产生尽可能低的噪音以及失真。两种,带内试验的范围也有一定的差别,比如,带内试验主要是检测信号的质量,如功率、频谱宽度、调制质量,而带外测试的是信号的杂散、谐波,主要是看对频带之外的干扰有多大。

cny70的博客 9629

react children的多样性

react children 作为传递数据的方式之一,他可以接受element/string/函数/数组多种方式。 class Mclass Menu extends Component { render () { return ( <ul>{this.props.children}</ul> ) } }

weixin_44294593的博客 178

新手必看:电路设计里的‘地’到底怎么接?单点、多点、混合接地保姆级图解

本文深入解析电路设计中的接地技术,涵盖单点、多点和混合接地的原理与应用。通过详细的图解和实战案例,帮助新手理解接地在提供参考电位、构成电流回路及抑制电磁干扰中的关键作用,避免常见设计误区,提升电路稳定性与抗干扰能力。

weixin_28455801的博客 301

React组件进阶

如果我们像上面 ListItem 标签里面写上东西 ,这样就相当于有了一个字节点,这样就会自动拥有了了children 属性,我们到页面上看看。

发果叁 563

6.14华为OD机试真题 新系统 - 字符串格式调整 (Java/Py/C/C++/Js/Go)

# **字符串格式调整** > 2026 华为OD机试真题 6月14日华为OD上机新系统考试真题 100 分题型 点击查看华为 OD 机试真题完整目录:[2026最新华为OD机试新系统卷 + 双机位C卷 真题题库目录|全覆盖题库 + 逐点算法考点详解](https://blog.csdn.net/banxia_frontend/article/details/160346662) # 题目描述 输入一个字符串,字符串中只包含大写字母和数字。要求将字符串中的所有数字提取出来,按出现的顺序组

算法大师! 951

QCC304x系列开发教程(基础篇)之2.1-QCC3040之开发环境搭建

一、安装MDE 1.解压qualcomm_mde.win.2.4_installer_2.4.1.4压缩包,安装MDE_WIN_2.4.1.4_x64.exe,路径自定义 点击NEXT, 安装完成后,点击Finish. 完成安装后,桌面生成快捷方式

心跳包的博客 6080

2020全新 React 16.12 第三季:React-Router/Hooks

React是一个用于构建用户界面的 JavaScript 库。起源于 Facebook 的内部项目,并与2013年5月开源。React拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它

一次请求穿过的六道关卡:微服务基础组件的通信与IO、事件驱动、负载均衡、服务路由、API网关与配置协调

微服务的稳定性往往取决于看不见的基础组件。本文跟随一次下单请求,依次穿过API网关、服务路由、负载均衡与服务通信,再沿事件分支扇出,并从控制面审视配置中心。通信层剖析握手成本、连接复用、epoll与主从Reactor、心跳判活、退避抖动、截止时间与重试预算;事件层讲解编舞与编排、事务发件箱和幂等消费;均衡与路由对比静态与动态算法、路由链、全链路灰度与同区保底;网关讨论过滤器链与限流算法;配置部分给出四类配置、长轮询与共识协调,最后归纳五道防线。文中关键数据均来自可在Java8运行的演示程序。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 172万+

React 源码系列 | React Children 详解 | Children 中 key 内部生成原理

本文基于 React V16.8.6,本文代码地址测试代码 https://github.com/lxfriday/react-source-analyse/commit...

止水聊技术 984

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

react解析 React.Children(二)

感谢 yck: 剖剖析 React 源码解析,本篇文章是在读完他的文章的基础上,将他的文章进行拆解和加工,加入我自己的一下理解和例子,便于大家理解。觉得yck写的真的很棒 。React 版本为 16.8.6,关于源码的阅读,可以移步到yck react源码解析本文永久有效链接: react解析 React.Children(二)在React实际开发中, React.Children 这个API我...

weixin_33692284的博客 423

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

react 数组遍历删除_React 源码系列 | React Children 详解

本文基于 React V16.8.6,本文代码地址测试代码 源码讲解React 中一个元素可能有 0 个、1 个或者多个直接子元素,React 导出的 Children 中包含 5 个处理子元素的方法。map 类似 array.mapforEach 类似 array.forEachcount 类似 array.lengthtoArrayonlyReact 内部处理 Children 的几个重要函数...

weixin_31720623的博客 673

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

react 遍历对象_React 源码系列 | React Children 详解

本文基于 React V16.8.6,本文代码地址测试代码 源码讲解React 中一个元素可能有 0 个、1 个或者多个直接子元素,React 导出的 Children 中包含 5 个处理子元素的方法。map 类似 array.mapforEach 类似 array.forEachcount 类似 array.lengthtoArrayonlyReact 内部处理 Children 的几个重要函数...

weixin_39832448的博客 523

React源码解析笔记---React.Children

v16.8.6 React.Children.map mapChildren function mapChildren(children, func, context) { if (children == null) { return children; } const result = []; mapIntoWithKeyPrefixInternal(children, ...

ck_1的博客 287

React16源码: React中的reconcileChildIterator和reconcileChildrenArray的源码实现

在 reconcileChildFibers 函数中调用的 reconcileChildrenIterator。在 reconcileChildFibers 函数中调用的 reconcileChildrenArray。新老children的对比过程,以及判断节点是否可复用的过程,这个过程会涉及到react的一个算法。先看下 reconcileChildrenArray 这个API。尽量减少 数组的遍历次数,达到复用节点的过程。

Wang的专栏 1540

react源码流程图—— ReactChildren

本文阅读react16.8.6版本ReactChildren.js文件。下面从mapChildren函数入手,给出React.Children.map的流程图。 请参考React源码阅读本文。 mapChildren遍历每个子节点调用函数并摊平子节点。 摊平子节点,即,把['a', ['b'], [['c'], 'd']]摊平成['a', 'b', 'c', 'd'...

Winne_Shen的专栏 1472

React16源码: React中的reconcileChildren的源码实现

在更新了一个节点之后,拿到它的props.children, 要根据这个children里面的 ReactElement 来去创建子树的所有的 fiber 对象, 要根据 props.children 来生成 fiber 子树,然后判断 fiber 对象它是否是可以复用的

Wang的专栏 2133

react classname多个_剖析 React 源码:先热个身

编者按:本文作者 yck,公众号「前端真好玩」这是我的 React 源码解读课的第一篇文章,首先来说说为啥要写这个系列文章:现在工作中基本都用 React 了,由此想了解下内部原理市面上 Vue 的源码解读数不胜数,但是反观 React 相关的却寥寥无几,也是因为 React 源码难度较高,因此我想来攻克这个难题自己觉得看懂并不一定看懂了,写出来让读者看懂才是真懂了,因此我要把我读懂的东...

weixin_39984952的博客 120

DC-DC转换器线性调整率与负载调整率:原理、测量与优化实践

在电源系统设计中,线性调整率(Line Regulation)与负载调整率(Load Regulation)是衡量DC-DC转换器输出电压稳定性的核心指标,直接影响后端电路的供电质量。线性调整率本质受反馈环路增益制约,用于抑制输入电压波动;负载调整率则主要由功率通路的寄生电阻和走线压降决定,在高端应用中可通过远程采样(Remote Sense)技术进行补偿。理解这两个参数的物理内涵及其测量条件,有助于工程师在实际项目中准确评估电源性能,并针对动态瞬态响应、PCB布局和补偿网络进行系统级优化。在工业控制、车载

weixin_33894640的博客 322

react源码分析:babel如何解析jsx

不管是类组件还是函数组件,最终我们写的jsx都被babel转化成了可识别的元素,其中我们也看了,,Component等内部实现,了解到了作为他是怎么被创建的,但是远远没有完,因为我们知道我们在写React的时候,会在后面带上一个,没错我们下一章节就要去探索一下方法了。

weixin_59558923的博客 828

react-outside-click-handler Props API参考:children、onOutsideClick、disabled、useCapture、display五大属性详解

react-outside-click-handler 是一款专门处理「点击外部」交互的 React 组件库:把元素包一层,用户点击元素范围之外的任意位置时就会自动触发你的回调。下拉菜单、弹窗关闭、浮层收起等常见场景一行就能搞定。本文是一份完整的 Props API 参考,逐条拆解 children、onOutsideClick、disabled、useCapture、display 五大属性,新

gitblog_01034的博客 460

React.FC 的 children没法使用 简单解决方法

声明:是简单的解决方法,我并不知道原理,刚用没多久。

qq_45224286的博客 844
上一篇: React16源码: Hooks源码实现
下一篇: React16源码: memo, Fragment, StrictMode, cloneElement, createFactory源码实现
Wang's Blog
博客等级 码龄12年 7433粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值