前端调试指南指北

3,662 阅读12分钟

做人做事,安全第一

目录

1. input文本框按回车【Enter】键触发Form表单提交

现象描述: form表单中包含input text文本输入框,在input text文本框中完成输入后,直接按回车键【Enter键】,将会触发form表单提交。

input text按回车enter触发form表单提交

原因解析:

button的type="submit"时(默认为submit),input文本框(input type="text")输入后,直接按回车键【Enter键】将触发提交。

button的type="button"时,input文本框输入后,直接按回车键不会触发提交。

代码示例:

<!DOCTYPE html>
<html>
<head>
    <title>防止input文本框回车提交Form表单演示</title>
</head>
<body>
	<form method="post">
	    请输入用户ID: <input type="text" name="userid" id="userid" />
	    <br>	
	    请输入用户姓名: <input type="text" name="username" id="username" />
	    <br>
	    <!-- 1. 无type属性或type属性值为submit时,在input文本框中按Enter键都将触发提交操作 -->
	    <!-- 2. type属性值为button时,在input文本框中按Enter键不触发提交操作 -->
	    <button type="submit" onclick="commit_onclick()">点击提交</button>
	</form>	
	<script>
	    function commit_onclick() {
	        var userid = document.getElementById("userid").value;
	        var username = document.getElementById("username").value;
	        window.alert('Hello ' + userid + '[' + username + ']');
	    }
	</script>
</body>
</html>

说明:form表单中包含tabletable中包含input text输入框,也是类似的情况


2. 前端控制台抛出异常:Uncaught TypeError: $(...).bootstrapTable is not a function

异常原因总结:

<1> jQuery和bootstrap顺序颠倒

<2> js文件重复导入

<3> 没有初始化bootstrapTable,直接refresh

<4> bootstrap版本和bootstrap-table版本不匹配

详细分析如下:

<1> jQuery和bootstrap顺序颠倒

引入js时,jQuery必须放在最前面,然后是bootstrap,顺序不能颠倒。

Bootstrap官网(Bootstrap 4.0版本)给出了的模板,如下:

