番外一:Thymeleaf 与 ES6 语法

本文主要探讨Thymeleaf模板引擎的优势及在SpringBoot中的使用,包括数据提供、启动器引入、静态页面处理和模板缓存。同时,文章也详细介绍了ES6的语法特性,如let和const、字符串扩展、解构表达式、函数优化、map和reduce等,帮助读者深入理解这两个技术。

此博客用于个人学习,来源于网上,对知识点进行一个整理。

1. Thymeleaf :

SpringBoot 并不推荐使用 jsp,但是支持一些模板引擎技术:

  • Freemarker
  • Thymeleaf
  • Mustache

本项目用到的是 Thymeleaf 技术。

1.1 Thymeleaf 的优势:

Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP,其本身的特点有:

  • 动静结合:Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
  • 开箱即用:它提供标准和 spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL 表达式效果,避免每天套模板、改 jstl、改标签的困扰,同时开发人员也可以扩展和创建自定义的方言。
  • 多方言支持:Thymeleaf 提供 spring 标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
  • 与 SpringBoot 完美整合,SpringBoot 提供了 Thymeleaf 的默认配置,并且为 Thymeleaf 设置了视图解析器,可以像操作 jsp 一样来操作 Thymeleaf。代码几乎没有任何区别,就是在模板语法上有区别。

1.2 提供数据:

编写一个 controller 方法,返回一些用户数据,放入模型中,将来在页面渲染。

@GetMapping("/all")
public String all(ModelMap model) {
    // 查询用户
    List<User> users = this.userService.queryAll();
    // 放入模型
    model.addAttribute("users", users);
    // 返回模板名称(就是classpath:/templates/目录下的html文件名)
    return "users";
}

1.3 引入启动器:

通过 maven 引入依赖,SpringBoot 会自动为 Thymeleaf 注册一个视图解析器:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Thymeleaf 也会根据前缀和后缀来确定模板文件的位置:

在这里插入图片描述

  • 默认前缀:classpath:/templates/
  • 默认后缀:.html

所以如果我们返回视图:users,会指向到 classpath:/templates/users.html 。

1.4 静态页面:

模板默认放在 classpath 下的 templates 文件夹,我们新建一个 html 文件放入其中,渲染模型中的数据。把 html 的名称空间,改成:xmlns:th=“http://www.thymeleaf.org” 会有语法提示。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <style type="text/css">
        table {border-collapse: collapse; font-size: 14px; width: 80%; margin: auto}
        table, th, td {border: 1px solid darkslategray;padding: 10px}
    </style>
</head>
<body>
<div style="text-align: center">
    <span style="color: darkslategray; font-size: 30px">欢迎光临!</span>
    <hr/>
    <table class="list">
        <tr>
            <th>id</th>
            <th>姓名</th>
            <th>用户名</th>
            <th>年龄</th>
            <th>性别</th>
            <th>生日</th>
        </tr>
        <tr th:each="user : ${users}">
            <td th:text="${user.id}">1</td>
            <td th:text="${user.name}">张三</td>
            <td th:text="${user.userName}">zhangsan</td>
            <td th:text="${user.age}">20</td>
            <td th:text="${user.sex}"></td>
            <td th:text="${user.birthday}">1980-02-30</td>
        </tr>
    </table>
</div>
</body>
</html>

使用了以下语法:

  • ${} :这个类似与 el 表达式,但其实是 ognl 的语法,比 el 表达式更加强大。
  • th - 指令:th- 是利用了 Html5 中的自定义属性来实现的。如果不支持 H5,可以用 data-th- 来代替。
    • th:each:类似于 c:foreach 遍历集合,但是语法更加简洁。
    • th:text:声明标签中的文本
      • 例如 <td th-text=’${user.id}’>1</td>,如果 user.id 有值,会覆盖默认的1。
      • 如果没有值,则会显示 td 中默认的1。这正是 thymeleaf 能够动静结合的原因,模板解析失败不影响页面的显示效果,因为会显示默认值。

1.5 模板缓存:

Thymeleaf 会在第一次对模板解析之后进行缓存,极大的提高了并发处理能力。但是这给我们开发带来了不便,修改页面后并不会立刻看到效果,我们开发阶段可以关掉缓存使用。

# 开发阶段关闭thymeleaf的模板缓存
spring:
	thymeleaf:
		cache: false

在 Idea 中,我们需要在修改页面后按快捷键:Ctrl + Shift + F9 对项目进行 rebuild 才可以。

2. ES6 语法:

ECMAScript 是浏览器脚本语言的规范,而各种我们熟知的 js 语言,如 JavaScript 则是规范的具体实现。

2.1 let 和 const 命令:

之前,js 定义变量只有一个关键字:var,但这个关键字存在一个问题,就是定义的变量有时会莫名奇妙的成为全局变量。

for(var i = 0; i < 5; i++){
    console.log(i);
}
console.log("循环外:" + i)

结果为

