整体介绍

◆了解jQuery3的基本使用方法 ◆掌握Ajax处理流程与实现流程 ◆掌握jQueryr中Ajax方法的使用

JavaScript库

为了简化JavaScript开发,第三方厂商开发了JavaScript库

jQuery介绍

◆jQuery是一个轻量级JS库,使用十分简单 ◆jQuery的核心是选择器,用于获取页面元素 ◆jQuery提供了大量高效方法,开发速度大幅提升

jQuery下载与安装

jQuery官网:jquery.com,最新版本3.6.0 ◆jQuery采用独立JS文件发布:jquery-3.6.0js ◆lDE:Eclipse、Hbuilder、sublime、webstorm

Download jQuery | jQuery 学习中可以使用Download the uncompressed, development jQuery 3.6.0未压缩,源代码版 3.6.0.js 线上部署可以使用Download the compressed, production jQuery 3.6.0生产版本 3.6.0.min.js

.js版本是源代码的代码版本,笔记本打开易于阅读,但是文件大小比较大,200多k,所以不用于生产部署打包,而min.js是压缩打包过的,不易于阅读,但只有80多k,可以用于生产部署

min.js:

.js:

在webapps下新建js文件夹,在js目录下粘贴这两个文件,不同情况进行不同引用

jQuery选择器实验室

添加输入标签就选择相应的标签语句进行高亮

<!DOCTYPE html >
 
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jQuery实验室</title>
 
<style>
.myclass {
	font-style: italic;
	color: darkblue;
}
/* 高亮css类 */
.highlight {
	color: red;
	font-size: 30px;
	background: lightblue;
}
</style>
 
</head>
 
<body>
	<div class="section">
		<h2>jQuery选择器实验室</h2>
		<input style="height: 24px" id="txtSelector" />
		<button id="btnSelect" style="height: 30px">选择</button>
		<hr />
		<div>
			<p id="welcome">欢迎来到选择器实验室</p>
			<ul>
				<li>搜索引擎:<a href="http://www.baidu.com">百度</a> <span> <a
						style="color: darkgreen" href="http://www.so.com">360</a>
				</span>
				</li>
				<li>电子邮箱:<a href="http://mail.163.com">网易邮箱</a> <span> <a
						style="color: darkgreen" href="http://mail.qq.com">QQ邮箱</a>
				</span>
				</li>
				<li>中国名校:<a href="http://www.tsinghua.edu.cn">清华大学</a> <span>
						<a style="color: darkgreen" href="https://www.pku.edu.cn/">北京大学</a>
				</span>
				</li>
			</ul>
 
			<span class="myclass ">我是拥有myclass类的span标签</span>
 
			<p class="myclass">我是拥有myclass的p标签</p>
			<form id="info" action="#" method="get">
				<div>
					用户名:<input type="text" name="uname" value="admin" /> 密码:<input
						type="password" name="upsd" value="123456" />
				</div>
				<div>
					婚姻状况: <select id="marital_status">
						<option value="1">未婚</option>
						<option value="2">已婚</option>
						<option value="3">离异</option>
						<option value="4">丧偶</option>
					</select>
				</div>
				<div class="left clear-left">
					<input type="submit" value="提交" /> <input type="reset" value="重置" />
				</div>
			</form>
		</div>
	</div>
	<script type="text/javascript" src="js/jquery-3.6.0.js" ></script>
	<script type="text/javascript">
		/*
			id选择器使用"#id值"进行选择
			css选择器使用".css类名"进行选择
			$(".myclass").addClass("highlight");
		*/
 
		document.getElementById("btnSelect").onclick = function(){
			var selector = document.getElementById("txtSelector").value;
			//jquery的选择器方法
			//选择器
			$("*").removeClass("highlight");
			$(selector).addClass("highlight");
		}
	</script>
</body>
</html>

基本选择器

Web页面开发的两个要素

在使用HTML开发页面时,有两个基本点:

  1. 选择HTML页面上在哪些元素
  2. 在这些元素上做哪些动作

jQuery选择器

◆jQuery选择器用于选中需要操作的页面元素 ◆语法1:jQuery(选择器表达式) ◆语法2:$(选择器表达式)

