摘要:但是,最后一步,事件怎么綁定呢這塊沒有深入研究了,不過我想,應該這樣去實現也是沒有問題的。的具體做法是,把方法放到了一個叫做的組件上去實現這個功能,然后再把內容放進這個組件。其他的邏輯比如顯示隱藏之類,全部都放到組件自身上去實現。
1、Dialog組件提供什么功能,解決什么問題?
zent的Dialog組件,使用姿勢是這樣的(代碼摘自zent官方文檔:https://www.youzanyun.com/zan...)
import { Dialog, Button } from "zent"; class Example extends React.Component { state = { visible: false } triggerDialog = visible => { this.setState({ visible }); }; render() { return (); } } ReactDOM.render(, mountNode);
可以通過visible屬性控制彈層的顯示與隱藏
可以隨意的在Dialog組件里添加任意多的內容
可以在任意位置使用Dialog組件
2、如果我來實現會怎么做?如果我來實現,其實很簡單,用jQuery已經寫了無數遍了,但是,想想當初用jQuery來寫組件的時候,非常方便的可以在body下面插入一個div,并且綁定事件,或者,直接把彈層的div寫到body標簽下面。
但是,react,卻是組件嵌套組件,所有組件都渲染在一個被稱為root的div下面,這可怎么把一個節點掛載到body下面呢?
也簡單,我直接用document.body.appendChild把組件直接插入到body后面,但是發現,document.body.appendChild的參數必須是標準的dom節點,而react里面,通過this.props.children取出來的數據,并不是標準的dom節點,這也好辦,把這些節點轉成標準的dom節點,然后插入到body下面不就ok了?我是這么想的。但是,最后一步,事件怎么綁定呢?這塊沒有深入研究了,不過我想,應該這樣去實現也是沒有問題的。
順便說一下,曾經我還實現過一個React的彈層,但是必須放到最外層使用。。。哈哈,不說了,都是淚,侵入太強,無法做到在任意位置使用Dialog組件。
3、zent的Dialog實現方式zent實現方式,其實跟我上面說的基本思路是一致的,只是,用的方法不再是document.body.appendChild,而是用到了一個React提供的叫做ReactDOM.unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback)的方法,第一個參數是當前dialog所在的父組件,第二個參數是將要渲染的dialog內容,其實就是this.props.children,第三個參數是即將要掛載到body下面的一個div容器節點,callback就是成功之后的回調了。
從函數名可以看出,這個方法是不穩定的,但是,zent還是用了,不過效果很好,哈哈。
zent的具體做法是,把ReactDOM.unstable_renderSubtreeIntoContainer方法放到了一個叫做Portal的組件上去實現這個功能,然后再把dialog內容放進這個Portal組件。
{this.props.children}
Portal組件本身的功能非常簡單,僅僅只是負責把其子組件渲染到body下面的一個新創建的div下面去。其他的邏輯(比如顯示、隱藏、mask之類),全部都放到dialog組件自身上去實現。當然,顯示與隱藏的功能,還是由Portal來控制,隱藏的時候,Portal會把當前的子組件從body上面卸載掉。
4、極簡實現以下是一個極簡的Portal實現,即把自己的子組件渲染到body上面去。
import React from "react"; import ReactDOM from "react-dom"; export default class Portal extends React.Component { renderChildren() { const container = document.createElement("div"); document.body.appendChild(container); ReactDOM.unstable_renderSubtreeIntoContainer(this, React.Children.only(this.props.children), container); } componentDidMount() { this.renderChildren(); } render() { return null; } }
以下是,基于Portal的Dialog組件的極簡實現:
import React from "react"; import Portal from "./portal"; export default class Dialog extends React.Component { render() { return} } {this.props.children}
使用方式:
import React, { Component } from "react"; import ReactDOM, { render } from "react-dom"; import Dialog from "./dialog"; class App extends Component { onTextClick = () => { console.log("clicked") } render() { return (); } } render(, document.getElementById("root"));
當然,真正要實現一個Dialog需要考慮的問題還有很多,比如控制隱藏與顯示、定制動畫,自定義樣式,配置dialog的標題和其他屬性等等,只是這些我們在jQuery時代都已經做過。
這里主要分析了Portal的實現,畢竟,在React里面,要把組件渲染到app根節點外面去并不容易。
(全文完)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95589.html
摘要:引言組件中有很多彈出式組件,常見的如,以及等。這樣一種層次結構在實踐中大大降低了各類彈層組件的實現和維護成本。但是的組件實現了一個大多數組件庫都沒有實現的功能彈層的嵌套處理。 引言 UI 組件中有很多彈出式組件,常見的如 Dialog,Tooltip 以及 Select 等。這些組件都有一個特點,它們的彈出層通常不是渲染在當前的 DOM 樹中,而是直接插入在 body (或者其它類似的...
摘要:是有贊端規范的實現版本,提供了一整套基礎的組件以及常用的業務組件。目前我們有組件,其中包括以及等實用的業務組件。一套有贊設計師繪制的圖標庫。為了解決這些問題,提供了一套自己的時間選擇組件,包括日期選擇周選擇組件月選擇以及時間區間選擇。 Zent ( ?zent ) 是有贊 PC 端 Web UI 規范的 React 實現版本,提供了一整套基礎的 UI 組件以及常用的__業務組件__。通...
摘要:源碼真的這么可怕嗎從以上的事例中可以看出,其實并沒有。對于源碼的恐懼,讓我們漸漸思維固化,自己告訴自己不要去碰源碼,時間長了就遺忘了還有這樣一條路可走。 一個小需求 事情的起因,是昨天有一個新的需求被提出。 需求是要實現,讓我們自己定制的彈出層,具備按下 ESC 也能退出的功能。我把任務交給了同組的小伙伴S去實現。(這個項目用到了vue技術棧,以及餓了么的UI框架。) 我開完會回來,發...
摘要:近期給自己立了個小,讀源碼,每周至少讀篇源碼下面來談談和這兩個基于的框架源碼的基本結構以及區別。例如四兩個庫組件整體引入和按需引入整體引入兩個庫一樣的方法。 (近期給自己立了個小flag,讀源碼,每周至少讀1篇源碼) 下面來談談iview 和 Elemet UI 這兩個基于Vue 的UI 框架源碼的基本結構以及區別。 一、文件結構開發主要放在根文件夾下的src下: 1. ivew 文件...
閱讀 629·2021-09-24 09:48
閱讀 2492·2021-08-26 14:14
閱讀 517·2019-08-30 13:08
閱讀 1445·2019-08-29 15:22
閱讀 3066·2019-08-29 11:06
閱讀 1001·2019-08-26 18:26
閱讀 1034·2019-08-26 13:53
閱讀 2512·2019-08-26 12:21