Python测开28期-偕行-前后端开发综合案例

案例一:学生管理系统

遇到的问题

1、使用form表单发送post请求报错

问题原因:

当通过form表单发送POST请求时,默认的Content-Type是application/x-www-form-urlencoded ,而不是application/json 。因此,如果你想在发送POST请求时使用application/json 作为Content-Type,你需要手动设置请求头。

解决方案

不使用form表单发送请求,而是自定义函数发送请求,在自定义函数中手动添加请求header

知识扩展- 使用js发送请求的方式都有哪些

  1. XMLHttpRequest:可以使用 XMLHttpRequest 对象发送异步请求,可以使用 GET、POST 等方法,并可以设置请求头、发送数据等。

  2. Fetch API:Fetch API 为 JavaScript 提供了一个更现代、更强大的方式来发送网络请求,可以使用 GET、POST 等方法,并且可以链式调用各种方法。

  3. axios:axios 是一个基于 Promise 的 HTTP 客户端,可以在浏览器和 Node.js 中发送 HTTP 请求,使用方式简单,支持请求拦截器、响应拦截器等功能。

  4. jQuery.ajax:如果你使用了 jQuery 库,可以使用其提供的 ajax() 方法来发送请求,它支持多种请求方式,并且具有更好的兼容性。

  5. WebSocket:WebSocket 是一种更高级的通信协议,在客户端和服务器之间提供双向通信,可以通过 JavaScript 创建 WebSocket 连接,以发送和接收数据,可以实现实时通信。

  6. Native fetch:除了使用 Fetch API,原生的 JavaScript 也提供了 fetch 方法来发送网络请求,它的使用方式类似于 Fetch API,但有一些细微的差异。

A、使用fetch函数发送请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>添加学生</title>
    <!-- 引入css文件 -->
    <!-- <link rel="stylesheet" href="{{url_for('static',filename='css/add.css')}}"> -->

    <!-- 内部样式 -->
    <style>
        /* 全局背景图 */
        body {

            /* 设置背景图--使用rul_for加载静态图片,这是flask框架的用法 */
            background-image: url({{url_for('static',filename='img/school.jpg')}});
            /* 背景图垂直、水平方向居中 */
            /* background-position: center 0; */
            /* 图片不重复 */
            background-repeat: no-repeat;
            /* 让背景图基于容器大小伸缩 */
            background-size:cover;
        };
        /* 内容主区域 */
        .main{
            /* 宽高 */
            height: 700px;
            width: 1200px;
            /* border: 1px solid #000; */
        }
        /* 标题 */
        .title h1{
            /* 内容居中 */
            text-align: center;
            color:brown;
            margin-top: 100px ;
            /* border: 1px solid #000; */
        }
        .content div{
            text-align: center;
            margin-top: 10px;
        }
       
        
    </style>
    <!-- 引入jQuery-->
    <script src="{{url_for('static',filename='js/jquery-3.5.1.min.js')}}"></script>
    <script>
            // 点击添加按钮
            // 说明:这里使用fetch函数发送请求,有个问题:服务端返回的是一个页面,
            // 这个方式好像不能直接打开页面,需要对返回结果单独处理,导致页面时正确了,
            // 但是浏览器地址栏显示的是add地址,而不是首页
            function submitAddByFetch(){
            // 阻止表单默认提交行为  ---因为input的type是submit类型,点击后会使用form发送请求,这就是报错的根源
                event.preventDefault()
                //  获取表单输入框的值  
                var name = document.getElementById("name").value
                var age = document.getElementById("age").value
                var gender = document.getElementById("gender").value
                console.log(name,age,gender)
                // 使用fetch API发送请求,两个参数,第一个是url,第二个是一个{options}
                fetch(
                    // 请求url
                    "/add/",
                    {
                        // 请求方法post--注意是小写
                        method: 'post',
                        // 请求头
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        // 请求体
                        body: JSON.stringify({
                            "name": name,
                            "age": age,
                            "gender":gender
                        }),
                        
                    })
                    // 将响应体转为文本类型
                    .then(res => res.text())
                    // .then(res => console.log(typeof res))
                    // .then(res => console.log(res))
                    // 使用 DomParser API 对其进行解析
                    .then(res => {
                        // // 创建一个DOMParser对象
                        // var parser = new DOMParser();
                        
                        // // 解析html文档--Document 或 XMLDocument 类型文档
                        // var doc = parser.parseFromString(res, "application/xhtml+xml");
                        console.log(res)
                        console.log("==========================")
                        
                        // 在窗口中打开解析的html文档
                        // document.write(res) //info为html的字符串
                        // document.close()//必须关闭流,否则表单不生效
                        
                        // 使用document.write(res)是在当前页面直接把html文本渲染了,地址栏的地址有问题,还是http://127.0.0.1:5000/add/
                        // 添加成功需要回到首页才行,页面和地址都是首页
                        // 使用window的location对象在当前窗口打开一个链接
                        window.location.href = "http://127.0.0.1:5000/"

                    })
            };

    </script>

