當 React 遇上 KendoUI

kmokidd發表於2014-09-29

注:React.js 是 Facebook 推出的一個用來構建使用者介面的 JavaScript 庫。

ReactJS從根本上改變了我對待Web介面的態度。在短期接觸ReactJS的時間裡,它帶給了我從未體會過的驚喜。

讓人興奮的根源,我想是React對待UI的方式和我們之前接觸過的不太一樣。你不需要直接操作DOM,Readct的元件會渲染一個視覺化的DOM。這個視覺化的DOM會將它的改變展現出來,並會計算出更新所需要的最少步驟(然後真正地更新了DOM),這一點僅僅是作用在DOM需要改變的部分上(想要了解React reconciliation的機制,請看這裡這裡)。

到目前為止我使用過的庫或者框架都是直接操作DOM的,如果我不想放棄已經在使用UI部件,又想要使用React,我也能這麼做嗎?

你當然可以咯

當React遇上KendoUI

為了說明這一點,讓我們用KendoUI構建一個計量器(Radial Gauge,它還包含了KendoUI slider)來演示,並將它轉換成React元件。你可以點選上面的連結,看一看使用KendoUI和jQuery是如何寫出這個效果的(這是非React的方式)。(這裡我要提醒大家一下,Radial Gauge是KendoUI專業版的功能,這個版本是需要支付費用的,比起開源版的KendoUI core專業版提供了很多複雜的部件或視覺化效果。你可以看看這篇文章來對比這兩個版本。)

Radial Gauge

首先,建立一個RadiaGauge元件,它可以在DOM中渲染出一個div(這個步驟執行完畢之後,KendoUI部件將會鎖定這個元素):

不要擔心,它不會停在那兒的:)。

React元件有一些生命週期方法(lifecycle methods),我們將會用到的是componentDidMount。當一個元件第一次被渲染到頁面上時,這個方法就會被呼叫,這時我們就可以操作DOM了。我們可以使用getDOMNode來獲取剛剛那個div的引用。

好吧,上面的程式碼看起來糟糕透了,元件的配置完全是硬編碼。我們其實可以將這個配置的值用props來傳遞,預設值可以用getDefaultProps來使用:

現在看起來好多了,不過還有最後一道坎要跨。

“有一點很重要:因為我們是在元件渲染之後才開始操作DOM的,KendoUI部件是沒法使用ReactJS分析DOM前後不同這個功能。所以我們需要監聽部件的改變好及時作出反應。”

我們需要監聽props.value的值是否被改變,如果改變了就要重新渲染部件。componentWillReceivePropscomponentDidUpdate這兩個方法都能對props.value的改變做出反應。如果我們只是簡單的重新渲染KendoUi radial gauge,那就沒有辦法將那個改變的過程動畫化。所以目前我們是這麼做的:

componentWillReceiveProps中,如果發現部件發生改變,那麼部件中的某個值會變化,KendoUI會動畫化這個改變的過程。

從React角度上來看,RadialGauge元件就是渲染出一個div,所以監聽它的props改變只是微不足道的效能消耗。(對於componentWillReceiveProps來說,DOM的改變不一定會觸發KendoUI部件的更新。)但是如果你的元件渲染方法比較複雜,那最好還是要有shouldComponentUpdate

Slider

現在讓我們給輪播建立一個元件。第一步:渲染一個div,在componentDidMount呼叫這個元件:

這裡有一點不同。

事件(Events)

我們需要處理由於使用者的輸入導致輪播的值出現變化的情況。因為現在處理的是一個由React合成事件系統(synthetic events system)產生的事件,我們需要提供一個事件處理程式給這個KendoUI部件。還有一點要注意:如果這個元件從DOM中被移除了,那相應的事件處理程式也要移除掉,這個可以讓componentWillUnmount來做。

混合(Mixins)

在Slider元件中,我還用到了React的混合(mixins)。當一個子控制元件要通知其他控制元件它的值發生改變的時候,可選的方法並不多。我使用的是messaging mixin,這個方法可以使得我的元件值發生改變的時候告訴給其他元件(其他元件要監聽這個值):

請注意,我們在componentWillUnmount方法中呼叫了destroy(),這一步很重要。

再多說一點

難道就停在gauge和slider這裡了嗎?我想要用“傳統的”React元件來展示這個,所以現在你會在頁面上看到一個下拉選單,選單中的兩個選項是兩種不同的測量方式。

UnitOfMeasure Component

UnitOfMeasure元件使用了messaging mixin來展現所選擇的值的改變。

SpeedDisplay Component

這個元件沒有什麼好解釋的,它唯一的功能就是將文字展現在div中。

所有程式碼整合起來

KendoExample元件包含了兩個變數:speed和uom。這個元件會被UnitOfMeasureKendo.Slider影響,當上述的兩個元件中的任意一個產生了新的資訊,KendoExample都會呼叫setState

你可以在這裡看到演示結果。

包裝

我希望你覺得這篇文章很有用。如果你想要了解React和別的庫是如何結合使用的,可以看React BootstrapWingspan Forms

更新

Christopher Chedeau(React的天才開發人員之一)評議了這篇文章並指出關於RadialGauge元件這點,他傾向使用componentWillReceiveProps來比較新舊props,然後看情況更新DOM。原先更新radial gauge是在componentDidUpdate中完成的,現在我把componentWillReceiveProps的方法更新到例子中了。React的開發團隊很友善,所以不要害怕向他們提問。

相關文章