betacode

Используйте Layout в Thymeleaf

  1. Цель статьи
  2. Пример Thymeleaf Layout

1. Цель статьи

Page Layout (разметка страницы) относится к распределению текста, изрбражений и других объектов на одной странице, и это самый обсуждаемый вопрос дизайнеров website. В данной статье я представлю технику, которая используется в Thymeleaf, чтобы создать Layout.
Thymeleaf использует fragment, чтобы соединить вместе и создать страницу, поэтому вам стоит изучить fragment перед тем, как продолжить с данной статьей.
Один website может иметь много странц, но страницы имеют одинаковую структуру. Например, ниже является простая структура:
Основываясь на структуре выше, вы можете создать разные страницы:

2. Пример Thymeleaf Layout

Ниже является изображение приложения, написанного на Spring Boot, не волнуйтесь если вы используете другой фреймворк (framework), структура проекта может быть немного другой, но не будет сложно для вас понять, что я здесь выполняю.
Создать 2 файла main.css & main-layout.html:
Файл main-layout.html содержит 1 fragment имеет 6 параметров, эти параметры помогают сформировать полный интерфейс страницы.
layouts/main-layout.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org"
    th:fragment="main-fragment (title, otherStaticResources, header, nav, mainContent, footer)">
<head>
<meta charset="UTF-8" />
<title th:replace="${title}">Page 1 Title</title>
<link rel="stylesheet" type="text/css" th:href="@{/main.css}" href="../../static/main.css"/>
<!-- Other javascript, css source files -->
<th:block th:replace="${otherStaticResources} ?: ~{}"></th:block>
</head>
<body>
    <header th:insert="${header} ?: ~{}">
        <h2>Page 1</h2>
    </header>
    <section>
        <nav th:insert="${nav} ?: ~{}">
            <ul>
                <li><a href="#">Page 1</a></li>
                <li><a href="#">Page 2</a></li>
            </ul>
        </nav>
        <article th:insert="${mainContent} ?: ~{}">
            <h1>Page 1</h1>
            <p>Main content of Page 1</p>
        </article>
    </section>
    <footer th:insert="${footer} ?: ~{}">
        <p>Footer</p>
    </footer>
</body>
</html>
main.css
* {
    box-sizing: border-box;
}
header {
    background-color: #666;
    padding: 5px;
    text-align: center;
    font-size: 35px;
    color: white;
}
nav {
    float: left;
    width: 30%;
    height: 300px;
    background: #ccc;
    padding: 20px;
}
nav ul {
    list-style-type: none;
    padding: 0;
}
article {
    float: left;
    padding: 20px;
    width: 70%;
    background-color: #f1f1f1;
    height: 300px;
}
section:after {
    content: "";
    display: table;
    clear: both;
}
footer {
    background-color: #777;
    padding: 10px;
    text-align: center;
    color: white;
}
@media ( max-width : 600px) {
    nav, article {
        width: 100%;
        height: auto;
    }
}
Откройте файл main-layout.html напрямую на браузере и вы сможете увидеть его интерфейс.
Файл app-fragments.html содержит fragment, которые переиспользуются во многих разных Template приложения.
fragments/app-fragments.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>App Fragments</title>
</head>
<body>
    <!-- Default Navigator -->
    <ul th:fragment = "nav-default">
        <li><a th:href="@{/}">Home</a></li>
        <li><a th:href="@{/products}">Products</a></li>
        <li><a th:href="@{/about}">About</a></li>
    </ul>
    <!-- Admin Navigator -->
    <ul th:fragment = "nav-admin">
        <li><a th:href="@{/admin/products}">Product Management</a></li>
        <li><a th:href="@{/admin/orders}">Order Management</a></li>
    </ul>
    <div th:fragment="copyright">
      &copy; o7planning.org
    </div>
</body>
</html>
Создайте другие страницы для вашего приложения:
  • home.html, products.html, about.html.
