国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

從頭實現一個簡易版React(一)

meislzhua / 3084人閱讀

摘要:既然看不懂,那就看看社區前輩們寫的一些源碼分析文章以及實現思路吧,又這么過了幾天,總算是摸清點思路,于是在參考了前輩們的基礎上,實現了一個簡易版的。總結以上就是實現一個的總體思路,下節我們重點放在不同的上。

寫在開頭

工作中使用react也很長一段時間了,雖然對它的用法,原理有了一定的了解,但是總感覺停留在表面。本著知其然知其所以然的態度,我試著去看了react源碼,幾天下來,發現并不能看懂,反而更加云里霧里了- -!。既然看不懂,那就看看社區前輩們寫的一些源碼分析文章以及實現思路吧,又這么過了幾天,總算是摸清點思路,于是在參考了前輩們的基礎上,實現了一個簡易版的react。
這個系列我打算分為3節,第一節介紹下實現的思路以及結構,第二節講渲染,第三節講更新。

進入正題

眾所周知,react的核心是Virtual DOM,所以,我們的思路也是圍繞著Virtual DOM展開,包含Virtual DOM模型的建立,生命周期的管理,對比差異的diff算法,將Virtual DOM轉化為原生DOM并展示的patch方法等,setState異步機制以及react合成事件由于還沒有研究到,暫時先忽略,事件處理跟某位前輩的思路一樣,也是使用jquery事件代替,這里我們主要以實現渲染,更新為主,相信你在看完這個系列后,能對react的運行原理有一定理解。
項目地址:https://github.com/LuSuguru/f...,以下的所有代碼都是通過es6編寫,切勿用在生產環境。

Virtual DOM的實現

React的一切都基于Virtual DOM,我們第一步自然先實現它,如下:

/**
 * @param type :代表當前的節點屬性
 * @param key :用來標識element,用于優化以后的更新
 * @param props:節點的屬性
 */
function VDom(type, key, props) {
  this.type = type
  this.key = key
  this.props = props
}
// 代碼地址:src/react/reactElement.js  

實現了vDom后,理所需要一個方法來將我們寫的元素轉化為vDom。一般我們都是JSX來創建元素的,但它只不過是React.createElment的語法糖。所以,接下來,我們要實現的就是createElement方法:

function createElement(type, config, ...children) {
  const props = {}

  config = config || {}
  // 獲取key,用來標識element,方便以后高效的更新
  const { key = null } = config
 
  let propName = ""

  // 復制config里的內容到props
  for (propName in config) {
    if (config.hasOwnProperty(propName) && propName !== "key") {
      props[propName] = config[propName]
    }
  }

  // 轉化children
  if (children.length === 1 && Array.isArray(children[0])) {
    props.children = children[0]
  } else {
    props.children = children
  }

  return new VDom(type, key, props)
}
// 代碼地址:src/react/reactElement.js  

這段代碼也非常簡單,根據我們傳入的參數,生成對應的vDom

ReactComponent的實現

我們所創建的VDom類型分為3種:

文本類型

原生DOM類型

自定義類型

不同的類型,肯定有不同的渲染和更新邏輯,我們把這些邏輯與vDom一起,封裝成對應的ReactComponent類,通過ReactComponent類控制vDom,這里我把它們命名為ReactTextComponent,ReactDomComponent,ReactCompositeComponent,分別對應三種類型。
首先是基類ReactComponet:

// component基類,用來處理不同的虛擬dom更新,渲染
class Component {
  constructor(element) {
    this._vDom = element
    // 用來標識當前component
    this._rootNodeId = null
  }
}
// 代碼地址:src/react/component/ReactComponent.js  

接著再讓不同類型的component繼承這個基類,每種component類型都有mount和update兩個方法,用來執行渲染和更新

class ReactDomComponent extends ReactComponent {
    // 渲染
  mountComponent() {}

  // 更新
  updateComponent() {}
}
class ReactCompositeComponent extends ReactComponent {
    // 渲染
  mountComponent() {}

  // 更新
  updateComponent() {}
}
class ReactTextComponent extends ReactComponent {
    // 渲染
  mountComponent() {}

  // 更新
  updateComponent() {}
}
入口的實現

實現了ReactComponent后,我們自然需要一個入口去得到ReactComponent并調用它的mount。在使用React時,通常都是通過

import React from "react"
import ReactDOM from "react-dom"

class App extends React.Component {
}

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

這段代碼來充當渲染的入口,下面我們來實現這個入口,(為了方便說明,我把render方法也放在了React對象中)

import Component from "./Component"
import createElement from "./ReactElement"
import instantiateReactComponent from "./component/util"
import $ from "jquery"