循环外:5

  1. let:let 所声明的变量,只在 let 命令所在的代码块内有效,将上面的代码改为 let 关键字,会出现错误。
  2. const:const 声明的变量是常量,不能被修改。

2.2 字符串扩展:

ES6 为字符串扩展了几个新的API:

  • includes():返回布尔值,表示是否找到了参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。

’ '来作为字符串模板标记,在两个‘之间的部分都会被作为字符串的值,不管你任意换行,甚至加入 js 脚本。

2.3 解构表达式:

  1. 数组解构:

    比如有一个数组:

    let arr = [1,2,3]
    

    如果想获取其中的值,只能通过角标。ES6 可以这样:

    const [x,y,z] = arr;// x,y,z将与arr中的每个位置对应来取值
    // 然后打印
    console.log(x,y,z);
    
  2. 对象解构:

    例如有个person对象:

    const person = {
        name:"jack",
        age:21,
        language: ['java','js','css']
    }
    

    如果想获取对象的值,可以这么做:

    // 解构表达式获取值
    const {name,age,language} = person;
    // 打印
    console.log(name);
    console.log(age);
    console.log(language);
    

    如过想要用其它变量接收,需要额外指定别名:

    //name是person中的属性名,冒号后面的n是解构后要赋值给的变量。
    const {name:n} = person;
    console.log(n);
    

2.4 函数优化:

  1. 函数参数默认值:

    在 ES6 以前,无法给一个函数参数设置默认值,只能采用变通写法:

    function add(a , b) {
        // 判断b是否为空,为空就给默认值1
        b = b || 1;
        return a + b;
    }
    // 传一个参数
    console.log(add(10));
    

    现在可以这么写:

    function add(a , b = 1) {
        return a + b;
    }
    // 传一个参数
    console.log(add(10));
    
  2. 箭头函数:

    ES6 中定义函数的简写方式:

    一个参数时:

    var print = function (obj) {
        console.log(obj);
    }
    // 简写为:
    var print = obj => console.log(obj);
    

    多个参数:

    // 两个参数的情况:
    var sum = function (a , b) {
        return a + b;
    }
    // 简写为:
    var sum = (a,b) => a+b;
    

    代码不止一行,可以用 {} 括起来:

    var sum = (a,b) => {
        return a + b;
    }
    
  3. 对象的函数属性简写:

    比如一个 Person 对象,里面有 eat 方法:

    let person = {
        name: "jack",
        // 以前:
        eat: function (food) {
            console.log(this.name + "在吃" + food);
        },
        
        // 箭头函数版:
        eat: food => console.log(person.name + "在吃" + food),// 这里拿不到this
        
        // 简写版:
        eat(food){
            console.log(this.name + "在吃" + food);
        }
    }
    
  4. 箭头函数结合解构表达式:

    比如有一个函数:

    const person = {
        name:"jack",
        age:21,
        language: ['java','js','css']
    }
    
    function hello(person) {
        console.log("hello," + person.name)
    }
    

    如果用箭头函数和解构表达式

    var hi = ({name}) =>  console.log("hello," + name);
    

2.5 map 和 reduce:

  1. map:

    map() :接收一个函数,将原数组中的所有元素用这个函数处理后放入新数组返回。

    举例:有一个字符串数组,我们希望转为 int 数组。

    let arr = ['1','20','-5','3'];
    console.log(arr)
    
    arr = arr.map(s => parseInt(s));
    console.log(arr)
    
  2. reduce:

    reduce() :接收一个函数(必须)和一个初始值(可选)。

    第一个参数(函数)接收两个参数:第一个参数是上一次 reduce 处理的结果;第二个参数是数组中要处理的下一个元素。

    reduce() 会从左到右依次把数组中的元素用 reduce 处理,并把处理的结果作为下次 reduce 的第一个参数。如果是第一次,会把前两个元素作为计算参数,或者把用户指定的初始值作为起始参数。

    举例:

    const arr = [1,20,-5,3]
    

    没有初始值:

    arr.reduce((a,b) => a+b)
    

    结果是 19。

    指定初始值:

    arr.reduce((a,b) => a+b,1)
    

    结果是 20。

2.6 对象扩展:

ES6 给 Object 拓展了许多新的方法,如:

  • keys(obj):获取对象的所有 key 形成的数组。
  • values(obj):获取对象的所有 value 形成的数组。
  • entries(obj):获取对象的所有 key 和 value 形成的二维数组。格式:[[k1,v1],[k2,v2],…]
  • assign(dest, …src) :将多个 src 对象的值 拷贝到 dest 中(浅拷贝)。

2.7 数组扩展:

ES6 给数组新增了许多方法:

  • find(callback):数组实例的 find 方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为 true 的成员,然后返回该成员。如果没有符合条件的成员,则返回 undefined。
  • findIndex(callback):数组实例的 findIndex 方法的用法与 find 方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。
  • includes(数组元素):与 find 类似,如果匹配到元素,则返回 true,代表找到了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值