天天看點

Vaadin學習筆記——自定義vaadin元件的樣式

在開始閱讀本文之前,你需要先了解以下内容:

CSS相關知識(如選擇器、如何編寫CSS rule等)

HTML相關知識(元素、class屬性、DOM層級結構等)

Vaadin相關知識(如怎樣建立、運作Vaadin項目,怎樣建立一個vaadin頁面)

習慣了SSH的小夥伴們遇到vaadin這樣的技術時,肯定會一臉懵逼。我當初看到這個東西時眼前飄過的絕對不是6666666666,而是一大堆????????????。

有人說Vaadin就像swing,果真如此嗎?No!形似而已。真要上手去用去寫,你就會發現——這TM就是一坨屎。

好啦,不抱怨了。由于公司大部分産品都是基于Vaadin建立的,為了提高代碼品質,再屎的東西也要硬着頭皮去學。

在學習Vaadin的時候,有一個坎,那就是theming。Vaadin真不像Swing,再怎麼說swing的LAF還沒有跳脫Java的範疇,可以說他們還是在同一個體系中的。而Vaadin的style(或者說theming)則與你寫的Java代碼沒有關系,哦,這樣說并不确切。确切的說,絕大多數靈活的theming工作都要用到CSS(SCSS)。在Java代碼中僅能對一些元件做最基礎的尺寸等樣式調整,至于什麼margin、space、padding啥的,不能做(space僅有一個開關,代表“有space”和“沒有space”)。如果你想對vaadin的元件進行更大尺度的樣式化,請使用SCSS。

1、用java語言編寫頁面,添加頁面元素。

2、給頁面元素指定一個特定的class name。

3、在SCSS中針對特定的class name編寫樣式規則。

4、編譯,試運作,看結果。

元件的Caption中填寫“Mr. Wangbagaozi”,value中填寫“1000 year-old”。

List-1

<code>Label label = </code><code>new</code> <code>Label();</code>

<code>label.setCaption(</code><code>"Mr. Wangbagaozi"</code><code>);</code>

<code>label.setValue(</code><code>"1000 year-old"</code><code>);</code>

先讓我們運作一下,看看界面上的效果。

<a href="https://s4.51cto.com/wyfs02/M00/8C/B1/wKioL1h022CTZS41AAAL3rNpZRQ373.png" target="_blank"></a>

這是Vaadin根據我們的Java代碼自動生成的前端代碼:

List-2

<code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-widget v-has-caption v-caption-on-top v-has-width"</code> <code>style</code><code>=</code><code>"width: 100%;"</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-caption"</code> <code>id</code><code>=</code><code>"gwt-uid-2"</code> <code>for</code><code>=</code><code>"gwt-uid-3"</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>span</code> <code>class</code><code>=</code><code>"v-captiontext"</code><code>&gt;Mr. Wangbagaozi&lt;/</code><code>span</code><code>&gt;</code>

<code>    </code><code>&lt;/</code><code>div</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-label v-widget v-has-width"</code> <code>id</code><code>=</code><code>"gwt-uid-3"</code> <code>aria-labelledby</code><code>=</code><code>"gwt-uid-2"</code> <code>style</code><code>=</code><code>"width: 100%;"</code><code>&gt;1000 year-old&lt;/</code><code>div</code><code>&gt;</code>

<code>&lt;/</code><code>div</code><code>&gt;</code>

現在,我希望caption中的内容字号24px并且加粗,value中的内容字号16px,灰色,斜體。之前說過,vaadin的元件樣式是通過CSS來調整的,那麼,作為CSS編寫規則的最重要的選擇器就那麼幾種,class、id、element name等。vaadin推薦使用class name。Okay,我們看一下生成的前端HTML代碼,就清楚該怎樣編寫我們的CSS規則了。注:在CSS和SCSS中,有些需求可以使用多種方式來實作,本文介紹其中一種方式。方式無好壞,你覺得好用就好。

通過分析,我們看到,帶有Caption的label被解析成了一個div包裹着兩個同級div。提煉一下:

List-3

<code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-widget v-has-caption v-caption-on-top v-has-width"</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-caption"</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>span</code> <code>class</code><code>=</code><code>"v-captiontext"</code><code>&gt;Mr. Wangbagaozi&lt;/</code><code>span</code><code>&gt; </code><code>&lt;!--這裡是caption--&gt;</code>

<code>    </code><code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-label v-widget v-has-width"</code><code>&gt;1000 year-old&lt;/</code><code>div</code><code>&gt; </code><code>&lt;!--這裡是value--&gt;</code>

我們嘗試寫一下SCSS(vaadin中使用SCSS,你需要先編寫SCSS,編譯時vaadin會自動将SCSS編譯為CSS)。

List-4

<code>.v-captiontext {</code>

<code>    </code><code>font-size</code><code>: </code><code>24px</code><code>;</code>

<code>    </code><code>font-weight</code><code>: </code><code>bold</code><code>;</code>

<code>}</code>