const React = {
  nextReactRootIndex: 0, // 標識id,確定每個vDom的唯一性
  Component, // 所有自定義組件的父類
  createElement, // 創建vdom

  render(vDom, container) { // 入口
    var componentInstance = instantiateReactComponent(vDom) //通過vDom生成Component
    var markup = componentInstance.mountComponent(this.nextReactRootIndex++)

    container.innerHTML = markup
    $(document).trigger("mountReady")
  }
}
// 代碼地址:src/react/index.js  

由于渲染和更新都已經封裝在不同的ReactComponent里,所以,這里也需要一個方法,根據不同的vDom類型生成對應的ReactComponent,下面我們就來實現這個方法:

// component工廠,用來返回一個component實例
function instantiateReactComponent(node) {
  // 文本節點的情況
  if (typeof node === "string" || typeof node === "number") {
    return new ReactTextComponent(node)
  }

  // 瀏覽器默認節點的情況
  if (typeof node === "object" && typeof node.type === "string") {
    return new ReactDomComponent(node)
  }

  // 自定義的元素節點
  if (typeof node === "object" && typeof node.type === "function") {
    return new ReactCompositeComponent(node)
  }
}

然后再調用入口ReactComponent的mount方法,獲取渲染內容,再將其渲染出來就行。

總結

以上就是實現一個react的總體思路,下節我們重點放在不同ReactComponet的mount上。
下一節地址:https://segmentfault.com/a/11...

參考資料,感謝幾位前輩的分享:
https://www.cnblogs.com/sven3...
https://github.com/purplebamb...
陳屹 《深入React技術棧》

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93118.html

相關文章

  • 從頭實現簡易React(二)

    摘要:寫在開頭從頭實現一個簡易版一地址上一節,我們詳細介紹了實現一個簡易的思路以及整體的結構,但是對于渲染和更新的原理,卻還沒有提及,因此,本節我們將重點放在的渲染上。 寫在開頭 從頭實現一個簡易版React(一)地址:https://segmentfault.com/a/11...上一節,我們詳細介紹了實現一個簡易React的思路以及整體的結構,但是對于渲染和更新的原理,卻還沒有提及,因此...

    vvpvvp 評論0 收藏0
  • 從頭實現簡易React(三)

    摘要:寫在開頭從頭實現一個簡易版二地址在上一節,我們的已經具備了渲染功能。參考資料,感謝幾位前輩的分享陳屹深入技術棧 寫在開頭 從頭實現一個簡易版React(二)地址:https://segmentfault.com/a/11...在上一節,我們的react已經具備了渲染功能。在這一節我們將著重實現它的更新,說到更新,大家可能都會想到React的diff算法,它可以說是React性能高效的保...

    yvonne 評論0 收藏0
  • 基于react native的登錄界面demo 超簡易教程 redux

    摘要:登錄視圖登陸失敗用戶名或密碼不能為空彈出提示框成功是點擊登錄按鈕后調用的函數,這里的功能比較簡單。通過把發出去密碼登錄聲明組件需要整個中的哪一部分數據作為自己的將和組件聯系在一起編寫是負責生成的,所以在大項目中還會用到合并。 本豬說 本豬豬剛學react,也剛看RN,就叫寫這個,苦不堪言,搭環境就搭了好久。看網上教程也是改了好多小地方才寫完了。本著雷鋒精神手把手教你寫(假的)。 sho...

    scq000 評論0 收藏0
  • 借助Docker和Kodexplorer實現簡易化部署Discuz類論壇網站

    摘要:在主機輸入框中輸入自己的云服務器分配的公網,其他設置不變,點擊連接之后會出現安全警告,如果是在自己的電腦上操作的話,接受并保存即可。 基于DiscuzX系列構建的論壇可以說是大家在日常瀏覽各類BBS網站中接觸最多的論壇類型了。本教程旨在引導讀者通過簡單明確的一些步驟就打造出自己的論壇網站,做一個實實在在的站長。 工具/原料 騰訊云服務器 CentOS 7.2 64位;遠程控制程序 ...

    happen 評論0 收藏0
  • 借助Docker和Kodexplorer實現簡易化部署Discuz類論壇網站

    摘要:在主機輸入框中輸入自己的云服務器分配的公網,其他設置不變,點擊連接之后會出現安全警告,如果是在自己的電腦上操作的話,接受并保存即可。 基于DiscuzX系列構建的論壇可以說是大家在日常瀏覽各類BBS網站中接觸最多的論壇類型了。本教程旨在引導讀者通過簡單明確的一些步驟就打造出自己的論壇網站,做一個實實在在的站長。 工具/原料 騰訊云服務器 CentOS 7.2 64位;遠程控制程序 ...

    LeexMuller 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<