基本选择器

◆基本选择器是jQuery最基础也是最常用的选择器表达式

层叠与属性选择器

层叠选择器

◆层叠选择器是根据元素的位置关系来获取元素的选择器表达式

例如:

属性选择器

◆属性选择器是根据元素的属性值来选择元素的选择器表达式

例如:

搭配基本选择器使用: 在基本选择器中选中搜索框:

在属性选择器中:

属性选择器只有明确书写了属性名和属性值才会进行匹配

位置与表单选择器

位置选择器

位置选择器是指通过位置获取指定的元素,例如“获取第3个元素”

例如:

表单选择器

◆表单选择器是获取表单元素的简化形式,例如:获取所有文本框

例如:

无论是否书写了text这个选择器名,只要是个标准的文本框就会被选中,不像属性选择器必须有对应属性名和属性值

操作元素属性

Web页面开发的两个要素

在使用HTML开发页面时,有两个基本点:

  1. 选择HTML页面上在哪些元素
  2. 在这些元素上做哪些动作

上面的选择器学习完成第一步 下面学习进行第二步

操作元素属性

◆attr(nameproperties key)-获取或设置元素属性 ◆removeAttr(name)-移除元素属性

<script type="text/javascript" src="js/jquery-3.3.1.js"></script>
	<script type="text/javascript">书写语句</script>

一个参数表示获取属性

var href_attr =  $("a[href*='163']").attr("href");
alert(href_attr);

两个参数表示设置属性

$("a[href*='163']").attr("href" , "http://www.163.com");

如果获取多个属性,比如获取所有a标签

var attr = $("a").attr("href");
alert(attr);

会默认返回第一个属性值 注意获取多个属性值会默认返回第一个,而设置多个属性值会全部进行赋值设置

移除属性:移除所有超链接

$("a").removeAttr("href");

操作元素CSS样式

◆CSS()-获取或设置匹配元素的样式属性 ◆addClass()-为每个匹配的元素添加指定的类名 ◆removeClass0-从所有匹配的元素中删除全部或者指定的类

<script type="text/javascript" src="js/jquery-3.6.0.js"></script>
	<script type="text/javascript">书写语句</script>

使用json格式添加CSS样式

$("a").css({"color" : "red" , "font-weight" : "bold" , "font-style" : "italic"});

像上一节一样添加高亮样式:

$("li").addClass("highlight");

<style>
.myclass {
	font-style: italic;
	color: darkblue;
}
/* 高亮css类 */
.highlight {
	color: red;
	font-size: 30px;
	background: lightblue;
}
</style>

$("li").addClass("highlight myclass"); 用过空格+类名添加样式,可以无限添加

设置元素内容

◆val()-获取或设置输入项的值 ◆text()-获取或设置元素的纯文本 ◆html()-获取或设置元素内部的HTML

设置输入值:

$("input[name='uname']").val("administrator"); 设置文本框值为administrator

获取输入值:

var v = $("input[name='uname']").val();
		alert(v);

//text与html方法最大的区别在于对于文本中的html标签是否进行转义
                //即<b>标签是否转义出来
		//$("span.myclass").text("<b>锄禾日当午,汗滴禾下土</b>");
		$("span.myclass").html("<b>锄禾日当午,汗滴禾下土</b>");

获取html内容:

var vspan = $("span.myclass").text();
		alert(vspan);

同理,使用text()获取的内容也有<b>标签,而使用html()没有 工作中一般使用text()

jQuery事件处理方法

◆on(“click”,function)-为选中的页面元素绑定单击事件 ◆click(function)-是绑定事件的简写形式 ◆处理方法中提供了event参数包含了事件的相关信息

<script type="text/javascript" src="js/jquery-3.3.1.js"></script>
 
<script type="text/javascript">
	//onload是指在页面所有资源加载完成后执行
	window.onload = function(){
		//alert(1);
	}
 
	//ready()则是在页面dom被浏览器解释完成后执行
	$(document).ready(function(){
		alert("页面准备就绪");
	})
 
	//简化形式
	$(function(){
		$("p.myclass").on("click" , function(){
			//$(this)是指当前事件产生的对象
			$(this).css("background-color" , "yellow");
		});
 
		$("span.myclass").click(function(){
			$(this).css("background-color" , "lightgreen");
		})
 
		$("input[name='uname']").keypress(function(event){
			console.log(event);
			if(event.keyCode == 32){
				$(this).css("color" , "red");
			}
		})
	})
