英雄案例实现过程
1.内容实现ajax的增删改查
目标
回顾ajax的操作,如果发请求和如何接收响应
回顾模板引擎的使用,完善整个异步操作实现动态渲染的过程
进一步理解前后台交互的流程
整体需要完成一套数据的增加删除修改和查询
回顾前端三层分离的原则
2前期准备
在合适的位置创建项目目录
将资料中资源拷贝到当前项目目录中
将页面的目录名称修改为views
用户列表页
这个页面主要的任务是来实现用户数据的动态渲染
1找到接口
2.ajax请求,获取数据
3.进行数据分析,分析获取的数据是否能够满足渲染的要求
4.根据静态结构创建模板–使用简洁语法
5.调用模板引擎,生成动态结构
6.填充到指定的位置
动态渲染的实现步骤
接口 》 ajax请求 》 模板创建 》 调用模板引擎 》 填充
创建js目录添加index.js文件
引入所需要的外部资源
<!-- 引入资源文件 -->
<script src="../libs/jquery.js"></script>
<script src="../libs/template-web.js"></script>
<script src="../js/index.js"></script>
创建模板结构
使用Script标签,type设置为text/template,添加id号(重点id号是为了后面能拿到模板)
使用简洁语法
1.输出表达式:{{}}
2.逻辑表达式:{{}}
3.each循环的时候,如果没有自己命名,就默认使用$value和$index
<!-- 添加列表结构的模板 -->
<script type='text/template' id='userlistTemp'>
{{each data}}
<tr>
<td>{{$index + 1}}</td>
<td>{{$value.name}}</td>
<td>{{$value.gender}}</td>
<td><img src="http://127.0.0.1:3002/images/{{$value.img}}"></td>
<td><a href="#">查看</a> <a href="javascript:;">修改</a>
<a href="javascript:;">删除</a></td>
</tr>
{{/each}}
</script>
ajax请求获取数据实现动态渲染
// 实现页面的动态渲染
// 9:“英雄”案例获取所有数据
// - 请求路径:http://127.0.0.1:3002/getalldata
// - 请求方法:get
$.ajax({
url: 'http://127.0.0.1:3002/getalldata',
dataType: 'json',
success: function (res) {
console.log(res)
$('tbody').html(template('userlistTemp', res))
}
})
注意细节:
图片应该是从服务器端获取的,所以在渲染图片路径的时候应该自己在名称前面拼接服务器的基地址:http://127.0.0.1:3002/images
本来的地址为./images改为http://127.0.0.1:3002/images
## 常见错误
1.dataType:不要写错,如果这个值写错了,对于 jq的ajax而言,默认的类型是text/html
2.如果人为修改了数据,那么一定要注意保存文件时的编码格式,
可以这样:右下的UTF-8单击一下》》选择编码格式保存》》UTF-8
3.没有引入js资源,模板的id一定要写对
4.在实现动态渲染的时候,没有报错但是又没有结果
a.事件有没有触发
b.dataType是否正确
c.模板的id是否正确
d:js资源是否正确的引入
用户新增
实现新增页面的跳转
重点细节:后台接口所需要的的数据有
1用户名
2姓名
3用户头像的名称,这个名称是图片存储在服务器的名称,意味着我们要先实现文件的上传获取到服务器返回的图片名称
实现图片上传
实现用户新增
## 实现新增页面的跳转
<a class="btn btn-success pull-right" href="./add.html">添加英雄</a>
引入必需的js文件
<script src="../libs/jquery.js"></script>
<script src="../js/add.js"></script>
实现图片上传
用户一选择就进行文件的上传
一定要获取到后台的返回的图片的名称,以后作为参数传递的
上传文件的步骤有:
1使用formdata收集文件数据
2ajax请求,以formdata为参数
3.注意要设置两个属性为false:processData contentType 因为formdata会有自己的编码格式避免冲突所以在ajax请求要设置这两个属性
4.分析返回数据,获取图片的名称,实现预览
// 实现文件上传,选择好文件就会触发change事件
$('#img').on('change', function () {
// 1.使用formdata收集文件数据
let myfile = $('#img')[0].files[0]
// 我们现在只是实现文件的上传,并不需要将表单的其它元素的数据也传递过去,所以不使用传入整个表单的方式来收集数据
let formdata = new FormData()
// 将文件数据追加到formdata中
formdata.append('img', myfile)
// 2.ajax请求,以formdata做为参数
// 8:图片上传(英雄案例中图片上传也是使用这个)
// - 请求路径:http://127.0.0.1:3002/uploadFile
// - 请求方法:post
$.ajax({
type: 'post',
url: 'http://127.0.0.1:3002/uploadFile',
data: formdata,
// 3.注意要设置两个属性为false:processData contentType
processData: false, // 不要让ajax进行数据的处理
contentType: false,// 不要让ajax进行参数的编码处理
dataType: 'json',
success: function (res) {
console.log(res)
if (res.code == 200) {
// 实现预览
$('#photo').attr('src', 'http://127.0.0.1:3002/images/' + res.img)
}
}
})
})
细节
1.收集图片的方式,formdata只支持原生的方式
2.一定要设置两个属性为false --processData contentType
3.不要将jq和js混合
实现用户新增
关键的操作就是:收集后台接口所需要的数据,从当前页面来看,使用jq的serialize方法似乎最简单
关键的操作就是:收集后台接口所需要的数据,从当前页面来看,使用jq的serialize方法似乎最简单
1.serialize()可以收集指定表单中拥有name属性的表单元素的value值,所以默认情况下,img是无法成功的获取
a.可以人为拼接,要求我们使用一个全局变量存储res.img,但是不要这么做,因为需要多创建全局变量,同时不安全
b.推荐使用隐藏域,隐藏域就是一个input表单元素,但是在页面中不会进行渲染(用户看不到,但是我们可以获取),前提是你得人为的为其赋值
- 在表单中添加一个隐藏域
- 在图片上传成功之后为隐藏域赋值
- 直接通过serialize方法获取用户数据
数据收集之后就实现ajax请求‘
在表单中添加一个隐藏域’
<form id="myform>
<!-- 在表单的任意位置添加隐藏域,现在添加一个存储图片名称的隐藏域 -->
<input type="hidden" name="img" value=">
.......
</form>
在图片上传成功之后为隐藏域赋值
.... add.js > $('#img').on('change', function () {
-----------------------------------
success: function (res) {
console.log(res)
if (res.code == 200) {
// 实现预览
$('#photo').attr('src', 'http://127.0.0.1:3002/images/' + res.img)
// 将图片的名称存储到隐藏域
$('[name=img]').val(res.img)
}
}
...
实现新增操作
// 实现用户数据的新增
// 10:"英雄"案例实现新增用户信息
// - 请求路径:http://127.0.0.1:3002/add
// - 请求方法:post
$('#sub').on('click', function () {
//data 拿到表单中所有的name的value值
// let data = $('#myform').serialize()
// console.log(data)
$.ajax({
type: 'post',
url: 'http://127.0.0.1:3002/add',
data: $('#myform').serialize(),
dataType: 'json',
success: function (res) {
console.log(res)
if (res.code == 200) {
alert('新增成功')
// 重新跳转到列表页
location.href = './index.html'
}
}
})
})
常见错误
1.图片可以成功的上传但是无法成功的获取
原因:1.是否将成功上传的图片名称存储到隐藏域 2.看add.html文件是中否有同名的隐藏域,要保证只有一个针对于img的隐藏域
2.页面不跳转
相对路径写错,你要注意,在js中引入一个路径,不是参照当前js文件所在路径,而是参照使用这个js文件的html页面的路径
用户编辑
页面跳转,传入单前用户的id
1.展示用户默认数据
a.获取参数id
b.根据id获取用户数据
c.展示默认的数据-模板/dom操作
2.实现用户数据的编辑,类似新增
a.分析接口,准备好接口所需要的数据
ajax请求
页面跳转,传入当前用户的id
<!-- 添加列表结构的模板 第9行传递了参数 -->
<script type='text/template' id='userlistTemp'>
{{each data}}
<tr>
<td>{{$index + 1}}</td>
<td>{{$value.name}}</td>
<td>{{$value.gender}}</td>
<td><img src="http://127.0.0.1:3002/images/{{$value.img}}"></td>
<td><a href="#">查看</a> <a href="./edit.html?id={{$value.id}}">修改</a>
<a href="javascript:;">删除</a></td>
</tr>
{{/each}}
</script>
在编辑页面获取用户id
// 1.获取参数
// 下面这种方式权宜之计,它只适合只有一个参数的情况下,但是现实的开发场景中,多参数的情况比比皆是
// 通用的作法是将key=value&key=value这种格式的字符串转换为对象
// let id = location.search.split('=')[1]
let id = itcast.getParameter(location.search).id
console.log(id)
根据id查询用户数据进行动态渲染
常规操作:为三个元素赋值用于展示,为两个隐藏域赋值用于参数的获取
<script type="text/template" id='usercontentTemp'>
<tr>
<td>姓名:</td>
<td><input type="text" name="name" value='{{name}}'></td>
</tr>
<tr>
<td>性别:</td>
<td>
<input id="nan" name="gender" value="男" type="radio" {{gender == '男'? 'checked' : ''}}><label for="nan">男</label>
<input name="gender" value="女" type="radio" id="nv" {{gender == '女'? 'checked' : ''}}><label for="nv">女</label>
</td>
</tr>
<tr>
<td>头像:</td>
<td>
<img src="http://127.0.0.1:3002/images/{{img}}" alt="" id="photo" width="100"
style='border: 1px solid #ccc;margin-bottom: 5px;'>
<input type="file" id="img">
</td>
</tr>
</script>
ajax渲染
// 2.根据参数查询用户数据,进行默认数据的渲染
// 13:"英雄"案例根据ID查询单个英雄数据
// - 请求路径:http://127.0.0.1:3002/getHeroById
// - 请求方法:get
$.ajax({
url: 'http://127.0.0.1:3002/getHeroById',
data: { id }, // ES6的新语法,如果对象的key和值同名,那么就只需要写一个
dataType: 'json',
success: function (res) {
console.log(res)
if (res.code == 200) {
$('.usercontent').html(template('usercontentTemp', res.data))
}
}
})
重点细节
后台要什么,你得给什么
id号是进行编辑的唯一标识,如果没有id号,编辑操作不可能真正的成功
编辑操作的时候,我们不能强迫用户修改每一个值,意味着如果用户没有修改某个值,那么还应该保留原始的数据,如用户图片
实现过程
1.添加两个隐藏域,分别用于存储用户id和用户img
2.在获取用户数据之后,对这个两个隐藏域进行赋值
<input type="hidden" name="id" value='{{id}}'>
<input type="hidden" name="img" value='{{img}}'>
if (res.code == 200) {
$('.usercontent').html(template('usercontentTemp', res.data))
}
文件上传
基本代码和新增页面中的文件上传完全一样
区别:编辑页面中,我们使用了模板,所以img表单元素是一个动态元素,动态元素在绑定事件的时候应该使用事件委托
代码:$(’.usercontent’).on(‘change’, ‘#img’, function ()
实现用户编辑
// 实现用户编辑
// 11:"英雄"案例实现用户编辑提交
// - 请求路径:http://127.0.0.1:3002/edit
// - 请求方法:post
$('#sub').on('click', function () {
console.log($('#myform').serialize())
$.ajax({
type: 'post',
url: 'http://127.0.0.1:3002/edit',
data: $('#myform').serialize(),
dataType: 'json',
success: function (res) {
if (res.code == 200) {
alert('编辑成功')
location.href = './index.html'
}
}
})
})
用户删除
分析接口,发现删除操作需要传入用户的id
我们要以异步的方式来删除
通过事件委托的方式绑定删除事件
1.获取当前删除按钮所对应的id号
2.实现ajax请求
关于数据的获取
1.自己没有,要求传递
2.别人不传递,自己先存储再获取,一般选择使用自定义属性
a.定义自定义属性
b.获取自定义属性
添加自定义属性的设置
<a href="javascript:;" class='userdel' data-id='{{$value.id}}'>删除
实现用户删除
// 实现用户的删除
// 12:"英雄"案例实现删除单个用户
// - 请求路径:http://127.0.0.1:3002/delete
// - 请求方法:get
$('tbody').on('click', '.userdel', function (e) {
let data = $(this).data()
if (confirm('是否真的需要删除?')) {
$.ajax({
url: 'http://127.0.0.1:3002/delete',
data: data,
dataType: 'json',
success: function (res) {
console.log(res)
if (res.code == 200) {
alert('删除成功')
// 刷新
init()
}
}
})
}
})```