摘要:并不是組件中的任何地方都能夠使用獲取結(jié)構(gòu),只對掛載后的組件生效。組件的一個特殊屬性,接受一個回調(diào)函數(shù)作為參數(shù)。反之,則表示卸載失敗。再看一下這段代碼這個回調(diào)函數(shù)其實是沒有參數(shù)的,但是,當(dāng)方法變成異步方法之后,說不定就會向其注入一些參數(shù)了。
在react的組件的開發(fā)過程中,一般來說,我們并不會真正的去操作dom。只有在頂層組件的渲染的過程中,我們借助ReactDOM.render()方法,將我們的應(yīng)用渲染到html結(jié)構(gòu)中。然而,由于react框架自身的限制,在某些特定的情況下,我們必須要手動的操作dom。這時,我們就需要使用ReactDOM了。
先說一個小事,在react 0.14版本的時候,ReactDOM就從react的核心庫中分離出來了。所以,根據(jù)你使用的react版本的不同,我們引入ReactDOM的方式也就不一樣??偠灾簿拖旅鎯煞N基本的方法。
以下所有的代碼,都會通過EcmaScript6進行編寫
React < 0.14之前的版本
import React, { ReactDOM } from "react"
React >= 0.14之后的版本
yarn add react-dom
import ReactDOM from "react-dom"ReactDOM的API
ReactDOM給我們提供了僅僅三個api。所以相對來說學(xué)習(xí)起來還是比較簡單的。
這三個api 如下:
ReactDOM.findDOMNode
ReactDOM.unmountComponentAtNode
ReactDOM.render
下面,我們就簡單的扯扯,這三個api我們應(yīng)該怎么使用。
ReactDOM.findDOMNode在絮叨這個api之前啊,先扯兩個你應(yīng)該知道的東西。
Q:DOM被真正添加到HTML中是什么時候?
A:生命周期方法componentDidMount和componentDidUpdate
Q:還有沒有其他獲取DOM的方法
A:有,比如this.refs。
說這干啥,就是為了告訴你應(yīng)該什么時候去獲取DOM。不要以為在任何地方都能獲取,否則更多等待你的就是error * 3。
好了,下面我們就好好扯扯findDOMNode該怎么用。
先看一下接口定義:
DOMElement findDOMNode(ReactComponent)
簡單的說就是:給它一點綠蔭(ReactComponent),還你一片森林(DOM Tree)。
比如,下面這個小demo,在組件加載完成的時候,獲取真正的dom結(jié)構(gòu)。
import React from "react"; import {findDOMNode, render} from "react-dom"; class App extends React.Component { constructor(props) { super(props) console.info("GET DOM IN %c constructor", "color:red") console.log(findDOMNode(this)) } componentWillMount() { console.info("GET DOM IN %c componentWillMount", "color:red") console.log(findDOMNode(this)) } componentDidMount() { console.info("GET DOM IN %c componentDidMount", "color:red") console.log(findDOMNode(this)) } render() { return () } } render( The menuThe person informationThe content wrapper, document.getElementById("root"));
哎呀,慘不忍睹。
所以,把constructor的findDOMNode操作去掉,你會看到:
可以看出,在componentWillMount中findDOMNode的操作結(jié)果是null。
但是,你會不會想,不是吧,返回null不能完全說明我沒獲取到元素啊。的確,比如:
import React from "react"; import {findDOMNode, render} from "react-dom"; class App extends React.Component { constructor(props) { super(props) // console.info("GET DOM IN %c constructor", "color:red") // console.log(findDOMNode(this)) } componentWillMount() { console.info("GET DOM IN %c componentWillMount", "color:red") console.log(findDOMNode(this)) } componentDidMount() { console.info("GET DOM IN %c componentDidMount", "color:red") console.log(findDOMNode(this)) } render() { return null } } render(, document.getElementById("root"));
如你所愿,findDOMNode的操作結(jié)果都是null。但是,對比之中你應(yīng)該清楚兩件事。
并不是組件中的任何地方都能夠使用findDOMNode獲取DOM結(jié)構(gòu),findDOMNode只對掛載后的組件生效。
如果組件的render函數(shù)返回null,則在任何地方使用findDOMNode的結(jié)果都是null。
ReactDOM.findDOMNode with ref
先扯兩句ref。ref--組件的一個特殊屬性,接受一個回調(diào)函數(shù)作為參數(shù)。兩種情況:
給原生的html結(jié)構(gòu)添加ref屬性,其參數(shù)就是其對應(yīng)的DOM元素。這時候,直接使用即可。
給class聲明的組件添加ref屬性的時候,參數(shù)則是這個已經(jīng)加載完成的react組件。這時候,就可以和findDOMNode來個親密碰撞了。
如下面的操作:
import React from "react"; import {findDOMNode, render} from "react-dom"; class FieldInput extends React.Component { render() { return } } class App extends React.Component { constructor(props) { super(props) } componentDidMount() { console.info("The value of %c this.input", "color:red") console.log(this.input) console.info("The value of %c findDOMNode(this.input)", "color:red") console.log(findDOMNode(this.input)) } render() { return{ this.input = input }} /> } } render( , document.getElementById("root"));
結(jié)果,就是你想的那樣美好。
ReactDOM.unmountComponentAtNode最后呢,記住一句話,findDOMNode不能用在函數(shù)式組件中哦
來先把接口的名稱拆分一下:
unmount: 卸載
component: 組件
at: 在
node: 節(jié)點(DOM元素)
意思就是,從DOM元素中卸載已經(jīng)掛載的組件,除此呢,還會清除它的事件處理器和state。來,看下面的代碼:
import React, { Component } from "react"; import {findDOMNode, render, unmountComponentAtNode} from "react-dom"; class FieldOne extends Component { componentWillUnmount() { console.log("%c FieldOne will unmount") } render() { returnThe One} } class FieldTwo extends Component { componentWillUnmount() { console.log("%c FieldTwo will unmount") } render() { returnThe Two} } class App extends Component { constructor(props) { super(props) } componentDidMount() { render(, this.fieldOne) } handleClick() { console.log(unmountComponentAtNode(this.fieldOne)) console.log(unmountComponentAtNode(this.fieldTwo)) } render() { return ( ) } } render(this.fieldOne = fieldOne}>this.fieldTwo = fieldTwo}>, document.getElementById("root"))
簡單的分析這段代碼之前,先扯一個小的問題。react中的組件渲染有幾種方式?一般來說,兩種:
通過下面render函數(shù),將組件渲染到DOM結(jié)構(gòu)中。
由React自身渲染
這兩種渲染方式,分別對應(yīng)于上述代碼中的FieldOne和FieldTwo組件的渲染方式。所以,你必須先搞明白一件事情,unmountComponentAtNode并不能卸載所有已經(jīng)掛載到DOM中的組件,它只能卸載通過render函數(shù)渲染的組件。
所以,當(dāng)我們點擊button按鈕的時候,會在控制臺中看到,下面這些東西。
其中,當(dāng)unmountComponentAtNode的返回值為true的時候,表示卸載成功。反之,則表示卸載失敗。
下面是點擊按鈕之前的DOM結(jié)構(gòu)的對比情況。
點擊前
點擊后
ReactDOM.renderreact最讓人爽的地方就是,接口名稱的語意化很明顯。所以,從字面意義上我們就能知道render是干啥的。干啥?用于渲染。
先簡單的了解下接口定義。
ReactDOM.render( ReactComponent, DOMElement, [callback] )
一句話概括:
渲染一個ReactComponent,將其作為DOMElement的innerHTML。
記住兩件事:
這個方法只會進行一次整體更新
第一次渲染后,會將DOMElement的innerHTML用ReactComponent的實例所替換,之后的渲染,便采用高效的diff算法進行更新。
幾個問題:
這個方法是同步的還是異步的?
這個方法有沒有返回值?
callback函數(shù),有參數(shù)嗎?
來一起扯扯:
先看這個代碼:
import React from "react"; import {findDOMNode, render} from "react-dom"; // 函數(shù)式組件一 const FieldInput = (props) => { return () } class App extends React.Component { constructor(props) { super(props) } render() { return () } } console.log("%c begin render", "color:red") const baseComponent = render(The header , document.getElementById("root")) console.log(baseComponent) console.log("%c end render", "color:red")
結(jié)果呢,是這樣的。不錯,同步調(diào)用的。而且返回值就是我們的根組件的實例。
挺好的,可是,官方有聲明:
所以嘞,我們應(yīng)該避免使用這種方式獲取根組件實例(一般也不會采用這種方法操作根組件實例,只需要知道有這么回事就好了)。
再看一下這段代碼:
import React from "react"; import {findDOMNode, render} from "react-dom"; class App extends React.Component { constructor(props) { super(props) } render() { return (test) } } render(, document.getElementById("root"), (...args) => { console.log(args) // [] })
這個回調(diào)函數(shù)其實是沒有參數(shù)的,但是,當(dāng)render方法變成異步方法之后,說不定就會向其注入一些參數(shù)了。具體的,拭目以待。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/85176.html
摘要:結(jié)果如下打開試試下一步,我們將把組件功能自己設(shè)置定時器并且能每秒更新。這是一個設(shè)置定時器的好地方注意我們是怎么保存定時器的。我們將在這個生命周期的函數(shù)方法中卸載掉定時器最后,我們會每一秒跑方法。 下面是react官方文檔的個人翻譯,如有翻譯錯誤,請多多指出原文地址:https://facebook.github.io/re... Consider the ticking clock e...
摘要:注不做翻譯是中最小的構(gòu)建部件。在里渲染讓我們看一下在下面有在你文件中無處不在的標(biāo)簽我們會把這元素成為元素因為的所有東西都會放在這個元素里面。通過方法,我們能吧渲染到我們根節(jié)點上。更新被渲染的是不可變的。 下面是react官方文檔的個人翻譯,如有翻譯錯誤,請多多指出原文地址:https://facebook.github.io/re...特別感謝Hevaen,同時也向豪大React群所有...
摘要:本文將對源碼做一個初步解析。首先在方法中校驗參數(shù)是否合法,然后調(diào)用在中,調(diào)用拿到了的一個實例,調(diào)用拿到了,用于注入到,和作為返回值,調(diào)用開始調(diào)度過程在中,首先清理了中的所有子節(jié)點,然后了一個并返回是如何調(diào)度的是一個什么樣的類的操作是在哪里 初步看了react-dom這個包的一些源碼,發(fā)現(xiàn)其比react包要復(fù)雜得多,react包中基本不存在跨包調(diào)用的情況,他所做的也僅僅是定義了React...
前言:使用react也有二年多了,一直停留在使用層次。雖然很多時候這樣是夠了。但是總覺得不深入理解其背后是的實現(xiàn)邏輯,很難體會框架的精髓。最近會寫一些相關(guān)的一些文章,來記錄學(xué)習(xí)的過程。 備注:react和react-dom源碼版本為16.8.6 本文適合使用過React進行開發(fā),并有一定經(jīng)驗的人閱讀。 好了閑話少說,我們一起來看源碼吧寫過react知道,我們使用react編寫代碼都離不開webpa...
閱讀 2913·2021-09-28 09:36
閱讀 3729·2021-09-27 13:59
閱讀 2523·2021-08-31 09:44
閱讀 2322·2019-08-30 15:54
閱讀 2375·2019-08-30 15:44
閱讀 1216·2019-08-30 13:45
閱讀 1257·2019-08-29 18:38
閱讀 1246·2019-08-29 18:37