天天看点

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