( 链接为 : v4.bootcss.com/docs/4.0/ge…

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <title>Hello, world!</title>
  </head>
  <body>
    <h1>Hello, world!</h1>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdn.bootcss.com/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://cdn.bootcss.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
  </body>
</html>

涉及到bootstrap-table,bootstrap-table-zh-CN(汉化),给出正确的导入顺序,如下:

<script src="${pageContext.request.contextPath}/js/jquery-3.1.0.min.js"></script>
<script src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
<script src="${pageContext.request.contextPath}/js/bootstrap-table.min.js"></script>
<script src="${pageContext.request.contextPath}/js/bootstrap-table-zh-CN.min.js"></script>

<2> js文件重复导入

在同一个html或jsp文件中,js文件一般不会重复导入,没有人会这么干,除非前后放置位置不同,没有发现,删掉重复的js即可。

一般出现js文件重复导入都是在html或jsp文件有嵌套的情况,如下所示:

index.jsp文件 : 已经导入了bootstrap相关js文件

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"/>
    <title>Hello, RangDanDanFei</title>
</head>
<body>
<%@ include file="/jsp/head.jsp" %>
<h1>Hello, RangDanDanFei</h1>

<script src="${pageContext.request.contextPath}/js/jquery-3.1.0.min.js"></script>
<script src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
<script src="${pageContext.request.contextPath}/js/bootstrap-table.min.js"></script>
<script src="${pageContext.request.contextPath}/js/bootstrap-table-zh-CN.min.js"></script>
</body>
</html>

head.jsp文件 : 重复导入了bootstrap相关js文件

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div class="panel panel-default">
    <div class="panel-heading"></div>
    <div class="panel-body">
        <div class="row">
            <div class="col-sm-2"></div>
        </div>
    </div>
</div>

<script src="${pageContext.request.contextPath}/js/jquery-3.1.0.min.js"></script>
<script src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
<script src="${pageContext.request.contextPath}/js/bootstrap-table.min.js"></script>
<script src="${pageContext.request.contextPath}/js/bootstrap-table-zh-CN.min.js"></script>

<3> 没有初始化bootstrapTable,直接refresh

Stack Overflow有该问题的描述以及解答,链接地址为:stackoverflow.com/questions/5…

<4> bootstrap版本和bootstrap-table版本不匹配

尝试升级其中一个版本


3. input文本框禁止输入

有两种方式:

<1> 增加readonly属性:表示该输入域只能读,不能写,可复制,可选择,可接收焦点,后台会接收到传值。

<input type="text" name="inputname" readonly="readonly" />

注意:readonly属性只能与type="text"配合使用

<2> 增加disabled属性:不可编辑,不可选择,不能接收焦点,后台不会接收到传值,页面显示置灰。

<input type="text" name="inputname" disabled="disabled" /> 

4. input文本框自动清除用户输入记录

增加autocomplete="off"属性,即可在每次重新请求页面时,自动清空用户输入记录。

<input type="text" autocomplete="off" />

相对应:
autocomplete="on"或者默认没有autocomplete属性,每次不会自动清空用户输入记录。

5. input文本框输入值的监听

总结:

<1> 文本框输入完成,失去焦点,触发change事件监听:

$('#id').on('change', function() {...})
或 $('#id').change(function() {...})
或 $('#id').bind('change', function() {...});

<2> 文本框输入值实时变化,触发input事件或者propertyChange事件监听:

$('#id').on('input propertychange', function() {...})
或
$('#id').bind('input propertychange', function() {...});

详细解析:

<1> 失去焦点的监听:即在文本框输入完成后,将焦点切出,触发change事件

触发change事件,需要满足以下两个条件:

1. 当前对象属性改变,并且是由键盘或鼠标事件触发的(脚本触发的无效)
2. 当前对象失去焦点

三种实现方式如下:

1. $('#id').on('change', function() {...});
2. $('#id').change(function() {...});
3. $('#id').bind('change', function() {...});

扩展:

change事件还可以用于以下事件:

1. select选择框:选中项发生变化

2. checkbox复选框:选中状态发生变化
    <input type="checkbox" id="checkboxId" />

3. radio单选按钮:选中状态发生变化
    <div>
        <input type="radio" name="colors" value="red"/>红色<br>
        <input type="radio" name="colors" value="blue"/>蓝色<br>
        <input type="radio" name="colors" value="green"/>绿色<br>	
    </div>

示例代码如下:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<title>input文本框输入失去焦点的监听</title>
</head>
<body>
	<input type="text" id="textId" placeholder="请输入字符!" /><i id="textTip"></i>
	<br>

	<select id="selectId">
		<option value="bejing">北京</option>
		<option value="shanghai">上海</option>
		<option value="shenzhen">深圳</option>
	</select>
	<i id="selectTip"></i>
	<br>

	<input type="checkbox" id="checkboxId" /><i id="checkboxTip"></i>
	<br>

	<div id="radioId">
		请选择你喜欢的颜色!<br>
		<input type="radio" name="colors" value="red"/>红色<br>	
		<input type="radio" name="colors" value="blue"/>蓝色<br>
		<input type="radio" name="colors" value="green"/>绿色<br>	
	</div>
	<i id="radioTip"></i>
	
	<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
	<script>
		$(document).ready(function() {
			$('#textId').on('change', function(){
				$('#textTip').html("共输入了 " + $(this).val().length + " 个字符!");
			});

			$('#selectId').on('change', function() {
				$('#selectTip').html("您选择的城市是" + $(this).find("option:selected").text());
			});

			$('#checkboxId').on('change', function() {
				if (document.getElementById("checkboxId").checked == true) {
					$('#checkboxTip').html("您已经选中");
				} else {
					$('#checkboxTip').html("您已经取消选择");
				}
			});

			$('#radioId').on('change', function() {
				var radios = document.getElementsByName('colors');
				for (var i = 0, len = radios.length; i < len; i++) {
					if (radios[i].checked) {
						$('#radioTip').html("您喜欢的颜色是" + radios[i].nextSibling.data);
						break;
					}
				}
			});
		});
	</script>
</body>
</html>

失去焦点监听示例代码执行展示

<2> 实时监听:实时监听文本框中值的变化,触发input事件或者propertyChange事件

input事件:是HTML5的标准事件,一般浏览器都支持。当input的value发生变化时,无论是键盘输入、鼠标粘贴或脚本修改都能触发。IE9以下版本不支持input事件。

propertychange事件(IE专属):只要当前对象属性发生改变,都会触发,不仅仅会监听到input的value属性,还包括其他的属性标签,比如:span元素的style属性改变。同时在事件发生时还可以用 event.propertyName 访问到改变的属性名。

(由于IE9以下不支持input事件,所以要用到IE的专属propertychange事件)

实现方式:

1. $('#id').on('input propertychange', function() {...});
2. $('#id').bind('input propertychange', function() {...});

示例代码:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<title>input文本框输入实时监听</title>
</head>
<body>
	<input type="text" id="textId" placeholder="请输入字符!" /><i id="textTip"></i>

	<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
	<script>
		$(document).ready(function() {
			$('#textId').on('input propertychange', function() {
				$('#textTip').html("您已经输入了 " + $(this).val().length + " 个字符!");
			});
		});
	</script>
</body>
</html>

实时监听示例代码执行展示


6. 获取表格指定的行,列

先看一下HTML构建简单表格的结构:

simple_table_structure

对简单表格操作总结:

  1. 获取表格行数
形式1: $('#tableId tr').length
形式2: $('#tableId').find('tr').length
  1. 获取表格列数
形式1: $('#tableId th').length
形式2: $('#tableId tr:eq(1) td').length
形式3: $('#tableId tr:eq(1)').find('td').length
注意:表头行标签形式为:
<thead>
  <tr>
      <th></th>
      <th></th>
  </tr>
</thead>
<tr>中嵌套的标签是<th>,不是<td>
所以上面形式2,形式3中选择器:eq(index)的index值不是0,即跳过表头
  1. 获取表格某一行的值
例如:获取表格第二行的值(表头算表的第一行)
形式1: $('#tableId tr:eq(1)').text();
形式2: $('#tableId tr').eq(1).text();
形式3: $('#tableId').find('tr').eq(1).text();
  1. 获取表格某一行某一列的值
例如:获取表格第二行第一列的值(表头算表的第一行)
形式1: $('#tableIndex tr:eq(1) td:eq(0)').text()
形式2: $('#tableIndex tr').eq(1).find('td:eq(0)').text())
形式3: $('#tableIndex').find('tr').eq(1).find('td').eq(0).text())

