React source code
React source code
React source code
8.context
Example 8.1.
/* * @Author: dfh * @Date: 2021-02-24 18:18:22 * @LastEditors: dfh * @LastEditTime: 2021-03-01 13:25:37 * @Modified By: dfh * @FilePath: /day25-react/src/index.js */
import React from 'react';
import ReactDOM from 'react-dom';
const PersonContext = React.createContext();
function getStyle(color) {
return {
border: `5px solid ${color}`.padding: '5px'.marigin: '5px'}}class Person extends React.Component {
state = {
color: 'red'
}
changeColor = (color) = > this.setState({ color })
render() {
const value = { color: this.state.color, changeColor: this.changeColor }
return <PersonContext.Provider value={value}>
<div style={{ . getStyle(this.state.color), width: '200px' }}>
Person
<Head />
<Body />
</div>
</PersonContext.Provider>}}class Head extends React.Component {
static contextType = PersonContext;
render() {
return (
<div style={getStyle(this.context.color)}>
Head
<Eye />
</div>)}}class Body extends React.Component {
static contextType = PersonContext;
render() {
return (
<div style={getStyle(this.context.color)}>
Body
<Hand />
</div>)}}class Hand extends React.Component {
static contextType = PersonContext;
render() {
return (
<div style={getStyle(this.context.color)}>
Hand
<button onClick={()= >Enclosing context. ChangeColor () 'red'} > to become red</button>
<button onClick={()= >Enclosing context. ChangeColor (' green ')} > turn green</button>
</div>)}}function Eye() {
return <PersonContext.Consumer>
{content => <div style={getStyle(content.color)}>Eye</div>}
</PersonContext.Consumer>
}
ReactDOM.render(<Person />.document.getElementById('root'));
Copy the code
8.2. To achieve
8.2.1.src/react.js
/* * @Author: dfh * @Date: 2021-02-24 18:34:24 * @LastEditors: dfh * @LastEditTime: 2021-03-01 13:33:21 * @Modified By: dfh * @FilePath: /day25-react/src/react.js */
import Component from './Component';
import { wrapToVdom } from './utils';
/ * * * *@param {*} Type Element type *@param {*} Config Configures the object *@param {*} Children */
function createElement(type, config, children) {
let ref, key;
if (config) {
delete config.__source;
delete config.__self;
ref = config.ref;
key = config.key;
delete config.ref;
delete config.key;
}
letprops = { ... config };if (arguments.length > 3) {//children is an array
props.children = Array.prototype.slice.call(arguments.2).map(wrapToVdom);
} else {
props.children = wrapToVdom(children);
}
return {
type,
props,
ref,
key
}
}
function createRef() {
return { current: null}} +function createContext(initialValue) {
+ Provider._value = initialValue;
+ function Provider(props) {+const { value } = props;
+ if (Provider._value) {
+ Object.assign(Provider._value, value)
+ } else{ + Provider._value = value; +},returnprops.children; +},function Consumer(props) {+returnprops.children(Provider._value); +},return{ Provider, Consumer }; +}const React = {
createElement,
Component,
createRef,
+ createContext
}
export default React;
Copy the code
8.2.2.src/react-dom.js
/* * @Author: dfh * @Date: 2021-02-24 18:34:32 * @LastEditors: dfh * @LastEditTime: 2021-03-01 13:40:33 * @Modified By: dfh * @FilePath: /day25-react/src/react-dom.js */
import { REACT_TEXT } from './constants';
import { addEvent } from './event';
/** * when the container is mounted@param {*} Vdom requires the rendering of the virtual DOM *@param {*} The container vessel * /
function render(vdom, container) {
const dom = createDOM(vdom);
// Mount the real DOM
container.appendChild(dom);
// Call the lifecycle method componentDidMount
dom.componentDidMount && dom.componentDidMount();
}
/** * create validation DOM *@param {*} Vdom Virtual DOM */
export function createDOM(vdom) {
const {
type,
props,
key,
ref
} = vdom;
// Create the real DOM
let dom;
if (type === REACT_TEXT) {/ / is the text
dom = document.createTextNode(props.content);
} else if (typeof type === 'function') {// Custom function components
if (type.isReactComponent) {/ / class components
return mountClassComponent(vdom);
} else {// Function components
returnmountFunctionComponent(vdom); }}else {// Native components
dom = document.createElement(type);
}
// Update the properties of the newly created real DOM with the properties of the virtual DOM
updateProps(dom, {}, props);
if (typeof props.children === 'object' && props.children.type) {// There is only one son, and it is a virtual DOM
render(props.children, dom);// Turn the son into a real DOM and mount it on your own
} else if (Array.isArray(props.children)) {// Have multiple sons
reconcileChildren(props.children, dom);
}
// Mount the real DOM to the virtual DOM for later retrieval
vdom.dom = dom;
// After the real DOM is created from the virtual DOM, the current property of the ref property of the virtual DOM is equal to the real DOM
ref && (ref.current = dom);
return dom;
}
/** * Converts a virtual DOM of type custom class component into a real DOM and returns *@param {*} The vDOM type is the virtual DOM */ of the custom class component
function mountClassComponent(vdom) {
const { type: Clazz, props } = vdom;
// Get an instance of the class
const classInstance = new Clazz(props);
/ / the implementation of the context
+ if(Clazz.contextType) { + classInstance.context = Clazz.contextType.Provider._value; +}// Make the classInstance property of the virtual DOM of this class component point to an instance of this class component
vdom.classInstance = classInstance;
// Call the lifecycle method componentWillMount
if (classInstance.componentWillMount) {
classInstance.componentWillMount();
}
// Execute the lifecycle method getDerivedStateFromProps
if (Clazz.getDerivedStateFromProps) {
const partialState = Clazz.getDerivedStateFromProps(classInstance.props, classInstance.state)
if(partialState) { classInstance.state = { ... classInstance.state, ... partialState }; }}// Get the virtual DOM
const oldRenderVdom = classInstance.render();
// Mount the virtual DOM to the component instance for later dom-diff use
classInstance.oldRenderVdom = vdom.oldRenderVdom = oldRenderVdom;
// Get the real DOM
const dom = createDOM(oldRenderVdom);
if (classInstance.componentDidMount) {
dom.componentDidMount = classInstance.componentDidMount;
}
// Attach the real DOM to the instance
classInstance.dom = dom;
return dom;
}
/** * Converts a virtual DOM of type custom function component into a real DOM and returns *@param {*} The vDOM type is the virtual DOM */ of the custom function component
function mountFunctionComponent(vdom) {
const { type: FunctionComponent, props } = vdom;
const renderVdom = FunctionComponent(props);
vdom.oldRenderVdom = renderVdom;
return createDOM(renderVdom);
}
/ * * * *@param {*} The virtual DOM for the childrenVdom@param {*} ParentDOM The real DOM to mount to */
function reconcileChildren(childrenVdom, parentDOM) {
for (let i = 0; i < childrenVdom.length; i++) {
const child = childrenVdom[i];
render(child, parentDOM);// My son is attached to my body}}/** * Update the properties of the newly created real DOM with the properties of the virtual DOM *@param {*} Dom Real DOM *@param {*} The props virtual DOM attribute */
function updateProps(dom, oldProps, props) {
for (const key in props) {
if (key === 'children') continue;// Handle it separately, not here
if (key === 'style') {
const styleObj = props.style;
for (const attr instyleObj) { dom.style[attr] = styleObj[attr]; }}else if (key.startsWith('on')) {//onClick=>onclick
// dom[key.toLocaleLowerCase()]=props[key];
addEvent(dom, key.toLocaleLowerCase(), props[key]);
} else {// Class is defined in JS using className, so do not change itdom[key] = props[key]; }}}/** * Dom-diff * for the current component@param {*} ParentDOM is the real DOM *@param {*} OldRenderVdom is the old virtual DOM *@param {*} NewRenderVdom New virtual DOM *@param {*} NextDom Is the next real DOM, mainly used to insert the location with */
export function compareTwoVdom(parentDOM, oldRenderVdom, newRenderVdom, nextDom) {
if(! oldRenderVdom && ! newRenderVdom) {// Both new and old virtual DOM are null
return null;
} else if(oldRenderVdom && ! newRenderVdom) {// The new virtual DOM is NULL, so the old DOM exists
const currentDOM = findDOM(oldRenderVdom);// Find the real DOM corresponding to this virtual DOM
currentDOM && parentDOM.removeChild(currentDOM);// Remove this old real DOM
// Call the lifecycle method
oldRenderVdom.classInstance && oldRenderVdom.classInstance.componentWillUnmount && oldRenderVdom.classInstance.componentWillUnmount()
} else if(! oldRenderVdom && newRenderVdom) {// New virtual DOM exists, old virtual DOM is NULL
const newDOM = createDOM(newRenderVdom);// Get the real DOM
if (nextDom) {
parentDOM.insertBefore(newDOM, nextDom);
} else{ parentDOM.appendChild(newDOM); }}else if(oldRenderVdom && newRenderVdom && oldRenderVdom.type ! == newRenderVdom.type) {// Both the old and new virtual DOM exist, but of different types
const oldDOM = findDOM(oldRenderVdom);// Old real DOM
const newDOM = createDOM(newRenderVdom);// The new real DOM
parentDOM.replaceChild(newDOM, oldDOM);
// Call the lifecycle method
oldRenderVdom.classInstance && oldRenderVdom.classInstance.componentWillUnmount && oldRenderVdom.classInstance.componentWillUnmount()
} else {// Both old and new, the same type, to do deep DOM-diffupdateElement(oldRenderVdom, newRenderVdom); }}/** * In depth compare two virtual DOM *@param {*} OldRenderVdom is the old virtual DOM *@param {*} NewRenderVdom New virtual DOM */
function updateElement(oldRenderVdom, newRenderVdom) {
if (oldRenderVdom.type === REACT_TEXT) {/ / text
const currentDOM = newRenderVdom.dom = oldRenderVdom.dom;// Reuse old real DOM nodes
currentDOM.textContent = newRenderVdom.props.content;// Modify the old DOM node files directly
} else if (typeof oldRenderVdom.type === 'string') {// The specification is a native component
const currentDOM = newRenderVdom.dom = oldRenderVdom.dom;// Reuse old real DOM
// Update the attributes first
updateProps(currentDOM, oldRenderVdom.props, newRenderVdom.props);
// Compare sons
updateChildren(currentDOM, oldRenderVdom.props.children, newRenderVdom.props.children);
} else if (typeof oldRenderVdom.type === 'function') {
if (oldRenderVdom.type.isReactComponent) {
updateClassComponent(oldRenderVdom, newRenderVdom);// Update the class component
} else {
updateFunctionComponent(oldRenderVdom, newRenderVdom);// New and old are function components, function component update}}}/** * If the old virtual DOM node and the new virtual DOM node are functions, use this update logic *@param {*} OldVdom is the old virtual DOM *@param {*} NewVdom New virtual DOM */
function updateFunctionComponent(oldVdom, newVdom) {
const parentDOM = findDOM(oldVdom).parentNode;// Find the old parent node
const { type: FunctionComponent, props } = newVdom;
const oldRenderVdom = oldVdom.oldRenderVdom;// Old render virtual DOM
const newRenderVdom = FunctionComponent(props);// New render virtual DOM
compareTwoVdom(parentDOM, oldRenderVdom, newRenderVdom);// Compare the virtual DOM
newVdom.oldRenderVdom = newRenderVdom;
}
/** * If the old virtual DOM node and the new virtual DOM node are class components, use this update logic *@param {*} OldVdom is the old virtual DOM *@param {*} NewVdom New virtual DOM */
function updateClassComponent(oldVdom, newVdom) {
const classInstance = newVdom.classInstance = oldVdom.classInstance;// Reuse old class instances
newVdom.oldRenderVdom = oldVdom.oldRenderVdom;// The last class component's rendering of the virtual DOM
if (classInstance.componentWillReceiveProps) {// The component will receive a new attribute
classInstance.componentWillReceiveProps();
}
// Trigger an update to the component, passing in the new property
classInstance.updater.emitUpdate(newVdom.props);
}
/** * In depth compare children *@param {*} DOM parentDOM father *@param {*} OldChildren have old sons@param {*} NewChildren New sons */
function updateChildren(parentDOM, oldChildren, newChildren) {
// Children can be arrays or objects (single nodes are objects)
oldChildren = Array.isArray(oldChildren) ? oldChildren : [oldChildren];
newChildren = Array.isArray(newChildren) ? newChildren : [newChildren];
// Get the maximum length
const maxLen = Math.max(oldChildren.length, newChildren.length);
for (let i = 0; i < maxLen; i++) {
// Find the index greater than the current index in the sons
const nextDOM = oldChildren.find((item, index) = > index > i && item && item.dom)
// Compare children recursivelycompareTwoVdom(parentDOM, oldChildren[i], newChildren[i], nextDOM && nextDOM.dom); }}/** * Find the real DOM of this virtual DOM object@param {*} vdom
*/
export function findDOM(vdom) {
const { type } = vdom;
let dom;
if (typeof type === 'function') {
dom = findDOM(vdom.oldRenderVdom)
} else {
dom = vdom.dom;
}
return dom
}
const ReactDOM = {
render
}
export default ReactDOM;
Copy the code
9. Advanced components
9.1. The configuration
- The installation
npm install react-app-rewired customize-cra @babel/plugin-proposal-decorators- D
Copy the code
package.json
"scripts": {
"start": "react-app-rewired start"."build": "react-app-rewired build"."test": "react-app-rewired test"."eject": "react-app-rewired eject"
}
Copy the code
config-overrides.js
const {override,addBabelPlugin}=require('customize-cra');
module.exports=override(
addBabelPlugin([
'@babel/plugin-proposal-decorators', {'legacy':true}]))Copy the code
jsconfig.json
{
'compilerOptions': {'experimentalDecorators':true}}Copy the code
9.2. Arguably
9.2.1. Property proxy
/* * @Author: dfh * @Date: 2021-02-24 18:18:22 * @LastEditors: dfh * @LastEditTime: 2021-03-01 15:25:38 * @Modified By: dfh * @FilePath: /day25-react/src/index.js */
import React from 'react';
import ReactDOM from 'react-dom';
/** * Advanced components have three application scenarios * 1. Property proxy */
const widthLoading = msg= > OldComponent= > {
return class extends React.Component {
show = () = > {
const div = document.createElement('div')
div.setAttribute('id'.'load');
div.innerHTML = ` <p style="position:absolute; top:50%; left:50%; z-index:10; background-color:gray">${msg}</p>
`
document.body.appendChild(div);
}
hide = () = > {
document.getElementById('load').remove();
}
render() {
return <OldComponent show={this.show} hide={this.hide} />
}
}
}
@widthLoading('Loading... ')
class Hello extends React.Component {
render() {
return <div>
<p>hello</p>
<button onClick={this.props.show}>According to</button>
<button onClick={this.props.hide}>hidden</button>
</div>
}
}
ReactDOM.render(<Hello />.document.getElementById('root'));
Copy the code
9.2.2. Reverse inheritance
Existing components can be extended based on reverse inheritance
src/index.js
/* * @Author: dfh * @Date: 2021-02-24 18:18:22 * @LastEditors: dfh * @LastEditTime: 2021-03-01 17:21:34 * @Modified By: dfh * @FilePath: /day25-react/src/index.js */ import React from './react'; import ReactDOM from './react-dom'; /** * Advanced components have three application scenarios * 1. Property broker * 2. */ class extends React.Component {state = {name: } componentWillMount() {console.log('button componentWillMount'); } componentDidMount() { console.log('button componentDidMount') } render() { return (<button name={this.state.name} title={this.props.title}></button>) } } const wrapper = Button => { return class extends Button { state = { number: 0 } componentWillMount() { console.log('WrapperButton componentWillMount'); } componentDidMount() { console.log('WrapperButton componentDidMount'); } handlerClick = () => { this.setState({ number: this.state.number + 1 }); } render() { const renderElement = super.render(); const newProps = { ... renderElement.props, ... this.state, onClick: this.handlerClick } return React.cloneElement(renderElement, newProps, this.state.number); }}} const WrapperButton = wrapper(Button) reactdom.render (<WrapperButton title=' title '/>, document.getElementById('root'));Copy the code
src/react.js
/* * @Author: dfh * @Date: 2021-02-24 18:34:24 * @LastEditors: dfh * @LastEditTime: 2021-03-01 17:21:21 * @Modified By: dfh * @FilePath: /day25-react/src/react.js */
import Component from './Component';
import { wrapToVdom } from './utils';
/ * * * *@param {*} Type Element type *@param {*} Config Configures the object *@param {*} Children */
function createElement(type, config, children) {
let ref, key;
if (config) {
delete config.__source;
delete config.__self;
ref = config.ref;
key = config.key;
delete config.ref;
delete config.key;
}
letprops = { ... config };if (arguments.length > 3) {//children is an array
props.children = Array.prototype.slice.call(arguments.2).map(wrapToVdom);
} else {
props.children = wrapToVdom(children);
}
return {
type,
props,
ref,
key
}
}
function createRef() {
return { current: null}}function createContext(initialValue) {
Provider._value = initialValue;
function Provider(props) {
const { value } = props;
if (Provider._value) {
Object.assign(Provider._value, value)
} else {
Provider._value = value;
}
return props.children;
}
function Consumer(props) {
return props.children(Provider._value);
}
return { Provider, Consumer };
}
+ function cloneElement(oldElement, newProps, ... newChildren) {+let children = oldElement.props.children;
+ // Children may be undefined, object, array
+ if (children) {
+ if (!Array.isArray(children)) {// is an object
+ children = [children]
+ }
+ } else {//undefined+ children = []; + } + children.push(... newChildren); + children = children.map(wrapToVdom); +if (children.length === 0) {
+ children = undefined; +}else if (children.length === 1) {
+ children = children[0];
+ }
+ newProps.children = children;
+ constprops = { ... oldElement.props, ... newProps }; +return{... oldElement, props }; +}const React = {
createElement,
Component,
createRef,
createContext,
+ cloneElement
}
export default React;
Copy the code
10.render props
render props
Is the value of one inreact
Between components that use a value of functionprops
Simple techniques for sharing code- with
render props
The component takes a function that returns areact
Element and call it instead of implementing your own rendering logic render props
Is a function that tells the component what to renderprops
10.1. Native implementation
/* * @Author: dfh * @Date: 2021-02-24 18:18:22 * @LastEditors: dfh * @LastEditTime: 2021-03-01 19:06:45 * @Modified By: dfh * @FilePath: /day25-react/src/index.js */ import React from 'react'; import ReactDOM from 'react-dom'; class MouseTracker extends React.Component { constructor(props) { super(props); this.state = { x: 0, y: 0 }; } handeMouseMove = event => { this.setState({ x: event.clientX, y: Event.clienty})} render() {return <div onMouseMove={this.handemousemove}> <h1> ({this.state.x},{this.state.y})</p> </div> } } ReactDOM.render(<MouseTracker />, document.getElementById('root'));Copy the code
10.2 render properties
/* * @Author: dfh * @Date: 2021-02-24 18:18:22 * @LastEditors: dfh * @LastEditTime: 2021-03-01 19:17:45 * @Modified By: dfh * @FilePath: /day25-react/src/index.js */ import React from 'react'; import ReactDOM from 'react-dom'; Class MouseTracker extends react.component.ponent {/** ** render props * 1. constructor(props) { super(props); this.state = { x: 0, y: 0 }; } handeMouseMove = event => { this.setState({ x: event.clientX, y: event.clientY }) } render() { return <div onMouseMove={this.handeMouseMove}> {this.props.render(this.state)} </div> } } <MouseTracker render={props => <> <h1> </h1> <p> ({props.x},{props.y})</p> </>} />, document.getElementById('root'));Copy the code
10.3. The children
Children is a rendering method
/*
* @Author: dfh
* @Date: 2021-02-24 18:18:22
* @LastEditors: dfh
* @LastEditTime: 2021-03-01 19:21:16
* @Modified By: dfh
* @FilePath: /day25-react/src/index-render-props1.js
*/
import React from 'react';
import ReactDOM from 'react-dom';
class MouseTracker extends React.Component {
constructor(props) {
super(props);
this.state = { x: 0, y: 0 };
}
handeMouseMove = event => {
this.setState({
x: event.clientX,
y: event.clientY
})
}
render() {
return <div onMouseMove={this.handeMouseMove}>
{this.props.children(this.state)}
</div>
}
}
ReactDOM.render(<MouseTracker >{
props => <>
<h1>移动鼠标</h1>
<p>当前的鼠标位置是:({props.x},{props.y})</p>
</>
}</MouseTracker>, document.getElementById('root'));
Copy the code
10.4. Hoc
/* * @Author: dfh * @Date: 2021-02-24 18:18:22 * @LastEditors: dfh * @LastEditTime: 2021-03-01 19:35:21 * @Modified By: dfh * @FilePath: /day25-react/src/index.js */ import React from 'react'; import ReactDOM from 'react-dom'; function widthTracker(OldComponent) { return class MouseTracker extends React.Component { constructor(props) { super(props); this.state = { x: 0, y: 0 }; } handeMouseMove = event => { this.setState({ x: event.clientX, y: event.clientY }) } render() { return <div onMouseMove={this.handeMouseMove}> <OldComponent {... This. State} /> </div>}} function Show(props) {return <> <h1> mouse </h1> <p> ({props.x},{props.y})</p> </> } const MouseTracker = widthTracker(Show); ReactDOM.render(<MouseTracker />, document.getElementById('root'));Copy the code
11.shouldComponentUpdate
- When a component
props
orstate
Change,React
The newly returned element is compared to the previously rendered element to determine if it is necessary to update the real DOM when they are not identicalReact
The DOM will be updated - If there are a lot of components to render, you can override the lifecycle method
shouldComponentUpdate
To optimize shouldComponentUpdate
Method fires before rerendering. The default implementation is to return true. If the component does not need to be updated, it can be updated in theshouldComponentUpdate
To skip the entire rendering process. Which contains the componentrender
Calls and subsequent operations.
11.1. Examples – Component
Problem: Whether you click on button in Number1 or butter in Number2, all render is executed
/* * @Author: dfh * @Date: 2021-02-24 18:18:22 * @LastEditors: dfh * @LastEditTime: 2021-03-01 19:41:39 * @Modified By: dfh * @FilePath: /day25-react/src/index.js */ import React from 'react'; import ReactDOM from 'react-dom'; /** * By default, all components update whenever state changes, regardless of property changes */ class Counter extends React.Component {state = {num1:0, num2: 0 } addNum1 = () => { this.setState({ num1: this.state.num1 + 1 }) } addNum2 = () => { this.setState({ num2: this.state.num2 + 1 }) } render() { console.log('render Counter') return <div> <Number1 num={this.state.num1} add={this.addNum1} /> <Number2 num={this.state.num2} add={this.addNum2} /> </div> } } class Number1 extends React.Component { render() { console.log('render Number1') return <div> <button onClick={this.props.add}>Number1:{this.props.num}</button> </div> } } class Number2 extends React.Component { render() { console.log('render Number2') return <div> <button onClick={this.props.add}>Number2:{this.props.num}</button> </div> } } ReactDOM.render(<Counter />, document.getElementById('root'));Copy the code
11.2. Examples – PuerComponent
When clicking on the button in Number1, only render Counter and render Number1 go, but when clicking on the button in Number2, only render Counter and render Number2 go
/* * @Author: dfh * @Date: 2021-02-24 18:18:22 * @LastEditors: dfh * @LastEditTime: 2021-03-01 19:46:48 * @Modified By: dfh * @FilePath: /day25-react/src/index.js */ import React from 'react'; import ReactDOM from 'react-dom'; class Counter extends React.Component { state = { num1: 0, num2: 0 } addNum1 = () => { this.setState({ num1: this.state.num1 + 1 }) } addNum2 = () => { this.setState({ num2: this.state.num2 + 1 }) } render() { console.log('render Counter') return <div> <Number1 num={this.state.num1} add={this.addNum1} /> <Number2 num={this.state.num2} add={this.addNum2} /> </div> } } class Number1 extends React.PureComponent { render() { console.log('render Number1') return <div> <button onClick={this.props.add}>Number1:{this.props.num}</button> </div> } } class Number2 extends React.PureComponent { render() { console.log('render Number2') return <div> <button onClick={this.props.add}>Number2:{this.props.num}</button> </div> } } ReactDOM.render(<Counter />, document.getElementById('root'));Copy the code
11.3. PuerComponent implementation
/* * @Author: dfh * @Date: 2021-03-01 19:49:40 * @LastEditors: dfh * @LastEditTime: 2021-03-01 22:28:52 * @Modified By: dfh * @FilePath: /day25-react/src/PureComponent.js */
import Component from './Component';
class PureComponent extends Component {
shouldComponentUpdate(nextProps, nextState) {
constvalue=! shallowEqual(this.props, nextProps) || ! shallowEqual(this.state, nextState)
console.log(value)
returnvalue; }}/** * if obj1 is equal to obj2, it is equal if the memory address is the same@param {*} obj1
* @param {*} obj2
*/
function shallowEqual(obj1, obj2) {
if (obj1 === obj2) return true;
if (typeofobj1 ! = ='object' || obj1 === null || typeofobj2 ! = ='object' || obj2 === null) return false;
const key1 = Object.keys(obj1);
const key2 = Object.keys(obj2);
if(key1.length ! == key2.length)return false;
for (let key of key1) {
if(! obj2.hasOwnProperty(key) || obj1[key] ! == obj2[key])return false;
}
return true;
}
export default PureComponent;
Copy the code