diff --git a/src/index.js b/src/index.js
index 82433470761e01cd6adcfe1e06535ee1819bc83b..737a3a15d81d829177cbbb94eab5ebb3cdde4073 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,26 +1,20 @@
-
-import React, { Component } from './react';
-import ReactDOM from 'react-dom';
+import React, { Component } from './react'
+import ReactDOM from 'react-dom'
class Child extends Component {
render() {
- console.log(this.props.children);
+ // console.log(this.props.children)
const mappedChildren = React.Children.map(
this.props.children,
- (item, index) => (
- [
{item}
, {item}
]
- )
- );
- console.log(mappedChildren);
- return (
-
- {mappedChildren}
-
+ (item, index) => [
+ {item}
,
+ {item}
,
+ ]
)
+ console.log(mappedChildren)
+ return {mappedChildren}
}
}
class App extends Component {
-
-
render() {
/* [1, 2, 3].map(item => {item});
1.map(item => {item});
@@ -31,16 +25,14 @@ class App extends Component {
child1
child2
child3
- {
- [
- child4
,
- child5
,
- child6
- ]
- }
+ {[
+ child4
,
+ child5
,
+ child6
,
+ ]}
)
}
}
-console.log('App.prototype.isReactComponent', App.prototype.isReactComponent);
-ReactDOM.render(, document.getElementById('root'));
\ No newline at end of file
+console.log('App.prototype.isReactComponent', App.prototype.isReactComponent)
+ReactDOM.render(, document.getElementById('root'))
diff --git a/src/react/ReactBaseClasses.js b/src/react/ReactBaseClasses.js
index ae81361f38bb31afdfbfd45dc99eca0b0babfadb..6e5ee051dcf3144990c7e66f7b9f640af8b5ad98 100644
--- a/src/react/ReactBaseClasses.js
+++ b/src/react/ReactBaseClasses.js
@@ -1,17 +1,15 @@
-
-let emptyObject = {};
+let emptyObject = {}
class Component {
- constructor(props, context) {
- this.props = props;
- this.context = context;
- this.refs = emptyObject;
- }
+ constructor(props, context) {
+ this.props = props
+ this.context = context
+ this.refs = emptyObject
+ }
}
- //在React内部是凭这个变量来判断是不是一个React组件的
- //因为组件定义的有两种方式,一种是类组件,一种函数组件,都被babel编译成函数
- Component.prototype.isReactComponent = {
-};
+//在React内部是凭这个变量来判断是不是一个React组件的
+//因为组件定义的有两种方式,一种是类组件,一种函数组件,都被babel编译成函数
+Component.prototype.isReactComponent = {}
-class PureComponent extends Component { }
-PureComponent.prototype.isPureReactComponent = true;
-export { Component }
\ No newline at end of file
+class PureComponent extends Component {}
+PureComponent.prototype.isPureReactComponent = true
+export { Component }
diff --git a/src/react/ReactChildren.js b/src/react/ReactChildren.js
index bbc07d81edaad3705a3dca0942e1cbc01bff2624..48243f313f0fbeaa6139810ab49bc1e879050b3c 100644
--- a/src/react/ReactChildren.js
+++ b/src/react/ReactChildren.js
@@ -1,8 +1,78 @@
+import { cloneAndReplaceKey } from './ReactElement'
+
function mapChildren(children, func, context) {
- //TODO实现此mapChildren方法
- return children;
+ // TODO实现此mapChildren方法
+ if (children == null) {
+ return children
+ }
+ const result = []
+ mapIntoArray(children, result, '', func)
+ return result
+}
+
+let count = 0
+function mapIntoArray(children, array, escapedPrefix, callback) {
+ const type = typeof children
+
+ if (type === 'undefined' || type === 'boolean') {
+ children = null
+ }
+
+ for (let i = 0; i < children.length; i++) {
+ const element = children[i]
+ if (element.length > 0) {
+ mapIntoArray(element, array, i, callback)
+ } else {
+ let preKey = ''
+ if (element.key) {
+ preKey = element.key
+ }
+ let res = callback(element, count)
+
+ let res2 = res.map((item) => {
+ let key = handleKey(item, count, preKey, escapedPrefix)
+ return cloneAndReplaceKey(item, key)
+ })
+
+ count++
+ array.push(...res2)
+ }
+ }
}
-export {
- mapChildren as map,
-};
\ No newline at end of file
+// 总的来说就是要评Key,我这个写法好像是只能满足一层数组,如果是多层数组,比如:[a,[a,[a,a]]],我这个方法应该就会出问题
+// 源码中好像是用正则去实现这个问题的,但是我还没看明白,还要再去研究研究……
+function handleKey(element, count, preKey, escapedPrefix) {
+ let key = ''
+
+ if (preKey !== '') {
+ key += `.$${preKey}/`
+ } else {
+ key += `.${count}/`
+ }
+
+ if (element.key) {
+ key = `${key}.$${element.key}`
+ }
+
+ if (escapedPrefix !== '') {
+ key = `.${escapedPrefix}:${key}`
+ }
+ console.log(key)
+ return key
+}
+
+export { mapChildren as map }
+
+// .0/.$div0A
+// .0/.$div0B
+// .$key2/.$div1A
+// .$key2/.$div1B
+// .$key3/.$div2A
+// .$key3/.$div2B
+// .3:$key4/.$div3A
+// .3:$key4/.$div3B
+// .3:$key5/.$div4A
+// .3:$key5/.$div4B
+// .3:$key6/.$div5A
+// .3:$key6/.$div5B
diff --git a/src/react/ReactCurrentOwner.js b/src/react/ReactCurrentOwner.js
index 0bc1545e2fe09b0d681f38dc97fc7f27254aecd6..b12000645f6c13e36bc33962592574647b83d9c7 100644
--- a/src/react/ReactCurrentOwner.js
+++ b/src/react/ReactCurrentOwner.js
@@ -1,5 +1,5 @@
const ReactCurrentOwner = {
- current: null
-};
+ current: null,
+}
-export default ReactCurrentOwner;
\ No newline at end of file
+export default ReactCurrentOwner
diff --git a/src/react/ReactElement.js b/src/react/ReactElement.js
index 25fdf5ea1b24116f963f57890892d03e3d2e3a78..4dbe43e0ef09d8ba2df8cdd0cbaa3ed2de5d23cb 100644
--- a/src/react/ReactElement.js
+++ b/src/react/ReactElement.js
@@ -1,74 +1,98 @@
+import ReactCurrentOwner from './ReactCurrentOwner'
+import { REACT_ELEMENT_TYPE } from '../shared/ReactSymbols'
-import ReactCurrentOwner from './ReactCurrentOwner';
-import { REACT_ELEMENT_TYPE } from '../shared/ReactSymbols';
function hasValidRef(config) {
- return config.ref !== undefined;
+ return config.ref !== undefined
}
+
function hasValidKey(config) {
- return config.key !== undefined;
+ return config.key !== undefined
}
+
const RESERVED_PROPS = {
- key: true,
- ref: true,
- __self: true,
- __source: true
+ key: true,
+ ref: true,
+ __self: true,
+ __source: true,
}
+
export function createElement(type, config, children) {
- let propName;//定义一个变量叫属性名
- const props = {};//定义一个元素的props对象
- let key = null;//在兄弟节点中唯一标识自己的唯一性的,在同一个的不同兄弟之间key要求不同
- let ref = null;//ref=React.createRef() "username" this.refs.username {input=>this.username = input} 从而得到真实的DOM元素
- let self = null;//用来获取真实的this指针
- let source = null;//用来定位创建此虚拟DOM元素在源码的位置 哪个文件 哪一行 哪一列
- if (config !== null) {
- if (hasValidRef(config)) {
- ref = config.ref;
- }
- if (hasValidKey(config)) {
- key = config.key;
- }
- self = config.__self === undefined ? null : config.__self;
- source = config.__source === undefined ? null : config.__source;
- for (propName in config) {
- if (!RESERVED_PROPS.hasOwnProperty(propName)) {
- props[propName] = config[propName]
- }
- }
+ let propName //定义一个变量叫属性名
+ const props = {} //定义一个元素的props对象
+ let key = null //在兄弟节点中唯一标识自己的唯一性的,在同一个的不同兄弟之间key要求不同
+ let ref = null //ref=React.createRef() "username" this.refs.username {input=>this.username = input} 从而得到真实的DOM元素
+ let self = null //用来获取真实的this指针
+ let source = null //用来定位创建此虚拟DOM元素在源码的位置 哪个文件 哪一行 哪一列
+ if (config !== null) {
+ if (hasValidRef(config)) {
+ ref = config.ref
}
- const childrenLength = arguments.length - 2;
- if (childrenLength === 1) {
- props.children = children;//如果说是独生子的话children是一个对象
- } else if (childrenLength > 1) {
- const childArray = Array(childrenLength);
- for (let i = 0; i < childrenLength; i++) {
- childArray[i] = arguments[i + 2];
- }
- props.children = childArray;//如果说是有多个儿子的话,props.children就是一个数组了
+ if (hasValidKey(config)) {
+ key = config.key
}
- if (type && type.defaultProps) {
- const defaultProps = type.defaultProps;
- //只有当属性对象没有此属性对应的值的时候,默认属性才会生效,否则直接忽略
- for (propName in defaultProps) {
- if (props[propName] === undefined) {
- props[propName] = defaultProps[propName]
- }
- }
+ self = config.__self === undefined ? null : config.__self
+ source = config.__source === undefined ? null : config.__source
+ for (propName in config) {
+ if (!RESERVED_PROPS.hasOwnProperty(propName)) {
+ props[propName] = config[propName]
+ }
}
- //ReactCurrentOwner此元素的拥有者
- return ReactElement(
- type, key, ref, self, source, ReactCurrentOwner.current, props
- )
+ }
+ const childrenLength = arguments.length - 2
+ if (childrenLength === 1) {
+ props.children = children //如果说是独生子的话children是一个对象
+ } else if (childrenLength > 1) {
+ const childArray = Array(childrenLength)
+ for (let i = 0; i < childrenLength; i++) {
+ childArray[i] = arguments[i + 2]
+ }
+ props.children = childArray //如果说是有多个儿子的话,props.children就是一个数组了
+ }
+ if (type && type.defaultProps) {
+ const defaultProps = type.defaultProps
+ //只有当属性对象没有此属性对应的值的时候,默认属性才会生效,否则直接忽略
+ for (propName in defaultProps) {
+ if (props[propName] === undefined) {
+ props[propName] = defaultProps[propName]
+ }
+ }
+ }
+ //ReactCurrentOwner此元素的拥有者
+ return ReactElement(
+ type,
+ key,
+ ref,
+ self,
+ source,
+ ReactCurrentOwner.current,
+ props
+ )
}
+
function ReactElement(type, key, ref, _self, _source, _owner, props) {
- const element = {
- $$typeof: REACT_ELEMENT_TYPE,
- type,
- key,
- ref,
- props,
- _owner,
- _self,
- _source
- }
- return element;
-}
\ No newline at end of file
+ const element = {
+ $$typeof: REACT_ELEMENT_TYPE,
+ type,
+ key,
+ ref,
+ props,
+ _owner,
+ _self,
+ _source,
+ }
+ return element
+}
+
+export function cloneAndReplaceKey(oldElement, newKey) {
+ const newElement = ReactElement(
+ oldElement.type,
+ newKey,
+ oldElement.ref,
+ oldElement._self,
+ oldElement._source,
+ oldElement._owner,
+ oldElement.props
+ )
+
+ return newElement
+}
diff --git a/src/react/index.js b/src/react/index.js
index 51cf135836b6657bff218651e9772d977541fa6e..fbaca878c91f3e28f61a7eda1f3146dfd184c37a 100644
--- a/src/react/index.js
+++ b/src/react/index.js
@@ -1,15 +1,11 @@
-
-
-import { Component } from './ReactBaseClasses';
-import { createElement } from './ReactElement';
-import { map } from './ReactChildren';
+import { Component } from './ReactBaseClasses'
+import { createElement } from './ReactElement'
+import { map } from './ReactChildren'
const React = {
- createElement,
- Children: {
- map
- },
+ createElement,
+ Children: {
+ map,
+ },
}
-export {
- Component
-}
-export default React;
\ No newline at end of file
+export { Component }
+export default React
diff --git a/src/shared/ReactSymbols.js b/src/shared/ReactSymbols.js
index bad4224d526d09a4942eae3e6d00b47f19293baa..80bf07f45362ffe344ed667a3942bb6ecfeb357d 100644
--- a/src/shared/ReactSymbols.js
+++ b/src/shared/ReactSymbols.js
@@ -1 +1 @@
-export const REACT_ELEMENT_TYPE = Symbol.for('react.element')
\ No newline at end of file
+export const REACT_ELEMENT_TYPE = Symbol.for('react.element')