说明:

1. jQuery选择器:
<1> $('#tableId tr') 表示:匹配id为"tableId"的表格下的<tr>元素
<2> $(':eq(index)') 表示:选择器选取带有指定index值的元素,index值从0开始,所有第一个元素的index值是0
    如果index是负数,则从集合中的最后一个元素倒着往回计数
    例如:$('#tableId tr:eq(-1)') 表示:id为"tableId"的表格的倒数第一行

2. jQuery方法:
<1> .eq(index) 表示:匹配元素集合中索引为index的元素上,index值从0开始,表示第一个元素,
    如果index是负数,则从集合中的最后一个元素倒着往回计数

代码示例:

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <title>Hello, Simple Table!</title>
  </head>
  <body>
    <table id="usertable" border="1">
      <thead>
        <tr>
          <th>ID</th>
          <th>姓名</th>
          <th>职业</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>让蛋蛋飞</td>
          <td>尼古拉斯蛋蛋</td>
          <td>程序员</td>
        </tr>
        <tr>
          <td>夏至未至</td>
          <td>李木子</td>
          <td>医生</td>
        </tr>
      </tbody>
    </table>
    <br>
    <div id="rowSize"></div>
    <div id="colSize"></div>
    <div id="tipth"></div>
    <div id="tiptr"></div>
    <div id="tiptd"></div>
    <div id="tiptrtd"></div>

    <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
    <script>
      $(document).ready(function() {
        $('#rowSize').html("此表共" + $('#usertable tr').length + "行");
        $('#colSize').html("此表共" + $('#usertable th').length + "列");
        $('#tipth').html("此表表头的值为:" + $('#usertable th').text());
        $('#tiptr').html("此表第二行(表头为第一行)的值为:" + $('#usertable tr:eq(1)').text());
        $('#tiptd').html("此表第一列的值为:" + $('#usertable td:nth-child(1)').text());
        $('#tiptrtd').html("此表第三行第二列的值为:" + $('#usertable tr:eq(2) td:eq(1)').text());
      });
    </script>
  </body>
</html>

simple_table

说明:
:nth-child(n)是CSS3选择器,匹配属于其父元素的第 N 个子元素,不论元素的类型。不支持IE8及更早版本。

实例解析:
$('#usertable td:nth-child(1)'):在usertable表中td的父元素为tr,则td是子,tr是父,
表示匹配tr中第一个子元素td,表中有两行<tr>包含<td>,因此最终会匹配到usertable表中第一列的值(不含表头)。

延伸:
:nth-child(n)中 n 可以为公式,(an + b)表示:周期的长度,n是计数器(从0开始),b是偏移量。
示例:指定了下标是3的倍数的所有p元素的背景色
p:nth-child(3n+0) {
    backgroup:#ff0000;
}

7. 获取表格中控件的值

有两种方式:以#6中的表格为例(表头为第一行)

方式一:

例如:获取usertable表第二行中id="userid"或name="userid"的文本框(input text)的值
$('#usertable tr:eq(1)').find('#userid').val();
或者 
$('#usertable tr:eq(1)').find('input[name="userid"]').val();

方式二:

例如:只知某表的某行中文本框组件id为"userid",表的相关信息不知,想要获取该行中文本框name="userjob"的值
$('#userid').closest('tr').find('input[name="userjob"]').val();

某表某行input id=

