文章目录
前言
目的:简要的复习 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.获取b1按钮 $("#b1").click(function(){ alert("abc"); });
-
入口函数
$(function () { });
window.onload
和$(function)
区别
-
window.onload
只能定义一次,如果定义多次,后边的会将前边的覆盖掉 -
$(function)
可以定义多次的。 -
window.onload = function () {}; // JavaScript $(document).ready(function () {}); // jQuery
-
样式控制:CSS
// $("#div1").css("background-color","red"); $("#div1").css("backgroundColor","pink");
1.3.2.选择器分类
基本选择器
- 标签选择器(元素选择器)
语法:$("html标签名")
获得所有匹配标签名称的元素 - id 选择器
语法:$("#id的属性值")
获得与指定 id 属性值匹配的元素 - 类选择器
语法:$(".class的属性值")
获得与指定的class属性值匹配的元素 - 并集选择器:
语法:$("选择器1,选择器2....")
获取多个选择器选中的所有元素
层级选择器
- 后代选择器
语法:$("A B ")
选择A元素内部的所有 B 元素(全部后代) - 子选择器
语法:$("A > B")
选择A元素内部的所有B子元素(一代)
属性选择器
-
属性名称选择器
语法:
$("A[属性名]")
包含指定属性的选择器 -
属性选择器
语法:
$("A[属性名='值']")
包含指定属性等于指定值的选择器如: 属性 title 值等于 test 的 div 元素背景色为 粉红色
$("div[title='test']").css("backgroundColor","pink");
-
复合属性选择器
- 语法:
$("A[属性名='值'][]...")
包含多个属性条件的选择器 - 如:选取有属性 id 的 div 元素,然后在结果中选取属性 title 值含有
es
的 div 元素背景色为粉红色
- 语法:
$("div[id][title='es']").css("backgroundColor","pink");
过滤选择器
-
首元素选择器
- 语法:
:firs
t 获得选择的元素中的第一个元素 - 如: 改变第一个 div 元素的背景色为 粉红色
- 语法:
$("div:first").css("backgroundColor","pink");
-
尾元素选择器
语法:
:last
获得选择的元素中的最后一个元素 -
非元素选择器
- 语法:
:not(selector)
不包括指定内容的元素 - 如: 改变class不为 one 的所有 div 元素的背景色为 粉红色
- 语法:
$("div:not(.one)").css("backgroundColor","pink");
-
偶数选择器
语法:
:even
偶数,从 0 开始计数 -
奇数选择器
语法::odd
奇数,从 0 开始计数 -
等于索引选择器
语法::eq(index)
指定索引元素 -
大于索引选择器
语法::gt(index)
大于指定索引元素 -
小于索引选择器
语法::lt(index)
小于指定索引元素 -
标题选择器
语法::header
获得标题(h1~h6)元素,固定写法
表单过滤选择器
-
可用元素选择器
语法:
:enabled
获得可用元素 -
不可用元素选择器
语法:
:disabled
获得不可用元素 -
选中选择器
-
语法:
:checked
获得单选/复选框选中的元素 -
如:利用 jQuery 对象的 length 属性获取复选框选中的个数
-
alert($("input[type='checkbox']:checked").length);
-
选中选择器
语法:
:selected
获得下拉框选中的元素
1.4.DOM操作
1.4.1.内容操作
-
html()
: 获取/设置元素的标签体内容<p id="test">这是段落中的<b>粗体</b>文本。</p>
//结果:这是段落中的粗体文本,试过了,"" 包裹jq对象会报错 alert("Text: " + $("#test").text()); //结果:这是段落中的<b>粗体</b>文本 alert("HTML: " + $("#test").html());
-
text()
: 获取/设置元素的标签体纯文本内容 -
val()
: 获取/设置元素的 value 属性值
1.4.2.属性操作
通用属性操作
-
attr()
: 获取/设置元素的属性。可用函数来设置值。 -
removeAttr()
:删除属性 -
prop()
:获取/设置元素的属性 -
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)
-
addClass()
:添加class属性值。需提前写好对应的.class
选择器,方可看到效果。 -
removeClass()
:删除class属性值 -
toggleClass()
:切换class属性
toggleClass("one")
: 判断如果元素对象上存在class="one"
,则将属性值one删除掉。 如果元素对象上不存在class="one"
,则添加 -
css()
:设置或返回样式属性
1.4.3.CRUD操作
append()
:父元素将子元素追加到末尾
对象1.append(对象2)
: 将对象2添加到对象1元素内部,并且在末尾prepend()
:父元素将子元素追加到开头
对象1.prepend(对象2)
:将对象2添加到对象1元素内部,并且在开头appendTo()
:
对象1.appendTo(对象2)
:将对象1添加到对象2内部,并且在末尾prependTo()
:
对象1.prependTo(对象2)
:将对象1添加到对象2内部,并且在开头after()
:添加元素到元素后边
对象1.after(对象2)
: 将对象2添加到对象1后边。对象1和对象2是兄弟关系before()
:添加元素到元素前边
对象1.before(对象2)
: 将对象2添加到对象1前边。对象1和对象2是兄弟关系insertAfter()
对象1.insertAfter(对象2)
:将对象1添加到对象2后边。对象1和对象2是兄弟关系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"));
});
-
remove()
:移除元素对象.remove()
: 删除被选元素及其子元素。 -
empty()
:清空元素的所有后代元素。
对象.empty()
: 将对象的后代元素全部清空,但是保留当前对象以及其属性节点
1.5.动画
三种方式显示和隐藏元素
- 默认显示和隐藏方式
-
show([speed,[easing],[fn]])
:显示参数:
-
speed
:动画的速度。三个预定义的值(slow
,normal
,fast
)或表示动画时长的毫秒数值(如:1000) -
easing
:用来指定切换效果,默认是"swing",可用参数"linear"-
swing
:动画执行时效果是 先慢,中间快,最后又慢 -
linear
:动画执行时速度是匀速的
-
-
fn
:在动画完成时执行的函数,每个元素执行一次。
-
-
hide([speed,[easing],[fn]])
: 隐藏 -
toggle([speed],[easing],[fn])
:显示被隐藏的元素,并隐藏已显示的元素
- 滑动显示和隐藏方式
slideDown([speed],[easing],[fn])
:向下滑动slideUp([speed,[easing],[fn]])
:向上滑动slideToggle([speed],[easing],[fn])
:在 slideDown() 与 slideUp() 方法之间进行切换。
- 淡入淡出显示和隐藏方式
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.事件的绑定
-
jquery 标准的绑定方式
jq对象.事件方法(回调函数);
注:如果调用事件方法,不传递回调函数,则会触发浏览器默认行为。
表单对象.submit(); //让表单提交
对象.focus(); //获得焦点
$("#name").click(function () {
alert("我被点击了...")
});
- on 绑定事件/ off解除绑定
jq对象.on("事件名称",回调函数)
jq对象.off("事件名称")
- 如果off方法不传递任何参数,则将组件上的所有事件全部解绑
//1.使用on给按钮绑定单击事件 click
$("#btn").on("click",function () {
alert("我被点击了。。。")
}) ;
-
事件切换: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的功能
- 实现方式:
-
$.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(); }); });
-
$.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
异步的JavaScript
和XML
-
异步和同步:客户端和服务器端相互通信的基础上
- 同步:客户端必须等待服务器端的响应。在等待的期间客户端不能做其他操作。
- 异步:客户端不需要等待服务器端的响应。在服务器处理请求的过程中,客户端可以进行其他的操作。
-
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方式
-
$.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"//设置接受到的响应数据的格式 }); }
-
$.get()
:发送 get 请求语法:
$.get(url, [data], [callback], [type])
参数:
- url:请求路径
- data:请求参数
- callback:回调函数
- type:响应结果的类型
//定义方法 function fun() { $.get("ajaxServlet",{username:"rose"},function (data) { alert(data); },"text"); }
-
$.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-urlencoded
、multipart/form-data
、text/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-Origin
和Access-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 是后端解决,而这个主要是前端对接口进行代理,也就是:
- 前端 ajax 请求的是本地接口
- 本地接口接收到请求后向实际的接口请求数据,然后再将信息返回给前端
- 一般用 node.js 即可代理
- Node.js配合node-http-proxy解决本地开发ajax跨域问题
3.JSON
3.1.概述
- 概念:
JavaScript Object Notation
JavaScript
对象表示法 var p = {"name":"张三","age":23,"gender":"男"};
- json 现在多用于存储和交换文本信息的语法
- 进行数据的传输
- JSON 比 XML 更小、更快,更易解析。
3.2.基本语法
3.2.1.基本规则
-
数据在名称/值对中:json 数据是由键值对构成的
-
键用引号(单双都行)引起来,也可以不使用引号
-
值的取值类型:
- 数字(整数或浮点数)
- 字符串(在双引号中)
- 逻辑值(true 或 false)
- 数组(在方括号中)
{"persons":[{},{}]}
- 对象(在花括号中)
{"address":{"province":"陕西"....}}
- null
-
数据由逗号分隔:多个键值对由
,
分隔 -
花括号保存对象:使用
{}
定义 json 格式 -
方括号保存数组:
[]
3.2.2.获取数据
-
json对象.键名
-
json对象["键名"]
变量时使用 -
数组对象[索引]
-
遍历:
需注意遍历时 对象的选择。
//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.相互转化
- 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); }
-
Java 对象转换 JSON
-
调用ObjectMapper的相关方法进行转换
-
转换方法:
-
writeValue(参数1,obj):
参数1:
File:将 obj 对象转换为 JSON 字符串,并保存到指定的文件中
Writer:将 obj 对象转换为 JSON 字符串,并将json数据填充到字符输出流中
OutputStream:将 obj 对象转换为JSON字符串,并将json数据填充到字节输出流中
-
writeValueAsString(obj)
: 将对象转为 json 字符串
-
-
注解:
@JsonIgnore
:排除属性。@JsonFormat
:属性值得格式化@JsonFormat(pattern = "yyyy-MM-dd")
-
复杂java对象转换
List
:数组,方式相同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); } }
- 传统 eat:
-
箭头函数结合结构表达式:
({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的第一个参数。如果是第一次,会把前两个元素作为计算参数,或者把用户指定的初始值作为起始参数
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
。而是Thymeleaf
和Freemarker
等,而Thymeleaf
与SpringMVC
的视图技术,及SpringBoot
的自动化配置集成非常完美,几乎没有任何成本,你只用关注Thymeleaf
的语法即可。
特点
- 动静结合:Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
- 开箱即用:它提供标准和 spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL表达式效果,避免每天套模板、改 jstl 、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
- 多方言支持:Thymeleaf 提供 spring 标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
- 与SpringBoot完美整合:SpringBoot 提供了 Thymeleaf 的默认配置,并且为 Thymeleaf 设置了视图解析器,我们可以像以前操作 jsp 一样来操作 Thymeleaf。代码几乎没有任何区别,就是在模板语法上有区别。
5.2.快速使用
- maven导入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 默认配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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
来刷新工程。
- 编写 Controller
@Controller
public class HelloController {
@GetMapping("show1")
public String show1(Model model){
model.addAttribute("msg", "Hello, Thymeleaf!");
return "hello";
}
}
<!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
的标签属性中,这个叫做指令
动静结合
[
指令:
-
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:switch
和 th: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>