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!就是我想要的效果。

相关文章
相关标签/搜索