vue3大事件管理系统 === 首页 layout & 文章分类页面 -

目录

[首页 layout 架子 element-plus 菜单](#首页 layout 架子 [element-plus 菜单])

基本架子拆解

登录访问拦截

用户基本信息获取&渲染

[退出功能 element-plus 确认框](#退出功能 [element-plus 确认框])

[文章分类页面 - element-plus 表格](#文章分类页面 - [element-plus 表格])

[基本架子 - PageContainer](#基本架子 - PageContainer)

文章分类渲染

[封装API - 请求获取表格数据](#封装API - 请求获取表格数据)

[el-table 表格动态渲染](#el-table 表格动态渲染)

[el-table 表格 loading 效果](#el-table 表格 loading 效果)

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

点击显示弹层

[封装弹层组件 ChannelEdit](#封装弹层组件 ChannelEdit)

准备弹层表单

确认提交

文章分类删除


首页 layout 架子 element-plus 菜单

基本架子拆解

架子组件列表:

el-container

  • el-aside 左侧

    • el-menu 左侧边栏菜单
  • el-container 右侧

    • el-header 右侧头部

      • el-dropdown
    • el-main 右侧主体

      • router-view

登录访问拦截

需求:只有登录页,可以未授权的时候访问,其他所有页面,都需要先登录再访问

复制代码
// 登录访问拦截
router.beforeEach((to) => {
  const userStore = useUserStore()
  if (!userStore.token && to.path !== '/login') return '/login'
})

用户基本信息获取&渲染

  1. api/user.js封装接口

    export const userGetInfoService = () => request.get('/my/userinfo')

  2. stores/modules/user.js 定义数据

    const user = ref({})
    const getUser = async () => {
    const res = await userGetInfoService() // 请求获取数据
    user.value = res.data.data
    }

  3. layout/LayoutContainer页面中调用

    import { useUserStore } from '@/stores'
    const userStore = useUserStore()
    onMounted(() => {
    userStore.getUser()
    })

  4. 动态渲染

    黑马程序员:{{ userStore.user.nickname || userStore.user.username }}

退出功能 element-plus 确认框

  1. 注册点击事件

    <el-dropdown placement="bottom-end" @command="onCommand">

    基本资料 更换头像 重置密码 退出登录
  2. 添加退出功能

    const onCommand = async (command) => {
    if (command === 'logout') {
    await ElMessageBox.confirm('你确认退出大事件吗?', '温馨提示', {
    type: 'warning',
    confirmButtonText: '确认',
    cancelButtonText: '取消'
    })
    userStore.removeToken()
    userStore.setUser({})
    router.push(/login)
    } else {
    router.push(/user/${command})
    }
    }

  3. pinia user.js 模块 提供 setUser 方法

    const setUser = (obj) => (user.value = obj)

文章分类页面 - element-plus 表格

基本架子 - PageContainer

  1. 基本结构样式,用到了 el-card 组件

  2. 考虑到多个页面复用,封装成组件

    • props 定制标题
    • 默认插槽 default 定制内容主体
    • 具名插槽 extra 定制头部右侧额外的按钮
  3. 页面中直接使用测试 ( unplugin-vue-components 会自动注册)

  • 文章分类测试:

  • 文章管理测试:

文章分类渲染

封装API - 请求获取表格数据
  1. 新建 api/article.js 封装获取频道列表的接口

    import request from '@/utils/request'
    export const artGetChannelsService = () => request.get('/my/cate/list')

  2. 页面中调用接口,获取数据存储

    const channelList = ref([])

    const getChannelList = async () => {
    const res = await artGetChannelsService()
    channelList.value = res.data.data
    }

el-table 表格动态渲染
复制代码
<el-table :data="channelList" style="width: 100%">
  <el-table-column label="序号" width="100" type="index"> </el-table-column>
  <el-table-column label="分类名称" prop="cate_name"></el-table-column>
  <el-table-column label="分类别名" prop="cate_alias"></el-table-column>
  <el-table-column label="操作" width="100">
    <template #default="{ row }">
      <el-button
        :icon="Edit"
        circle
        plain
        type="primary"
        @click="onEditChannel(row)"
      ></el-button>
      <el-button
        :icon="Delete"
        circle
        plain
        type="danger"
        @click="onDelChannel(row)"
      ></el-button>
    </template>
  </el-table-column>
  <template #empty>
    <el-empty description="没有数据" />
  </template>
</el-table>


const onEditChannel = (row) => {
  console.log(row)
}
const onDelChannel = (row) => {
  console.log(row)
}
el-table 表格 loading 效果
  1. 定义变量,v-loading绑定

    const loading = ref(false)

  2. 发送请求前开启,请求结束关闭

    const getChannelList = async () => {
    loading.value = true
    const res = await artGetChannelsService()
    channelList.value = res.data.data
    loading.value = false
    }

文章分类添加编辑 element-plus 弹层

点击显示弹层
  1. 准备弹层

    const dialogVisible = ref(false)

    我是内容部分
  2. 点击事件

    <template #extra><el-button type="primary" @click="onAddChannel">添加分类

    const onAddChannel = () => {
    dialogVisible.value = true
    }

封装弹层组件 ChannelEdit

添加 和 编辑,可以共用一个弹层,所以可以将弹层封装成一个组件

组件对外暴露一个方法 open, 基于 open 的参数,初始化表单数据,并判断区分是添加 还是 编辑

  1. open({ }) => 添加操作,添加表单初始化无数据
  2. open({ id: xx, ... }) => 编辑操作,编辑表单初始化需回显

具体实现:

  1. 封装组件 article/components/ChannelEdit.vue

  2. 通过 ref 绑定

    const dialog = ref()

  3. 点击调用方法显示弹窗

    const onAddChannel = () => {
    dialog.value.open({})
    }
    const onEditChannel = (row) => {
    dialog.value.open(row)
    }

准备弹层表单
  1. 准备数据 和 校验规则

    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'
    }
    ]
    }

  2. 准备表单

    <el-form
    :model="formModel"
    :rules="rules"
    label-width="100px"
    style="padding-right: 30px"

  3. 编辑需要回显,表单数据需要初始化

    const open = async (row) => {
    dialogVisible.value = true
    formModel.value = { ...row }
    }

  4. 基于传过来的表单数据,进行标题控制,有 id 的是编辑

    :title="formModel.id ? '编辑分类' : '添加分类'"

确认提交
  1. api/article.js 封装请求 API

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

  2. 页面中校验,判断,提交请求

    const formRef = ref()
    const onSubmit = async () => {
    await formRef.value.validate()
    formModel.value.id
    ? await artEditChannelService(formModel.value)
    : await artAddChannelService(formModel.value)
    ElMessage({
    type: 'success',
    message: formModel.value.id ? '编辑成功' : '添加成功'
    })
    dialogVisible.value = false
    }

  3. 通知父组件进行回显

    const emit = defineEmits(['success'])

    const onSubmit = async () => {
    ...
    emit('success')
    }

  4. 父组件监听 success 事件,进行调用回显

    <channel-edit ref="dialog" @success="onSuccess">

    const onSuccess = () => {
    getChannelList()
    }

文章分类删除

  1. api/article.js封装接口 api

    // 删除文章分类
    export const artDelChannelService = (id) =>
    request.delete('/my/cate/del', {
    params: { id }
    })

  2. 页面中添加确认框,调用接口进行提示

    const onDelChannel = async (row) => {
    await ElMessageBox.confirm('你确认删除该分类信息吗?', '温馨提示', {
    type: 'warning',
    confirmButtonText: '确认',
    cancelButtonText: '取消'
    })
    await artDelChannelService(row.id)
    ElMessage({ type: 'success', message: '删除成功' })
    getChannelList()
    }

相关推荐
梦梦代码精7 小时前
2026年PHP开源商城系统实测对比:架构、多商户、商用授权,谁才是真·省心?
vue.js·docker·架构·开源·代码规范
threelab7 小时前
Three.js 物理模拟着色器 | 三维可视化 / AI 提示词
开发语言·前端·javascript·人工智能·3d·着色器
武器大师727 小时前
lv_binding_js 代码解读
开发语言·javascript·ecmascript
Patrick_Wilson9 小时前
router.replace 之后紧跟 reload,页面为什么无限刷新?
javascript·react.js·浏览器
mONESY10 小时前
JavaScript 栈、队列、数组与链表核心知识点总结
javascript·面试
ZengLiangYi10 小时前
TypeScript 项目配置:tsconfig、ESM、路径别名
javascript·typescript·aigc
晓131310 小时前
【Cocos Creator 3.x】篇——第二章 入门
前端·javascript·游戏引擎
想要成为糕糕手11 小时前
前端必修课:JavaScript 数组与数据结构底层逻辑全解析
javascript·数据结构·面试
xiaofeichaichai11 小时前
React Hooks
前端·javascript·react.js
数据知道11 小时前
C++ 层拦截:修改 Blink 引擎与 V8 绑定的底层逻辑
javascript·数据采集·指纹浏览器·风控