</script>

当用户输入有空格时就变红:

$("input[name='uname']").keypress(function(event){
			console.log(event);
			if(event.keyCode == 32){
				$(this).css("color" , "red");
			}
		})

使用event进行事件处理,输入admin+空格,观察出空格的keyCode为32

Ajax介绍

◆Asynchronous JavaScript And XML(异步的JavaScript和XML) ◆Ajax可以在不刷新页面的前提下,进行页面局部更新 ◆Ajax不是新的技术,Ajax并不是W3C的标准

Ajax使用流程

◆创建XmlHttpReqeust对象 ◆发送Ajax请求 ◆处理服务器响应

创建XmlHttpReqeust对象

◆XMLHttpRequest是Ajax的核心,Ajax使用该对象发起请求、接收响应 ◆XMLHttpRequest并不是W3C的标准,不同浏览器的创建方式不同

加载按钮:

<input id="btnLoad" type="button" value="加载"/>
    <div id="divContent"></div>
//1. 创建XMLHttpRequest对象
            var xmlhttp;
            if(window.XMLHttpRequest){
                xmlhttp = new XMLHttpRequest();
            }else{
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            console.log("XMLHttpRequest:",xmlhttp);

发送Ajax请求

◆xmlhttp.open()用于创建请求 ◆xmlhttp.send()用于发送请求

//2. 发送Ajax请求
            xmlhttp.open("GET", "/content"true);
            xmlhttp.send();

第三个参数代表是否采用异步 同级目录直接使用/content链接

src下新建ContentServlet.Java文件

@WebServlet("/content")
public class ContentServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().println("<b style='color:red'>I'm server content</b>");
    }
}

网络录制点击加载按钮 我们发现只出现content文件,请求方式和html一样,但是没有出现index.html文件,说明确实之发生了局部刷新,而没有全局刷新

得到响应但是该如何进行加载到浏览器界面?这时需要进行Ajax第三步

处理服务器响应

◆xmlhttp.onreadystatechange()事件用于监听Ajax的执行过程 ◆xmlhttp.readyState属性说明XMLHttpRequest当前状态

◆xmlhttp.status属性服务器响应状态码,200:成功404:未找到。…

//3. 处理服务器响应
            xmlhttp.onreadystatechange = function(){
                if(xmlhttp.readyState == 4  && xmlhttp.status == 200){
                    var t = xmlhttp.responseText;
                    console.log(t);
                    document.getElementById("divContent").innerHTML = document.getElementById("divContent").innerHTML + "<br/>" + t;
                }
            }

每点击一次就出现一次,而且是整个不刷新的状态直接获取内容

大部分服务器返回的不是HTML片段,AJAX获取到的而是JSON数据,下回讲解

同步与异步

//2. 发送Ajax请求
            xmlhttp.open("GET", "/content"true);
            xmlhttp.send();

true是同步,false是异步,默认异步

◆同步是在服务器未返回JSON前,JS程序一直处于阻塞等待的状态 ◆异步是在服务器未返回JSON前,不阻塞程序,Ajax通过回调获取结果

利用Jackson实现JSON序列化输出

Ajax+JSON开发模式

Jackson

◆Jackson是国内外著名的Java开源JSON序列化组件 ◆Jackson国内拥有大量使用者,拥有API简单,效率高等优点 ◆Jackson也是众多Java框架的底层组件,掌握Jackson很重要

添加jackson的maven依赖,让其自动下载

<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
</dependency>

记得在pom.xml文件下右键点击maven重新加载项目

由于国内外通信原因,可能无法下载,导致一串报红,可以添加阿里云镜像

<repositories>
        <repository>
            <id>aliyun</id>
            <name>aliyun</name>
            <url>https://maven.aliyun.com/repository/public</url>
        </repository>
    </repositories>