Файл home.html использует Layout определенный файлом main-layout.html, и передает (pass) значения для параметрв.
home.html
<!DOCTYPE html>
<!--  main-fragment (title, otherStaticResources, header, nav, mainContent, footer)  -->
<html xmlns:th="http://www.thymeleaf.org"
      th:replace="~{layouts/main-layout :: main-fragment(  
                                                ~{::title},
                                                ~{:: #home-static-resources},
                                                ~{:: #home-header},
                                                ~{:: #home-nav},
                                                ~{:: #home-main-content},  
                                                ~{:: #home-footer}
                                               )}">
                                              
<head>
    <title>Title of Home Page</title>
    <th:block id="home-static-resources">
        <script type="text/javascript" src="../static/home.js" th:src="@{/home.js}"></script>
        <link rel="stylesheet" type="text/css" href="../static/home.css" th:href="@{/home.css}"/>
    </th:block>
</head>
<body>
    <div id="home-header">
        Header of Home Page
    </div>
    <div id="home-nav" th:replace="~{/fragments/app-fragments :: nav-default}">
        Home Nav
    </div>
    <div id="home-main-content">
        <h2>Home content</h2>
        <div>Content of Home Page</div>
    </div>
    <div id="home-footer" th:replace="~{/fragments/app-fragments :: copyright}">
        Footer
    </div>
</body>
</html>
products.html
<!DOCTYPE html>
<!--  main-fragment (title, otherStaticResources, header, nav, mainContent, footer)  -->
<html xmlns:th="http://www.thymeleaf.org"
      th:replace="~{layouts/main-layout :: main-fragment(  
                                                ~{::title},
                                                ~{:: #products-static-resources},
                                                ~{:: #products-header},
                                                ~{:: #products-nav},
                                                ~{:: #products-main-content},  
                                                ~{:: #products-footer}
                                               )}">
                                              
<head>
    <title>Title of Products Page</title>
    <th:block id="products-static-resources">  
       <script type="text/javascript" src="../static/products.js" th:src="@{/products.js}"></script>
    </th:block>
</head>
<body>
    <div id="products-header">
        Header of Products Page
    </div>
    <div id="products-nav" th:replace="~{/fragments/app-fragments :: nav-default}">
         Nav
    </div>
    <div id="products-main-content">
        <h2>Product</h2>
        <p>Samsung</p>
        <p>iPhone</p>
        <p>Nokia</p>
    </div>
    <div id="products-footer" th:replace="~{/fragments/app-fragments :: copyright}">
        Footer
    </div>
</body>
</html>
about.html
<!DOCTYPE html>
<!--  main-fragment (title, otherStaticResources, header, nav, mainContent, footer)  -->
<html xmlns:th="http://www.thymeleaf.org"
      th:replace="~{layouts/main-layout :: main-fragment(  
                                                ~{::title},
                                                ~{:: #about-static-resources},
                                                ~{:: #about-header},
                                                ~{:: #about-nav},
                                                ~{:: #about-main-content},  
                                                ~{:: #about-footer}
                                               )}">
                                              
<head>
    <title>Title of About Page</title>
    <th:block id="about-static-resources">
        <script type="text/javascript" src="../static/about.js" th:src="@{/about.js}"></script>
    </th:block>
</head>
<body>
    <div id="about-header">
        Header of About Page
    </div>
    <div id="about-nav" th:replace="~{/fragments/app-fragments :: nav-default}">
         Nav
    </div>
    <div id="about-main-content">
        <h2>About</h2>
        <div>Content of About Page</div>
    </div>
    <div id="about-footer" th:replace="~{/fragments/app-fragments :: copyright}">
        Footer
    </div>
</body>
</html>
MainController.java
package org.o7planning.thymeleaf.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MainController {
    @RequestMapping("/")
    public String home() {
        return "home";
    }
    @RequestMapping("/products")
    public String products() {
        return "products";
    }
    @RequestMapping("/about")
    public String about() {
        return "about";
    }
}