共计 10652 个字符,预计需要花费 27 分钟才能阅读完成。
温习呢有一个很直观的感触,就是以前学的货色,萌懂半懂的,这一来全副都分明了,你以前认为你学的并不好然而温习一次把以前的案例一做,竟然可能本人独立实现,知识点看着把握的还不错。
1.
两天工夫就把整个 ajax 温习完了,一天目前还临时做不到哈哈,的确还是有很多案例都要思考一会,间接从案例下手吧,一个图书治理的案例,在这个案例外面吧就是用三个接口来获取图书,减少图书,删除图书,在 js 方面没多大问题,在 html 方面,还让我多相熟了下 vscode 疾速编程 bootstrap,间接 bs3,form-inline 类名能够让每个表单项为行内块元素,table-hover 能够减少表格的每一行悬停成果。
获取图书列表:封装为一个函数,通过 ajax 发动 get 申请,而后把拿到的数据通过 foreach 循环进去。
减少图书列表:也是发动一起申请,而后要从新获取一下列表
<!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="./lib/bootstrap.css">
<style>
.panel-body {text-align: center;}
.input-group {
width: 30%;
margin: 0 10px;
}
.panel {
width: 90%;
margin: 0 auto;
}
.table {
width: 90%;
margin: 15px auto 0;
}
</style>
</head>
<body>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"> 增加新图书 </h3>
</div>
<!-- 1. 增加了一个类名 form-inline 可使外面的表单元素变成行内块元素 -->
<div class="panel-body form-inline">
<div class="input-group">
<div class="input-group-addon"> 书名 </div>
<input type="text" class="form-control bookname" id="exampleInputAmount" placeholder="请输出书名">
</div>
<div class="input-group">
<div class="input-group-addon"> 作者 </div>
<input type="text" class="form-control author" id="exampleInputAmount" placeholder="请输出作者">
</div>
<div class="input-group">
<div class="input-group-addon"> 出版社 </div>
<input type="text" class="form-control publisher" id="exampleInputAmount" placeholder="请输出出版社">
</div>
<button type="button" class="btn btn-primary"> 增加 </button>
</div>
</div>
<!-- 2.table-borderred 能够为每一个表单元素减少边框 table-hover 增加鼠标滑过表单的悬停状态 -->
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>id</th>
<th> 书名 </th>
<th> 作者 </th>
<th> 出版社 </th>
<th> 操作 </th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script src="./lib/jquery.js"></script>
<script>
/* $.get('http://www.liulongbin.top:3006/api/getbooks', res => {// console.log(res);
if (res.status !== 200) return console.log(获取数据失败);
let htmlStr = ''let str =''
res.data.forEach(item => {
htmlStr = `<tr>
<td>${item.id}</td>
<td>${item.bookname}</td>
<td>${item.author}</td>
<td>${item.publisher}</td>
<td><a href="javascript:;"> 删除 </a></td>
</tr>`
str += htmlStr
})
document.querySelector('tbody').innerHTML = str
}) */
// 3. 下面我本人的做的办法诚然能够然而这里既然是用的 jq 那就用 jq 的办法来实现
function getBook() {
$.ajax({
method : 'get',
url : 'http://www.liulongbin.top:3006/api/getbooks',
success : res => {if (res.status !== 200) return alert('获取数据失败')
// jq 的循环办法
// 留神这里的 i 不能省略
let arr = []
$.each(res.data, (i, item) => {
arr.push(`<tr>
<td>${item.id}</td>
<td>${item.bookname}</td>
<td>${item.author}</td>
<td>${item.publisher}</td>
<td><a href="javascript:;" data-id="${item.id}" class="del"> 删除 </a></td>
</tr>`)
})
$('tbody').empty().append(arr.join(''))
}})
}
getBook()
// 删除图书模块
function delBook() {
// 4. 删除图书也要用到一个接口
// 4.1 留神这里的 jq 的事件委托,在后辈选择器这里,不论是写 id 还是 class 还是标签都不再须要 $ 符号间接引号写上来即可
$('tbody').on('click', '.del' , function() {
// 这里点谁就会触发谁,用到了事件委托,阐明当初每个 a 标签上也有点击事件了他们就是事件的调用者
// attr 这个办法能够设置能够获取属性的值,删除用 removeAttr
let id = $(this).attr('data-id')
console.log(id);
$.get('http://www.liulongbin.top:3006/api/delbook', {id : id}, res => {if (res.status !== 200) return alert('删除失败')
// 删除胜利刷新一下表格
getBook()})
})
}
delBook()
// 增加图书模块
function addBook() {$('.btn').on('click', function() {
$.post('http://www.liulongbin.top:3006/api/addbook',{bookname : $('.bookname').val(),
author : $('.author').val(),
publisher : $('.publisher').val()}, res => {console.log(res);
if (res.status !== 201) return alert(res.msg)
getBook()
return alert(res.msg)
})
})
}
addBook()
</script>
</body>
</html>
2.
第二个是一个聊天机器人的案例,以前也说过这些案例,只是这次来做感想又深刻了一步,这个案例分为了三步,先是把本人发的音讯可能渲染到聊天界面,而后增加一个 resetui 重置右侧滚动条的函数,能够让聊天界面跟着咱们的刚发的音讯走,而后把获取机器人回复音讯封装为一个函数,具体外面是通过咱们发的音讯为一个参数而后去获取申请,会给你传回来一个参数,同时能够把这个参数以机器人回复的姿势渲染到聊天界面,最初就是语音播放性能,把机器人的音讯作为一个参数封装一个函数,html 减少一个 audio 标签,src 就为咱们这次申请的 src,要加上网页的一个根门路哦
<!DOCTYPE html>
<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" />
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/main.css" />
<script type="text/javascript" src="js/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="js/jquery-ui.min.js"></script>
<script type="text/javascript" src="js/jquery.mousewheel.js"></script>
<title> 聊天机器人 </title>
</head>
<body>
<div class="wrap">
<!-- 头部 Header 区域 -->
<div class="header">
<h3> 小思同学 </h3>
<img src="img/person01.png" alt="icon" />
</div>
<!-- 两头 聊天内容区域 -->
<div class="main">
<ul class="talk_list" style="top: 0px;">
</ul>
<div class="drag_bar" style="display: none;">
<div
class="drager ui-draggable ui-draggable-handle"
style="display: none; height: 412.628px;"
></div>
</div>
</div>
<!-- 底部 音讯编辑区域 -->
<div class="footer">
<img src="img/person02.png" alt="icon" />
<input type="text" placeholder="说的什么吧..." class="input_txt" />
<input type="button" value="发 送" class="input_sub" />
</div>
</div>
<audio src="" autoplay></audio>
<!-- <script type="text/javascript" src="./js/scroll.js"></script> -->
<!-- <script>
$(function(){
// 初始化右侧滚动条
// 这个办法定义在 scroll.js 中
resetui()})
</script> -->
<!-- 1. 上面两个 jq 的 js 都是为了配合最初一个能够用 resetui 函数来初始化右侧滚动条让滚动条跟着屏幕内容走 -->
<script src="./js/jquery-1.12.4.min.js"></script>
<script src="./js/jquery-ui.min.js"></script>
<script src="./js/jquery.mousewheel.js"></script>
<script src="./js/scroll.js"></script>
<script>
// 先实现点击发送增加音讯性能
let content = ''$('.input_sub').on('click', function() {content = $('.input_txt').val()
if (content.trim() == '') return
$('.talk_list').append(`<li class="right_word">
<img src="img/person02.png" /> <span>${content}</span>
</li>`
)
$('.input_txt').val('')
resetui()
getBoot(content)
})
// 机器人回复
// 2. 留神这里机器人的回复是怎么做到的 是再点击后调用的这个函数
function getBoot(text) {$.get('http://www.liulongbin.top:3006/api/robot',{spoken : text},res => {console.log(res);
if (res.message == 'success') {$('.talk_list').append(`<li class="left_word">
<img src="img/person01.png" /> <span>${res.data.info.text}</span>
</li>`
)
}
resetui()
getSpeaker(res.data.info.text)
})
}
// 语音回复
// 3. 留神这里也是须要被他人调用函数
function getSpeaker(text) {
$.ajax({
method : 'get',
url : 'http://www.liulongbin.top:3006/api/synthesize',
data : {text : text},
success : res => {if (res.status !== 200) return alert('获取语音失败')
$('audio').attr('src', res.voiceUrl)
}
})
}
// 最初回车发送音讯
$('.input_txt').on('keyup', (e) => {// console.log(e.keyCode);
if (e.keyCode == 13) {$('.input_sub').trigger('click')
}
})
</script>
</body>
</html>
3.
制作简易版模板引擎,对于模板引擎这方面,只有牢牢记住他的一个规定,先导入,而后定义数据,定义模板,再去调用,最初渲染,根本没啥问题,而后定义模板那里的一些规范语法等等
<!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>
</head>
<body>
<div></div>
<!-- 2. 模板 -->
<script type="text/html" id="model">
<div> 我的名字:{{name}}</div>
<div> 我的年龄:{{age}}</div>
<div> 我的性别:{{sex}}</div>
<div> 我的家庭住址:{{address}}</div>
</script>
<script>
// 3. 封装函数
function template(id, data) {let str = document.getElementById(id).innerHTML
// console.log(str);
let reg = /{{([a-zA-Z]+)}}/
let result = reg.exec(str)
while (result !== null) {str = str.replace(result[0], data[result[1]])
result = reg.exec(str)
}
return str
}
</script>
<script>
// 1. 定义数据
let data = {
name : '王五',
age : 18,
sex : '男',
address : '重庆市江北区'
}
// 4. 调用
let htmlStr = template('model', data)
// 5. 渲染
document.querySelector('div').innerHTML = htmlStr
</script>
</body>
</html>
以下就是一个残缺的模板引擎应用案例,在这个案例中我的几个谬误点:一个是如果你规范语法应用了循环后,在你的每一个循环的项外面有一个字符串你想给转换成数组,还记得你上面要获取数据吗,那么就在这里做一个循环,对每一条 data 数据外面的字符串,push 进数组,谬误点二就是规范语法外面对于图片这一点,首先要晓得凡事用到了规范语法那就必须{{}}包起来,因为你图片还有一个根门路嘛,所以也要一起包着进去。
<!DOCTYPE html>
<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>
</head>
<body>
<div id="news-list">
</div>
</body>
<script type="text/html" id="model">
{{each data}}
<div class="news-item">
<!-- <img class="thumb" src="http://www.liulongbin.top:3006'+${{$value.img}}+'"alt="" /> -->
<!-- 2. 谬误点二,但凡用到变量的中央都须要规范语法 这里须要把整个都包起来 -->
<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 {{tags}} | arrFormat}}
<span>{{$value}}</span>
{{/each}} -->
<!-- 1. 谬误点一 这里我想的太简单了,不必过滤器来做,然而我认为这样做应该能够只是不晓得哪一步搞错了,这里有个更简便的办法
在获取数据的时候就能够将每一个 tags 有字符串改为数组 -->
<span>{{$value.tags[0]}}</span>
<span>{{$value.tags[1]}}</span>
<span>{{$value.tags[2]}}</span>
</div>
<div class="footer">
<div>
<span>{{$value.source}}</span>
<span>{{$value.time | timeFormat}}</span>
</div>
<span> 评论数:{{$value.cmtcount}}</span>
</div>
</div>
</div>
{{/each}}
</script>
<script>
$.ajax({
type : 'GET',
url : 'http://www.liulongbin.top:3006/api/news',
success : res => {if (res.status !== 200) return alert('获取新闻列表失败')
console.log(res);
for (let i = 0; i < res.data.length; i++) {
// 1.1 留神 这一换成数组后须要将以后整个赋值给她
res.data[i].tags = res.data[i].tags.split(',')
}
let htmlStr = template('model', res)
$('#news-list').append(htmlStr)
}
})
template.defaults.imports.timeFormat = function(value) {let date = new Date(value)
let y = date.getFullYear()
let m = addZero(date.getMonth() + 1)
let d = addZero(date.getDate())
let hh = addZero(date.getHours())
let mm = addZero(date.getMinutes())
let ss = addZero(date.getSeconds())
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
// 补零函数
function addZero(n) {return n < 10? '0' + n : n}
</script>
</html>
4.
而后封装本人的 ajax 函数,用到原生 js 的 xhr 办法,在封装外面去判断你是 get 还是 post 申请通过 toUpperCase,包含 xhr level2 的一些新性能,设置 HTTP 时限,xhr.timout 对应还有一个事件 ontimeout,formdata 表单治理能够拿来模仿表单数据,同样也能够拿来获取表单数据,第三个是能够上传文件了,关键步骤在于获取到上传文件的表单元素前面跟一个.files 就会失去一个上传的文件的数组,跟第四个新个性组合起来就是有进度显示,通过一个事件 xhr.upload.onprogress 外面有三个 e 的属性然而要留神这个工夫必须写到 open 和 send 函数之前,而后就是 jq 外面的 ajaxstart 和 ajaxend 两个事件。
而后就是 jsonp,其原理就是通过 script 标签不受同源策略限度而通过 src 发动的服务器申请,把回到函数、参数都加进去,在 jq 外面 jsonp 通过 ajax 办法来做,datatype 改为 jsonp。
一个案例来综合展现 jsonp、防抖和全局缓存,首先咱们的关键字须要作为一个参数去获取倡议列表,而后再定义模板这里循环 res,外面就写一个标签,因为外面的 value 使咱们数组外面的每一项,间接取第一个,而后会依据数组的长度主动给你多少个标签,渲染到页面上
防抖就是会定义一个函数外面是一个定时器去执行咱们获取倡议列表的函数,当你一触发这个事件,首先会革除这个定时器而后在执行定时器函数,你想想我如果设置个工夫 50ms,那么咱们打字的速度,必定是比这个还快的,所以你始终在输出他也始终在分明定时器,定时器就始终没有执行,当你停下来了,这个时候失常执行定时器,获取到咱们的倡议列表,上面会有两个图来具体展现一下区别,有防抖和没有防抖的。
而后就是全局缓存,就是咱们的输出一个 apple 再来一个 mac,这个时候是两个单词吧,那我把 mac 一删,难道又要去申请一次 apple,那不就申请三次了吗,我只申请两次实现这个操作能够吗,那就要用到全局缓存,定义一个全局空对象,在咱们渲染 html 那里,空对象的属性名为搜寻的关键字 = 为咱们的 res,而后当咱们搜寻的时候先去判断搜寻的关键字通过一个 for in 循环看看对象外面有没有这个关键字,如果有先执行缓存外面的 res,就不再去申请服务器了。
最初是一个节流策略,就是咱们限度咱们的触发次数,跟防抖还是有本质区别的,通过一个节流阀,定义一个 timer 为 null,进入这个事件给她定义为多少 ms 的定时器,进入这个事件先去检测,timer 是不是为空,如果不为空就 return 只有当为 null 才会去执行
<!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>
<style>
img {
position: absolute;
left: 0;
top: 0;
}
html,
body {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<img src="./angel.gif" alt="">
<script>
let timer = null
document.body.addEventListener('mousemove', (e) => {if (timer) return
timer = setTimeout(() => {document.querySelector('img').style.left = e.pageX + 'px'
document.querySelector('img').style.top = e.pageY+ 'px'
console.log(11);
timer = null
// console.log(e.pageX);
}, 15);
})
</script>
</body>
</html>