电子书编辑和删除功能开发
电子书列表
知识点 directive waves用法 v-waves
pagination用它封装好的组件 这些都是可以传入的参数
<template>
<div class="app-container">
<!-- 查询条件 -->
<div class="filter-container">
<!-- filter -->
<el-input
v-model="listQuery.title"
placeholder="书名"
size="normal"
clearable
style="width: 200px"
class="filter-item"
@keyup.enter.native="handleFilter"
@clear="handleFilter"
@blur="handleFilter"
></el-input>
<el-input
v-model="listQuery.author"
placeholder="作者"
size="normal"
clearable
style="width: 200px"
class="filter-item"
@keyup.enter.native="handleFilter"
@clear="handleFilter"
@blur="handleFilter"
></el-input>
<el-select
v-model="listQuery.category"
placeholder="分类"
clearable
class="filter-item"
@change="handleFilter"
@clear="handleFilter"
>
<el-option
v-for="item in categoryList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
<el-button
type="primary"
class="filter-item"
size="default"
icon="el-icon-search"
style="margin-left: 10px"
@click="handleFilter"
>
点击查询
</el-button>
<el-button
type="primary"
class="filter-item"
size="default"
icon="el-icon-search"
style="margin-left: 10px"
@click="handleCreate"
>
点击新增
</el-button>
<el-checkbox
v-model="showCover"
label=""
:indeterminate="false"
class="filter-item"
style="margin-left: 10px"
@change="changeShowCover"
>
显示封面
</el-checkbox>
</div>
<!-- 表格组件 -->
<el-table></el-table>
<!-- 翻页 -->
<Pagination :total="0" />
</div>
</template>
<script>
import Pagination from "../../components/Pagination/index";
import { getCategory } from "../../api/book";
// 这个老是报错,应该是依赖的问题,使用方法:v-waves
// import waves from '../../components/directive/waves'
export default {
components: { Pagination },
data() {
return {
listQuery: {},
showCover: false,
// 查询条件是动态的
categoryList: [],
};
},
mounted() {
this.getCategoryList();
},
methods: {
getCategoryList() {
getCategory().then((response) => {
this.categoryList = response.data;
});
},
changeShowCover(value) {
this.showCover = value;
console.log(this.showCover);
},
handleFilter() {
console.log("handleFilter", this.listQuery);
},
handleCreate() {
// 页面切换到/book/create 切换到上传图书
this.$router.push("/book/create");
},
},
};
</script>
<style lang="scss" scoped>
</style>
水波效果
api
拿到category以后就去请求,请求以后赋值,之后显示到页面
写label两种方式
图书分类api
打开category视图
有个疑问
这里return的categoryList能在then里面接收到吗,我的认知里面应该是要return一个promise对象的
我知道了,async里面return的对象会自动帮我们转换成promise
图书列表样式
https://element.eleme.io/#/zh-CN/component/table#ji-chu-biao-ge
https://element.eleme.io/#/zh-CN/component/table#table-column-attributes
https://element.eleme.io/#/zh-CN/component/table#table-column-attributes
el-table
sort-change事件排序
<el-table
:key="tableKey"
v-loading="listLoading"
:data="list"
border
fit
highlight-current-row
style="width: 100%"
@sort-change="sortChange"
>
<el-table-column
prop="id"
label="ID"
sortable="custom"
align="center"
width="80"
>
</el-table-column>
<el-table-column label="书名" sortable="custom" align="center" width="80">
<template slot-scope="{ row: { title } }">
<span>{
{ title }}</span>
</template>
</el-table-column>
</el-table>
接下来拿数据
虽然还没写接口逻辑,但是可以先验证一下query数据有没有传进去
来尝试一下
可以看到已经不报404了 而且后端能收到数据了 这样流程就串起来了
有个问题,author和title应该采取模糊查询
有个难点,不确定category,author,title是否传入
前端收到数据
<template>
<div class="app-container">
<!-- 查询条件 -->
<div class="filter-container">
<!-- filter -->
<el-input
v-model="listQuery.title"
placeholder="书名"
size="normal"
clearable
style="width: 200px"
class="filter-item"
@keyup.enter.native="handleFilter"
@clear="handleFilter"
@blur="handleFilter"
></el-input>
<el-input
v-model="listQuery.author"
placeholder="作者"
size="normal"
clearable
style="width: 200px"
class="filter-item"
@keyup.enter.native="handleFilter"
@clear="handleFilter"
@blur="handleFilter"
></el-input>
<el-select
v-model="listQuery.category"
placeholder="分类"
clearable
class="filter-item"
@change="handleFilter"
@clear="handleFilter"
>
<el-option
v-for="item in categoryList"
:key="item.value"
:label="item.label + '(' + item.num + ')'"
:value="item.value"
>
</el-option>
</el-select>
<el-button
type="primary"
class="filter-item"
size="default"
icon="el-icon-search"
style="margin-left: 10px"
@click="handleFilter"
>
点击查询
</el-button>
<el-button
type="primary"
class="filter-item"
size="default"
icon="el-icon-search"
style="margin-left: 10px"
@click="handleCreate"
>
点击新增
</el-button>
<el-checkbox
v-model="showCover"
label=""
:indeterminate="false"
class="filter-item"
style="margin-left: 10px"
@change="changeShowCover"
>
显示封面
</el-checkbox>
</div>
<!-- 表格组件 -->
<el-table
:key="tableKey"
v-loading="listLoading"
:data="list"
border
fit
highlight-current-row
style="width: 100%"
@sort-change="sortChange"
>
<el-table-column
prop="id"
label="ID"
sortable="custom"
align="center"
width="80"
>
</el-table-column>
<el-table-column
label="书名"
sortable="custom"
align="center"
width="180"
>
<template slot-scope="{ row: { title } }">
<span>{
{ title }}</span>
</template>
</el-table-column>
<el-table-column
label="作者"
sortable="custom"
align="center"
width="100"
>
<template slot-scope="{ row: { author } }">
<span>{
{ author }}</span>
</template>
</el-table-column>
<!-- 换种方式 ,不使用插槽 -->
<el-table-column
label="出版社"
prop="publisher"
sortable="custom"
align="center"
width="150"
>
</el-table-column>
<el-table-column
label="分类"
prop="categoryText"
sortable="custom"
align="center"
width="150"
>
</el-table-column>
<el-table-column
label="语言"
prop="language"
sortable="custom"
align="center"
width="80"
>
</el-table-column>
<el-table-column
v-if="showCover"
label="封面"
prop="cover"
align="center"
width="150"
>
<template slot-scope="{ row: { cover } }">
<a :href="cover" target="_blank">
<img :src="cover" style="width: 120px; height: 180px" />
</a>
</template>
</el-table-column>
<!-- <el-table-column v-if="showCover" label="封面" prop="cover" align="center" width="150">
<template slot-scope="scope">
<a :href="scope.row.cover" target="_blank">
<img :src="scope.row.cover" style="width:120px;height:180px">
</a>
</template>
</el-table-column> -->
<el-table-column
label="文件名"
prop="fileName"
sortable="custom"
align="center"
width="150"
>
</el-table-column>
<el-table-column
label="文件路径"
prop="filePath"
sortable="custom"
align="center"
width="150"
>
</el-table-column>
</el-table>
<!-- 翻页 -->
<Pagination :total="0" />
</div>
</template>
<script>
import Pagination from "../../components/Pagination/index";
import { getCategory, listBook } from "../../api/book";
// 这个老是报错,应该是依赖的问题,使用方法:v-waves
// import waves from '../../components/directive/waves'
export default {
components: { Pagination },
data() {
return {
// 存在多个table的时候能够对table进行区分
tableKey: 0,
listLoading: true,
listQuery: {},
showCover: false,
// 查询条件是动态的
categoryList: [],
// 表格数据源
list: [],
};
},
mounted() {
this.getCategoryList();
this.getList();
},
methods: {
getList() {
this.listLoading = true;
listBook(this.listQuery).then((response) => {
console.log(response);
const { list } = response.data;
this.list = list;
this.listLoading = false;
});
},
// 排序事件
sortChange(data) {
console.log("sortChange", data);
},
getCategoryList() {
getCategory().then((response) => {
this.categoryList = response.data;
});
},
changeShowCover(value) {
this.showCover = value;
console.log(this.showCover);
},
handleFilter() {
console.log("handleFilter", this.listQuery);
this.getList();
},
handleCreate() {
// 页面切换到/book/create 切换到上传图书
this.$router.push("/book/create");
},
},
};
</script>
<style lang="scss" scoped>
</style>
因为写了fit 所以无法左右横移
经常采用的方法:–fixed
使用前:
使用后
<el-table-column label="操作" align="center" width="120">
<template slot-scope="{ row }">
<el-button
type="text"
size="default"
@click="handleUpdate(row)"
icon="el-icon-edit"
></el-button>
</template>
</el-table-column>
携带分页参数
分页和查询
本来pageSize应该是20的,因为我把老的数据都删掉了,所以数据比较少,pageSize写小点测试一下
接下来加入查询条件
这里的操作很妙
标题的模糊查询
模糊查询高亮
//new
wrapperKeyword(k,v){
function highlight(value){
return `<span style='color:#18900f'>${
value}</span>`
}
if(!this.listQuery[k]){
return v
}else{
// return v.replace(new RegExp(this.listQuery[k]),v=>{
// return highlight(v)
// })
return v.replace(new RegExp(this.listQuery[k]),v=>highlight(v))
}
},
getList() {
this.listLoading = true;
listBook(this.listQuery).then((response) => {
console.log(response);
const {
list } = response.data;
this.list = list;
this.listLoading = false;
//new
this.list.forEach(book=>{
book.titleWrapper=this.wrapperKeyword('title',book.title)
book.authorWrapper=this.wrapperKeyword('author',book.author)
})
});
},
bug
bug 一个书名无法匹配多个 只能匹配第一个 还有一个不区分大小写
解决办法就是在正则表达式加一些参数
排序&分页优化
取出prop,order
我们设desc为-id asc为+id
点击以后需要再次发请求
服务端
解出sort之后
分页功能
先查询book表里有多少电子书
返回值:一个数组
返回给前端
看到返回的是字符串
修改
这几个参数返回给前端主要是要修改pagination这个组件
但是点击翻页按钮并没有变化,而且切换每页显示的数量也没有变化
这样翻页功能和改变每页的数量的功能就实现了
接下来有个显示图片的bug
过滤器优化表格字段显示
现在假如说有一本文件路径是空的
增加个上传时间
parseTime utils下面自带的方法
删除功能
拿到点击的fileName 通过fileName来进行后续的操作
服务端
优化 完结
刷新url的时候原来的查询条件全部丢失
方案:把参数保存到url中
实现这个功能需要进行一些改造
在created调用了parseQuery
在parseQuery里面不仅要对page,pageSize,sort进行封装,还要增加一步:获取到一个新的对象(this.route.query)
之后和当前的query做一个合并
if(query){
query.page&&(query.page = +query.page)
query.pageSize&&(query.pageSize = +query.pageSize)
}
getList就不适用了
点击查询
点击下面的翻页并没有更新
解决:
但是又有问题了 就是鼠标移开以后不会更新
虽然push了 但是路由并没有更新
这是一个难点 虽然路由更新了,但是页面并没有刷新
需要通过路由钩子来解决,监听两次路由的变化
现在的问题就是更新完了以后列表没有刷新
如何比较两个对象相不相等呢 变成json字符串来对比
这样就ok了
还有个问题
category还原的方法有很多,比较推荐的是
服务端:
还有个问题,先选到第二页,在输入查询条件(只有一页)这时候会出现这种情况
所以每次查询的时候都要讲页数置为1
现在是修排序的状态bug
浏览器地址栏回车以后虽然能正确排序,但是那个箭头没有变颜色
有个地方写错了 default-sort应该写在el-table下面