Web 前端快速复习二

前言

​ 目的:简要的复习 web 前端知识,写完发现内容有点多

​ 主参考链接:https://www.w3school.com.cn/

1.JQuery

1.1.概述

  • 概念: 一个JavaScript框架。简化 JS 开发。
  • jQuery是一个快速、简洁的JavaScript框架,是继 Prototype 之后又一个优秀的 JavaScript 代码库(或JavaScript 框架)。jQuery 设计的宗旨 是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装 JavaScript 常用的功能代码,提供一种简便的 JavaScript 设计模式,优化 HTML 文档操作、事件处理、动画设计和 Ajax 交互。

  • JavaScript 框架:本质上就是一些 js 文件,封装了 js 的原生代码而已参考教程

1.2.快速入门

  • 下载 jQuery 库,把 jQuery 添加到您的网页

    <head>
    	<script src="jquery.js"></script>
    </head>
    
  • 基础使用

    var div1 = $("#div1");
    alert(div1.html());
    
  • JQuery 对象和 JS 对象区别与转换

    参考链接:

    JavaScript

    JavaScript 提供多个内建对象,比如 String、Date、Array 等等。

    • 对象只是带有属性和方法的特殊数据类型
    • 通过 js 获取的 DOM 对象就是 js 对象
    • 当浏览器支持 js 的 DOM 接口(api)时,这里狭义的 DOM 对象是以 js 对象的形式出现的,也就是一个 js 对象

    JQuery

    • JQuery 对象在操作时,更加方便。
    • JQuery 对象和 js 对象方法不通用的.
      • jQuery 对象不能使用 DOM 对象的方法和属性
      • DOM 对象不能使用 jQuery 对象的方法和属性
    • jQuery 对象其实是一个 JavaScrip 的数组。
    • jQuery 对象是通过 jQuery 包装的 DOM 对象后产生的。

    两者相互转换

    • jq -- > js : jq对象[索引] 或者 jq对象.get(索引)
    var doc2=$("#idDoc2")[0];
    var doc2=$("#idDoc2").get(0);
    
    • js -- > jq : $(js对象)

1.3.选择器

1.3.1.基本操作学习

  1. 事件绑定

    //1.获取b1按钮
     $("#b1").click(function(){
    	alert("abc");
    });
    
  2. 入口函数

     $(function () {		 });
    

window.onload$(function) 区别

  • window.onload 只能定义一次,如果定义多次,后边的会将前边的覆盖掉

  • $(function)可以定义多次的。

  • window.onload

    window.onload = function () {};    // JavaScript 
    $(document).ready(function () {}); // jQuery
    
  1. 样式控制:CSS

    // $("#div1").css("background-color","red");
    	$("#div1").css("backgroundColor","pink");
    

1.3.2.选择器分类

基本选择器

  1. 标签选择器(元素选择器)
    语法: $("html标签名") 获得所有匹配标签名称的元素
  2. id 选择器
    语法: $("#id的属性值") 获得与指定 id 属性值匹配的元素
  3. 类选择器
    语法: $(".class的属性值") 获得与指定的class属性值匹配的元素
  4. 并集选择器:
    语法: $("选择器1,选择器2....") 获取多个选择器选中的所有元素

层级选择器

  1. 后代选择器
    语法: $("A B ") 选择A元素内部的所有 B 元素(全部后代)
  2. 子选择器
    语法: $("A > B") 选择A元素内部的所有B子元素(一代)

属性选择器

  1. 属性名称选择器

    语法: $("A[属性名]") 包含指定属性的选择器

  2. 属性选择器

    语法: $("A[属性名='值']") 包含指定属性等于指定值的选择器

    如: 属性 title 值等于 test 的 div 元素背景色为 粉红色

 	   $("div[title='test']").css("backgroundColor","pink");
  1. 复合属性选择器

    • 语法: $("A[属性名='值'][]...") 包含多个属性条件的选择器
    • 如:选取有属性 id 的 div 元素,然后在结果中选取属性 title 值含有es的 div 元素背景色为粉红色
	$("div[id][title='es']").css("backgroundColor","pink"); 	   

过滤选择器

  1. 首元素选择器

    • 语法: :first 获得选择的元素中的第一个元素
    • 如: 改变第一个 div 元素的背景色为 粉红色
  $("div:first").css("backgroundColor","pink");
  1. 尾元素选择器

    语法::last 获得选择的元素中的最后一个元素

  2. 非元素选择器

    • 语法: :not(selector) 不包括指定内容的元素
    • 如: 改变class不为 one 的所有 div 元素的背景色为 粉红色
  $("div:not(.one)").css("backgroundColor","pink");
  1. 偶数选择器

    语法: :even 偶数,从 0 开始计数

  2. 奇数选择器
    语法: :odd 奇数,从 0 开始计数

  3. 等于索引选择器
    语法: :eq(index) 指定索引元素

  4. 大于索引选择器
    语法: :gt(index) 大于指定索引元素

  5. 小于索引选择器
    语法: :lt(index) 小于指定索引元素

  6. 标题选择器
    语法: :header 获得标题(h1~h6)元素,固定写法

表单过滤选择器

  1. 可用元素选择器

    语法: :enabled 获得可用元素

  2. 不可用元素选择器

    语法: :disabled 获得不可用元素

  3. 选中选择器

    • 语法: :checked 获得单选/复选框选中的元素

    • 如:利用 jQuery 对象的 length 属性获取复选框选中的个数

 alert($("input[type='checkbox']:checked").length);
  1. 选中选择器

    语法: :selected 获得下拉框选中的元素

1.4.DOM操作

1.4.1.内容操作

  1. html(): 获取/设置元素的标签体内容

    	<p id="test">这是段落中的<b>粗体</b>文本。</p>
    
    	//结果:这是段落中的粗体文本,试过了,"" 包裹jq对象会报错
        alert("Text: " + $("#test").text());
    
    	//结果:这是段落中的<b>粗体</b>文本
    	alert("HTML: " + $("#test").html());
    
  2. text(): 获取/设置元素的标签体纯文本内容

  3. val(): 获取/设置元素的 value 属性值

1.4.2.属性操作

