Vue + ElementUI的電商管理系統實例11 商品分類

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,完成!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章