成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

【React源碼解讀】- 組件的實(shí)現(xiàn)

SoapEye / 2207人閱讀

摘要:可以看到,組件其實(shí)是一個(gè)對(duì)象,并不是一個(gè)真實(shí)的。引入了一種新的原始數(shù)據(jù)類型,表示獨(dú)一無(wú)二的值。你好,這里是組件可以看到,都發(fā)生了變化,值就是我們賦予的值,中嵌套了屬性。根據(jù)最初的代碼,我們組件用到了。

前言

react使用也有一段時(shí)間了,大家對(duì)這個(gè)框架褒獎(jiǎng)有加,但是它究竟好在哪里呢?
讓我們結(jié)合它的源碼,探究一二?。ó?dāng)前源碼為react16,讀者要對(duì)react有一定的了解)

回到最初

根據(jù)react官網(wǎng)上的例子,快速構(gòu)建react項(xiàng)目

npx create-react-app my-app

cd my-app

npm start

打開項(xiàng)目并跑起來(lái)以后,暫不關(guān)心項(xiàng)目結(jié)構(gòu)及語(yǔ)法糖,看到App.js里,這是一個(gè)基本的react組件 我們console一下,看看有什么結(jié)果。

import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";

class App extends Component {

  render() {
    return (
      

Edit src/App.js and save to reload.

); } } export default App; console.log()

可以看到,組件其實(shí)是一個(gè)JS對(duì)象,并不是一個(gè)真實(shí)的dom。

ES6 引入了一種新的原始數(shù)據(jù)類型Symbol,表示獨(dú)一無(wú)二的值。有興趣的同學(xué)可以去阮一峰老師的ES6入門詳細(xì)了解一下

上面有我們很熟悉的props,ref,key,我們稍微修改一下console,看看有什么變化。

console.log(
你好,這里是App組件
)

可以看到,props,key都發(fā)生了變化,值就是我們賦予的值,props中嵌套了children屬性??墒菫槭裁次覀兦度氲氖莇iv,實(shí)際上卻是一個(gè)對(duì)象呢?

打開源碼
/node_modules/react

首先打開index.js

"use strict";

if (process.env.NODE_ENV === "production") {
  module.exports = require("./cjs/react.production.min.js");
} else {
  module.exports = require("./cjs/react.development.js");
}

可以知道目前用上的是./cjs/react.development.js,直接打開文件。
根據(jù)最初的代碼,我們組件用到了React.Component。找到React暴露的接口:

接著找到Component: Component方法,

function Component(props, context, updater) {
  this.props = props;
  this.context = context;
  // If a component has string refs, we will assign a different object later.
  this.refs = emptyObject;
  // We initialize the default updater but the real one gets injected by the
  // renderer.
  this.updater = updater || ReactNoopUpdateQueue;
}

Component.prototype.isReactComponent = {};

Component.prototype.setState = function (partialState, callback) {
  !(typeof partialState === "object" || typeof partialState === "function" || partialState == null) ? invariant(false, "setState(...): takes an object of state variables to update or a function which returns an object of state variables.") : void 0;
  this.updater.enqueueSetState(this, partialState, callback, "setState");
};

Component.prototype.forceUpdate = function (callback) {
  this.updater.enqueueForceUpdate(this, callback, "forceUpdate");
};

上面就是一些簡(jiǎn)單的構(gòu)造函數(shù),也可以看到,我們常用的setState是定義在原型上的2個(gè)方法。

至此,一個(gè)組件已經(jīng)有一個(gè)大概的雛形:

到此為止了嗎?這看了等于沒看啊,究竟組件是怎么變成div的?render嗎?
可是全局搜索,也沒有一個(gè)function是render啊。

原來(lái),我們的jsx語(yǔ)法會(huì)被babel編譯的。

這下清楚了,還用到了React.createElement

createElement: createElementWithValidation,

通過(guò)createElementWithValidation,

