1、form表单
表单主要负责数据采集功能,通过FORM把采集的信息提到服务器进行处理。
(1)基本使用
白经网认为,三部分组成:表单标签、表单域(表单域:文本,密码,隐藏,多行,筛选,单选等)、表单按钮。
form表单的属性是用来规定如何把信息提交到服务器:
action:
向何处发送表单数据,其属性是后端提供的一个URL地址;如果没有指定属性值,提交到当前页面;当提交页面表单后,页面会立即跳转到action属性值指定的URL。
target
可选值有5个,属性值_self默认在相同的框架下打开,_blank在新窗口打开,_parent在父窗口中打开,_top在整个窗口中打开。
method
以何种方式把表单数据提到到action url。默认是get,把数据提交到action url,URL中有提交的数据;post,数据不在URL中,相对安全。 name对应表单域的名子,填写之后,会在URL中显示。
get简单的,少量的数据;而大量的,上传的,涉及安全性的用post。
enctype
有3个参数,默认是application/x-www-form-urlencoded,表示在发送前编码所有字符;multipart/form-data不对字符进行编码,在使用包含文件上传控制的表单时必须使用该值;text/plain,空格转化为加号,但是不对字符编码,很少用。
表单的同步提交
通过提交按钮,页面会跳转到action指定的页面。缺点是,跳转一用户指定的页面,用户体验差;页面之前的状态和数据会丢失;如何解决这两个问题:
可以让表单只采集数据,让ajax提交数据。
(2)通过ajax提取表单数据
使用ajax操作元素之前,都要先引入jQuery。
①监听表单提交事件
方法1
<script>
$(function() {
$('#form').submit(function() {
alert('监听到了submit提交事件')
})
})
</script>
方法2
<script>
$(function() {
$('#form').on('submit',function() {
alert('监听表单提交了哈哈')
})
})
</script>
②阻止表单提交的默认行为
也就是不让表单提交后跳转到新的页面,不管哪个表单事件,都可以通过事件对象阻止表单的默认行为
<script>
$(function() {
$('#form').on('submit',function(e) {
alert('监听表单提交了哈哈')
e.preventDefault();
})
})
③获取表单中的所有数据
常规的方法,通过DOM也可以获取表单中的数据,但是可以使用serialize()一次获取表单中的所有数据。使用serialize()函数时,必须要给每个元素添加name属性。
<script>
$(function() {
$('#form').on('submit',function(e) {
e.preventDefault();
// var data = $(this).serialize();
var data = $('#form').serialize();
console.log(data);
})
})
</script>
(3)案例:评论列表
引入bootstrap和jQuery之后,再组织代码结构、JS内容。
<body style="padding: 20px">
<!-- 评论面板 -->
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">发表评论</h3>
</div>
<form class="panel-body" id="form">
<div>评论人</div>
<input type="text" class="form-control" name="username">
<div>评论内容</div>
<textarea class="form-control" name="content" id=""></textarea>
<button class="btn btn-primary">发表评论</button>
</form>
</div>
<!-- 评论列表 -->
<ul class="list-group" id="cmtlist">
<li class="list-group-item">
<span class="badge" style="background-color: orange">评论时间:</span>
<span class="badge" style="background-color:skyblue">评论人:</span>
Item 1
</li>
</ul>
<script>
//1.获取评论列表
function getComment() {
$.ajax({
method: 'get',
url: 'http://www.liulongbin.top:3006/api/cmtlist',
data: {},
success: function(e) {
console.log(e);
if(e.status !== 200) return alert('获取数据失败')
// 1、定义一个空数据用来接收服务器响应的数据
var rows = [];
//2.循环从服务器上获取数据并存入空数组
$.each(e.data,function(i,item) {
var str = '<li class="list-group-item"><span class="badge" style="background-color: orange">评论时间:' + item.time + '</span><span class="badge" style="background-color:skyblue">评论人:' + item.username + '</span>' + item.content + '</li>';
rows.push(str);
})
//3.把获取的数组元素拼接后放入UL列表
$('#cmtlist').empty().append(rows.join(''));
}
})
}
getComment();
//2.提交数据
$(function() {
// 2-1监听提交按钮
$('#form').submit(function(e) {
// 2-2阻止默认行为
e.preventDefault();
// 2-3获取评论人、评论内容数据
var data = $(this).serialize();
// 2-4提交数据
$.post('http://www.liulongbin.top:3006/api/addcmt',data,function(e) {
if(e.status !== 201) {
return alert('提交数据失败');
}
// 2-5刷新评论列表
getComment();
//2-6清空输入框
$('#form')[0].reset();
})
})
})
</script>
</body>
2、模板引擎
通过字符串拼接的形式渲染UI结构,如果UI结构比较复杂,需要特别注意UI之间标签的嵌套,修改也非常麻烦。模板引擎可以解决这样的问题。
(1)基本概念
根据程序员的模板结构和数据,自动生成一个完整的HTML结构。把数据和模板结构提交给模板引擎,会自动生成HTML结构。
减少了字符串的拼接过程;代码结构更加清楚;代码更易于阅读与后期的维护。
(2)art-tempplate模板引擎
简约、超快的模板引擎,查看官网首页。
①传统方式渲染UL结构与数据
<body>
<div class="info"></div>
<div>姓名:<span class="name"></span></div>
<div>年龄:<span class="age"></span></div>
<div>isVIP:<span class="isvip"></span></div>
<div>注册时间:<span class="regTime"></span></div>
<div>业余爱好:
<ul id="hobby">
<li>爱好1</li>
<li>爱好1</li>
<li>爱好1</li>
</ul>
</div>
<script>
var data = {
title: '<h3>用户信息</h3>',
name: 'zs',
age: 20,
isVIP: true,
regTime: new Date(),
hobby: ['吃饭', '睡觉', '打豆豆']
}
$(function() {
$('.info').html(data.title);
$('.name').html(data.name);
$('.age').html(data.age);
$('.isvip').html(data.isVIP);
$('.regTime').html(data.regTime);
var rows = [];
$.each(data.hobby,function(i,item) {
var str = '<li>' + item + '</li>';
rows.push(str);
})
$('#hobby').html(rows.join(''));
})
</script>
</body>
②模板引擎的使用步骤
导入art-tempplate
定义数据:定义一个数据对象
定义模板:模板的HTML结构必须定义到script标签中,type="text/html"
调用template函数:两个参数分别为模板的ID,渲染的数据对象
渲染HTML结构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./bootstrap-3.4.1-dist/css/bootstrap.min.css">
<script src="./jquery-3.6.0/jquery-3.6.0.min.js"></script>
<!-- 1.导入模板库 -->
<script src="./jquery-3.6.0/template-web.js"></script>
</head>
<body>
<div id="container"></div>
<!-- 3.定义模板,必须指定type和id -->
<script type="text/html" id="tpl-user">
<h1>{{ name }}--{{ age }}岁了</h1>//两个花括号内放数据对象的属性名,即可调用数据
</script>
<script>
//2.定义数据
var data = {
name: '白龙网',
age: 18
}
//4.调用模板函数,需要指定模板ID与数据对象
var str = template('tpl-user',data);
//5.使用DOM把数据渲染到HTML
$('#container').html(str)
</script>
</body>
</html>
③标准语法
又花括号可以进行变量输出,循环输出。可以是变量{{value}}、对象属性{{obj.key}}、{{obj['key']}}、三元表达式{{a ? b : c}}、逻辑运算{{a || b}}、算术运算{{a + b}}等。
过滤器,需要处理的值,以参数的形式提交给过滤器函数,通过返回值,输出新值,过滤器函数本质上是一个函数。{{ value | filterName }}。注册过滤器函数的语法:
template.defaults.inports.filterName = function(value) {return处理结果}。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./bootstrap-3.4.1-dist/css/bootstrap.min.css">
<script src="./jquery-3.6.0/jquery-3.6.0.min.js"></script>
<script src="./jquery-3.6.0/template-web.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/html" id="tpl-user">
<!-- 1、原文输出 -->
{{@ Text }}
<!-- 2、条件输出 -->
{{if flag === 0}}
输出flag的值是0
{{else if flag === 1}}
输出flag的值是1
{{/if}}
<!-- 3、循环输出 -->
以each开始并添加数组名,以each结束,$index表示索引号,$value表示索引项
<ul>
{{each hobby}}
<li>{{ $index }},{{ $value }} </li>
{{/each}}
</ul>
<!-- 4.过滤器 -->
<h1>{{ regTime | dateFormat }}</h1>
</script>
<script>
template.defaults.imports.dateFormat = function(date) {
var y = date.getFullYear();
var m = date.getMonth() + 1;
var d = date.getDate();
return y + '-' + m + '-' + d;
}
var data = {
name: '白龙网',
age: 18,
Text: '<h3>原文输出添加@</h3>',
flag: 1,
hobby: ['学习','爬山','健身'],
regTime: new Date()
}
var str = template('tpl-user',data);
$('#container').html(str)
</script>
</body>
</html>
案例1:新闻列表获取数据
该案例涉及模板引擎的的使用,循环列表的定义,获取新闻列表,时间过滤函数,补0函数等功能。
<html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="./assets/news.css">
<script src="./lib/jquery.js"></script>
<script src="./lib/template-web.js"></script>
<script src="./js/news.js"></script>
</head>
<body>
<div id="news-list"></div>
<!-- 定义模板 -->
<script type="text/html" id="tpl-news">
{{each data}}
<div class="news-item">
<img class="thumb" src="{{'http://www.liulongbin.top:3006' + $value.img}}" alt="">
<div class="right-box">
<h1 class="title">{{$value.title}}</h1>
<div class="tags">
{{each $value.tags}}
<span>{{$value}}</span>
{{/each}}
</div>
<div class="footer">
<div>
<span>{{$value.source}}</span>
<span>{{$value.time | dateFormat}}</span>
</div>
<span>评论数:{{$value.cmtcount}}</span>
</div>
</div>
</div>
{{/each}}
</script>
<script>
// 定义过滤器
template.defaults.imports.dateFormat = function(datestr) {
var dt = new Date(datestr);
var y = dt.getFullYear();
var m = padZero(dt.getMonth() + 1);
var d = padZero(dt.getDate());
var hh = padZero(dt.getHours());
var mm = padZero(dt.getMinutes());
var ss = padZero(dt.getSeconds());
return y + '-' + m + '-' + d + ' ' + hh + ':' + mm + ':' + ss;
}
// 补0函数
function padZero(n) {
if (n < 10) {
return '0' + n;
} else {
return n;
}
}
// 获取新闻列表
$(function() {
function getNewslist() {
$.get('http://www.liulongbin.top:3006/api/news',function(e) {
if (e.status !==200) {
return alert('获取新闻列表失败');
}
for (var i = 0 ; i < e.data.length; i++) {
e.data[i].tags = e.data[i].tags.split(',');
}
console.log(e);
var htmlstr = template('tpl-news',e);
$('#news-list').html(htmlstr);
})
};
getNewslist();
})
</script>
</body>
</html>
(3)模板引擎的基本原理
①exec()函数
检测字符串中的正则表达式是否匹配,如果字符串中有匹配的值,则返回匹配值,否则就返回null.
<script>
var str = 'hello';
var pattern = /o/;
var result = pattern.exec(str);
console.log(result);
</script>
②提取分组()
<script>
var str = '<div>我是{{nameMy}}</div>';
var pattern = /{{([a-zA-z]+)}}/;
var result = pattern.exec(str);
console.log(result);
</script>
③替换内容replace()
用一部分内容替换另外一部分内容。先定义字符串,再写正则,打印匹配结果,再用第一个元素替换第二个元素。
<script>
var str = '<div>我是{{nameMy}}</div>';
var pattern = /{{([a-zA-Z]+)}}/;
var patternResult = pattern.exec(str);
str = str.replace(patternResult[0],patternResult[1]);
</script>
④多次匹配替换
这里需要注意的是\s*表示匹配0至多个空格。
<script>
var str = '<div>{{ name }}今年{{ age }}岁了</div>';
var pattern = /{{\s*([a-zA-Z]+)\s*}}/;
var patternResult = pattern.exec(str);
// 第一次匹配到name
str = str.replace(patternResult[0],patternResult[1]);
console.log(str);
// 第二次匹配age
var patternResult2 = pattern.exec(str);
console.log(patternResult2);
str = str.replace(patternResult2[0],patternResult2[1]);
console.log(str);
// 第三次匹配null
var patternResult3 = pattern.exec(str);
console.log(patternResult3);
</script>
⑤循环多次替换操作
根据匹配结果,判断是否循环替换内容,简化了程序。
<script>
var str = '<div>{{ name }}今年{{ age }}岁了,他读{{ grade }}年级了</div>';
var pattern = /{{\s*([a-zA-Z]+)\s*}}/;
var patternResult = null;
while(patternResult = pattern.exec(str)) {
str = str.replace(patternResult[0],patternResult[1]);
}
console.log(str);
</script>
从对象中获取数据替换字符串中的内容,需要注意的是data[patternResult[1]]中方括号内不能加引号
<script>
var data = {
name: '白龙网',
age: 20,
grade:30
}
console.log(data.name);
console.log(data['age']);
var str = '<div>{{ name }}今年{{ age }}岁了,他读{{ grade }}年级了</div>';
var pattern = /{{\s*([a-zA-Z]+)\s*}}/;
var patternResult = null;
while(patternResult = pattern.exec(str)) {
str = str.replace(patternResult[0],data[patternResult[1]]);
}
console.log(str);
</script>
⑥实现简易的模板引擎
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./jquery-3.6.0/template-web.js"></script>
</head>
<body>
<div id="user-box"></div>
<!-- 1、定义模板结构 -->
<script type="text/html" id="tpl-user">
<div>姓名:{{name}}</div>
<div>年龄:{{ age }}</div>
<div>性别:{{ gender}}</div>
<div>地址:{{address }}</div>
</script>
<!-- 2、定义数据调用模板引擎渲染数据 -->
<script>
//2-1定义数据
var data = {
name: '白龙网',
age: 20,
gender: '男',
address: '北京海淀中关村'
}
//2-2调用模板引擎
var htmlstr = template('tpl-user',data);
//2-3定当HTML结构
document.getElementById('user-box').innerHTML = htmlstr;
//2-3封闭函数
</script>
<!-- 3、封装函数 -->
<script>
function template(id,data) {
var str = document.getElementById('id').innerHTML;
var pattern = /{{\s*([a-zA-Z]+)\s*}}/;
var patternResult = null;
while(patternResult = pattern.exec(str)) {
str = str.replace(patternResult[0],data[patternResult[1]]);
}
return str;
}
</script>
</body>
</html>