通用属性操作

  1. attr(): 获取/设置元素的属性。可用函数来设置值。

  2. removeAttr():删除属性

  3. prop():获取/设置元素的属性

  4. removeProp():删除属性

  • attr和prop区别?
    • 如果操作的是元素的固有属性,则建议使用 prop
    • 如果操作的是元素自定义的属性,则建议使用 attr
   			//获取北京节点的name属性值
			var name = $("#bj").attr("name");
            //设置北京节点的name属性的值为dabeijing
            $("#bj").attr("name","dabeijing");
            //新增北京节点的discription属性 ,属性值是didu
            $("#bj").attr("discription","didu");
            //删除北京节点的name属性并检验name属性是否存在
            $("#bj").removeAttr("name");
            //获得hobby的的选中状态
			var checked = $("#hobby").prop("checked");
			alert(checked);

            //var checked = $("#hobby").attr("checked"); //获取不到,弹出undefined

对 class 属性操作( 操作 CSS)

  1. addClass():添加class属性值。需提前写好对应的 .class选择器,方可看到效果。

  2. removeClass():删除class属性值

  3. toggleClass():切换class属性
    toggleClass("one"): 判断如果元素对象上存在class="one",则将属性值one删除掉。 如果元素对象上不存在class="one"则添加

  4. css():设置或返回样式属性

1.4.3.CRUD操作

  1. append():父元素将子元素追加到末尾
    对象1.append(对象2): 将对象2添加到对象1元素内部,并且在末尾
  2. prepend():父元素将子元素追加到开头
    对象1.prepend(对象2):将对象2添加到对象1元素内部,并且在开头
  3. appendTo():
    对象1.appendTo(对象2):将对象1添加到对象2内部,并且在末尾
  4. prependTo()
    对象1.prependTo(对象2):将对象1添加到对象2内部,并且在开头
  5. after():添加元素到元素后边
    对象1.after(对象2): 将对象2添加到对象1后边。对象1和对象2是兄弟关系
  6. before():添加元素到元素前边
    对象1.before(对象2): 将对象2添加到对象1前边。对象1和对象2是兄弟关系
  7. insertAfter()
    对象1.insertAfter(对象2):将对象1添加到对象2后边。对象1和对象2是兄弟关系
  8. insertBefore()
    对象1.insertBefore(对象2): 将对象1添加到对象2前边。对象1和对象2是兄弟关系
 		<ul id="city">
		 	 <li id="bj" name="beijing">北京</li>
			 <li id="tj" name="tianjin">天津</li>
			 <li id="cq" name="chongqing">重庆</li>
		 </ul>
		 
		 
		  <ul id="love">
		 	 <li id="fk" name="fankong">反恐</li>
			 <li id="xj" name="xingji">星际</li>
		 </ul>
 			 // <input type="button" value="将反恐放置到city的后面"  id="b1"/>

			 $("#b1").click(function () {
				 //append
				 //$("#city").append($("#fk"));
				 //appendTo
                 $("#fk").appendTo($("#city"));
             });

             // <input type="button" value="将反恐插入到天津前面"  id="b4"/>
             $("#b4").click(function () {
                 //before
                 //$("#tj").before($("#fk"));
                 //insertBefore
                 $("#fk").insertBefore($("#tj"));

             });
  1. remove():移除元素

    对象.remove(): 删除被选元素及其子元素。

  2. empty():清空元素的所有后代元素。
    对象.empty(): 将对象的后代元素全部清空,但是保留当前对象以及其属性节点

1.5.动画

三种方式显示和隐藏元素

  1. 默认显示和隐藏方式
  • show([speed,[easing],[fn]])显示

    参数:

    1. speed:动画的速度。三个预定义的值(slow,normal, fast)或表示动画时长的毫秒数值(如:1000)

    2. easing:用来指定切换效果,默认是"swing",可用参数"linear"

      • swing:动画执行时效果是 先慢,中间快,最后又慢

      • linear:动画执行时速度是匀速的

    3. fn:在动画完成时执行的函数,每个元素执行一次。

  • hide([speed,[easing],[fn]])隐藏

  • toggle([speed],[easing],[fn])显示被隐藏的元素,并隐藏已显示的元素

  1. 滑动显示和隐藏方式
    • slideDown([speed],[easing],[fn])向下滑动
    • slideUp([speed,[easing],[fn]])向上滑动
    • slideToggle([speed],[easing],[fn])在 slideDown() 与 slideUp() 方法之间进行切换。
  2. 淡入淡出显示和隐藏方式
    • fadeIn([speed],[easing],[fn])淡入已隐藏的元素。
    • fadeOut([speed],[easing],[fn])淡出可见元素。
    • fadeToggle([speed,[easing],[fn]])在 fadeIn() 与 fadeOut() 方法之间进行切换。
		$("#showDiv").fadeOut("slow"); //淡出

		$("#showDiv").slideDown("slow","swing",function(){
		alert("显示了...")
		});	
		$("#showDiv").toggle("slow");

1.6.遍历

1.61. js 的遍历方式

  • for(初始化值;循环结束条件;步长)

1.62. jq 的遍历方式

1.jq对象.each(callback)

  • jquery对象.each(function(index,element){});
    • index : 就是元素在集合中的索引
    • element:就是集合中的每一个元素对象
  • this:集合中的每一个元素对象
 	       $(function () { 
               var citys = $("#city li");		
               citys.each(function (index,element) { 
                    //3.1 获取li对象 第一种方式 this
                    //alert(this.innerHTML);//js对象,效果相同
                    alert($(this).html());//jq对象,方法更多                
                    //3.2 获取li对象 第二种方式 在回调函数中定义参数
                	// index(索引) element(元素对象)
                    //alert(index+":"+element.innerHTML);//js对象
                    alert(index+":"+$(element).html());//jq对象 
                   
                   //判断如果是上海,则结束循环
                    if("上海" === $(element).html()){
                        //如果当前function返回为false,则结束循环(break)。
                        //如果返回为true,则结束本次循环,继续下次循环(continue)
                        return true;
                    }
                    alert(index+":"+$(element).html());
                });
               });
  • 回调函数返回值
    • 如果当前function返回为 false ,则结束循环 (break)
    • 如果当前function返回为 true,则结束本次循环,继续下次循环 (continue)

