77- vue3案例 - 08-文章分类

一. 文章分类页面 - [element-plus 表格]

功能需求说明:
        (1). 基本架子- PageContainer 封装

        (2). 文章分类渲染&loading 处理

        (3). 文章分类添加编辑[element-plus 弹层]

        (4). 文章分类删除

1. 定义公共 静态页面结构

        src\components\PageContainer.vue

<script setup>
defineProps({
  title: {
    required: true,
    type: String
  }
})
</script>
<template>
  <el-card class="page-container">
    <template #header>
      <div class="header">
        <span>{{ title }}</span>
        <div class="extra">
          <!-- 右侧按钮: 使用具名插槽 -->
          <slot name="extra"></slot>
        </div>
      </div>
    </template>
    <!-- 插槽定义内容 -->
    <slot></slot>
  </el-card>
</template>

<style lang="scss" scoped>
.page-container {
  min-height: 100%;
  box-sizing: border-box;
  .header {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
}
</style>
2. 文章分类组件调用公共组件

        src\views\article\AtricleChannel.vue

<template>
    <!-- 可以直接使用components里的公共组件-->
  <page-container title="文章分类">
    <!-- 具名插槽 -->
    <template #extra>
      <el-button>添加分类</el-button>
    </template>
    <!-- 普通插槽内容 -->
    主题部分,是表格
  </page-container>
</template>

<style lang="scss" scoped></style>
3. 文章管理组件调用公共组件

        src\views\article\AtricleManage.vue

<template>
  <!-- 可以直接使用components里的组件-->
  <page-container title="文章管理">
    <!-- 具名插槽 -->
    <template #extra>
      <el-button>添加文章</el-button>
    </template>
    <!-- 普通插槽内容 -->
    主题部分,是表格 + 分页
  </page-container>
</template>

<style lang="scss" scoped></style>

二. 文章分类渲染

1. 封装获取文章分类api

        src\api\article.js

import request from '@/utils/request'

// 获取文章分类
export const artGetChannelService = () => request.get('/my/cate/list')
2. 页面中调用接口获取分类数据

        src\views\article\AtricleChannel.vue

<script setup>
import { ref } from 'vue'
import { artGetChannelService } from '../../api/article'
const channelList = ref([])

const getChannlList = async () => {
  const res = await artGetChannelService() // 调用api
  channelList.value = res.data.data
  console.log(channelList.value)
}
getChannlList() // 一进页面直接调用
</script>
3. el-table 表格动态渲染数据

          src\views\article\AtricleChannel.vue

<script>
...
//编辑和删除的点击事件
const onEditChannel = (row, $index) => {
  console.log(row, $index)
}
const onDelChannel = (row, $index) => {
  console.log(row, $index)
}
</script>

<template>
...
 <!-- 普通插槽内容 -->
    <el-table :data="channelList" style="width: 100%">
      <el-table-column type="index" label="序号" width="100"> </el-table-column>
      <el-table-column prop="cate_name" label="分类名称"> </el-table-column>
      <el-table-column prop="cate_alias" label="分类别名"> </el-table-column>
      <el-table-column label="操作" width="150">
        <!-- row 就是 channelList的一项, $index 下标 -->
        <template #default="{ row, $index }">
          <el-button
            :icon="Edit"
            circle
            plain
            type="primary"
            @click="onEditChannel(row, $index)"
          ></el-button>
          <el-button
            :icon="Delete"
            circle
            plain
            type="danger"
            @click="onDelChannel(row, $index)"
          ></el-button>
        </template>
      </el-table-column>
       
      <!--空状态组件-->
      <template #empty>
        <el-empty description="没有数据"></el-empty>
      </template>
    </el-table>
</template>
4. el-table 表格 添加loading 效果

        src\views\article\AtricleChannel.vue

<script>
// 定义默认loading状态
const loading = ref(false)
...
const getChannlList = async () => {
  loading.value = true  // 发送请求前开启
  const res = await artGetChannelService() // 调用api
  channelList.value = res.data.data
  loading.value = false // 结束请求后关闭
}
...
</script>


<template>
    <!-- 普通插槽内容 -->
    <el-table v-loading="loading" ...>
      ...
    </el-table>
</template>

三. 添加分类-显示弹层

1. 封装弹层组件

        src\views\article\components\ChannelEdit.vue

<script setup>
import { ref } from 'vue'
const dialogVisible = ref(false)

// 组件对外暴露一个方法 open,基于open传来的参数,区分添加还是编辑
// open({}) => 表单无需渲染,说明是添加
// open({ id, cate_name,...}) => 表单需要渲染,说明是编辑
// open 调用后,可以打开弹窗

const open = (row) => {
  console.log(row)
  dialogVisible.value = true
}

// 向外暴露方法
defineExpose({
  open
})
</script>

<template>
  <el-dialog v-model="dialogVisible" title="添加弹层" width="30%">
    <div>渲染表单</div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="dialogVisible = false">
          确认
        </el-button>
      </span>
    </template>
  </el-dialog>
</template>
2. 文章分类调用弹层组件

        src\views\article\AtricleChannel.vue

<script>
import ChannelEdit from './components/ChannelEdit.vue' // 导入弹层组件
...
const dialog = ref()
...
// 编辑,调用方法显示弹层
const onEditChannel = (row) => {
  dialog.value.open(row)
}
// 添加,调用方法显示弹层
const onAddChannel = () => {
  dialog.value.open({})
}
</script>

<template>
<page-container title="文章分类">
  <!-- 具名插槽 -->
  <template #extra>
    <el-button @click="onAddChannel">添加分类</el-button>
  </template>
  <!-- 普通插槽内容 -->
  <el-table>
    <el-button :icon="Edit"... @click="onEditChannel(row, $index)"></el-button>
  </el-table>

  <!--弹层组件,获取组件-->
  <channel-edit ref="dialog"></channel-edit>
</page-container>
</template>

四. 添加分类-添加完成

1. 弹层组件准备数据 和 校验规则

        src\views\article\components\ChannelEdit.vue

<script setup>
...

const formModel = ref({
  cate_name: '',
  cate_alias: ''
})

const rules = {
  cate_name: [
    { required: true, message: '请输入分类名称', trigger: 'blur' },
    {
      pattern: /^\S{1,10}$/,
      message: '分类名称必须是1-10位的非空字符',
      trigger: 'blur'
    }
  ],
  cate_alias: [
    { required: true, message: '请输入分类别名', trigger: 'blur' },
    {
      pattern: /^[a-zA-Z0-9]{1,15}$/,
      message: '分类别名必须是1-15位的字母或数字',
      trigger: 'blur'
    }
  ]
}

...
</script>
2. 准备表单绑定校验

        src\views\article\components\ChannelEdit.vue

<template>
  <el-dialog v-model="dialogVisible" title="添加弹层" width="30%">
    <!-- 内容改为form表单 -->
    <!--1. el-form绑定formModel数据对象 和 rules校验对象-->
    <el-form
      :model="formModel"
      :rules="rules"
      lable-width="100px"
      style="padding-right: 30px"
    >
      <!--2.el-form-item 直接绑定属性-->
      <el-form-item label="分类名称" prop="cate_name">
        <!--3.el-input 绑定数据对象中的属性-->
        <el-input
          v-model="formModel.cate_name"
          placeholder="请输入分类名称"
        ></el-input>
      </el-form-item>
      <el-form-item label="分类别名" prop="cate_alias">
        <el-input
          v-model="formModel.cate_alias"
          placeholder="请输入分类别名"
        ></el-input> </el-form-item
    ></el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="dialogVisible = false">
          确认
        </el-button>
      </span>
    </template>
  </el-dialog>
</template>
3. 回显数据

          src\views\article\components\ChannelEdit.vue

<script setup>
...
const open = (row) => {
  dialogVisible.value = true
  formModel.value = { ...row } // 添加 -> 重置了表单内容, 编辑 ->  存储了需要回显的数据
}
...
</script>

<template>
<!--基于传过来的表单数据,进行标题控制,有 id 的是编辑-->
<el-dialog
    v-model="dialogVisible"
    :title="formModel.id ? '编辑分类' : '添加分类'"
    width="30%"
  >
</template>
4. 提交确认
        (1). 封装提交api

                src\api\article.js

import request from '@/utils/request'

...

// 添加文章分类
export const artAddChannelService = (data) => request.post('/my/cate/add', data)

// 编辑文章分类
export const artEditChannelService = (data) =>
  request.put('/my/cate/info', data)
        (2). 页面中预校验提交请求

                src\views\article\components\ChannelEdit.vue

<script>
import { artEditChannelService, artAddChannelService } from '@/api/article.js'
...
// 定义formRef 
const formRef = ref()
...
const onSubmit = async () => {
  await formRef.value.validate() // 校验表单
  const isEdit = formModel.value.id // 尝试获取id
  if (isEdit) {
    // 能获取到id 就是编辑分类
    await artEditChannelService(formModel.value)
    ElMessage.success('编辑成功')
  } else {
    //添加分类
    await artAddChannelService(formModel.value)
    ElMessage.success('添加成功')
  }
  // 关闭弹层
  dialogVisible.value = false
}
...
</script>

<template>
    <!-- ref获取表单 -->
    <el-form ref="formRef" ... >...</el-form>

    <!--确认按钮定义点击事件-->
    <el-button type="primary" @click="onSubmit"> 确认 </el-button>
</template>
        (3) .通知父组件刷新页面数据

                src\views\article\components\ChannelEdit.vue

<script>
// 定义子传父事件,通知父组件刷新页面数据
const emit = defineEmits(['success'])
const onSubmit = async () => {
  ...
  // 关闭弹层
  dialogVisible.value = false
  emit('success') // 父子通信
}
</script>
        (4). 父组件接收通知,刷新数据

                src\views\article\AtricleChannel.vue

<script>
...
// 重新调用获取分类api
const onSuccess = () => {
  getChannlList()
}
</script>

<template>
  <!--监听事件: success,进行调用回显-->
  <channel-edit ref="dialog" @success="onSuccess"></channel-edit>
</template>

五. 文章分类删除

1. 封装删除api

        src\api\article.js

import request from '@/utils/request'
...

//删除文章分类
export const artDelChannelService = (id) =>
  request.delete('/my/cate/del', {
    params: { id }
  })
2. 页面中调用删除接口

        src\views\article\AtricleChannel.vue

<script>
import { artGetChannelService, artDelChannelService } from '../../api/article'
...

//删除
const onDelChannel = async (row) => {
  await ElMessageBox.confirm('你确认删除该分类信息吗?', '温馨提示', {
    type: 'warning',
    confirmButtonText: '确认',
    cancelButtonText: '取消'
  })
  await artDelChannelService(row.id) // 调用删除api
  ElMessage.success('删除成功')
  getChannlList() // 重新调用获取数据接口渲染数据
}
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值