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

在開始閱讀本文以前,你須要先了解如下內容:
  • CSS相關知識(如選擇器、如何編寫CSS rule等) css

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

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

前言

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

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

好啦,不抱怨了。因爲公司大部分產品都是基於Vaadin建立的,爲了提升代碼質量,再屎的東西也要硬着頭皮去學。 學習

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

調整樣式的大體步驟

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

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

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

四、編譯,試運行,看結果。


實例:樣式化一個Label組件

接下來我就以Label組件爲例,詳細講述如何爲vaadin組件修改樣式。在例子中,我將建立一個Label用來顯示某人的姓名和年齡。而後針對姓名和年齡兩個部分分別樣式化。若是建立Label部分不熟悉,你能夠參考個人另外一篇文章《Vaadin組件筆記——Label》。另:如何建立Vaadin項目,怎樣編譯運行,不在本文範疇以內,你能夠參考其餘相關資料。

第一步:用java語言編寫頁面,添加一個Label組件。

組件的Caption中填寫「Mr. Wangbagaozi」,value中填寫「1000 year-old」。

List-1

Label label = new Label();
label.setCaption("Mr. Wangbagaozi");
label.setValue("1000 year-old");

先讓咱們運行一下,看看界面上的效果。

wKioL1h022CTZS41AAAL3rNpZRQ373.png

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

List-2

<div class="v-widget v-has-caption v-caption-on-top v-has-width" style="width: 100%;">
    <div class="v-caption" id="gwt-uid-2" for="gwt-uid-3">
        <span class="v-captiontext">Mr. Wangbagaozi</span>
    </div>
    <div class="v-label v-widget v-has-width" id="gwt-uid-3" aria-labelledby="gwt-uid-2" style="width: 100%;">1000 year-old</div>
</div>

第二步:給頁面元素指定一個特定的class name。

如今,我但願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

<div class="v-widget v-has-caption v-caption-on-top v-has-width">
    <div class="v-caption">
        <span class="v-captiontext">Mr. Wangbagaozi</span> <!--這裏是caption-->
    </div>
    <div class="v-label v-widget v-has-width">1000 year-old</div> <!--這裏是value-->
</div>

咱們嘗試寫一下SCSS(vaadin中使用SCSS,你須要先編寫SCSS,編譯時vaadin會自動將SCSS編譯爲CSS)。

List-4

.v-captiontext {
    font-size: 24px;
    font-weight: bold;
}
.v-label {
    font-size: 16px;
    color: gray;
    font-style: italic;
}

運行一下看看結果:

wKioL1h0466z112HAAARCWLZrO0705.png

第三步:在SCSS中針對特定的class name編寫樣式規則。

樣式改變了,貌似這樣就能夠了?等等!這樣寫有問題,讓我再增長一個label組件到頁面上,大家就知道問題在哪兒了。下面我增長一個label,用來顯示這位Wangbagaozi先生的地址還有電話號碼。

List-5

Label label2 = new Label();
label2.setCaption("South China sea.");
label2.setValue("13399988888.");

運行一下看看結果:

wKiom1h05PGBIQO2AAAe1YdoQZY392.png

Whaaat!! 這是什麼鬼東西?沒錯,被放入label2的caption的內容也隨之改變,而這並非咱們想要的結果。咱們但願label2的caption和value都按照普通方式顯示,不要加樣式。

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

List-6

<div class="v-slot">
    <!--下面是label生成的代碼-->
    <div class="v-widget v-has-caption v-caption-on-top v-has-width" style="width: 100%;">
        <div class="v-caption" id="gwt-uid-2" for="gwt-uid-3">
            <span class="v-captiontext">Mr. Wangbagaozi</span>
        </div>
        <div class="v-label v-widget v-has-width" id="gwt-uid-3" aria-labelledby="gwt-uid-2" style="width: 100%;">1000 year-old</div>
    </div>
</div>
<div class="v-slot">
    <!--下面是label2生成的代碼-->
    <div class="v-widget v-has-caption v-caption-on-top v-has-width" style="width: 100%;">
        <div class="v-caption" id="gwt-uid-4" for="gwt-uid-5">
            <span class="v-captiontext">South China sea.</span>
        </div>
        <div class="v-label v-widget v-has-width" id="gwt-uid-5" aria-labelledby="gwt-uid-4" style="width: 100%;">13399988888.</div>
    </div>
</div>

呃……label和label2生成的前端代碼中用於區別的class name如出一轍,除了進行噁心的相對定位選擇就沒有別的辦法了嗎?固然不是,Vaadin不會這麼蠢!既然沒法利用自動生成的class name,咱們還能夠利用咱們自定義的class name來對這兩個label進行區別。咱們只須要針對第一個label進行樣式化,其餘的不用加載樣式。Okay,稍加修改List-1的代碼:

List-7

Label label = new Label();
label.setCaption("Mr. Wangbagaozi");
label.setValue("1000 year-old");
label.addStyleName("special-label");  <--- Look here!

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

List-8

<div class="v-slot v-slot-special-label">
    <!--下面是爲label生成的代碼-->
    <div class="v-widget v-has-caption v-caption-on-top v-has-width" style="width: 100%;">
        <div class="v-caption v-caption-special-label" id="gwt-uid-2" for="gwt-uid-3">
            <span class="v-captiontext">Mr. Wangbagaozi</span>
        </div>
        <div class="v-label v-widget special-label v-label-special-label v-has-width" id="gwt-uid-3" aria-labelledby="gwt-uid-2" style="width: 100%;">1000 year-old</div>
    </div>
</div>
<div class="v-slot">
    <!--下面是爲label2生成的代碼-->
    <div class="v-widget v-has-caption v-caption-on-top v-has-width" style="width: 100%;">
        <div class="v-caption" id="gwt-uid-4" for="gwt-uid-5">
            <span class="v-captiontext">South China sea.</span>
        </div>
        <div class="v-label v-widget v-has-width" id="gwt-uid-5" aria-labelledby="gwt-uid-4" style="width: 100%;">13399988888.</div>
    </div>
</div>

注意看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

.v-caption-special-label .v-captiontext {
    font-size: 24px;
    font-weight: bold;
}
.v-label-special-label {
    font-size: 16px;
    color: gray;
    font-style: italic;
}

運行看看效果:

wKioL1h08s2iSFCTAAAbk96AwQE039.png

Bingo!就是我想要的效果。

相關文章
相關標籤/搜索