Vue + ElementUI的电商管理系统实例11 商品分类

vue

1、创建商品分类分支goods_cate并push到远程

查看分支:

git branch

创建分支:

git checkout -b goods_cate

推送到远程:(以前码云中没有该分支,所以要加-u,如果码云中有该分支,则不需要加-u)

git push -u origin goods_cate

2、通过路由加载商品分类组件

新建goods文件夹和Cate.vue文件:

<template>

<div>

<h3>商品分类组件</h3>

</div>

</template>

<script>

export default {

}

</script>

<style lang="less" scoped>

</style>

添加路由:

import Cate from \'../components/goods/Cate.vue\'

const routes = [

{ path: \'/\', redirect: \'/login\' }, // 重定向

{ path: \'/login\', component: Login },

{

path: \'/home\',

component: Home,

redirect: \'/welcome\', // 重定向

children: [ // 子路由

{ path: \'/welcome\', component: Welcome },

{ path: \'/users\', component: Users }, // 用户列表

{ path: \'/rights\', component: Rights }, // 权限列表

{ path: \'/roles\', component: Roles }, // 角色列表

{ path: \'/categories\', component: Cate } // 商品分类

]

}

]

点击左侧菜单的商品分类的效果如图:

3、绘制商品分类组件的基本布局

还是面包屑和card视图:

<template>

<div>

<!--面包屑导航区域-->

<el-breadcrumb separator-class="el-icon-arrow-right">

<el-breadcrumb-item :to="{ path: \'/home\' }">首页</el-breadcrumb-item>

<el-breadcrumb-item>商品管理</el-breadcrumb-item>

<el-breadcrumb-item>商品分类</el-breadcrumb-item>

</el-breadcrumb>

<!--卡片视图区域-->

<el-card>

<!--添加角色按钮区域-->

<el-row>

<el-col>

<el-button type="primary">添加分类</el-button>

</el-col>

</el-row>

<!--分类列表区域-->

<!--分页区域-->

</el-card>

</div>

</template>

<script>

export default {

}

</script>

<style lang="less" scoped>

</style>

4、调用api接口获取商品分类列表数据

商品分类数据列表,请求路径:categories,请求方法:get,

请求参数
type    [1,2,3]    值:1,2,3 分别表示显示一层二层三层分类列表  【可选参数】如果不传递,则默认获取所有级别的分类
pagenum   当前页码值  【可选参数】如果不传递,则默认获取所有分类
pagesize    每页显示多少条数据  【可选参数】如果不传递,则默认获取所有分类

<script>

export default {

data() {

return {

// 查询条件

queryInfo: {

type: 3,

pagenum: 1,

pagesize: 5

},

cateList: [], // 商品分类列表数据

total: 0 // 总数据条数

}

},

created() {

this.getCateList()

},

methods: {

// 获取商品分类数据

async getCateList() {

const { data: res } = await this.$http.get(\'categories\', { params: this.queryInfo })

if (res.meta.status !== 200) {

return this.$message.error(\'获取商品分类失败\')

}

console.log(res.data)

this.cateList = res.data.result

// 带参数请求,返回的数据多一层result,还有总数total,当前页pagenum,当然页条数pagesize

this.total = res.data.total

}

}

}

</script>

注意:这里请求接口时记得带参数,否则会返回一个总数据的data,而没有total、pagenum,pagesize参数。

5、使用vue-table-with-tree-grid树形表格组件

element没有相应的组件,要通过第三方插件来实现

打开vue ui面板,找到依赖项,点击安装依赖,在弹出的对话框中,搜索:vue-table-with-tree-grid,进行安装。

然后查看文档,有两种用法:

import Vue from \'vue\'

import ZkTable from \'vue-table-with-tree-grid\'

Vue.use(ZkTable)

// 或者

import Vue from \'vue\'

import ZkTable from \'vue-table-with-tree-grid\'

Vue.component(ZkTable.name, ZkTable)

打开入口文件main.js,导入插件:

import TreeTable from \'vue-table-with-tree-grid\'

Vue.component(\'tree-table\', TreeTable)

参考官方文档给的示例代码,重新回到Cate.vue文件,使用插件:

<!--分类列表区域-->

<tree-table :data="cateList" :columns="columns" :selection-type="false" :expand-type="false"

show-index index-text="#" border :show-row-hover="false"></tree-table>

data  表格各行的数据
columns  表格各列的配置(具体见下文:Columns Configs)
selection-type  是否为多选类型表格
expand-type  是否为展开行类型表格(为 True 时,需要添加名称为 \'$expand\' 的作用域插槽, 它可以获取到 row, rowIndex)
show-index  是否显示数据索引
index-text  数据索引名称
border  是否显示纵向边框
show-row-hover  鼠标悬停时,是否高亮当前行

定义columns:

// 为table表格各列的配置定义

columns: [

{

label: \'分类名称\', // 列标题名称

prop: \'cat_name\' // 对应列内容的属性名

},

{

label: \'是否有效\'

},

{

label: \'排序\'

},

{

label: \'操作\'

}

]

此时效果图:

6、使用自定义模板渲染表格数据

先自定义是否有效模板: 

// 为table表格各列的配置定义

columns: [

{

label: \'分类名称\', // 列标题名称

prop: \'cat_name\' // 对应列内容的属性名

},

{

label: \'是否有效\',

type: \'template\', // 表示:把当前列定义为模板列

template: \'isok\' // 表示当前这列使用的模板名称

},

{

label: \'排序\'

},

{

label: \'操作\'

}

]

添加到表格:

<!--分类列表区域-->

<tree-table :data="cateList" :columns="columns" :selection-type="false" :expand-type="false"

show-index index-text="#" border :show-row-hover="false">

<template slot="isok" scope="scope">

<i v-if="!scope.row.cat_deleted" class="el-icon-success"></i>

<i v-else class="el-icon-error"></i>

</template>

</tree-table>

<style lang="less" scoped>

.el-icon-success{color: lightgreen;}

.el-icon-error{color:red;}

</style>

此时效果图:

7、 渲染排序和操作对应的UI

columns:

// 为table表格各列的配置定义

columns: [

{

label: \'分类名称\', // 列标题名称

prop: \'cat_name\' // 对应列内容的属性名

},

{

label: \'是否有效\',

type: \'template\', // 表示:把当前列定义为模板列

template: \'isok\' // 表示当前这列使用的模板名称

},

{

label: \'排序\',

type: \'template\', // 表示:把当前列定义为模板列

template: \'order\' // 表示当前这列使用的模板名称

},

{

label: \'操作\',

type: \'template\', // 表示:把当前列定义为模板列

template: \'operate\' // 表示当前这列使用的模板名称

}

]

排序和操作列代码:

<!--排序的作用域插槽-->

<template slot="order" scope="scope">

<el-tag v-if="scope.row.cat_level == 0">一级</el-tag>

<el-tag v-else-if="scope.row.cat_level == 1" type="success">二级</el-tag>

<el-tag v-else type="warning">三级</el-tag>

</template>

<!--操作的作用域插槽-->

<template slot="operate" scope="scope">

<el-button size="mini" type="primary" icon="el-icon-edit">编辑</el-button>

<el-button size="mini" type="danger" icon="el-icon-delete">删除</el-button>

</template>

此时效果图:

8、实现分页功能

添加分页代码:

<!--分页区域-->

<el-pagination

@size-change="handleSizeChange"

@current-change="handleCurrentChange"

:current-page="queryInfo.pagenum"

:page-sizes="[3, 5, 10, 15]"

:page-size="queryInfo.pagesize"

layout="total, sizes, prev, pager, next, jumper"

:total="total"

></el-pagination>

添加handleSizeChange和handleCurrentChange:

// 监听 pagesize 改变

handleSizeChange(newSize) {

this.queryInfo.pagesize = newSize

this.getCateList()

},

// 监听pagenum 改变

handleCurrentChange(newPage) {

this.queryInfo.pagenum = newPage

this.getCateList()

}

给添加分类按钮和表格之间添加间距:

<!--分类列表区域-->

<tree-table class="treeTable" :data="cateList" :columns="columns" :selection-type="false" :expand-type="false"

show-index index-text="#" border :show-row-hover="false">

<style lang="less" scoped>

.el-icon-success{color: lightgreen;}

.el-icon-error{color:red;}

.treeTable{margin-top:15px;}

</style>

此时效果图:

9、添加分类的对话框和表单

添加分类按钮添加点击事件:

<!--添加分类按钮区域-->

<el-row>

<el-col>

<el-button type="primary" @click="showAddCateDialog">添加分类</el-button>

</el-col>

</el-row>

<script>

export default {

。。。

methods: {

// 点击按钮 弹出添加分类对话框

showAddCateDialog() {

this.addCateDialogVisible = true

}

}

}

</script>

添加对话框代码:

<!--添加分类的对话框-->

<el-dialog title="添加分类" :visible.sync="addCateDialogVisible" width="50%" >

<!--添加分类表单区域-->

<el-form :model="addCateForm" :rules="addCateFormRules" ref="addCateFormRef" label-width="90px">

<el-form-item label="分类名称" prop="cat_name">

<el-input v-model="addCateForm.cat_name"></el-input>

</el-form-item>

<el-form-item label="父级分类">

</el-form-item>

</el-form>

<!--底部按钮区域-->

<span slot="footer" class="dialog-footer">

<el-button @click="addCateDialogVisible = false">取 消</el-button>

<el-button type="primary" @click="addCateDialogVisible = false">确 定</el-button>

</span>

</el-dialog>

<script>

export default {

data() {

return {

addCateDialogVisible: false, // 控制添加分类对话框是否显示

// 添加分类的表单数据对象

addCateForm: {

cat_name: \'\', // 将要添加的分类名称

cat_pid: 0, // 父分类的ID

cat_level: 0 // 要添加分类的等级,默认要添加的是一级分类

},

// 添加分类表单的验证规则对象

addCateFormRules: {

cat_name: [

{ required: true, message: \'请输入分类名称\', trigger: \'blur\' }

]

}

}

}

}

</script>

此时效果图:

10、获取父级分类的数据列表

商品分类数据列表接口,参数type:2 表示只获取前两级的分类数据。因为最多有三级分类,所以父级分类最多两级。

添加代码获取父级分类数据:

parentCateList: [] // 父级分类列表数据

// 点击按钮 弹出添加分类对话框

showAddCateDialog() {

// 获取父级分类的数据列表

this.getParentCateList()

this.addCateDialogVisible = true

},

// 获取父级分类的数据列表

async getParentCateList() {

const { data: res } = await this.$http.get(\'categories\', { params: { type: 2 } })

console.log(res)

if (res.meta.status !== 200) {

return this.$message.error(\'获取父级分类数据失败\')

}

this.parentCateList = res.data

}

11、通过级联选择器渲染数据

Cascader 级联选择器
当一个数据集合有清晰的层级结构时,可通过级联选择器逐级查看并选择。

先导入到element.js里,这里就不写了。

value / v-model  选中项绑定值,数组
options  可选项数据源,键名可通过 Props 属性配置
props  配置选项,具体见下表
clearable  是否支持清空选项

expandTrigger  次级菜单的展开方式
checkStrictly  是否严格的遵守父子节点不互相关联
value  指定选项的值为选项对象的某个属性值
label  指定选项标签为选项对象的某个属性值
children  指定选项的子选项为选项对象的某个属性值

添加代码:

<el-form-item label="父级分类">

<!--级联选择器-->

<!-- options用来指定数据源 props用来指定配置对象-->

<el-cascader

v-model="selectedKeys"

:options="parentCateList"

:props="cascaderProps"

@change="parentCateChanged" clearable></el-cascader>

</el-form-item>

<script>

export default {

data() {

return {

parentCateList: [], // 父级分类列表数据

// 指定级联选择器的配置对象

cascaderProps: {

expandTrigger: \'hover\', // 次级菜单的展开方式 click / hover

checkStrictly: true, // 允许选择任意一级的选项

value: \'cat_id\', // 指定选中值的属性

label: \'cat_name\', // 指定选中标签的名称

children: \'children\' // 指定父子嵌套的属性

},

// 选中的父级分类的ID数组

selectedKeys: []

}

},

methods: {

// 选择项发生变化时触发这个函数

parentCateChanged() {

console.log(this.selectedKeys)

}

}

}

</script>

<style lang="less" scoped>

.el-cascader{width: 100%;}

</style>

还要记得在全局样式global.css里添加:

.el-cascader-panel{height:200px;}

否则选项框会超长。

注意:是否允许选择任意一级的选项(例如只选第一级),以前版本的element是添加change-on-select,新版本是在props里添加checkStrictly: \'true\'。

此时效果图:

新版bug问题

  1. 点击圆圈后理想是自动收起下拉,但是他这个也没有
  2. 而且只能点击圆圈才能选中,点击文字 label 没有效果

去百度找了一些资料,终于解决了这两个问题:

<el-cascader v-model="selectedKeys" :options="parentCateList" :props="cascaderProps"

@change="parentCateChanged" clearable ref="cascaderRef"

@expand-change="cascaderClick" @visible-change="cascaderClick"></el-cascader>

cascadderClick函数:

// 解决bug:点击圆圈后是自动收起下拉;点击文字label同样实现效果

cascaderClick() {

let that = this

setTimeout(function() {

document.querySelectorAll(\'.el-cascader-node__label\').forEach(el => {

el.onclick = function() {

this.previousElementSibling.click()

that.$refs.cascaderRef.dropDownVisible = false

}

})

document

.querySelectorAll(\'.el-cascader-panel .el-radio\')

.forEach(el => {

el.onclick = function() {

that.$refs.cascaderRef.dropDownVisible = false

}

})

}, 100)

}

OK,现在可以完美实现效果。

12、根据父分类的变化处理表单中的数据

// 添加分类的表单数据对象

addCateForm: {

cat_name: \'\', // 将要添加的分类名称

cat_pid: 0, // 父分类的ID

cat_level: 0 // 要添加分类的等级,默认要添加的是一级分类

},

根据刚才建立的表单数据对象分析:如果在表单中只添加分类名称 ,那么父分类id是0,当前要添加分类的等级是0,默认添加的是一级分类;如果选中了一级分类,那么父分类id就是选中的分类id值,当前要添加分类的等级是1,添加的是二级分类;如果选中了一级和二级分类,那么父分类id就是选中的数组中二级分类id的值,当前要添加的分类的等级是2,添加的是三级分类。说的有点绕,具体看代码吧。。

// 选择项发生变化时触发这个函数

parentCateChanged() {

console.log(this.selectedKeys)

// 如果 selectedKeys 数据中的 length 大于0,则证明选中了父级分类

// 反之,就说明没有选中任何父级分类

if (this.selectedKeys.length > 0) {

// 选择最后一项当作父分类ID赋值

this.addCateForm.cat_pid = this.selectedKeys[this.selectedKeys.length - 1]

// 为当前要添加的分类的等级赋值

this.addCateForm.cat_level = this.selectedKeys.length

return

} else {

// 父分类ID赋值

this.addCateForm.cat_pid = 0

// 为当前要添加的分类的等级赋值

this.addCateForm.cat_level = 0

}

console.log(this.addCateForm)

}

此时三种情况的打印结果分别为:

13、在对话框添加close事件,重置表单数据

给对话框添加colse关闭事件:

<!--添加分类的对话框-->

<el-dialog title="添加分类" :visible.sync="addCateDialogVisible" width="50%" @close="addCateDialogClosed">

addCateDialogClosed事件函数:

// 监听 添加分类对话框的关闭事件

addCateDialogClosed() {

// 表单内容重置为空

this.$refs.addCateFormRef.resetFields() // 通过ref引用调用resetFields方法

// 选中的父级分类的ID数组 重置为空

this.selectedKeys = []

// 父分类id 和 当前分类等级 重置为空

this.addCateForm.cat_pid = 0

this.addCateForm.cat_level = 0

}

14、完成添加分类的操作

调用api的添加分类接口,请求路径:categories,请求方法:post,
请求参数
cat_pid  分类父 ID  不能为空,如果要添加1级分类,则父分类Id应该设置为 `0`
cat_name  分类名称  不能为空
cat_level  分类层级  不能为空,`0`表示一级分类;`1`表示二级分类;`2`表示三级分类

继续完善addCate函数:请求参数前面已经定义过了addCateForm

// 点击按钮,添加新的分类

addCate() {

// console.log(this.addCateForm)

this.$refs.addCateFormRef.validate(async valid => {

if (!valid) return

// 可以发起添加分类的网络请求

const { data: res } = await this.$http.post(\'categories\', this.addCateForm)

if (res.meta.status !== 201) {

this.$message.error(\'添加商品分类失败!\')

}

this.$message.success(\'添加商品分类成功!\')

this.getCateList()

this.addCateDialogVisible = false

})

}

此时效果图:

15、实现编辑分类功能操作

先给编辑按钮添加点击事件:

<el-button size="mini" type="primary" icon="el-icon-edit"

@click="editCateDialog(scope.row.cat_id)">编辑</el-button>

添加编辑对话框代码:

打开对话框是请求根据 id 查询分类的接口,请求路径:categories/:id,请求方法:get

然后把查询到的数据赋值给编辑分类的表单数据

<!--编辑商品分类的对话框-->

<el-dialog

title="编辑分类信息"

:visible.sync="editDialogVisible"

width="50%"

@close="editDialogClosed"

>

<!--内容主体区域-->

<el-form :model="editForm" :rules="addCateFormRules" ref="editFormRef" label-width="90px">

<el-form-item label="分类名称" prop="cat_name">

<el-input v-model="editForm.cat_name"></el-input>

</el-form-item>

</el-form>

<!--底部按钮区域-->

<span slot="footer" class="dialog-footer">

<el-button @click="editDialogVisible = false">取 消</el-button>

<el-button type="primary" @click="editCateInfo">确 定</el-button>

</span>

</el-dialog>

<script>

export default {

data() {

return {

editDialogVisible: false, // 控制编辑分类的对话框是否显示

// 编辑分类信息的表单数据

editForm: {

cat_name: \'\'

}

}

},

methods: {

// 监听 编辑分类对话框

async editCateDialog(id) {

// 发起根据 id 查询分类的网络请求

const { data: res } = await this.$http.get(\'categories/\' + id)

if (res.meta.status !== 200) {

this.$message.error(\'查询分类信息失败\')

}

this.editForm = res.data

this.editDialogVisible = true

},

// 监听 编辑分类信息对话框的关闭事件

editDialogClosed() {

// 表单内容重置为空

this.$refs.editFormRef.resetFields() // 通过ref引用调用resetFields方法

}

}

}

</script>

添加确定按钮绑定点击事件,完成用户信息的修改:

先预校验,然后调用api的编辑提交分类接口,请求路径:categories/:id,请求方法:put,请求参数:cat_name  分类名称 不能为空

// 点击按钮 修改角色信息

editRoleInfo() {

this.$refs.editFormRef.validate(async valid => {

if (!valid) return

// 可以发起修改用户信息的网络请求

const { data: res } = await this.$http.put(\'categories/\' + this.editForm.cat_id,

{ cat_name: this.editForm.cat_name })

if (res.meta.status !== 200) {

return this.$message.error(\'编辑商品分类失败!\')

}

this.$message.success(\'编辑商品分类成功!\')

this.getCateList()

this.editDialogVisible = false

})

}

ok,测试已经可以编辑分类名称:

16、实现删除分类功能操作

 给删除按钮添加点击事件:根据id

<el-button size="mini" type="danger" icon="el-icon-delete"

@click="delCateDialog(scope.row.cat_id)">删除</el-button>

根据分类id,调用api的删除分类接口,请求路径:categories/:id,请求方法:delete

// 监听 删除分类对话框

async delCateDialog(id) {

console.log(id)

// 弹框 询问用户是否删除

const confirmResult = await this.$confirm(\'此操作将永久删除该分类, 是否继续?\', \'提示\', {

confirmButtonText: \'确定\',

cancelButtonText: \'取消\',

type: \'warning\'

}).catch(err => err)

// 如果用户确认删除,则返回值为字符串 confirm

// 如果用户取消删除,则返回值为字符串 cancel

// console.log(confirmResult)

if (confirmResult !== \'confirm\') {

return this.$message.info(\'已取消删除\')

}

// console.log(\'确认删除\')

const { data: res } = await this.$http.delete(\'categories/\' + id)

if (res.meta.status !== 200) {

return this.$message.error(\'删除分类失败!\')

}

this.$message.success(\'删除分类成功!\')

this.getCateList()

}

完成效果图:

17、将goods_cate提交到远程仓库

先查看分支:

git branch

查看当前文件状态:

git status

然后提交到暂存区:

git add .

把当前提交到goods_cate分支:

git commit -m "完成了商品分类功能的开发"

推送到云端goods_cate分支:

git push

把goods_cate分支合并到master:

git checkout master

git merge goods_cate

git push

ok,完成!

以上是 Vue + ElementUI的电商管理系统实例11 商品分类 的全部内容, 来源链接: utcz.com/z/379619.html

回到顶部