2.$.each(object, [callback])

$.each(citys,function () {
                        alert($(this).html());
                    });

3.for..of : jquery 3.0 版本之后提供的方式

  • for(元素对象 of 容器对象)
		 for(li of citys){
                    alert($(li).html());
                }

1.7.事件的绑定

  1. jquery 标准的绑定方式

    jq对象.事件方法(回调函数);

    注:如果调用事件方法,不传递回调函数,则会触发浏览器默认行为

表单对象.submit();  //让表单提交
对象.focus(); //获得焦点

$("#name").click(function () {
               alert("我被点击了...")
           });
  1. on 绑定事件/ off解除绑定
    • jq对象.on("事件名称",回调函数)
    • jq对象.off("事件名称")
    • 如果off方法不传递任何参数,则将组件上的所有事件全部解绑
//1.使用on给按钮绑定单击事件  click
  	           $("#btn").on("click",function () {
  	               alert("我被点击了。。。")
  	           }) ; 	
  1. 事件切换:toggle

    • jq对象.toggle(fn1,fn2...)

    • 当单击jq对象对应的组件后,会执行fn1.第二次点击会执行fn2

注意:1.9版本 .toggle() 方法删除, jQuery Migrate(迁移)插件可以恢复此功能。

<script src="../js/jquery-migrate-1.0.0.js" type="text/javascript" charset="utf-8"></script>
	$("#btn").toggle(function () {
               //改变div背景色backgroundColor 颜色为 green
               $("#myDiv").css("backgroundColor","green");
           },function () {
               //改变div背景色backgroundColor 颜色为 pink
               $("#myDiv").css("backgroundColor","pink");
           });

1.8.增强JQuery的功能

插件:增强JQuery的功能

  • 实现方式
  1. $.fn.extend(object)

    • 增强通过 JQuery 获取的对象的功能
    • 所有的 jq 对象都可以调用该方法;使用 $("#id")
      //1.定义jqeury的对象插件
            $.fn.extend({
                //定义了一个check()方法。所有的jq对象都可以调用该方法
                check:function () {
                   //让复选框选中
                    //this:调用该方法的jq对象
                    this.prop("checked",true);
                }
            });
    
            $(function () {
               // 获取按钮
                //$("#btn-check").check();
                //复选框对象.check();
                $("#btn-check").click(function () {
                    //获取复选框对象
                    $("input[type='checkbox']").check();
                });        
            });
    
  2. $.extend(object)

    • 增强 JQeury 对象自身的功能
    • 全局, 使用$ /jQuery
     //对全局方法扩展2个方法,扩展min方法:求2个值的最小值;扩展max方法:求2个值最大值
            
            $.extend({
                max:function (a,b) {
                    //返回两数中的较大值
                    return a >= b ? a:b;
                },
                min:function (a,b) {
                    //返回两数中的较小值
                    return a <= b ? a:b;
                }            
                
            });
    
            //调用全局方法
            var max = $.max(4,3);
            //alert(max);
            var min = $.min(1,2);
            alert(min);
    

1.9.杂项

1.9.1.表单验证

仅示意,详细请参考

编写表单

<form method="post" action="#">
        <div class="int">
            <label for="name">姓名:</label>
            <input type="text" id="name" class="required" />
        </div>
        <div class="int">
            <label for="address">住址:</label>
            <input type="text" id="address" />
        </div>
        <div class="int">
            <input type="submit" value="提交" id="send" style="margin-left: 70px;" />
            <input type="reset" value="重置" id="res" />
        </div>
    </form>    