然后继续在pom.xml文件下右键点击maven重新加载项目 这时,idea会在后台进行下载,下载成功后,不再爆红,在外部库即可观察到下载的依赖项

注意:当程序使用tomcat发布时,记得将添加的依赖加入到out文件夹下或者target文件夹下web-inf下的lib目录,否则无法运行,具体操作点击项目结构工件找到新添加的依赖选中右键添加到lib目录

Ajax处理JSON数据

news.java文件

package com.imooc.Ajax.entity;
 
public class News {
    private String title;
    private String date;
    private String source;
    private String content;
 
    public News(String title, String date, String source, String content) {
        this.title = title;
        this.date = date;
        this.source = source;
        this.content = content;
    }
 
    public String getTitle() {
        return title;
    }
 
    public void setTitle(String title) {
        this.title = title;
    }
 
    public String getDate() {
        return date;
    }
 
    public void setDate(String date) {
        this.date = date;
    }
 
    public String getSource() {
        return source;
    }
 
    public void setSource(String source) {
        this.source = source;
    }
 
    public String getContent() {
        return content;
    }
 
    public void setContent(String content) {
        this.content = content;
    }
}

NewsServlet.java文件

@WebServlet("/news")
public class NewsServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String t = request.getParameter("t");
        List<News> list = new ArrayList<News>();
        if(t.equals("tiobe")) {
            list.add(new News("TIOBE:2018年编程语言排行趋势", "2018-5-1", "TIOBE", "..."));
            list.add(new News("TIOBE:2019年编程语言排行趋势", "2019-5-1", "TIOBE", "..."));
            list.add(new News("TIOBE:2020年编程语言排行趋势", "2020-5-1", "TIOBE", "..."));
            list.add(new News("TIOBE:2021年编程语言排行趋势", "2021-5-1", "TIOBE", "..."));
        }else if(t.equals("pypl")){
            list.add(new News("PYPL:2018年编程语言排行趋势", "2018-5-1", "PYPL", "..."));
            list.add(new News("PYPL:2019年编程语言排行趋势", "2019-5-1", "PYPL", "..."));
            list.add(new News("PYPL:2020年编程语言排行趋势", "2020-5-1", "PYPL", "..."));
            list.add(new News("PYPL:2021年编程语言排行趋势", "2021-5-1", "PYPL", "..."));
        }
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(list);
        response.setContentType("text/json;charset=utf-8");
//        response.setContentType("application/json;charset=utf-8");
        response.getWriter().println(json);
    }
 
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

在news.html的script标签对里:

var xmlhttp;
    if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest();
    } else {
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.open("GET", "/news");
    xmlhttp.send();
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            var str = xmlhttp.responseText;
            console.log(str);

此处只能获得json结构的字符串,需要转换为JSON对象

var json = JSON.parse(str);
            console.log(json);
            for (var i = 0; i < json.length; i++) {
                var news = json[i];
                var container = document.getElementById("container");
                container.innerHTML = container.innerHTML + "<h2>" + news.title + "</h2>";
            }

这时获取到的才是json数据 html渲染:获取到数据进行二次开发的过程 缺点:每发送一次ajax,就要遵循一次创建对象,发送请求,服务响应的过程,比较繁琐,下面学习ajax的封装js库

Axios快速入门

axios中文网|axios API 中文文档 | axios (axios-js.com)

在webapp下新建js目录,创建axios.js文件,将https://unpkg.com/[email protected]/dist/axios.min.js 里面内容全部复制粘贴进去,因为是min.js文件,是压缩过的,不具有可读性

发送get请求

引入js文件后

例如:执行 GET 请求

// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 上面的请求也可以这样做
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});

预留一个对象axios,.get方法即执行get请求,‘/user’是预处理的url,params是请求参数,改为使用json格式进行表达,.then表示服务器成功响应返回后会执行里面代码,response是从服务器返回的对象,通过response就能拿到服务器返回的json数据,.catch是异常情况进行处理的代码

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/js/axios.js"></script>
</head>
<body>
<div id="container"></div>
<script>
      axios.get('/news', {params:{"t":"pypl"}}).then(function (response) {
        console.log(response);
        var json = response.data;
        for (var i = 0; i < json.length; i++) {
            var news = json[i];
            var container = document.getElementById("container");
            container.innerHTML = container.innerHTML + "<h2>" + news.title + "</h2>";
        }
    }).catch(function (error) {
        console.log(error);
    });