function createElementWithValidation(type, props, children) {
······

  var element = createElement.apply(this, arguments);


  return element;
}

可以看到,return了一個(gè)element,這個(gè)element又是繼承自createElement,接著往下找:

function createElement(type, config, children) {
  var propName = void 0;

  // Reserved names are extracted
  var props = {};

  var key = null;
  var ref = null;
  var self = null;
  var source = null;
······
  return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
}

這里又返回了一個(gè)ReactElement方法,再順著往下找:

var ReactElement = function (type, key, ref, self, source, owner, props) {
  var element = {
    // This tag allows us to uniquely identify this as a React Element
    $$typeof: REACT_ELEMENT_TYPE,

    // Built-in properties that belong on the element
    type: type,
    key: key,
    ref: ref,
    props: props,

    // Record the component responsible for creating this element.
    _owner: owner
  };

······
  return element;
};

誒,這里好像返回的就是element對(duì)象,再看我們最初的的結(jié)構(gòu),是不是很像

驗(yàn)證一下我們的探索究竟對(duì)不對(duì),再每一個(gè)方法上我們都打上console,(注意,將App里的子元素全部刪空,利于我們觀察)

React.createElement 、 createElementWithValidation 、 createElement 、 ReactElement,通過(guò)這些方法,我們用class聲明的React組件在變成真實(shí)dom之前都是ReactElement類型的js對(duì)象

createElementWithValidation:

首先校驗(yàn)type是否是合法的

校驗(yàn)了props是否符合設(shè)置的proptypes

校驗(yàn)了子節(jié)點(diǎn)的key,確保每個(gè)數(shù)組中的元素都有唯一的key

createElement

type是你要?jiǎng)?chuàng)建的元素的類型,可以是html的div或者span,也可以是其他的react組件,注意大小寫

config中包含了props、key、ref、self、source等

向props加入children,如果是一個(gè)就放一個(gè)對(duì)象,如果是多個(gè)就放入一個(gè)數(shù)組。

那如果type.defaultProps有默認(rèn)的props時(shí),并且對(duì)應(yīng)的props里面的值是undefined,把默認(rèn)值賦值到props中

也會(huì)對(duì)key和ref進(jìn)行校驗(yàn)

ReactElement

ReactElement就比較簡(jiǎn)單了,創(chuàng)建一個(gè)element對(duì)象,參數(shù)里的type、key、ref、props、等放進(jìn)去,然后return了。最后調(diào)用Object.freeze使對(duì)象不可再改變。

組件的掛載

我們上面只是簡(jiǎn)單的探究了的結(jié)構(gòu)和原理,那它究竟是怎么變成真實(shí)dom的呢

ReactDOM.render(, document.getElementById("root"));

我們接著用babel編譯一下:

原來(lái)ReactDOM.render調(diào)用的是render方法,一樣,找暴露出來(lái)的接口。

var ReactDOM = {
······
  render: function (element, container, callback) {
    return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
  },
······
};

它返回的是一個(gè)legacyRenderSubtreeIntoContainer方法,這次我們直接打上console.log

這是打印出來(lái)的結(jié)果,

legacyRenderSubtreeIntoContainer
這個(gè)方法除主要做了兩件事:

清除dom容器元素的子元素

while (rootSibling = container.lastChild) {
      {
        if (!warned && rootSibling.nodeType === ELEMENT_NODE && rootSibling.hasAttribute(ROOT_ATTRIBUTE_NAME)) {
          warned = true;
        }
      }
      container.removeChild(rootSibling);
    }

創(chuàng)建ReactRoot對(duì)象

源碼暫時(shí)只讀到了這里,關(guān)于React16.1~3的新功能,以及新的生命周期的使用和原理、Fiber究竟是什么,我們將在后續(xù)文章接著介紹。

廣而告之

本文發(fā)布于薄荷前端周刊,歡迎Watch & Star ★,轉(zhuǎn)載請(qǐng)注明出處。