</head>
<body>
    <!-- 展示区域 -->
    <div class="main">
        <!-- 标题 -->
        <div class="title">
            <h1>添加学生</h1>
        </div>
        <!-- 内容区域--自定义请求方式 -->
        <div class="content">
            <!-- form表单post请求进行添加 -->
            <form action="/add/" method="post" id="form">
                <!-- 每个输入框独占一行 -->
                <div> 姓名:<input type="text" name="name" id="name"> </div>
                <div> 年龄:<input type="text" name="age" id="age"> </div>
                <div> 性别:<input type="text" name="gender" id="gender"> </div>
                <div id="op">
                    <input type="reset" value="重置">
                    <input type="submit" value="确认添加" onclick=submitAddByFetch()>
                </div>
            </form>
        </div>
    </div>
</body>
</html>

说明: fetch函数接收两个参数

  • 第一个是请求url
  • 第二个是{options}可选项对象,options有:请求方式、请求头、请求体;
{
                        // 请求方法post--注意是小写
                        method: 'post',
                        // 请求头
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        // 请求体
                        body: JSON.stringify({
                            "name": name,
                            "age": age,
                            "gender":gender
                        }),
                        
                    }

B、使用XMLHttpRequest的open方法发送请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>添加学生</title>
    <!-- 引入css文件 -->
    <!-- <link rel="stylesheet" href="{{url_for('static',filename='css/add.css')}}"> -->

    <!-- 内部样式 -->
    <style>
        /* 全局背景图 */
        body {

            /* 设置背景图--使用rul_for加载静态图片,这是flask框架的用法 */
            background-image: url({{url_for('static',filename='img/school.jpg')}});
            /* 背景图垂直、水平方向居中 */
            /* background-position: center 0; */
            /* 图片不重复 */
            background-repeat: no-repeat;
            /* 让背景图基于容器大小伸缩 */
            background-size:cover;
        };
        /* 内容主区域 */
        .main{
            /* 宽高 */
            height: 700px;
            width: 1200px;
            /* border: 1px solid #000; */
        }
        /* 标题 */
        .title h1{
            /* 内容居中 */
            text-align: center;
            color:brown;
            margin-top: 100px ;
            /* border: 1px solid #000; */
        }
        .content div{
            text-align: center;
            margin-top: 10px;
        }
       
        
    </style>
    <!-- 引入jQuery-->
    <script src="{{url_for('static',filename='js/jquery-3.5.1.min.js')}}"></script>
    <script>
            // 点击添加按钮
            function submitAddByXMLHttpRequest(){
                // 阻止表单默认提交行为  
                event.preventDefault()
                // 获取表单元素
                var form = document.getElementById("form")
                // 获取表数据对象
                var formdata = new FormData(form)
                console.log(formdata)
                console.log("name=",formdata.get("name"))
                console.log("age=",formdata.get("age"))
                console.log("gender=",formdata.get("gender"))
                console.log(typeof formdata)
                // 创建一个XMLHttpRequest对象
                var request = new XMLHttpRequest()
                //  设置请求方法和URL
                request.open('post','/add/',true)
                // 预期服务器返回文档对象
                request.responseType='document '
                // 设置请求头信息
                request.setRequestHeader('Content-Type', 'application/json')
                // 封装请求数据
                const data = {
                    "name":formdata.get("name"),
                    "age":formdata.get("age"),
                    "gender":formdata.get("gender"),
                }
                // 将表单数据转换为JSON格式字符串并发送  
                console.log("是个啥:",JSON.stringify(data))
                var result = request.send(JSON.stringify(data) )
                console.log(result)// underfined

                // 监听onreadystatechange事件
                request.onreadystatechange = function(){
                    // 如果数据接收完毕并且响应状态码为200则跳转到首页
                    if(request.readyState === 4 && request.status === 200){
                        // 返回结果是个啥
                        console.log("返回结果:",request.responseText)
                        // 使用window的location对象在当前窗口打开一个链接
                        window.location.href = "http://127.0.0.1:5000/"
                    }
                }
            };
    </script>

