這次帶給大家使用React將元件渲染到指定DOM節點,使用React將元件渲染到指定DOM節點的注意事項有哪些,以下就是實戰案例,一起來看一下。
眾所周知React優點之一就是他的API特別簡單。透過render 方法傳回一個元件的基本結構,如同一個簡單的函數,就可以得到一個可以重複使用的react元件。但有時候還是會有些限制的,尤其是他的API中,無法控制元件所應該渲染的DOM節點,這就讓一些彈層元件很難控制。當父元素設定為<a href="http://www.php.cn/wiki/923.html" target="_blank">overflow</a>:hidden
的時候,問題就會出現了。
例如就像下面的:
我們實際上期待的效果是這樣的:
# 幸運的是,雖然不是很明顯,但有一個相當優雅的方式來繞過這個問題。我們學到的第一個react函數是render 方法,他的函數簽章是這樣的:
ReactComponent render( ReactElement element, DOMElement container, [function callback] )
通常情況下我們會使用該方法將整個應用程式渲染到一個DOM節點。好消息是該方法並不僅限於此。我們可以在一個元件中,使用ReactDom.render
方法將另一個元件渲染到一個指定的DOM 元素中。作為一個元件的render 方法,其必須是純淨的(例如:不能改變state或與DOM互動).所以我們需要在componentDidUpdate 或 componentDidMount 中呼叫ReactDom.render
方法。
另外我們要確保在父元素被卸載的時候,改組件也要被卸載掉.
整理下,我們得到下面的一個元件:
import React,{Component} from 'react'; import ReactDom from 'react-dom'; export default class RenderInBody extends Component{ constructor(p){ super(); } componentDidMount(){//新建一个p标签并塞进body this.popup = document.createElement("p"); document.body.appendChild(this.popup); this._renderLayer(); } componentDidUpdate() { this._renderLayer(); } componentWillUnmount(){//在组件卸载的时候,保证弹层也被卸载掉 ReactDom.unmountComponentAtNode(this.popup); document.body.removeChild(this.popup); } _renderLayer(){//将弹层渲染到body下的p标签 ReactDom.render(this.props.children, this.popup); } render(){ return null; } }
總結下就是:
在componentDidMount的時候手動向body內塞一個p標籤,然後使用ReactDom.render 將元件渲染到這個p標籤
# 當我們想把元件直接渲染到body上的時候,只需要在該元件的外麵包一層RenderInBody 就可以了.
export default class Dialog extends Component{ render(){ return { <RenderInBody>i am a dialog render to body</RenderInBody> } } }
譯者增加:
將以上元件改造一下,我們就可以在指定的dom節點中渲染和卸載元件,並加上位置控制,如下:
//此组件用于在body内渲染弹层 import React,{Component} from 'react' import ReactDom from 'react-dom'; export default class RenderInBody extends Component{ constructor(p){ super(p); } componentDidMount(){ /** popupInfo={ rootDom:***,//接收弹层组件的DOM节点,如document.body left:***,//相对位置 top:***//位置信息 } */ let {popupInfo} = this.props; this.popup = document.createElement('p'); this.rootDom = popupInfo.rootDom; this.rootDom.appendChild(this.popup); //we can setAttribute of the p only in this way this.popup.style.position='absolute'; this.popup.style.left=popupInfo.left+'px'; this.popup.style.top=popupInfo.top+'px'; this._renderLayer() } componentDidUpdate() { this._renderLayer(); } componentWillUnmount(){ this.rootDom.removeChild(this.popup); } _renderLayer(){ ReactDom.render(this.props.children, this.popup); } render(){ return null; } }
註:位置獲取和根結點判斷函數
export default (dom,classFilters)=> { let left = dom.offsetLeft, top = dom.offsetTop + dom.scrollTop, current = dom.offsetParent, rootDom = accessBodyElement(dom);//默认是body while (current !=null ) { left += current.offsetLeft; top += current.offsetTop; current = current.offsetParent; if (current && current.matches(classFilters)) { rootDom = current; break; } } return { left: left, top: top ,rootDom:rootDom}; } /*** 1. dom:为响应弹层的dom节点,或者到该dom的位置后,可以做位置的微调,让弹层位置更佳合适 * 2. classFilters:需要接收弹层组件的DOM节点的筛选类名 /
相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!
推薦閱讀:
以上是使用React將元件渲染到指定DOM節點的詳細內容。更多資訊請關注PHP中文網其他相關文章!