编写触发函数

 //为表单的必填文本框添加提示信息(选择form中的所有后代input元素)
    $("form :input.required").each(function () {
        //通过jquery api:$("HTML字符串") 创建jquery对象
        var $required = $("<strong class='high'>*</strong>");
        //添加到this对象的父级对象下
        $(this).parent().append($required);
    });
   //为表单元素添加失去焦点事件
        $("form :input").blur(function(){
            var $parent = $(this).parent();
            //验证姓名
            if($(this).is("#name")){
                var nameVal = $.trim(this.value); //原生js去空格方式:this.replace(/(^\s*)|(\s*$)/g, "")
                var regName = /[~#^$@%&!*()<>:;'"{}【】  ]/;
                if(nameVal == "" || nameVal.length < 6 || regName.test(nameVal)){
                    var errorMsg = " 姓名非空,长度6位以上,不包含特殊字符!";
                    //class='msg onError' 中间的空格是层叠样式的格式
                    $parent.append("<span class='msg onError'>" + errorMsg + "</span>");
                }
                else{
                    var okMsg=" 输入正确";
                    $parent.find(".high").remove();
                    $parent.append("<span class='msg onSuccess'>" + okMsg + "</span>");
                }
            }

1.9.2.其它方法

.data

$.data() 向被选元素附加数据,或者从被选元素获取数据。参见

  • 这是一个底层方法,.data() 方法更方便使用。
  • 通过 data() 函数存取的数据都是临时数据,一旦页面刷新,之前存放的数据都将被移除。
//从元素返回数据
$(selector).data(name)
//向元素附加数据
$(selector).data(name,value)
//使用对象向元素附加数据
$(selector).data(object)

<script type="text/javascript">
    $(document).ready(function(){
      testObj=new Object();
      testObj.greetingMorn="Good Morning!";
      testObj.greetingEve="Good Evening!";
      $("#btn1").click(function(){
        $("div").data(testObj);
      });
      $("#btn2").click(function(){
        alert($("div").data("greetingEve"));
      });
    });
</script>
// JavaScript 是弱类型语言,.data() 获取到的值的类型会自动转化。
<div class="version" data-tag="1.0"></div>
var version_tag = $('.version').data('tag') // 该表达式获取的值为 1,而非 1.0
var version_tag = $('.version').attr('data-tag') // 该表达式获取的值为 1.0

serialize

serialize() 方法通过序列化表单值创建 URL 编码文本字符串。您可以选择一个或多个表单元素(如输入和/或文本区),或表单元素本身。序列化的值可在生成 AJAX 请求时用于 URL 查询字符串中。参见

$(document).ready(function(){
    $("button").click(function(){
        $("div").text($("form").serialize());
    });
});

bind

bind() 方法为被选元素添加一个或多个事件处理程序,并规定事件发生时运行的函数。

//定义一个 $(selector).bind(event,data,function)
//data 可选。规定传递到函数的额外数据。
$(document).ready(function(){
  $("button").bind("click",function(){
    $("p").slideToggle();
  });
});
//定义多个 $(selector).bind({event:function, event:function, ...})
$(document).ready(function(){
  $("button").bind({
    click:function(){$("p").slideToggle();},
    mouseover:function(){$("body").css("background-color","red");},  
    mouseout:function(){$("body").css("background-color","#FFFFFF");}  
  });
});

zTree 插件

核心:zTree(setting, [zTreeNodes]) 实现了 异步加载 树形结构数据的功能

这个函数接受一个 JSON 格式的数据对象 setting 和一个 JSON 格式的数据对象 zTreeNodes,从而建立 Tree。

2.AJAX

2.1.概述

  • 概念ASynchronous JavaScript And XML 异步的 JavaScriptXML

  • 异步和同步:客户端和服务器端相互通信的基础上

    • 同步:客户端必须等待服务器端的响应。在等待的期间客户端不能做其他操作。
    • 异步:客户端不需要等待服务器端的响应。在服务器处理请求的过程中,客户端可以进行其他的操作。
  • Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术

  • 通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

  • 传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面。提升用户的体验。

2.2.实现方式

2.2.1.原生 JS(了解)

XMLHttpRequest 是 AJAX 的基础。参见

			 //1.创建核心XMLHttpRequest对象
	            var xmlhttp;
	            if (window.XMLHttpRequest)
	            {//老版本的 code for IE7+, Firefox, Chrome, Opera, Safari
	                xmlhttp =new XMLHttpRequest();   
	            }
	            else
	            {// code for IE6, IE5
	                xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	            }
	
	            //2. 建立连接
	            /*
	                参数:
	                    1. 请求方式:GET、POST
	                        * get方式,请求参数在URL后边拼接。send方法为空参
	                        * post方式,请求参数在send方法中定义
	                    2. 请求的URL:
	                    3. 同步或异步请求:true(异步)或 false(同步)
	
	             */
	            xmlhttp.open("GET","ajaxServlet?username=tom",true);
	
	            //3.发送请求
	            xmlhttp.send();
	
	            //4.接受并处理来自服务器的响应结果
	            //获取方式 :xmlhttp.responseText
	            //什么时候获取?当服务器响应成功后再获取
	
	            //当xmlhttp对象的就绪状态改变时,触发事件onreadystatechange。
	            xmlhttp.onreadystatechange=function()
	            {
	                //判断readyState就绪状态是否为4,判断status响应状态码是否为200
	                if (xmlhttp.readyState==4 && xmlhttp.status==200)
	                {
	                   //获取服务器的响应结果
	                    var responseText = xmlhttp.responseText;
	                    alert(responseText);
	                }
	            }

2.2.2.JQuery方式

  1. $.ajax()

     	语法:`$.ajax({键值对});`
    

    async 默认是 true,即为异步方式, $.ajax执行后,会继续执行ajax后面的脚本,直到服务器端返回数据后,触发 $.ajax 里的success方法,这时候执行的是两个线程。

    若要将其设置为 false,则所有的请求均为同步请求,在没有返回值之前,同步请求将锁住浏览器,用户其它操作必须等待请求完成才可以执行。

    		//定义方法
    	        function  fun() {
    	            //使用$.ajax()发送异步请求
    	
    	            $.ajax({
                        //async: false,
    	                url:"ajaxServlet1111" , // 请求路径
    	                type:"POST" , //请求方式
    	                //data: "username=jack&age=23",//请求参数
    	                data:{"username":"jack","age":23},
    	                success:function (data) {
    	                    alert(data);
    	                },//响应成功后的回调函数
    	                error:function () {
    	                    alert("出错啦...")
    	                },//表示如果请求响应出现错误,会执行的回调函数
    	
    	                dataType:"text"//设置接受到的响应数据的格式
    	            });
    	        }
    
  2. $.get():发送 get 请求

    语法:$.get(url, [data], [callback], [type])

    参数:

    • url:请求路径
    • data:请求参数
    • callback:回调函数
    • type:响应结果的类型
      //定义方法
            function  fun() {
                $.get("ajaxServlet",{username:"rose"},function (data) {
                    alert(data);
                },"text");
    
            }
    
  3. $.post():发送 post 请求

    语法:$.post(url, [data], [callback], [type])

    参数:

    • url:请求路径
    • data:请求参数
    • callback:回调函数
    • type:响应结果的类型
           //定义方法
            function  fun() {
    
                $.post("ajaxServlet",{username:"rose"},function (data) {
                    alert(data);
                },"text");
            }
    

2.3.跨域问题

跨域问题来源于 JavaScript的同源策略,即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问。跨域问题是浏览器对于ajax请求的一种安全限制:一个页面发起的ajax请求,只能是与当前页域名相同的路径,这能有效的阻止跨站攻击。

​ 跨域问题是针对 JS 和 ajax 的,html 本身没有跨域问题,比如 a 标签、script 标签、甚至 form 标签(可以直接跨域发送数据并接收数据)等 。推荐阅读,蛮详细的

如何解决 ajax 跨域?

JSONP方式解决跨域问题

​ jsonp 解决跨域问题是一个比较古老的方案(实际中不推荐使用),这里做简单介绍(实际项目中如果要使用JSONP,一般会使用JQ等对JSONP进行了封装的类库来进行ajax请求)

原理:

  • JSONP之所以能够用来解决跨域方案,主要是因为 <script>脚本拥有跨域能力,而 JSONP 正是利用这一点来实现。

注意:

  • 基于 JSONP 的实现原理,所以 JSONP 只能是“GET”请求,不能进行较为复杂的 POST 和其它请求,所以遇到那种情况,就得参考下面的 CORS 解决跨域了(所以如今它也基本被淘汰了)

具体实现省略,参见

CORS 解决跨域问题

服务端进行控制是否允许跨域,可自定义规则支持各种请求方式,缺点是会产生额外的请求

什么是cors ?

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

  • 浏览器端:

    目前,所有浏览器都支持该功能(IE10以下不行)。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。

  • 服务端:

    CORS通信与AJAX没有任何差别,因此你不需要改变以前的业务逻辑。只不过,浏览器会在请求中携带一些头信息,我们需要以此判断是否允许其跨域,然后在响应头中加入一些信息即可。这一般通过过滤器完成即可。

原理有点复杂,搬教程

浏览器会将 ajax 请求分为两类,其处理方案略有差异:简单请求、特殊请求。

简单请求:

只要同时满足以下两大条件,就属于简单请求。

  • 求方法是以下三种方法之一(HEAD、GET、POST)

  • HTTP的头信息不超出以下几种字段:

    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

    当浏览器发现发起的 aja 请求是简单请求时,会在请求头中携带一个字段:Origin.它会指出当前请求属于哪个域(协议+域名+端口)。服务会根据这个值决定是否允许其跨域。

    如果服务器允许跨域,需要在返回的响应头中携带下面信息:

Access-Control-Allow-Origin: http://manage.leyou.com
Access-Control-Allow-Credentials: true
Content-Type: text/html; charset=utf-8
  • Access-Control-Allow-Origin:可接受的域,是一个具体域名或者*(代表任意域名)
  • Access-Control-Allow-Credentials:是否允许携带cookie,默认情况下,cors不会携带cookie,除非这个值是true

要想操作cookie,需要满足3个条件:

  • 服务的响应头中需要携带Access-Control-Allow-Credentials并且为true。
  • 浏览器发起ajax需要指定withCredentials 为true
  • 响应头中的Access-Control-Allow-Origin一定不能为*,必须是指定的域名

特殊请求:

不符合简单请求的条件,会被浏览器判定为特殊请求,,例如请求方式为 PUT。

预检请求

特殊请求会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

OPTIONS /cors HTTP/1.1
Origin: http://manage.leyou.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.leyou.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

上述为一个“预检”请求的样板,与简单请求相比,除了Origin以外,多了两个头:

  • Access-Control-Request-Method:接下来会用到的请求方式,比如 PUT
  • Access-Control-Request-Headers:会额外用到的头信息

预检请求的响应

服务的收到预检请求,如果许可跨域,会发出响应:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://manage.leyou.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Max-Age: 1728000
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

除了Access-Control-Allow-OriginAccess-Control-Allow-Credentials以外,这里又额外多出3个头:

  • Access-Control-Allow-Methods:允许访问的方式
  • Access-Control-Allow-Headers:允许携带的头
  • Access-Control-Max-Age:本次许可的有效时长,单位是秒,过期之前的ajax请求就无需再次进行预检了

如果浏览器得到上述响应,则认定为可以跨域,后续就跟简单请求的处理是一样的了。

实现

废话讲了一堆,实现非常简单

编写一个配置类

@Configuration
public class LeyouCorsConfiguration {
    @Bean
    public CorsFilter corsFilter(){
        //1.添加CORS配置信息
        CorsConfiguration config =new CorsConfiguration();
        //允许的域,不要写*否则cookie就无法使用了
        config.addAllowedOrigin("http://manage.leyou.com");
        config.addAllowedOrigin("http://www.leyou.com");//搜索跨域问题
        //是否发送Cookie信息
        config.setAllowCredentials(true);
        //允许的请求方式
//        config.addAllowedMethod("OPTION");
//        config.addAllowedMethod("HEAD");
//        config.addAllowedMethod("GET");
//        config.addAllowedMethod("PUT");
//        config.addAllowedMethod("POST");
//        config.addAllowedMethod("DELETE");
//        config.addAllowedMethod("PATCH");
        config.addAllowedMethod("*");
        //允许的头信息
        config.addAllowedHeader("*");
        //2.cors配置源对象。添加映射路径。拦截一切请求
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**",config);
        //3.返回新的corsFilter
        return new CorsFilter(configSource);
    }
}

nginx反向代理

  • 思路是:利用 nginx 把跨域反向代理为不跨域,支持各种请求方式
  • 缺点:需要在nginx进行额外配置,语义不清晰

代理请求方式

注意,由于接口代理是有代价的,所以这个仅是开发过程中进行的。

与前面的方法不同,前面 CORS 是后端解决,而这个主要是前端对接口进行代理,也就是:

3.JSON

3.1.概述

  • 概念: JavaScript Object Notation JavaScript 对象表示法
  • var p = {"name":"张三","age":23,"gender":"男"};
    • json 现在多用于存储和交换文本信息的语法
    • 进行数据的传输
    • JSON 比 XML 更小、更快,更易解析。

3.2.基本语法

3.2.1.基本规则

  • 数据在名称/值对中:json 数据是由键值对构成的

  • 键用引号(单双都行)引起来,也可以不使用引号

  • 值的取值类型

    1. 数字(整数或浮点数)
    2. 字符串(在双引号中)
    3. 逻辑值(true 或 false)
    4. 数组(在方括号中) {"persons":[{},{}]}
    5. 对象(在花括号中) {"address":{"province":"陕西"....}}
    6. null
  • 数据由逗号分隔:多个键值对由 , 分隔

  • 花括号保存对象:使用{}定义 json 格式

  • 方括号保存数组:[]

3.2.2.获取数据

  1. json对象.键名

  2. json对象["键名"] 变量时使用

  3. 数组对象[索引]

  4. 遍历:

    需注意遍历时 对象的选择。

     		//1.定义基本格式
            var person = {"name": "张三", age: 23, 'gender': true};
    
            var ps = [{"name": "张三", "age": 23, "gender": true},
                {"name": "李四", "age": 24, "gender": true},
                {"name": "王五", "age": 25, "gender": false}];
    
    
    
            //获取person对象中所有的键和值
            //for in 循环
           for(var key in person){
                //这样的方式获取不行。因为相当于  person."name"
                //alert(key + ":" + person.key);
               //person.key无法取到值,显示undefined
                alert(key+":"+person[key]);
            }
    
           //获取ps中的所有值
            for (var i = 0; i < ps.length; i++) {
                var p = ps[i];
                for(var key in p){
                    alert(key+":"+p[key]);
                }
            }
    

3.2.3.相互转化

  1. JSON 转为 Java 对象
  • 导入 jackson 的相关jar包

  • 创建 Jackson 核心对象 ObjectMapper

  • 调用 ObjectMapper 的相关方法进行转换

    • readValue(json字符串数据,Class)
    public void test5() throws Exception {
           //1.初始化JSON字符串
            String json = "{\"gender\":\"男\",\"name\":\"张三\",\"age\":23}";
    
            //2.创建ObjectMapper对象
            ObjectMapper mapper = new ObjectMapper();
            //3.转换为Java对象 Person对象
            Person person = mapper.readValue(json, Person.class);
    
            System.out.println(person);
        }
    
  1. Java 对象转换 JSON

    • 调用ObjectMapper的相关方法进行转换

    • 转换方法

      • writeValue(参数1,obj):

        ​ 参数1:

        ​ File:将 obj 对象转换为 JSON 字符串,并保存到指定的文件中

        ​ Writer:将 obj 对象转换为 JSON 字符串,并将json数据填充到字符输出流中

        ​ OutputStream:将 obj 对象转换为JSON字符串,并将json数据填充到字节输出流中

      • writeValueAsString(obj): 将对象转为 json 字符串

    • 注解

      1. @JsonIgnore排除属性。
      2. @JsonFormat:属性值得格式化
        • @JsonFormat(pattern = "yyyy-MM-dd")
    • 复杂java对象转换

      1. List:数组,方式相同
      2. Map:方式相同
      	 public void test4() throws Exception {
              //1.创建map对象
              Map<String,Object> map = new HashMap<String,Object>();
              map.put("name","张三");
              map.put("age",23);
              map.put("gender","男");
      
              //2.转换
              ObjectMapper mapper = new ObjectMapper();
              String json = mapper.writeValueAsString(map);
              //{"name":"张三","age":23,"gender":"男"}
              System.out.println(json);//{"gender":"男","name":"张三","age":23}
          }
      

4.ES5、6新特性

我们这里只把一些常用的进行学习,更详细的大家参考:阮一峰的ES6教程

4.1. let与const

  • var : var有一个问题,就是定义的变量有时会莫名奇妙的成为全局变量
  • let : 声明一个变量,不会越界,只在let命令所在的代码块内有效。
  • const:声明一个常量,不能被修改。

4.2.字符串拓展

新的API

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

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

字符串模板

ES6中提供了 ` 来作为字符串模板标记。我们可以这么玩:

字符串模板

  • 在两个 ` 之间的部分都会被作为字符串的值,不管你任意换行,甚至加入 js 脚本

4.3.解构表达式

  • 数组:let [x,y,z]=arr
    • 可以用来给每个变量赋值
const [x,y,z] = arr;// x,y,z将与arr中的每个位置对应来取值
// 然后打印
console.log(x,y,z);
//可以赋默认值
let [x = 1, y = x] = [];     // x=1; y=1
let [x = 1, y = x] = [2];    // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = [];     // ReferenceError: y is not defined
  • 对象: let {name:a, age:b}=person

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

    别名

    • {name:n}:name 是 person 中的属性名,冒号后面的 n 是解构后要赋值给的变量。

4.4.箭头函数

  • 赋默认值:方法参数列表赋默认值 (a, b=1)=>{}

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

    var sum3 = (a,b) => {
        return a + b;
    }
    
  • 对象中定义函数:

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

    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);
    

4.5.map和reduce

  • map(fun):处理一个数组,遍历数组中的每一个元素用 fun 处理,把处理结果放入新的数组。
let arr = ['1','20','-5','3'];
console.log(arr)

arr = arr.map(s => parseInt(s));
console.log(arr)
  • reduce(fun(a, b)[, 100]):接收一个函数(必须)和一个初始值(可选)。

    第一个参数(函数)接收两个参数:

    • 第一个参数是上一次reduce处理的结果
    • 第二个参数是数组中要处理的下一个元素

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

    reduce示例

4.6.对象的扩展

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

  • keys(obj):获取对象的所有 key 形成的数组

  • values(obj):获取对象的所有 value 形成的数组

  • entries(obj):获取对象的所有 key 和 value 形成的二维数组。格式:[[k1,v1],[k2,v2],...]

  • assign(dest, ...src) :将多个 src 对象的值 拷贝到 dest中(浅拷贝)。

    对象拓展

4.7.数组扩展

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

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

仅示意,不完整代码

 		if (k === '品牌'){
			//返回品牌名称,一个分类id,
            //filters: [],  //过滤参数集合
      	return this.filters.find(f =>f.k === '品牌').options[0].name;}

 //过滤掉已选择的key值,filter返回符合条件的数组,includes匹配返回true,结果为返回不包含的key值数组
        return this.filters.filter(f => !keys.includes(f.k) && f.options.length > 1);

5. Thymeleaf

5.1.概述

  • 官方网站:https://www.thymeleaf.org/index.html

  • Thymeleaf 是用来开发 Web 和独立环境项目的现代服务器端 Java 模板引擎。

  • Spring 官方支持的服务的渲染模板中,并不包含 jsp 。而是 ThymeleafFreemarker 等,而 ThymeleafSpringMVC 的视图技术,及 SpringBoot 的自动化配置集成非常完美,几乎没有任何成本,你只用关注 Thymeleaf 的语法即可。

特点

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

5.2.快速使用

  1. maven导入
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
  1. 默认配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cOICQ614-1585752010419)(https://s1.ax1x.com/2020/03/12/8VfADf.png)]

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

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

  • Thymeleaf 默认会开启页面缓存,提高页面并发能力。但会导致我们修改页面不会立即被展现,因此我们关闭缓存:
# 关闭Thymeleaf的缓存
spring.thymeleaf.cache=false
  • 另外,修改完毕页面,需要使用快捷键:Ctrl + Shift + F9来刷新工程。
  1. 编写 Controller
@Controller
public class HelloController {

    @GetMapping("show1")
    public String show1(Model model){
        model.addAttribute("msg", "Hello, Thymeleaf!");
        return "hello";
    }
}
  1. 编写html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
	<head>
    	<meta charset="UTF-8">
    	<title>hello</title>
	</head>
	<body>
   	 	<h1 th:text="${msg}">大家好</h1>
	</body>
</html>

注意,把 html 的名称空间,改成:xmlns:th="http://www.thymeleaf.org" ,会有语法提示

5.3.基本语法

5.3.1.变量

示例:

​ 我们在页面获取user数据:

<h1>
    欢迎您:<span th:text="${user.name}">请登录</span>
</h1>

语法说明:

  • Thymeleaf 通过${}来获取 model 中的变量,注意这不是 el 表达式,而是 ognl 表达式,但是语法非常像。

  • 感觉跟el表达式几乎是一样的。不过区别在于,我们的表达式写在一个名为:th:text的标签属性中,这个叫做指令

动静结合

[8VIZyn.png

指令:

  • Thymeleaf崇尚自然模板,意思就是模板是纯正的 html 代码,脱离模板引擎,在纯静态环境也可以直接运行。现在如果我们直接在 html 中编写 ${} 这样的表达式,显然在静态环境下就会出错,这不符合 Thymeleaf 的理念。

  • Thymeleaf中所有的表达式都需要写在指令中,指令是HTML5中的自定义属性,在 Thymeleaf 中所有指令都是以th:开头。因为表达式${user.name}是写在自定义属性中,因此在静态环境下,表达式的内容会被当做是普通字符串,浏览器会自动忽略这些指令,这样就不会报错了!

说明

  • 静态页面中,th指令不被识别,但是浏览器也不会报错,把它当做一个普通属性处理。这样span的默认值请登录就会展现在页面
  • 如果是在 Thymeleaf 环境下,th指令就会被识别和解析,而th:text的含义就是替换所在标签中的文本内容,于是user.name的值就替代了 span中默认的请登录

向下兼容

  • 但是要注意,如果浏览器不支持Html5怎么办?
  • 如果不支持这种 th: 的命名空间写法,那么可以把th:text换成 data-th-text,Thymeleaf 也可以兼容。

th:utext

  • 另外,th:text指令出于安全考虑,会把表达式读取到的值进行处理,防止html的注入。

  • 例如,<p>你好</p> 将会被格式化输出为$lt;p$gt;你好$lt;/p$lt;

如果想要不进行格式化输出,而是要输出原始内容,则使用th:utext来代替.

ognl 表达式的语法糖

  • 刚才获取变量值,我们使用的是经典的对象.属性名方式。但有些情况下,我们的属性名可能本身也是变量,怎么办?

  • ognl 提供了类似 js 的语法方式:

    • 例如:${user.name} 可以写作 ${user['name']}

5.3.2.自定义变量

场景

看下面的案例:

<h2>
    <p>Name: <span th:text="${user.name}">Jack</span>.</p>
    <p>Age: <span th:text="${user.age}">21</span>.</p>
    <p>friend: <span th:text="${user.friend.name}">Rose</span>.</p>
</h2>

我们获取用户的所有信息,分别展示。

当数据量比较多的时候,频繁的写user.就会非常麻烦。

因此,Thymeleaf提供了自定义变量来解决:

示例:

<h2 th:object="${user}">
    <p>Name: <span th:text="*{name}">Jack</span>.</p>
    <p>Age: <span th:text="*{age}">21</span>.</p>
    <p>friend: <span th:text="*{friend.name}">Rose</span>.</p>
</h2>
  • 首先在 h2上 用 th:object="${user}"获取user的值,并且保存
  • 然后,在h2内部的任意元素上,可以通过 *{属性名}的方式,来获取user中的属性,这样就省去了大量的user.前缀了

总结

更多的语法参考

语法 名称 描述 作用
${…} Variable Expressions 变量表达式 取出上下文变量的值
*{…} Selection Variable Expressions 选择变量表达式 取出选择的对象的属性值
#{…} Message Expressions 消息表达式 使文字消息国际化,I18N
@{…} Link URL Expressions 链接表达式 用于表示各种超链接地址
~{…} Fragment Expressions 片段表达式 引用一段公共的代码片段

5.3.3.方法

ognl 表达式中的方法调用

ognl 表达式本身就支持方法调用,例如:

<h2 th:object="${user}">
    <p>FirstName: <span th:text="*{name.split(' ')[0]}">Jack</span>.</p>
    <p>LastName: <span th:text="*{name.split(' ')[1]}">Li</span>.</p>
</h2>
  • 这里我们调用了 name(是一个字符串)的 split 方法。

Thymeleaf 内置对象

Thymeleaf 中提供了一些内置对象,并且在这些对象中提供了一些方法,方便我们来调用。获取这些对象,需要使用#对象名来引用。

  • 一些环境相关对象
对象 作用
#ctx 获取 Thymeleaf 自己的 Context 对象
#requset 如果是 web 程序,可以获取 HttpServletRequest 对象
#response 如果是 web 程序,可以获取 HttpServletReponse 对象
#session 如果是 web 程序,可以获取 HttpSession 对象
#servletContext 如果是 web 程序,可以获取 HttpServletContext 对象
  • Thymeleaf 提供的全局对象:
对象 作用
#dates 处理 java.util.date 的工具对象
#calendars 处理 java.util.calendar 的工具对象
#numbers 用来对数字格式化的方法
#strings 用来处理字符串的方法
#bools 用来判断布尔值的方法
#arrays 用来护理数组的方法
#lists 用来处理 List 集合的方法
#sets 用来处理 set 集合的方法
#maps 用来处理 map 集合的方法
  • 举例

我们在环境变量中添加日期类型对象

@GetMapping("show3")
public String show3(Model model){
    model.addAttribute("today", new Date());
    return "show3";
}

在页面中处理

<p>
  今天是: <span th:text="${#dates.format(today,'yyyy-MM-dd')}">2020-04-25</span>
</p>

5.3.4.字面值

有的时候,我们需要在指令中填写基本类型如:字符串、数值、布尔等,并不希望被 Thymeleaf 解析为变量,这个时候称为字面值。

  • 字符串字面值

    使用一对'引用的内容就是字符串字面值了:

    <p>
      你正在观看 <span th:text="'thymeleaf'">template</span> 的字符串常量值.
    </p>
    
    • th:text中的thymeleaf并不会被认为是变量,而是一个字符串
  • 数字字面值

    数字不需要任何特殊语法, 写的什么就是什么,而且可以直接进行算术运算

<p>今年是 <span th:text="2018">1900</span>.</p>
<p>两年后将会是 <span th:text="2018 + 2">1902</span>.</p>
  • 布尔字面值
    • 布尔类型的字面值是 true 或 false
    • 这里引用了一个th:if指令,跟vue中的v-if类似
<div th:if="true">
    你填的是true
</div>

5.3.5.拼接

我们经常会用到普通字符串与表达式拼接的情况:

<span th:text="'欢迎您:' + ${user.name} + '!'"></span>

字符串字面值需要用'',拼接起来非常麻烦,Thymeleaf对此进行了简化,使用一对|即可

<span th:text="|欢迎您:${user.name}|"></span>

与上面是完全等效的,这样就省去了字符串字面值的书写。

5.3.6.运算

需要注意:${}内部的是通过 OGNL 表达式引擎解析的,外部的才是通过 Thymeleaf 的引擎解析,因此运算符尽量放在${}外进行。

  • 算术运算

    支持的算术运算符:+ - * / %

    <span th:text="${user.age}"></span>
    <span th:text="${user.age}%2 == 0"></span>
    
  • 比较运算

    支持的比较运算:>, <, >= and <= ,但是>, <不能直接使用,因为 xml 会解析为标签,要使用别名。

    注意 == and !=不仅可以比较数值,类似于 equals 的功能。

    可以使用的别名:gt (>), lt (<), ge (>=), le (<=), not (!). Also eq (==), neq/ne (!=).

  • 条件运算

    • 三元运算
    <span th:text="${user.sex} ? '':''"></span>
    

    ​ 三元运算符的三个部分:conditon ? then : else

    condition:条件

    then:条件成立的结果

    else:不成立的结果

    其中的每一个部分都可以是 Thymeleaf 中的任意表达式。

    • 默认值

    有的时候,我们取一个值可能为空,这个时候需要做非空判断,可以使用 表达式 ?: 默认值 简写:

<span th:text="${user.name} ?: '二狗'"></span>
  • 注意:?: 之间没有空格。当前面的表达式值为 null 时,就会使用后面的默认值。

5.3.7.循环

循环也是非常频繁使用的需求,我们使用th:each指令来完成:

假如有用户的集合:users 在 Context 中。

<tr th:each="user : ${users}"> 
    <td th:text="${user.name}">Onions</td>
    <td th:text="${user.age}">2.41</td>
</tr>
  • ${users} 是要遍历的集合,可以是以下类型:
    • Iterable,实现了Iterable接口的类
    • Enumeration,枚举
    • Interator,迭代器
    • Map,遍历得到的是Map.Entry
    • Array,数组及其它一切符合数组结果的对象

在迭代的同时,我们也可以获取迭代的状态对象:

<tr th:each="user,stat : ${users}">
    <td th:text="${user.name}">Onions</td>
    <td th:text="${user.age}">2.41</td>
</tr>

状态对象(stat)包含以下属性:

  • index,从0开始的角标
  • count,元素的个数,从1开始
  • size,总元素个数
  • current,当前遍历到的元素
  • even / odd,返回是否为奇偶,boolean值
  • first / last,返回是否为第一或最后,boolean值

5.3.8.逻辑判断

有了if和else,我们能实现一切功能_

Thymeleaf 中使用th:if 或者 th:unless ,两者的意思恰好相反。

<span th:if="${user.age} < 24">小鲜肉</span>

如果表达式的值为 true,则标签会渲染到页面,否则不进行渲染。

以下情况被认定为 true:

  • 表达式值为 true
  • 表达式值为非0数值
  • 表达式值为非0字符
  • 表达式值为字符串,但不是"false","no","off"
  • 表达式不是布尔、字符串、数字、字符中的任何一种

其它情况包括 null 都被认定为false

5.3.9.分支判断

这里要使用两个指令:th:switchth:case

<div th:switch="${user.role}">
  <p th:case="'admin'">用户是管理员</p>
  <p th:case="'manager'">用户是经理</p>
  <p th:case="*">用户是别的玩意</p>
</div>

需要注意的是,一旦有一个th:case 成立,其它的则不再判断。与 java 中的 switch 是一样的。

另外 th:case="*" 表示默认,放最后。

5.3.10. JS模板

模板引擎不仅可以渲染 html,也可以对 JS 中的进行预处理。而且为了在纯静态环境下可以运行,其 Thymeleaf 代码可以被注释起来:

<script th:inline="javascript">
    const user = /*[[${user}]]*/ {};
    const age = /*[[${user.age}]]*/ 20;
    console.log(user);
    console.log(age)
</script>
  • 在script标签中通过th:inline="javascript"来声明这是要特殊处理的 js 脚本

  • 语法结构:

    const user = /*[[Thymeleaf表达式]]*/ "静态环境下的默认值";
    

因为Thymeleaf被注释起来,因此即便是静态环境下, js代码也不会报错,而是采用表达式后面跟着的默认值。

即若后台有传输数据过来,则直接赋值给user对象,若没有,则赋值后面的默认值。

最后

写给自己的,注释的问题:

<body>
  <div class="cu">
	<!-- 注意大小写,注意不能使用//注释-->
	<em><span></span>{{goods.subTitle.length > 17 ? goods.subTitle.substring(0,17) :
                                        goods.subTitle}}</em>
    </div>

<script type="text/javascript">
 var vm = new Vue({
            el: "#searchApp",
            data: {
                ly,//引用,好在html模板中使用其函数,js不用引入也可使用
            }//省略 n 代码
     });
</script>
</body>
发布了17 篇原创文章 · 获赞 6 · 访问量 636

猜你喜欢

转载自blog.csdn.net/black210/article/details/105257904