<code>.v-label {</code>

<code>    </code><code>font-size</code><code>: </code><code>16px</code><code>;</code>

<code>    </code><code>color</code><code>: </code><code>gray</code><code>;</code>

<code>    </code><code>font-style</code><code>: </code><code>italic</code><code>;</code>

運作一下看看結果:

<a href="https://s2.51cto.com/wyfs02/M02/8C/B2/wKioL1h0466z112HAAARCWLZrO0705.png" target="_blank"></a>

樣式改變了,貌似這樣就可以了?等等!這樣寫有問題,讓我再增加一個label元件到頁面上,你們就知道問題在哪兒了。下面我增加一個label,用來顯示這位Wangbagaozi先生的位址還有電話号碼。

List-5

<code>Label label2 = </code><code>new</code> <code>Label();</code>

<code>label2.setCaption(</code><code>"South China sea."</code><code>);</code>

<code>label2.setValue(</code><code>"13399988888."</code><code>);</code>

<a href="https://s2.51cto.com/wyfs02/M01/8C/B5/wKiom1h05PGBIQO2AAAe1YdoQZY392.png" target="_blank"></a>

Whaaat!! 這是什麼鬼東西?沒錯,被放入label2的caption的内容也随之改變,而這并不是我們想要的結果。我們希望label2的caption和value都按照普通方式顯示,不要加樣式。

我們來看一下vaadin幫我們自動生成的前端代碼,找一下有什麼辦法将兩個Label進行區分。

List-6

<code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-slot"</code><code>&gt;</code>

<code>    </code><code>&lt;!--下面是label生成的代碼--&gt;</code>

<code>    </code><code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-widget v-has-caption v-caption-on-top v-has-width"</code> <code>style</code><code>=</code><code>"width: 100%;"</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-caption"</code> <code>id</code><code>=</code><code>"gwt-uid-2"</code> <code>for</code><code>=</code><code>"gwt-uid-3"</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>span</code> <code>class</code><code>=</code><code>"v-captiontext"</code><code>&gt;Mr. Wangbagaozi&lt;/</code><code>span</code><code>&gt;</code>

<code>        </code><code>&lt;/</code><code>div</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-label v-widget v-has-width"</code> <code>id</code><code>=</code><code>"gwt-uid-3"</code> <code>aria-labelledby</code><code>=</code><code>"gwt-uid-2"</code> <code>style</code><code>=</code><code>"width: 100%;"</code><code>&gt;1000 year-old&lt;/</code><code>div</code><code>&gt;</code>

<code>    </code><code>&lt;!--下面是label2生成的代碼--&gt;</code>

<code>        </code><code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-caption"</code> <code>id</code><code>=</code><code>"gwt-uid-4"</code> <code>for</code><code>=</code><code>"gwt-uid-5"</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>span</code> <code>class</code><code>=</code><code>"v-captiontext"</code><code>&gt;South China sea.&lt;/</code><code>span</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-label v-widget v-has-width"</code> <code>id</code><code>=</code><code>"gwt-uid-5"</code> <code>aria-labelledby</code><code>=</code><code>"gwt-uid-4"</code> <code>style</code><code>=</code><code>"width: 100%;"</code><code>&gt;13399988888.&lt;/</code><code>div</code><code>&gt;</code>

呃……label和label2生成的前端代碼中用于差別的class name一模一樣,除了進行惡心的相對定位選擇就沒有别的辦法了嗎?當然不是,Vaadin不會這麼蠢!既然無法利用自動生成的class name,我們還可以利用我們自定義的class name來對這兩個label進行差別。我們隻需要針對第一個label進行樣式化,其他的不用加載樣式。Okay,稍加修改List-1的代碼:

List-7

<code>label.addStyleName(</code><code>"special-label"</code><code>);  &lt;--- Look here!</code>

方法addStyleName其實就是給指定的元件添加一個class name。現在讓我們再看一下vaadin生成的前端代碼有什麼變化。

List-8

<code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-slot v-slot-special-label"</code><code>&gt;</code>

<code>    </code><code>&lt;!--下面是為label生成的代碼--&gt;</code>

<code>        </code><code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-caption v-caption-special-label"</code> <code>id</code><code>=</code><code>"gwt-uid-2"</code> <code>for</code><code>=</code><code>"gwt-uid-3"</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>div</code> <code>class</code><code>=</code><code>"v-label v-widget special-label v-label-special-label v-has-width"</code> <code>id</code><code>=</code><code>"gwt-uid-3"</code> <code>aria-labelledby</code><code>=</code><code>"gwt-uid-2"</code> <code>style</code><code>=</code><code>"width: 100%;"</code><code>&gt;1000 year-old&lt;/</code><code>div</code><code>&gt;</code>

<code>    </code><code>&lt;!--下面是為label2生成的代碼--&gt;</code>

注意看List-8中的代碼,相比較沒有用addStyleName方法添加額外class name的label2生成的代碼List-6,第4行的div元素class屬性中多了“v-caption-special-label”,還有第7行的div元素中多了“special-label”和"v-label-special-label"。

有了這些不同,我們就好差別對待了。修改SCSS如下:

List-9

<code>.v-caption-special-label .v-captiontext {</code>

<code>.v-label-special-label {</code>

運作看看效果:

<a href="https://s4.51cto.com/wyfs02/M02/8C/B2/wKioL1h08s2iSFCTAAAbk96AwQE039.png" target="_blank"></a>

Bingo!就是我想要的效果。

本文轉自 rickqin 51CTO部落格,原文連結:http://blog.51cto.com/rickqin/1890908