</head>
<body>
    <!-- 展示区域 -->
    <div class="main">
        <!-- 标题 -->
        <div class="title">
            <h1>添加学生</h1>
        </div>
        <!-- 内容区域--自定义请求方式 -->
        <div class="content">
            <!-- form表单post请求进行添加 -->
            <form action="/add/" method="post" id="form">
                <!-- 每个输入框独占一行 -->
                <div> 姓名:<input type="text" name="name" id="name"> </div>
                <div> 年龄:<input type="text" name="age" id="age"> </div>
                <div> 性别:<input type="text" name="gender" id="gender"> </div>
                <div id="op">
                    <input type="reset" value="重置">
                    <input type="submit" value="确认添加" onclick=submitAddByXMLHttpRequest()>
                </div>
            </form>
        </div>
    </div>
</body>
</html>

说明:

  • XMLHttpRequest.open (method, url, async, username, password)

    • method 参数是用于请求的 HTTP 方法。值包括 GET、POST 和 HEAD。–大小写不敏感;
    • url 参数是请求的主体。大多数浏览器实施了一个同源安全策略,并且要求这个 URL 与包含脚本的文本具有相同的主机名和端口。
      • 可以使用event.target.action获取当前窗口的地址;
    • async 参数指示请求使用应该异步地执行。如果这个参数是 false,请求是同步的,后续对 send() 的调用将阻塞,直到响应完全接收。如果这个参数是 true 或省略,请求是异步的,且通常需要一个 onreadystatechange 事件句柄。
    • usernamepassword 参数是可选的,为 url 所需的授权提供认证资格。如果指定了,它们会覆盖 url 自己指定的任何资格。
  • XMLHttpRequest.send(json字符串数据)

  • XMLHttpRequest.onload:当readyState等于4的时候触发;

  • XMLHttpRequest.onreadystatechange: 在通过Ajax向服务器发送请求的过程中,* *

  • XMLHttpRequest对象的状态会发生多次变化。由于 readystatechange 事件是在 xhr 对象状态变化时触发(不单是在得到响应时),也就意味着这个事件会被触发多次。

  • XMLHttpRequest对象的状态:有5种,用readyState属性来表示xhr对象的状态,值为0 1 2 3 4

C、使用 jQuery.ajax发送请求

步骤:

  • 1、使用$.ajaxSetup({})设置全局请求头;
  • 2、使用$.post()发送请求;
// 使用ajaxSetup设置请求头
        $.ajaxSetup({
            headers:{'Content-Type': 'application/json;charset=utf-8'}
        });

// 点击确认-发送请求
        function submitUpdate(){
            console.log("点击确定")
            // 从地址栏获取bid
            let bid = getBid()
            // 获取表单数据
            let formdata = getFormdata()
            console.log("请求时表单数据name:",formdata.get("name"))
            // 拼装请求参数
            var postdata = {
                "bid":bid,
                "name":formdata.get("name"),
                "price":formdata.get("price"),
                "quantity":formdata.get("quantity"),
                "summary":formdata.get("summary")
            }
            // 发送请求
            $.post("/book/update/"+bid,JSON.stringify(postdata),function(result){
                // alert("修改成功,返回首页!")
                // 请求成功直接进入首页
                window.location.href = "http://127.0.0.1:9528/book/"
            });
        };

2、使用div弹窗

