vue项目:商品列表页的渲染,删除,搜索,面包屑导航

简介: vue项目:商品列表页的渲染,删除,搜索,面包屑导航

页面效果:

目标做一个这样子的页面如何去做

前提:导入了element ui,本文章没有体现到编辑商品和添加商品,你需要有自己的后端接口文档你可以拿我的作为一个参考

1.面包屑导航

直接引用组件ui里面的模板就好了一键搞定

1. <!-- 面包屑导航区域 -->
2. <el-breadcrumb separator="/">
3. <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
4. <el-breadcrumb-item><a>商品管理</a></el-breadcrumb-item>
5. <el-breadcrumb-item>商品列表</el-breadcrumb-item>
6. </el-breadcrumb>

路由设置根据自己的需求来

2.搜索框一栏

我们需要用到了卡片视图就是el-card,将内容放在卡片里面

1. <el-card>
2. <el-row :gutter="20">
3. <el-col :span="8">
4. <el-input placeholder="请输入内容" v-model="queryInfo.query" clearable>
5. <el-button slot="append" icon="el-icon-search" @click="getGoodsList"></el-button>
6. </el-input>
7. </el-col>
8. <el-col :span="4">
9. <el-button type="primary" @click="goAddpage">添加商品</el-button>
10. </el-col>
11. </el-row>
12. <el-card>

:gutter="20"属性设置列之间的间距为20像素。

(Element UI 中,网格系统使用了 24 列的布局,每个列的宽度相等。)

`:span="8"` 表示当前的 `el-col` 组件将占据网格系统中的 8 列。

v-model是双向绑定文本输入框输入的数据存放到data中

clearable 属性表示输入框右侧会显示一个清除按钮。

slot="append"表示搜索按钮在输入框的右边

icon="el-icon-search"是搜索按钮图标

@click="getGoodsList"搜索商品的点击事件

以下本页面中的data数据

1. data() {
2. return {
3. // 获取商品列表的参数对象
4. queryInfo: {
5. query: '',
6. // 当前的页数
7. pagenum: 1,
8. // 当前页显示多少条数据
9. pagesize: 5,
10.             },
11. // 商品列表数组
12. goodsList: [],
13. // 数据条数
14. total: 0
15.         };

搜索就是依靠绑定信息后利用信息进行发起请求进行渲染商品列表

3.商品列表区域

1. <!-- 商品列表区域 -->
2. <el-table :data="goodsList" border stripe>
3. <el-table-column type="index" label="序号"></el-table-column>
4. <el-table-column label="商品名称" prop="goods_name"></el-table-column>
5. <el-table-column label="商品价格(元)" prop="goods_price"></el-table-column>
6. <el-table-column label="商品重量" prop="goods_weight"></el-table-column>
7. <el-table-column label="创建时间" prop="add_time">
8. <template slot-scope="scope">
9.             {{ scope.row.add_time | dateFormat }}
10. </template>
11. </el-table-column>
12. <el-table-column label="操作">
13. <template slot-scope="scope">
14. <el-button type="primary" icon="el-icon-edit" size="mini"
15.                 @click="showEditDialog(scope.row.attr_id)">编辑</el-button>
16. <el-button type="danger" icon="el-icon-delete" size="mini"
17.                 @click="removeById(scope.row.goods_id)">删除</el-button>
18. </template>
19. </el-table-column>
20. </el-table>

:data="goodsList"这个是绑定数据源

border:添加表格边框。

stripe:为表格的行添加斑马纹效果,交替显示不同的背景颜色。

type="index":指定列的类型为序号列,自动生成每一行的序号。

label="序号":设置该列的标题为 "序号"。label是列的名称

prop="goods_name":指定该列从数据源中获取的属性名称为 goods_name,表示该列要显示商品的名称。prop就是从绑定的数据源里面获取数据然后渲染

<template slot-scope="scope">:使用插槽方式定义列的内容,slot-scope="scope" 表示可以访问列数据的上下文。这个就是作用域插槽

{{ scope.row.add_time | dateFormat }}:在插槽中,使用 scope.row.add_time 获取当前行的 add_time 属性,并应用 dateFormat 过滤器对时间进行格式化。

因为我这个后端获取到数据的时间是一串数字所以针对时间加一个全局的时间过滤器进行渲染

type="primary":设置按钮类型为主要类型。

icon="el-icon-edit":设置按钮的图标为编辑图标。

size="mini":设置按钮的大小为迷你型。

@click="showEditDialog(scope.row.attr_id)":绑定按钮的点击事件,当按钮被点击时,会触发 Vue 实例中的 showEditDialog 方法,并传入当前行的 attr_id 属性作为参数。

@click="removeById(scope.row.goods_id)":绑定按钮的点击事件,当按钮被点击时,会触发 Vue 实例中的 removeById 方法,并传入当前行的 goods_id 属性作为参数。

在main.js注册

1. // 全局注册时间过滤器
2. Vue.filter('dateFormat',function(originVal){
3. const dt=new Date(originVal)
4. const y=dt.getFullYear()
5. const m=(dt.getMonth()+1+'').padStart(2,'0')
6. const d=(dt.getDate()+'').padStart(2,'0')
7. const hh=(dt.getHours()+'').padStart(2,'0')
8. const mm=(dt.getMinutes()+'').padStart(2,'0')
9. const ss=(dt.getSeconds()+'').padStart(2,'0')
10. // return `yyyy-mm-dd hh:mm:ss`
11. return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
12. })

在mian.js写好了全局的时间过滤器之后再到页面写作用域插槽

商品列表是向后端发起请求获取商品数据然后渲染到表格中

我这里的后端接口文档是

响应数据是:

1. {
2. "data": {
3. "total": 50,
4. "pagenum": "1",
5. "goods": [
6.             {
7. "goods_id": 144,
8. "goods_name": "asfdsd",
9. "goods_price": 1,
10. "goods_number": 1,
11. "goods_weight": 1,
12. "goods_state": null,
13. "add_time": 1512954923,
14. "upd_time": 1512954923,
15. "hot_mumber": 0,
16. "is_promote": false
17.             }
18.         ]
19.     },
20. "meta": {
21. "msg": "获取成功",
22. "status": 200
23.     }
24. }

所以我需要写的后端发起请求是:

首先这里还需要注意因为你打开页面就是需要有数据的所以你需要在开始出现页面的时候就调用请求数据的函数

1. created() {
2. // 根据分页获取对应的商品列表
3. this.getGoodsList()
4. },

然后在methods里面写请求函数

1. // 根据分页请求数据
2. async getGoodsList() {
3. const { data: res } = await this.$http.get('goods', { params: this.queryInfo })
4. if (res.meta.status !== 200) return this.$message.error('获取商品列表失败')
5. // console.log(res.data);
6. this.goodsList = res.data.goods
7. this.total = res.data.total
8. },

async和awit是异步操作,具体可以看我前一天的文章http://t.csdn.cn/RerDO

然后结构赋值然后将获取的数组赋值到我在data中创建的goodslist渲染表格还有获取总数据条数存放到total中渲染分页区域

4.分页区域

1. <!--分页区域  -->
2. <el-pagination @size-change="handleSizeChange" 
3. @current-change="handleCurrentChange"
4. :current-page="queryInfo.pagenum"
5. :page-sizes="[5, 10, 15, 20]"
6. :page-size="queryInfo.pagesize"
7. layout="total, sizes, prev, pager, next, jumper" :total="total" background>
8. </el-pagination>

@size-change="handleSizeChange":当每页显示条数发生变化时,触发 handleSizeChange 方法。

@current-change="handleCurrentChange":当当前页码发生变化时,触发 handleCurrentChange 方法。

:current-page="queryInfo.pagenum":绑定当前页码的值为 queryInfo.pagenum,即当前页码的变量值。

:page-sizes="[5, 10, 15, 20]":设置可选择的每页显示条数选项为 5、10、15 和 20。

:page-size="queryInfo.pagesize":绑定每页显示条数的值为 queryInfo.pagesize,即每页显示条数的变量值。

layout="total, sizes, prev, pager, next, jumper":设置分页组件的布局,具体含义如下:

total:显示总条数。

sizes:显示可选择的每页显示条数选项。

prev:显示上一页按钮。

pager:显示页码按钮。

next:显示下一页按钮。

jumper:显示跳转到指定页码的输入框和确定按钮。

:total="total":绑定总条数的值为 total,即总条数的变量值。

background:设置分页组件的背景为透明背景。

1. //在分页区域中监听页面pagesize改变的事件
2. handleSizeChange(newSize) {
3. // 这里就是根据修改 几条/页 切换之后重新请求
4. this.queryInfo.pagesize = newSize
5. this.getGoodsList()
6. },
7. // 监听页码值改变的事件
8. handleCurrentChange(newPage) {
9. // console.log(newPage)
10. // 这里就是监听到了页码改变然后重新请求这个页码中的x页数据
11. this.queryInfo.pagenum = newPage
12. this.getGoodsList()
13. },

5.删除商品

在操作区域的删除按钮中加入这个点击事件@click="removeById(scope.row.goods_id)然后写删除的请求,为了防止误删给用户添加了应该消息提示框让用户确认是否删除

我这里的弹框提示做了挂载在element.js中

1. import  MessageBox from 'element-ui'
2. // 挂载一个弹框提示的组件
3. Vue.prototype.$confirm=  MessageBox.confirm

然后就是删除的页面的交互

1. // 弹出消息提示框是否删除
2. async removeById(id) {
3. // 弹框询问用户是否删除数据
4. const confirmResult = await this.$confirm('此操作将永久删除该商品, 是否继续?', '提示', {
5. confirmButtonText: '确定',
6. cancelButtonText: '取消',
7. type: 'warning'
8.     }).catch(err => err)
9. // 如果用户确认删除,则返回值为字符串confirm
10. // 如果用户取消了删除,则返回的字符串为cancel
11. if (confirmResult !== 'confirm') { return this.$message.info('已经取消删除') }
12. // const { data: res } = await this.$http.delete(`goods/${id}` )
13. const { data: res } = await this.$http.delete('goods/' + id)
14. if (res.meta.status !== 200) { return this.$message.error('删除商品失败!') }
15. this.$message.success('删除商品成功!')
16. // 刷新重新获取商品列表
17. this.getGoodsList()
18. },

6.整个页面的代码:

1. <template>
2. <div>
3. <!-- 面包屑导航区域 -->
4. <el-breadcrumb separator="/">
5. <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
6. <el-breadcrumb-item><a>商品管理</a></el-breadcrumb-item>
7. <el-breadcrumb-item>商品列表</el-breadcrumb-item>
8. </el-breadcrumb>
9. 
10. <!-- 卡片视图区域 -->
11. <el-card>
12. <el-row :gutter="20">
13. <el-col :span="8">
14. <el-input placeholder="请输入内容" v-model="queryInfo.query" clearable>
15. <el-button slot="append" icon="el-icon-search" @click="getGoodsList"></el-button>
16. </el-input>
17. </el-col>
18. <el-col :span="4">
19. <el-button type="primary" @click="goAddpage">添加商品</el-button>
20. </el-col>
21. </el-row>
22. 
23. <!-- 商品列表区域 -->
24. <el-table :data="goodsList" border stripe>
25. <el-table-column type="index" label="序号"></el-table-column>
26. <el-table-column label="商品名称" prop="goods_name"></el-table-column>
27. <el-table-column label="商品价格(元)" prop="goods_price"></el-table-column>
28. <el-table-column label="商品重量" prop="goods_weight"></el-table-column>
29. <el-table-column label="创建时间" prop="add_time">
30. <template slot-scope="scope">
31.                         {{ scope.row.add_time | dateFormat }}
32. </template>
33. </el-table-column>
34. <el-table-column label="操作">
35. <template slot-scope="scope">
36. <el-button type="primary" icon="el-icon-edit" size="mini"
37.                             @click="showEditDialog(scope.row.attr_id)">编辑</el-button>
38. <el-button type="danger" icon="el-icon-delete" size="mini"
39.                             @click="removeById(scope.row.goods_id)">删除</el-button>
40. </template>
41. </el-table-column>
42. </el-table>
43. 
44. <!--分页区域  -->
45. <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
46. :current-page="queryInfo.pagenum" :page-sizes="[5, 10, 15, 20]" :page-size="queryInfo.pagesize"
47. layout="total, sizes, prev, pager, next, jumper" :total="total" background>
48. </el-pagination>
49. </el-card>
50. 
51. 
52. 
53. 
54. </div>
55. </template>
56. 
57. <script>
58. export default {
59. name: 'VueShopListComponent',
60. 
61. data() {
62. return {
63. // 获取商品列表的参数对象
64. queryInfo: {
65. query: '',
66. // 当前的页数
67. pagenum: 1,
68. // 当前页显示多少条数据
69. pagesize: 5,
70.             },
71. // 商品列表数组
72. goodsList: [],
73. // 数据条数
74. total: 0
75.         };
76.     },
77. created() {
78. // 根据分页获取对应的商品列表
79. this.getGoodsList()
80.     },
81. mounted() {
82. 
83.     },
84. 
85. methods: {
86. // 根据分页请求数据
87. async getGoodsList() {
88. const { data: res } = await this.$http.get('goods', { params: this.queryInfo })
89. if (res.meta.status !== 200) return this.$message.error('获取商品列表失败')
90. // console.log(res.data);
91. this.goodsList = res.data.goods
92. this.total = res.data.total
93.         },
94. //在分页区域中监听页面pagesize改变的事件
95. handleSizeChange(newSize) {
96. // 这里就是根据修改 几条/页 切换之后重新请求
97. this.queryInfo.pagesize = newSize
98. this.getGoodsList()
99.         },
100. // 监听页码值改变的事件
101. handleCurrentChange(newPage) {
102. // console.log(newPage)
103. // 这里就是监听到了页码改变然后重新请求这个页码中的x页数据
104. this.queryInfo.pagenum = newPage
105. this.getGoodsList()
106.         },
107. // 弹出消息提示框是否删除
108. async removeById(id) {
109. // 弹框询问用户是否删除数据
110. const confirmResult = await this.$confirm('此操作将永久删除该商品, 是否继续?', '提示', {
111. confirmButtonText: '确定',
112. cancelButtonText: '取消',
113. type: 'warning'
114.             }).catch(err => err)
115. // 如果用户确认删除,则返回值为字符串confirm
116. // 如果用户取消了删除,则返回的字符串为cancel
117. if (confirmResult !== 'confirm') { return this.$message.info('已经取消删除') }
118. // const { data: res } = await this.$http.delete(`goods/${id}` )
119. const { data: res } = await this.$http.delete('goods/' + id)
120. if (res.meta.status !== 200) { return this.$message.error('删除商品失败!') }
121. this.$message.success('删除商品成功!')
122. // 刷新重新获取商品列表
123. this.getGoodsList()
124.         },
125. // 添加商品,路由跳转访问添加商品页面
126. goAddpage(){
127. this.$router.push('/home/goods/add')
128.         }
129.     },
130. };
131. </script>
132. 
133. <style lang="less" scoped></style>


相关文章
|
6天前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
vue学习第四章
|
6天前
|
JavaScript 前端开发
vue学习第九章(v-model)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript与Vue的大一学生,自学前端2年半,正向全栈进发。此篇介绍v-model在不同表单元素中的应用及修饰符的使用,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
vue学习第九章(v-model)
|
6天前
|
JavaScript 前端开发 开发者
vue学习第十章(组件开发)
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文深入讲解Vue组件的基本使用、全局与局部组件、父子组件通信及数据传递等内容,适合前端开发者学习参考。持续更新中,期待您的关注!🎉🎉🎉
vue学习第十章(组件开发)
|
11天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
12天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
12天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
12天前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
|
11天前
|
JavaScript 前端开发 UED
vue学习第二章
欢迎来到我的博客!我是一名自学了2年半前端的大一学生,熟悉JavaScript与Vue,目前正在向全栈方向发展。如果你从我的博客中有所收获,欢迎关注我,我将持续更新更多优质文章。你的支持是我最大的动力!🎉🎉🎉
|
13天前
|
存储 JavaScript 开发者
Vue 组件间通信的最佳实践
本文总结了 Vue.js 中组件间通信的多种方法,包括 props、事件、Vuex 状态管理等,帮助开发者选择最适合项目需求的通信方式,提高开发效率和代码可维护性。
|
11天前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。自学前端2年半,熟悉JavaScript与Vue,正向全栈方向发展。博客内容涵盖Vue基础、列表展示及计数器案例等,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