摘要:并不是組件中的任何地方都能夠使用獲取結構,只對掛載后的組件生效。組件的一個特殊屬性,接受一個回調函數作為參數。反之,則表示卸載失敗。再看一下這段代碼這個回調函數其實是沒有參數的,但是,當方法變成異步方法之后,說不定就會向其注入一些參數了。
在react的組件的開發過程中,一般來說,我們并不會真正的去操作dom。只有在頂層組件的渲染的過程中,我們借助ReactDOM.render()方法,將我們的應用渲染到html結構中。然而,由于react框架自身的限制,在某些特定的情況下,我們必須要手動的操作dom。這時,我們就需要使用ReactDOM了。
先說一個小事,在react 0.14版本的時候,ReactDOM就從react的核心庫中分離出來了。所以,根據你使用的react版本的不同,我們引入ReactDOM的方式也就不一樣。總而言之,也就下面兩種基本的方法。
以下所有的代碼,都會通過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。所以相對來說學習起來還是比較簡單的。
這三個api 如下:
ReactDOM.findDOMNode
ReactDOM.unmountComponentAtNode
ReactDOM.render
下面,我們就簡單的扯扯,這三個api我們應該怎么使用。
ReactDOM.findDOMNode在絮叨這個api之前啊,先扯兩個你應該知道的東西。
Q:DOM被真正添加到HTML中是什么時候?
A:生命周期方法componentDidMount和componentDidUpdate
Q:還有沒有其他獲取DOM的方法
A:有,比如this.refs。
說這干啥,就是為了告訴你應該什么時候去獲取DOM。不要以為在任何地方都能獲取,否則更多等待你的就是error * 3。
好了,下面我們就好好扯扯findDOMNode該怎么用。
先看一下接口定義:
DOMElement findDOMNode(ReactComponent)
簡單的說就是:給它一點綠蔭(ReactComponent),還你一片森林(DOM Tree)。
比如,下面這個小demo,在組件加載完成的時候,獲取真正的dom結構。
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的操作結果是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的操作結果都是null。但是,對比之中你應該清楚兩件事。
并不是組件中的任何地方都能夠使用findDOMNode獲取DOM結構,findDOMNode只對掛載后的組件生效。
如果組件的render函數返回null,則在任何地方使用findDOMNode的結果都是null。
ReactDOM.findDOMNode with ref
先扯兩句ref。ref--組件的一個特殊屬性,接受一個回調函數作為參數。兩種情況:
給原生的html結構添加ref屬性,其參數就是其對應的DOM元素。這時候,直接使用即可。
給class聲明的組件添加ref屬性的時候,參數則是這個已經加載完成的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"));
結果,就是你想的那樣美好。
ReactDOM.unmountComponentAtNode最后呢,記住一句話,findDOMNode不能用在函數式組件中哦
來先把接口的名稱拆分一下:
unmount: 卸載
component: 組件
at: 在
node: 節點(DOM元素)
意思就是,從DOM元素中卸載已經掛載的組件,除此呢,還會清除它的事件處理器和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函數,將組件渲染到DOM結構中。
由React自身渲染
這兩種渲染方式,分別對應于上述代碼中的FieldOne和FieldTwo組件的渲染方式。所以,你必須先搞明白一件事情,unmountComponentAtNode并不能卸載所有已經掛載到DOM中的組件,它只能卸載通過render函數渲染的組件。
所以,當我們點擊button按鈕的時候,會在控制臺中看到,下面這些東西。
其中,當unmountComponentAtNode的返回值為true的時候,表示卸載成功。反之,則表示卸載失敗。
下面是點擊按鈕之前的DOM結構的對比情況。
點擊前
點擊后
ReactDOM.renderreact最讓人爽的地方就是,接口名稱的語意化很明顯。所以,從字面意義上我們就能知道render是干啥的。干啥?用于渲染。
先簡單的了解下接口定義。
ReactDOM.render( ReactComponent, DOMElement, [callback] )
一句話概括:
渲染一個ReactComponent,將其作為DOMElement的innerHTML。
記住兩件事:
這個方法只會進行一次整體更新
第一次渲染后,會將DOMElement的innerHTML用ReactComponent的實例所替換,之后的渲染,便采用高效的diff算法進行更新。
幾個問題:
這個方法是同步的還是異步的?
這個方法有沒有返回值?
callback函數,有參數嗎?
來一起扯扯:
先看這個代碼:
import React from "react"; import {findDOMNode, render} from "react-dom"; // 函數式組件一 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")
結果呢,是這樣的。不錯,同步調用的。而且返回值就是我們的根組件的實例。
挺好的,可是,官方有聲明:
所以嘞,我們應該避免使用這種方式獲取根組件實例(一般也不會采用這種方法操作根組件實例,只需要知道有這么回事就好了)。
再看一下這段代碼:
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) // [] })
這個回調函數其實是沒有參數的,但是,當render方法變成異步方法之后,說不定就會向其注入一些參數了。具體的,拭目以待。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/85176.html
摘要:結果如下打開試試下一步,我們將把組件功能自己設置定時器并且能每秒更新。這是一個設置定時器的好地方注意我們是怎么保存定時器的。我們將在這個生命周期的函數方法中卸載掉定時器最后,我們會每一秒跑方法。 下面是react官方文檔的個人翻譯,如有翻譯錯誤,請多多指出原文地址:https://facebook.github.io/re... Consider the ticking clock e...
摘要:注不做翻譯是中最小的構建部件。在里渲染讓我們看一下在下面有在你文件中無處不在的標簽我們會把這元素成為元素因為的所有東西都會放在這個元素里面。通過方法,我們能吧渲染到我們根節點上。更新被渲染的是不可變的。 下面是react官方文檔的個人翻譯,如有翻譯錯誤,請多多指出原文地址:https://facebook.github.io/re...特別感謝Hevaen,同時也向豪大React群所有...
摘要:本文將對源碼做一個初步解析。首先在方法中校驗參數是否合法,然后調用在中,調用拿到了的一個實例,調用拿到了,用于注入到,和作為返回值,調用開始調度過程在中,首先清理了中的所有子節點,然后了一個并返回是如何調度的是一個什么樣的類的操作是在哪里 初步看了react-dom這個包的一些源碼,發現其比react包要復雜得多,react包中基本不存在跨包調用的情況,他所做的也僅僅是定義了React...
前言:使用react也有二年多了,一直停留在使用層次。雖然很多時候這樣是夠了。但是總覺得不深入理解其背后是的實現邏輯,很難體會框架的精髓。最近會寫一些相關的一些文章,來記錄學習的過程。 備注:react和react-dom源碼版本為16.8.6 本文適合使用過React進行開發,并有一定經驗的人閱讀。 好了閑話少說,我們一起來看源碼吧寫過react知道,我們使用react編寫代碼都離不開webpa...
閱讀 2882·2021-09-28 09:36
閱讀 3608·2021-09-27 13:59
閱讀 2484·2021-08-31 09:44
閱讀 2278·2019-08-30 15:54
閱讀 2352·2019-08-30 15:44
閱讀 1180·2019-08-30 13:45
閱讀 1223·2019-08-29 18:38
閱讀 1207·2019-08-29 18:37