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接口獲取商品分類列表數據
請求參數
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>
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、獲取父級分類的數據列表
添加代碼獲取父級分類數據:
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問題
- 點擊圓圈後理想是自動收起下拉,但是他這個也沒有
- 而且只能點擊圓圈才能選中,點擊文字 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() {
// 表單內容重置爲空
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,完成!