思路

  1. 总体使用两个div,一个作为底层展示,一个做为弹出窗口;

  2. 两个窗口独立进行CSS设计,通过display属性进行设置显示与隐藏,此处建议使用display属性而不是visibility属性,visibility:hidden可以隐藏某个元素,但隐藏的元素仍需占用与未隐藏之前一样的空间,影响布局;

  3. 在js内设计两个onclick事件,分别指定函数,分别为开启弹窗和关闭弹窗。

A、设置两个div

<html>
<title>弹出窗口</title>
<head>
    <meta charset="UTF-8">
</head>
<body>
	// 底层div
    <div id="popLayer">
    </div>
	// 弹出层div
    <div id="popDiv">
    </div>
</body>
</html>

B、对两个div进行独立CSS设置,弹出窗口display设为none

<html>
<title>弹出窗口</title>
<head>
    <meta charset="UTF-8">
    <style type="text/css">
        #popDiv{
            display: none;
            background-color: crimson;
            z-index: 11;
            width: 600px;
            height: 600px;
            position:fixed;
            top:0;
            right:0;
            left:0;
            bottom:0;
            margin:auto;
        }
    </style>
</head>
<body>
	// 底层div
    <div id="popLayer">
        <button onclick="">弹窗</button>
    </div>
	
	// 弹出层div
    <div id="popDiv">
        <div class="close">
        	// 关闭按钮超链接
            <a href="" onclick="">关闭</a>
        </div>
            <p>此处为弹出窗口</p>
    </div>
</body>
</html>

C、定义并设置弹出和关闭窗口函数

<script type="text/javascript">
        // 显示弹框
        function popDiv(){
            var popBox = document.getElementById("popDiv");

            // 控制弹出层显示
            popBox.style.display = "block";
        }
        // 关闭弹框
        function closePop(){
            let popDiv = document.getElementById("popDiv");
            // 控制弹出层隐藏
            popDiv.style.display = "none";
        }
    </script>

D、将函数设置到onclick事件中

<!-- 底层div -->
    <div id="popLayer">
        <button id="add1" onclick=popDiv()>添加学生</button>
    </div>
    <div id="add2">
        <a href="/add/">添加学生</a>
    </div>
    <!-- 弹出层div -->
    <div id="popDiv">
        <div class="close">
            <!-- 关闭按钮超链接 -->
            <a href="" onclick=closePop()>关闭</a>
        </div>
        <div >
            <h3 id="popTitle">添加学生</h3>
        </div>

E、设置关闭链接CSS和pop界面的其余CSS

/* 关闭链接样式 */
        #popDiv .close a {
        /* 设置字体颜色 */
            color: #2D2C3B;
            text-decoration: none;
        }
        /* 弹出界面的关闭链接 */
        #popDiv .close{
            /* 设置文本靠右显示,也就是关闭按钮显示在右边 */
            text-align: right;
            margin-right: 5px;
            /* 背景颜色 */
            background-color: rgb(132, 132, 247);
        }

F、综合案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #popLayer{
            /* 不一行显示 */
            display: inline-block;
        }

        #popDiv{
            display: none;
            background-color:  rgb(132, 132, 247);
            z-index: 11;
            width: 400px;
            height: 300px;
            position:fixed;
            top:0;
            right:0;
            left:0;
            bottom:0;
            margin:auto;
        }
        /* 关闭链接样式 */
        #popDiv .close a {
        /* 设置字体颜色 */
            color: #2D2C3B;
            text-decoration: none;
        }
        /* 弹出界面的关闭链接 */
        #popDiv .close{
            /* 设置文本靠右显示,也就是关闭按钮显示在右边 */
            text-align: right;
            margin-right: 5px;
            /* 背景颜色 */
            background-color: rgb(132, 132, 247);
        }

        /* 添加 */
        #add1 {
            margin: 10px;
            background-color: rgb(238, 255, 0);
            color: red;
            border: 1px solid green;
        }

        #add2 {
            /* 不一行显示 */
            display: inline-block;
            margin: 10px;
            width: fit-content;
            color: red;
            background-color: chartreuse;
            border: 1px solid red;
            padding: 1px 4px 1px 4px;
            font-size: 14px;
        }

        /* 标题 */
        #popTitle{
            /* 内容居中 */
            text-align: center;
            color:brown;
            margin-top: 10px ;
            /* border: 1px solid #000; */
        }
        .content div{
            text-align: center;
            margin-top: 10px;
        }


    </style>
    <script type="text/javascript">
        // 显示弹框
        function popDiv(){
            var popBox = document.getElementById("popDiv");

            // 控制弹出层显示
            popBox.style.display = "block";
        }
        // 关闭弹框
        function closePop(){
            let popDiv = document.getElementById("popDiv");
            // 控制弹出层隐藏
            popDiv.style.display = "none";
        }
    </script>