歡迎討論,點(diǎn)個(gè)贊再走吧 ????? ~

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/98848.html

相關(guān)文章

  • React 源碼深度解讀(四):首次自定義組件渲染 - Part 1

    摘要:本篇開始介紹自定義組件是如何渲染的。組件將自定義組件命名為,結(jié)構(gòu)如下經(jīng)過(guò)編譯后,生成如下代碼構(gòu)建頂層包裝組件跟普通元素渲染一樣,第一步先會(huì)執(zhí)行創(chuàng)建為的。調(diào)用順序已在代碼中注釋。先看圖,這部分內(nèi)容將在下回分解 前言 React 是一個(gè)十分龐大的庫(kù),由于要同時(shí)考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級(jí)非常深,閱讀其源碼是一個(gè)非...

    Warren 評(píng)論0 收藏0
  • 解讀React源碼(一):初探React源碼

    摘要:前言的基本概念組件的構(gòu)建方法以及高級(jí)用法這背后的一切如何運(yùn)轉(zhuǎn)深入內(nèi)部的實(shí)現(xiàn)機(jī)制和原理初探源碼代碼組織結(jié)構(gòu)包含一系列的工具方法插件包含一系列同構(gòu)方法包含一些公用或常用方法如等包含一些測(cè)試方法等包含一些邊界錯(cuò)誤的測(cè)試用例是代碼的核心部分它包含了 前言 React的基本概念,API,組件的構(gòu)建方法以及高級(jí)用法,這背后的一切如何運(yùn)轉(zhuǎn),深入Virtual DOM內(nèi)部的實(shí)現(xiàn)機(jī)制和原理. 初探Rea...

    Eminjannn 評(píng)論0 收藏0
  • React 源碼深度解讀(六):依賴注入

    摘要:依賴注入和控制反轉(zhuǎn),這兩個(gè)詞經(jīng)常一起出現(xiàn)。一句話表述他們之間的關(guān)系依賴注入是控制反轉(zhuǎn)的一種實(shí)現(xiàn)方式。而兩者有大量的代碼都是可以共享的,這就是依賴注入的使用場(chǎng)景了。下一步就是創(chuàng)建具體的依賴內(nèi)容,然后注入到需要的地方這里的等于這個(gè)對(duì)象。 前言 React 是一個(gè)十分龐大的庫(kù),由于要同時(shí)考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級(jí)...

    glumes 評(píng)論0 收藏0
  • React 源碼深度解讀(三):首次 DOM 元素渲染 - Part 3

    摘要:在學(xué)習(xí)源碼的過(guò)程中,給我?guī)椭畲蟮木褪沁@個(gè)系列文章,于是決定基于這個(gè)系列文章談一下自己的理解。到此為止,首次渲染就完成啦總結(jié)從啟動(dòng)到元素渲染到頁(yè)面,并不像看起來(lái)這么簡(jiǎn)單,中間經(jīng)歷了復(fù)雜的層級(jí)調(diào)用。 前言 React 是一個(gè)十分龐大的庫(kù),由于要同時(shí)考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級(jí)非常深,閱讀其源碼是一個(gè)非常艱辛的過(guò)...

    U2FsdGVkX1x 評(píng)論0 收藏0
  • 【Under-the-hood-ReactJS-Part11】React源碼解讀

    摘要:技術(shù)上來(lái)說(shuō),當(dāng)方法被調(diào)用后或者發(fā)生改變后,方法都會(huì)被調(diào)用。下一步,會(huì)設(shè)置為。之后,檢測(cè)當(dāng)前更新是否由更新引起的。這是因?yàn)?,使用是?dǎo)致組件持久化更新,而會(huì)被方法的返回值重新賦值。 接上文, React流程圖:https://bogdan-lyashenko.gith... 更新組件 關(guān)于組件的更新,我們先看下代碼里的注釋: 對(duì)于已掛載組件的更新過(guò)程,React會(huì)首先調(diào)用component...

    hiyayiji 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<