</script>

发送post请求

执行 POST 请求

axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

与get请求方式不相同

axios.post("/news", "t=pypl&l=abc",  {headers: {"content-type": "application/x-www-form-urlencoded"}})

url后面不跟json对象,而是标准的请求参数形式,多个参数使用&符号链接,第三个参数需要为header请求头,固定为{"content-type": "application/x-www-form-urlencoded"}表示请求参数放置于请求体中

注意需要在servlet中重写post方法,否则返回405错误

axios提供一种面向对象的扩展方式进行post发送

const params = new URLSearchParams();
    params.append("t", "pypl");
    params.append("l", "abc");

调用方式也要发生改变:

axios.post("/news",params)
        .then(function (response) {
            console.log(response);
            var json = response.data;
            for (var i = 0; i < json.length; i++) {
                var news = json[i];
                var container = document.getElementById("container");
                container.innerHTML = container.innerHTML + "<h2>" + news.title + "</h2>";
            }
        })
        .catch(function (error) {
            console.log(error);
        });

此种方法可读性更好

实现二级联动菜单

在com.imooc.ajax.entity的文件目录下: 新建对channel的定义: Channel.java文件:

package com.imooc.ajax.entity;
 
public class Channel {
    private String code;
    private String name;
 
    public Channel() {
    }
 
    public Channel(String code, String name) {
        this.code = code;
        this.name = name;
    }
 
    public String getCode() {
        return code;
    }
 
    public void setCode(String code) {
        this.code = code;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

在com.imooc.ajax.servlet目录下:

package com.imooc.ajax.servlet;
 
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imooc.ajax.entity.Channel;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 
@WebServlet("/channel")
public class ChannelServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String level = request.getParameter("level");
        String parent = request.getParameter("parent");
        List<Channel> chlist = new ArrayList<>();
        if(level.equals("1")){
            chlist.add(new Channel("ai", "人工智能"));
            chlist.add(new Channel("web", "前端开发"));
        }else if(level.equals("2")){
            if(parent.equals("ai")){
                chlist.add(new Channel("dl", "深度学习"));
                chlist.add(new Channel("cv", "计算机视觉"));
                chlist.add(new Channel("nlp", "自然语言处理"));
            }else if(parent.equals("web")){
                chlist.add(new Channel("html", "HTML超文本标记语言"));
                chlist.add(new Channel("css", "CSS级联样式表"));
                chlist.add(new Channel("js", "JavaScript脚本"));
            }
        }
        //完成JSON序列化工作
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(chlist);
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().println(json);
 
    }
}

浏览器地址栏输入localhost:8080/ajax/channel?level=1 得到一级菜单数据

同理输入二级菜单

这时后端的交互数据已经完成,只需要前端做出页面交互就行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/js/axios.js"></script>
</head>
<body>
<select id="lv1" style="width: 200px;height: 30px">
    <option value="-1" selected="selected">请选择</option>
</select>
<select id="lv2" style="width: 200px;height: 30px"></select>
</body>
</html>

一级和二级菜单需要产生两个ajax请求

<script>
    var lv1 = document.getElementById("lv1");
    axios.get("/channel" , {params:{"level" : 1}})
        .then(function (response){
            var json = response.data;
            console.log(json);
            for(var i = 0 ; i  < json.length ; i++){
                var channel = json[i];
                lv1.options.add(new Option(channel.name, channel.code));
            }
        });
    var lv2 = document.getElementById("lv2");
    lv1.onchange = function(){
        axios.get("/channel" , {params:{"level":2,"parent" : lv1.value}})
            .then(function(response){
                var json = response.data;
                console.log(json);
                lv2.length = 0;
                for(var i = 0 ; i < json.length ; i++){
                    var channel = json[i];
                    lv2.options.add(new Option(channel.name,channel.code));
                }
            })
    }
</script>

在每次加载二级菜单时,应该清除原有数据再进行加载,否则会导致结果叠加出现 清除数据语句: lv2.length = 0;