</head>
<body>
    <!-- 底层div -->
    <div id="popLayer">
        <button id="add1" onclick=popDiv()>添加学生</button>
    </div>
    <div id="add2">
        <a href="/add/">添加学生</a>
    </div>
    <!-- 弹出层div -->
    <div id="popDiv">
        <div class="close">
            <!-- 关闭按钮超链接 -->
            <a href="" onclick=closePop()>关闭</a>
        </div>
        <div >
            <h3 id="popTitle">添加学生</h3>
        </div>
        <!-- 提交表单 -->
        <div class="content">
            <!-- form表单post请求进行添加 -->
            <form action="/add/" method="post" id="form">
                <!-- 每个输入框独占一行 -->
                <div> 姓名:<input type="text" name="name" id="name"> </div>
                <div> 年龄:<input type="text" name="age" id="age"> </div>
                <div> 性别:<input type="text" name="gender" id="gender"> </div>
                <div id="op">
                    <input type="reset" value="重置">
                    <input type="submit" value="确认添加" onclick=submitAddByXMLHttpRequest()>
                </div>
            </form>
        </div>
    </div>
</body>
</html>

案例二:图书管理系统

遇到的问题

1、summary的内容太多导致表格样式错乱

解决方案: 通过伪类选择器nth-child(),对指定的标签设置样式;

css选择器:nth-child()的用法

  • 找的就是冒号前面选择器的爹或者祖先的第n个儿子,只有顺序和冒号前面的选择器匹配的才会找到,顺序及选择器必须都正确才会匹配到;

  • 使用技巧:

    • 先使用父子关系连接符号 > 找出所有儿子;
    • 任何再用:nth-child(n)去找到第几个儿子;
    • 如果想再精确点,就同时指明儿子的选择器;
    • 注意:父子关系连接符号 > 后面不跟选择器可以找出所有的儿子,但是后代关系连接符号[空格]后面不跟选择器是找不出所有后代的,此时空格没任何意义;
A、 选择列表中的偶数标签:nth-child(2n)

image

B、 选择列表中的奇数标签 :nth-child(2n-1)

image

C、 选择从第6个开始的,直到最后:nth-child(n+6)

image

D、 选择第1个到第6个 :nth-child(-n+6)

image

E、 两者结合使用,可以限制选择某一个范围,选择第6个到第9个 :nth-child(n+6):nth-child(-n+9)

image

/* 选择第n个,n位数字  */
:nth-child(n)

/* 选择列表中的偶数标签 */
:nth-child(2n)

/*选择列表中的奇数标签 */
:nth-child(2n-1)

/*选择前几个元素 */
/*【负方向范围】选择第1个到第6个 */
:nth-child(-n+6){}

/*从第几个开始选择*/
/*【正方向范围】选择从第6个开始的,直到最后  */
:nth-child(n+6){}

/*两者结合使用,可以限制选择某一个范围 */
/*【限制范围】选择第6个到第9个,取两者的交集【感谢小伙伴的纠正~】 */
 :nth-child(n+6):nth-child(-n+9)

/*选择列表中的倒数第n个标签 n为数字 */
:nth-last-child(n) 

/*选择倒数最后n个 */
item:nth-last-child(-n+2){}

:nth-last-child() 选择器

该选择器匹配属于其元素的第 N 个子元素的每个元素,不论元素的类型,从最后一个子元素开始计数。

:nth-of-type(n)

该选择器匹配属于父元素的 指定类型 的并且 这个类型中第 N 个儿子 的元素.—n 可以是数字、关键词或公式。

