Vue3.0项目实战(四)——大事件管理系统文章管理页面 - [element-plus 强化]

目录

[1. 文章列表渲染](#1. 文章列表渲染)

[1.1 基本架子搭建](#1.1 基本架子搭建)

[1.2 中英国际化处理](#1.2 中英国际化处理)

[1.3 文章分类选择](#1.3 文章分类选择)

[1.4 封装 API 接口,请求渲染文章列表](#1.4 封装 API 接口,请求渲染文章列表)

[2. 分页渲染 [element-plus 分页]](#2. 分页渲染 [element-plus 分页])

[3. 添加 loading 处理](#3. 添加 loading 处理)

[4. 搜索 和 重置功能](#4. 搜索 和 重置功能)

[5. 文章发布&修改 [element-plus - 抽屉]](#5. 文章发布&修改 [element-plus - 抽屉])

[5.1 点击显示抽屉](#5.1 点击显示抽屉)

[5.2 封装抽屉组件 ArticleEdit](#5.2 封装抽屉组件 ArticleEdit)

[5.3 完善抽屉表单结构](#5.3 完善抽屉表单结构)

[5.4 上传图片文件预览 [element-plus - 文件预览]](#5.4 上传图片文件预览 [element-plus - 文件预览])

[5.5 富文本编辑器 [ vue-quill ]](#5.5 富文本编辑器 [ vue-quill ])

[5.6 添加文章功能](#5.6 添加文章功能)

[5.7 添加完成后的内容重置](#5.7 添加完成后的内容重置)

[5.8 编辑文章回显](#5.8 编辑文章回显)

[5.9 编辑文章功能](#5.9 编辑文章功能)

[6. 文章删除](#6. 文章删除)


1. 文章列表渲染

1.1 基本架子搭建

① 搜索表单

html 复制代码
 <!-- 表单区域   inline 将 el-form-item 在一行显示 -->
      <el-form inline>
        <el-form-item label="文章分类:">
          <!-- <el-select placeholder="请选择" size="large" style="width: 240px">
            <el-option label="体育" value="1111" />
            <el-option label="新闻" value="2222" />
          </el-select> -->
          <!-- vue2.0 v-model 是 :value 和 @input 的简写,
            相当于传递了一个 value 属性给子组件,自定义的事件是 input 事件 -->
          <!-- vue3.0 v-model 是 :modelValue 和 @update:modelValue 的简写 -->
          <!-- 或者也可以写为: 
          <ChannelSelect :modelValue="params.cate_id"></ChannelSelect> 
          -->
          <ChannelSelect v-model="params.cate_id"></ChannelSelect>
        </el-form-item>
        <el-form-item label="发布状态:">
          <el-select
            placeholder="请选择"
            size="large"
            style="width: 240px"
            v-model="params.state"
          >
            <el-option label="已发布" value="已发布" />
            <el-option label="草稿" value="草稿" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="onSearch">搜索</el-button>
          <el-button @click="onReset">重置</el-button>
        </el-form-item>
      </el-form>
      <!-- 表单区域 -->

② 文章列表表格准备,模拟假数据渲染

  • el-link 文字超链接

    |-----------|-------|
    | underline | 是否下划线 |

html 复制代码
<!-- 文章列表 -->
      <el-table
        style="width: 100%"
        stripe
        :data="tableData"
        v-loading="loading"
      >
        <el-table-column label="文章标题" prop="title" align="center">
          <template #default="scope">
            <el-link type="primary" :underline="false">
              {{ scope.row.title }}
            </el-link>
          </template>
        </el-table-column>
        <el-table-column
          label="分类"
          prop="cate_name"
          align="center"
        ></el-table-column>
        <el-table-column label="发布时间" prop="pub_date" align="center">
          <template #default="scope">
            {{ formatTime(scope.row.pub_date) }}
          </template>
        </el-table-column>
        <el-table-column
          label="状态"
          prop="state"
          align="center"
        ></el-table-column>
        <el-table-column label="操作" align="center">
          <template #default="scope">
            <div
              style="
                display: flex;
                justify-content: center;
                align-items: center;
              "
            >
              <el-button
                type="primary"
                :icon="Edit"
                circle
                plain
                @click="onEditArticle(scope.row)"
              ></el-button>
              <el-button
                type="danger"
                plain
                @click="onDeleteArticle(scope.row)"
                :icon="Delete"
                circle
              ></el-button>
            </div>
          </template>
        </el-table-column>
        <template #empty>
          <el-empty description="没有数据"></el-empty>
        </template>
      </el-table>

1.2 中英国际化处理

默认是英文的,由于这里不涉及切换, 所以在 App.vue 中直接导入设置成中文即可,

① 全局配置

② ConfigProvider

1.3 文章分类选择

为了便于维护,直接拆分成一个小组件 ChannelSelect.vue

① 新建 article/manage/components/ChannelSelect.vue

② 页面中导入渲染

③ 调用接口,动态渲染下拉分类,设计成 v-model 的使用方式

  • vue2.0 v-model 是 :value 和 @input 的简写,相当于传递了一个 value 属性给子组件,自定义的事件是 input 事件。

  • vue3.0 v-model 是 :modelValue 和 @update:modelValue 的简写。相当于传递了一个 modelValue 属性给子组件,自定义的事件是 update:modelValue 事件。

④ 父组件定义参数绑定

⑤ 发布状态,也绑定一下,便于将来提交表单

1.4 封装 API 接口,请求渲染文章列表

① api/article.js 封装接口

② 页面中调用保存数据

③ 新建 utils/format.js 封装格式化日期函数

④ 导入使用(vue 3.0 废弃了过滤器)

2. 分页渲染 [element-plus 分页]

① 分页组件

  • current-page / v-model:current-page:当前页数

  • page-size / v-model:page-size:每页显示条目个数

  • page-sizes:每页显示个数选择器的选项设置

  • background:是否为分页按钮添加背景色

  • layout:组件布局,子组件名用逗号分隔

  • total:总条目数

  • size-change:page-size 改变时触发

  • current-change:current-page 改变时触发

② 提供分页修改逻辑

  • 每页显示数据条数,处理函数
  • 当前页改变的时候触发,

3. 添加 loading 处理

① 准备数据

② el-table上面绑定

③ 发送请求时添加 loading

4. 搜索 和 重置功能

① 注册事件

② 绑定处理

5. 文章发布&修改 [element-plus - 抽屉]

5.1 点击显示抽屉

① 准备数据

② 准备抽屉容器

③ 点击修改布尔值显示抽屉

javascript 复制代码
<el-button type="primary" @click="onAddArticle">发布文章</el-button>

const drawer = ref(false)
const onAddArticle = () => {
  drawer.value = true
}

5.2 封装抽屉组件 ArticleEdit

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

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

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

具体实现:

① 封装组件 article/manage/components/ArticleEdit.vue,向外暴露 open 方法

② 父组件中通过 ref 绑定抽屉组件

③ 点击调用方法显示弹窗

5.3 完善抽屉表单结构

① 准备数据

② 准备 form 表单结构

html 复制代码
 <el-form :model="formModel">
      <el-form-item label="文章标题:" prop="title">
        <el-input
          placeholder="请输入文章标题"
          v-model="formModel.title"
        ></el-input>
      </el-form-item>
      <el-form-item label="文章分类:" prop="cate_id">
        <ChannelSelect
          v-model="formModel.cate_id"
          :width="'100%'"
        ></ChannelSelect>
      </el-form-item>
      <el-form-item label="文章封面:" prop="cover_img">
        <!--
          此处需要关闭 element-plus 的自动上传,不需要配置 action 等参数
          只需要做前端的本地预览图片即可,无需在提交之前上传图片
          语法: Window.ULR.createObjectURL() 创建本地预览的地址,来预览图片
          show-file-list	是否显示已上传文件列表
          on-change	文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用
          auto-upload	是否自动上传文件
         -->
        <el-upload
          class="avatar-uploader"
          :show-file-list="false"
          :on-change="onUploadFile"
          :auto-upload="false"
        >
          <img v-if="imageUrl" :src="imageUrl" class="avatar" />
          <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
        </el-upload>
      </el-form-item>
      <el-form-item label="文章内容:" prop="content">
        <div class="editor">
          <!-- 富文本编辑器 -->
          <QuillEditor
            ref="editorRef"
            theme="snow"
            v-model:content="formModel.content"
            content-type="html"
          />
        </div>
      </el-form-item>
      <el-form-item prop="state">
        <el-button type="primary" @click="onPublicArticle('已发布')">
          发布
        </el-button>
        <el-button type="info" @click="onPublicArticle('草稿')">草稿</el-button>
      </el-form-item>
    </el-form>

③ 一打开默认重置添加的 form 表单数据

④ 扩展 下拉菜单 width props

5.4 上传图片文件预览 [element-plus - 文件预览]

① 关闭自动上传,准备结构

  • 此处需要关闭 element-plus 的自动上传,不需要配置 action 等参数

  • 只需要做前端的本地预览图片即可,无需在提交之前上传图片

  • 语法: Window.ULR.createObjectURL() 创建本地预览的地址,来预览图片

  • show-file-list 是否显示已上传文件列表

  • on-change 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用

  • auto-upload 是否自动上传文件

② 准备数据 和 选择图片的处理逻辑

  • 为选中的文件创建一个临时的、本地的 URL,以便在页面上可以直接预览或访问这个文件,而不需要立即上传到服务器

  • window.URL.createObjectURL(file):使用浏览器的 URL.createObjectURL() 方法,为传入的 file 对象(即用户选择的文件)生成一个本地的临时 URL。

  • 立即将图片对象,存入 formModel.value.cover_img 中,将来点击发布按钮的时候,提交给后台的服务器

③ 样式美化

5.5 富文本编辑器 [ vue-quill ]

官网地址:VueQuill | Rich Text Editor Component for Vue 3

① 安装包

  • pnpm add @vueup/vue-quill@latest

② 注册成局部组件

③ 页面中使用绑定

④ 样式美化

5.6 添加文章功能

① 封装添加接口

② 注册点击事件调用

  • 提交给后台的 data 是一个 FormDate 对象

③ 父组件监听事件,重新渲染

5.7 添加完成后的内容重置

5.8 编辑文章回显

如果是编辑操作,一打开抽屉,就需要发送请求,获取数据进行回显

① 封装接口,根据 id 获取详情数据

② 页面中调用渲染

  • 显示图片 "cover_img": "/uploads/885eb38f6270eb10b42aedadd84fea23.jpg",需要与基地址拼接

  • 提交给后台的图片数据格式是 file 对象格式

  • 所以需要将网络地址 "cover_img": "/uploads/885eb38f6270eb10b42aedadd84fea23.jpg",又转化成 file 对象,存储起来 (正常情况下, 后台应该两个都支持)

③ chatGPT prompt:封装一个函数,基于 axios, 网络图片地址,转 file 对象, 请注意:写中文注释

javascript 复制代码
// 将网络图片地址转换为File对象
async function imageUrlToFile(url, fileName) {
  try {
    // 第一步:使用axios获取网络图片数据
    const response = await axios.get(url, { responseType: 'arraybuffer' });
    const imageData = response.data;

    // 第二步:将图片数据转换为Blob对象
    const blob = new Blob([imageData], { type: response.headers['content-type'] });

    // 第三步:创建一个新的File对象
    const file = new File([blob], fileName, { type: blob.type });

    return file;
  } catch (error) {
    console.error('将图片转换为File对象时发生错误:', error);
    throw error;
  }
}

5.9 编辑文章功能

① 封装编辑接口

② 提交时调用

6. 文章删除

① 封装删除接口

② 页面中添加确认框调用

相关推荐
崔庆才丨静觅4 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60615 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了5 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅5 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment6 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端
爱敲代码的小鱼7 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax