页面效果:
目标做一个这样子的页面如何去做
前提:导入了element ui,本文章没有体现到编辑商品和添加商品,你需要有自己的后端接口文档你可以拿我的作为一个参考
1.面包屑导航
直接引用组件ui里面的模板就好了一键搞定
<!-- 面包屑导航区域 -->
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item><a>商品管理</a></el-breadcrumb-item>
<el-breadcrumb-item>商品列表</el-breadcrumb-item>
</el-breadcrumb>
路由设置根据自己的需求来
2.搜索框一栏
我们需要用到了卡片视图就是el-card,将内容放在卡片里面
<el-card>
<el-row :gutter="20">
<el-col :span="8">
<el-input placeholder="请输入内容" v-model="queryInfo.query" clearable>
<el-button slot="append" icon="el-icon-search" @click="getGoodsList"></el-button>
</el-input>
</el-col>
<el-col :span="4">
<el-button type="primary" @click="goAddpage">添加商品</el-button>
</el-col>
</el-row>
<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数据
data() {
return {
// 获取商品列表的参数对象
queryInfo: {
query: '',
// 当前的页数
pagenum: 1,
// 当前页显示多少条数据
pagesize: 5,
},
// 商品列表数组
goodsList: [],
// 数据条数
total: 0
};
搜索就是依靠绑定信息后利用信息进行发起请求进行渲染商品列表
3.商品列表区域
<!-- 商品列表区域 -->
<el-table :data="goodsList" border stripe>
<el-table-column type="index" label="序号"></el-table-column>
<el-table-column label="商品名称" prop="goods_name"></el-table-column>
<el-table-column label="商品价格(元)" prop="goods_price"></el-table-column>
<el-table-column label="商品重量" prop="goods_weight"></el-table-column>
<el-table-column label="创建时间" prop="add_time">
<template slot-scope="scope">
{{ scope.row.add_time | dateFormat }}
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" size="mini"
@click="showEditDialog(scope.row.attr_id)">编辑</el-button>
<el-button type="danger" icon="el-icon-delete" size="mini"
@click="removeById(scope.row.goods_id)">删除</el-button>
</template>
</el-table-column>
</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注册
// 全局注册时间过滤器
Vue.filter('dateFormat',function(originVal){
const dt=new Date(originVal)
const y=dt.getFullYear()
const m=(dt.getMonth()+1+'').padStart(2,'0')
const d=(dt.getDate()+'').padStart(2,'0')
const hh=(dt.getHours()+'').padStart(2,'0')
const mm=(dt.getMinutes()+'').padStart(2,'0')
const ss=(dt.getSeconds()+'').padStart(2,'0')
// return `yyyy-mm-dd hh:mm:ss`
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
})
在mian.js写好了全局的时间过滤器之后再到页面写作用域插槽
商品列表是向后端发起请求获取商品数据然后渲染到表格中
我这里的后端接口文档是
响应数据是:
{
"data": {
"total": 50,
"pagenum": "1",
"goods": [
{
"goods_id": 144,
"goods_name": "asfdsd",
"goods_price": 1,
"goods_number": 1,
"goods_weight": 1,
"goods_state": null,
"add_time": 1512954923,
"upd_time": 1512954923,
"hot_mumber": 0,
"is_promote": false
}
]
},
"meta": {
"msg": "获取成功",
"status": 200
}
}
所以我需要写的后端发起请求是:
首先这里还需要注意因为你打开页面就是需要有数据的所以你需要在开始出现页面的时候就调用请求数据的函数
created() {
// 根据分页获取对应的商品列表
this.getGoodsList()
},
然后在methods里面写请求函数
// 根据分页请求数据
async getGoodsList() {
const { data: res } = await this.$http.get('goods', { params: this.queryInfo })
if (res.meta.status !== 200) return this.$message.error('获取商品列表失败')
// console.log(res.data);
this.goodsList = res.data.goods
this.total = res.data.total
},
async和awit是异步操作,具体可以看我前一天的文章http://t.csdn.cn/RerDO
然后结构赋值然后将获取的数组赋值到我在data中创建的goodslist渲染表格还有获取总数据条数存放到total中渲染分页区域
4.分页区域
<!--分页区域 -->
<el-pagination @size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="queryInfo.pagenum"
:page-sizes="[5, 10, 15, 20]"
:page-size="queryInfo.pagesize"
layout="total, sizes, prev, pager, next, jumper" :total="total" background>
</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:设置分页组件的背景为透明背景。
//在分页区域中监听页面pagesize改变的事件
handleSizeChange(newSize) {
// 这里就是根据修改 几条/页 切换之后重新请求
this.queryInfo.pagesize = newSize
this.getGoodsList()
},
// 监听页码值改变的事件
handleCurrentChange(newPage) {
// console.log(newPage)
// 这里就是监听到了页码改变然后重新请求这个页码中的x页数据
this.queryInfo.pagenum = newPage
this.getGoodsList()
},
5.删除商品
在操作区域的删除按钮中加入这个点击事件@click="removeById(scope.row.goods_id)然后写删除的请求,为了防止误删给用户添加了应该消息提示框让用户确认是否删除
我这里的弹框提示做了挂载在element.js中
import MessageBox from 'element-ui'
// 挂载一个弹框提示的组件
Vue.prototype.$confirm= MessageBox.confirm
然后就是删除的页面的交互
// 弹出消息提示框是否删除
async removeById(id) {
// 弹框询问用户是否删除数据
const confirmResult = await this.$confirm('此操作将永久删除该商品, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).catch(err => err)
// 如果用户确认删除,则返回值为字符串confirm
// 如果用户取消了删除,则返回的字符串为cancel
if (confirmResult !== 'confirm') { return this.$message.info('已经取消删除') }
// const { data: res } = await this.$http.delete(`goods/${id}` )
const { data: res } = await this.$http.delete('goods/' + id)
if (res.meta.status !== 200) { return this.$message.error('删除商品失败!') }
this.$message.success('删除商品成功!')
// 刷新重新获取商品列表
this.getGoodsList()
},
6.整个页面的代码:
<template>
<div>
<!-- 面包屑导航区域 -->
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item><a>商品管理</a></el-breadcrumb-item>
<el-breadcrumb-item>商品列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 卡片视图区域 -->
<el-card>
<el-row :gutter="20">
<el-col :span="8">
<el-input placeholder="请输入内容" v-model="queryInfo.query" clearable>
<el-button slot="append" icon="el-icon-search" @click="getGoodsList"></el-button>
</el-input>
</el-col>
<el-col :span="4">
<el-button type="primary" @click="goAddpage">添加商品</el-button>
</el-col>
</el-row>
<!-- 商品列表区域 -->
<el-table :data="goodsList" border stripe>
<el-table-column type="index" label="序号"></el-table-column>
<el-table-column label="商品名称" prop="goods_name"></el-table-column>
<el-table-column label="商品价格(元)" prop="goods_price"></el-table-column>
<el-table-column label="商品重量" prop="goods_weight"></el-table-column>
<el-table-column label="创建时间" prop="add_time">
<template slot-scope="scope">
{{ scope.row.add_time | dateFormat }}
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" size="mini"
@click="showEditDialog(scope.row.attr_id)">编辑</el-button>
<el-button type="danger" icon="el-icon-delete" size="mini"
@click="removeById(scope.row.goods_id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--分页区域 -->
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
:current-page="queryInfo.pagenum" :page-sizes="[5, 10, 15, 20]" :page-size="queryInfo.pagesize"
layout="total, sizes, prev, pager, next, jumper" :total="total" background>
</el-pagination>
</el-card>
</div>
</template>
<script>
export default {
name: 'VueShopListComponent',
data() {
return {
// 获取商品列表的参数对象
queryInfo: {
query: '',
// 当前的页数
pagenum: 1,
// 当前页显示多少条数据
pagesize: 5,
},
// 商品列表数组
goodsList: [],
// 数据条数
total: 0
};
},
created() {
// 根据分页获取对应的商品列表
this.getGoodsList()
},
mounted() {
},
methods: {
// 根据分页请求数据
async getGoodsList() {
const { data: res } = await this.$http.get('goods', { params: this.queryInfo })
if (res.meta.status !== 200) return this.$message.error('获取商品列表失败')
// console.log(res.data);
this.goodsList = res.data.goods
this.total = res.data.total
},
//在分页区域中监听页面pagesize改变的事件
handleSizeChange(newSize) {
// 这里就是根据修改 几条/页 切换之后重新请求
this.queryInfo.pagesize = newSize
this.getGoodsList()
},
// 监听页码值改变的事件
handleCurrentChange(newPage) {
// console.log(newPage)
// 这里就是监听到了页码改变然后重新请求这个页码中的x页数据
this.queryInfo.pagenum = newPage
this.getGoodsList()
},
// 弹出消息提示框是否删除
async removeById(id) {
// 弹框询问用户是否删除数据
const confirmResult = await this.$confirm('此操作将永久删除该商品, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).catch(err => err)
// 如果用户确认删除,则返回值为字符串confirm
// 如果用户取消了删除,则返回的字符串为cancel
if (confirmResult !== 'confirm') { return this.$message.info('已经取消删除') }
// const { data: res } = await this.$http.delete(`goods/${id}` )
const { data: res } = await this.$http.delete('goods/' + id)
if (res.meta.status !== 200) { return this.$message.error('删除商品失败!') }
this.$message.success('删除商品成功!')
// 刷新重新获取商品列表
this.getGoodsList()
},
// 添加商品,路由跳转访问添加商品页面
goAddpage(){
this.$router.push('/home/goods/add')
}
},
};
</script>
<style lang="less" scoped></style>