2、div弹框的样式太丑

解决方案: 再加一个div遮罩半透明;
效果:
呵呵

实现原理:

  1. html结构比较简单,即:
<div>遮罩层
      <div>弹框</div>
</div>
  1. 先写覆盖显示窗口的遮罩层div.box,因为要在整个窗口显示固定,所以position要设为fixed,background设为灰色半透明,由于要遮住整个显示屏,width和height都设为100%(body和html的width和height也都设为100%) ;
  2. 在遮罩层的div.box里写弹框的div.container,位置相对于父级定位;

案例:
html:

<div>
    <button class="open">点我弹出弹框</button>
</div>
<div class="box">
    <div class="container">
        <button class="close">关闭弹框</button>
    </div>
</div>

css:

html, body {
    width:100%;
    height:100%;
}
.box {
    display: none;
    width: 100%;
    height: 100%;
    position: fixed;
    top: 0;
    left: 0;
    background: rgba(51,51,51,0.5);
    z-index: 3;//根据自己页面情况设置
}
.container {
    width: 500px;
    height: 200px;
    position: absolute;
    top: 50%;//以下3行设置弹框居中页面,根据自己页面情况选择
    left: 50%;
    transform: translate(-50%, -50%);
    background: #fff;
    z-index: 5;//根据自己页面情况设置
}

js:

$(document).ready(function(){
    $(".open").click(function(){
        $(".box").show();
    })
    $(".close").click(function(){
        $(".box").hide();
    })
})

3、使用value给span标签赋值失败

问题:
使用ajax属性选择器获取元素之后使用元素.prop()给span标签设置属性失败;

$("#popname").prop({"value":formdate.get("name")})

解决方案: 使用Element.innerText属性设置值;
span标签显示的内容不是value属性的值,而是被标签包裹的内容,所以需要使用Element.innerText属性设置值;

// 给弹窗区域设置表单填写值
document.getElementById("popname").innerText=formdate.get("name");
document.getElementById("popprice").innerText=formdate.get("price");
document.getElementById("popquantity").innerText=formdate.get("quantity");
document.getElementById("popsummary").innerText=formdate.get("summary");

扩展:

  • span标签的取值
<!--js的取值方式-->
<span id="span_id">span的文本</span>
<script>
    var result = document.getElementById("span_id").innerText;
</script>

<!--jQuery的取值方式-->
<span id="span_id">span的文本</span>
<script>
    var result = $("#span_id").html();
</script>
  • span标签的赋值
<!--js的赋值方式-->
<span id="span_id"></span>
<script>
    document.getElementById("span_id").innerText="测试赋值";
</script>

<!--jQuery的赋值方式-->
<span id="span_id"></span>
<script>
    $("#span_id").html("测试赋值");
</script>

4、搜索框键盘事件-用户输入关键字Enter键入发起搜索请求

(1) JavaScript回车事件等键盘事件

(2)JavaScript键盘事件

在 JavaScript 中,当用户操作键盘时,会触发键盘事件,键盘事件主要包括下面 3 种类型:

  • 1)keydown:在键盘上按下某个键时触发。如果按住某个键,会不断触发该事件,但是 Opera 浏览器不支持这种连续操作。该事件处理函数返回 false 时,会取消默认的动作(如输入的键盘字符,在 IE 和 Safari 浏览器下还会禁止keypress 事件响应)。

  • 2)keypress:按下某个键盘键并释放时触发。如果按住某个键,会不断触发该事件。该事件处理函数返回 false 时,会取消默认的动作(如输入的键盘字符)。

  • 3)keyup:释放某个键盘键时触发。该事件仅在松开键盘时触发一次,不是一个持续的响应状态。

当用户正按下键码时,可以使用 keydown、keypress 和 keyup 事件获取这些信息。其中 keydown 和 keypress 事件基本上是同义事件,它们的表现也完全一致,不过一些浏览器不允许使用 keypress 事件获取按键信息。所有元素都支持键盘事件,但键盘事件多被应用在表单输入中。

(3)键盘事件属性