说明:
jQuery的closest()方法:
.closest(selector) : 从当前元素开始,沿DOM树向上遍历,直到找到一个匹配selector的元素为止,然后返回一个包含该找到元素的jQuery对象。
(未找到的话,则返回0个)

实例解析:
$('#userid').closest('tr').find('input[name="userjob"]').val(): 选择器先匹配找到id="userid"的元素,
然后从该元素开始,沿DOM树向上找<tr>元素,匹配到一个后返回,即定位到了该行,
然后用find找出该行name="userjob"的文本框,取值。

延伸:
.closest(selector, DOMContext) : 表示从当前元素开始,在指定的DOM元素范围中遍历搜索。
示例:
DOM树结构如下:
<ul>
  <li id="i1">I1</li>
  <li id="i2">I2
    <ul>
      <li class="item-a">Item A</li>
      <li class="item-b">Item B</li>
      <li class="item-c">Item C</li>
    </ul>
  </li>
  <li id="i3">I3</li>
</ul>  

$('li.item-a').closest('ul', document.getElementById('i2')): 表示从Item A元素开始,指定遍历搜索的DOM范围是id="i2"的列表元素集合。

8. 表头thead随表体tbody横向滚动

问题描述:

浏览器的窗口切换过后,发现表格的表头不随表体横向滚动,导致列标题与实际列数据错位。

解决方法:

  1. HTML编写的简单表格: 用<div>标签包裹<table>标签,并设置div的样式为:overflow-x: auto;

  2. bootstrapTable插件初始化的表格,去掉height属性

代码示例:

See the Pen thead_horizontal_scroll by rangdandanfei (@rangdandanfei) on CodePen.


9. 表头固定,不随滚动

现象描述:

当表格出现垂直滚动条时,让表头固定住,不随垂直滚动条上下移动。

表格垂直滚动时表头固定

解决方式:

方式一:BootstrapTable实现的table : 在<table>标签上增加data-height属性值,即可固定表头。【推荐这种方式】

<table id="table" data-toggle="table" data-height="460" data-url="https://examples.wenzhixin.net.cn/examples/bootstrap_table/data">
说明:data-url用来给table提供数据

BootstrapTable插件为我们提供了很好示例,见官方链接:examples.bootstrap-table.com/#options/ta…

注意:使用data-height属性时,官方API给出了如下提示:

Note that if there are multiple tables on a page and the height option is set at the same time, you need to add the id attribute to each table, otherwise, the window resize will not work properly.

即:一个页面有多个表时,且表都设置了"data-height"属性值,则要给每个表添加"id"属性,否则浏览器窗口大小切换调整,表格就不能正常工作。

代码示例:

<!DOCTYPE html>
<html>
<head>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://unpkg.com/bootstrap-table@1.15.4/dist/bootstrap-table.min.css" rel="stylesheet">
    <title>BootstrapTable表头固定</title>
</head>
<body>
    <table id="table" data-toggle="table" data-height="460" data-url="https://examples.wenzhixin.net.cn/examples/bootstrap_table/data">
        <thead>
            <tr>
                <th data-field="id">ID</th>
                <th data-field="name">Item Name</th>
                <th data-field="price">Item Price</th>
            </tr>
        </thead>
    </table>
    <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
    <script src="https://unpkg.com/bootstrap-table@1.15.4/dist/bootstrap-table.min.js"></script>
</body>
</html>

方式二:头身分离法

基于Bootstrap的CSS样式实现头身分离,表头固定,不用js脚本:

  1. 使用两个<table>,一个只有表头<thead>,一个只有表体<tbody>,分别用<div>包裹

  2. 表体的div增加class="pre-scrollable"实现,即带滚动条

    表体的div增加style="height:100px; margin-top:-22px;"样式

   说明:margin-top: 设置上边距,调整设置为一个负值,使表头div底线与表体div顶线重合,即两个表拼接成一个表
         当表行内容超过设置的heigh值时,出现垂直滚动条,这时上下滚动时,表头固定,表体随动。

代码示例:

<!-- 导入bootstrap.css样式 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
<div>
    <table class="table table-striped">
        <thead>
            <tr>
                <th>Heading</th>
                <th>Heading</th>
                <th>Heading</th>
            </tr>
        </thead>
    </table>
</div>
<div class="pre-scrollable" style="height:100px; margin-top: -22px;">
    <table class="table table-striped table-hover">
        <tbody>
            <tr>
                <td>RowCell</td>
                <td>RowCell</td>
                <td>RowCellg</td>
            </tr>
            <tr>
                <td>RowCell</td>
                <td>RowCell</td>
                <td>RowCellg</td>
            </tr>
            <tr>
                <td>RowCell</td>
                <td>RowCell</td>
                <td>RowCellg</td>
            </tr>
        </thead>
    </table>
</div>