键盘定义了很多属性,如下表所示。利用这些属性可以精确控制键盘操作。键盘事件属性一般只在键盘相关事件发生时才会存在于事件对象中,但是 ctrlKey 和 shiftKey 属性除外,因为它们可以在鼠标事件中存在。例如,当按下 Ctrl 或Shift 键时单击鼠标操作。

image

ctrlKey 和 shiftKey 属性可存在于键盘和鼠标事件中,表示键盘上的 Ctrl 和 Shift 键是否被按住。下面示例能够监测 Ctrl 和 Shift 键是否被同时按下。如果同时按下,且鼠标单击某个页面元素,则会把该元素从页面中删除。

document.onclick = function (e) {
	//标准化事件对象
    var e = e || window.event;  
    //获取发生事件的元素,兼容IE和DOM
    var t = e.target || e.srcElement;  
    //如果同时按下Ctrl和Shift键
    if (e.ctrlKey && e.shiftKey) {  
    	//移出当前元素
        t.parentNode.removeChild(t);  
    }
}

keyCode 和 charCode 属性使用比较复杂,但是它们在实际开发中又比较常用,故比较这两个属性在不同事件类型和不同浏览器中的表现时非常必要的,如下表所示。读者可以根据需要有针对性的选用事件响应类型和引用属性值。

某些键的可用性不是很正确,如 PageUp 和 Home 键等。不过常用功能键和字符键都是比较稳定的,如下表所示:

image

(4)键盘响应顺序

  • 当按下键盘时,会连续触发多个事件,它们将按如下顺序发生。
  • 对于字符键来说,键盘事件的响应顺序:keydown → keypress → keyup。
  • 对于非字符键(如功能键或特殊键)来说,键盘事件的相应顺序:keydown → keyup。
  • 如果按下字符键不放,则 keydown 和 keypress 事件将逐个持续发生,直至松开按键。
  • 如果按下非字符键不放,则只有 keydown 事件持续发生,直至松开按键。

(5) JavaScript 监听回车事件

jQuery用法:

$("#loginListen").bind("keydown", function (e) {
	//兼容浏览器的事件
    let theEvent = e || window.event;
    //兼容各浏览器的键盘事件
    let keyCode = theEvent.keyCode || theEvent.which || theEvent.charCode;
    if (keyCode == 13) {
        console.log("回车执行");
        $("#loginOp").click();
        //当然也可以禁止回车事件
        //theEvent.keyCode = 0;
        //theEvent.returnValue = false;
    }
})

说明:
a) $(“#loginListen”) 表示获取id为loginListen的标签元素,这是jQuery的写法,所以在使用时项目中需要先安装jQuery。
b) bind(“keydown”, function (e){…}),表示绑定keydown事件。
c) keyCode == 13表示回车事件。
d) $(“#loginOp”).click();表示id为loginOp的标签点击事件,这个标签一般来说为按钮。

原生js用法:

// 回车搜索
$(function () {
    // 定位搜索输入框并
    let keyinput = document.getElementById("querykeyword")
    // 绑定keyup事件--当为keyup(键盘按下抬起时执行)时执行后面的function
    keyinput.onkeyup = function (e) {
        //兼容浏览器的事件
        let theEvent = e || window.event;
        //兼容各浏览器的键盘事件
        let keyCode = theEvent.keyCode || theEvent.which || theEvent.charCode;
        if (theEvent && keyCode == 13) { //回车键的键值为13
            // 获取输入框中的值
            let keyword = keyinput.value
            console.log("值是:" + keyword);
            // 发送搜索请求
            $.get("/book/query", { "keyword": keyword }, function (result) {
                console.log("模糊查询结果:", result)
                console.log(typeof result)
                // 根据查询结果给出不同显示
                console.log("查询结果返回的字符串:", JSON.stringify(result))
                if (JSON.stringify(result) === "{}") {
                    // 如果是{}则alert
                    alert("没有" + keyword + "相关的内容!")
                } else {
                    // 如果不是{}则展示
                    // 根据返回数据动态创建表格
                    createTable(result)
                }
            });
        }
    };
});

说明:
a)使用Element类中的属性onkeyup获取监听事件;
b)function (e)是事件的回调函数,也就是获取到事件之后执行的逻辑;

(5) Keycode对照表