简介

写文章页面,使用 Markdown 编辑器, 关于Markdown编辑器,vue-admin-template 默认使用的是 tui.editor ,这里使用 mavonEditor,因为 mavonEditor 的用法更加简单,文档也通俗易通,而且个人感觉样式更加美观,可以根据个人喜好自行选择。

tui.editor : https://github.com/nhnent/tui.editor
mavonEditor : https://github.com/hinesboy/mavonEditor

代码实现

1、安装mavonEditor

npm install mavon-editor --save

2、在main.js中全局注册该组件

import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
// use mavonEditor
Vue.use(mavonEditor)

3、在@/views/editor/index.vue中使用组件,即可使用

<template>
  <div class="app-container">
    <mavon-editor v-model="article.content" class="editor" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      article: {
        content: "",
      },
    };
  },
  methods: {},
};
</script>

<style lang="scss" scoped>
.editor {
  height: 650px;
}
</style>

4、效果如图

编辑器预览

5、我们要做的是文章提交功能,所以这里还要在页面展示文章信息的表单

这里有两种思路:

  • 一种是将文章信息的表单展示在编辑器上方,文章信息的表单和文章内容在同一个页面中
  • 另一种是当用户点击提交的时候弹出提示框,让用户填写文章信息。

这里选择第二种思路,先显示一个文章标题的输入框

<div class="title-box">
  <input type="text" class="title" v-model="article.title" placeholder="请输入标题..." />
  <el-button type="text" @click="openDialog">提交</el-button>
</div>
<mavon-editor v-model="article.content" class="editor" />
.title-box {
  display: grid;
  grid-template-columns: 22fr 2fr;
}
.title {
  background: none;
  color: #303133;
  text-indent: 0px;
  outline: none;
  font-size: 16px;
  font-weight: bold;
  display: block;

  border: none;
  border-bottom: 1px solid #e0e0e0;
  border-radius: 0;
  line-height: 1;
  overflow: visible;
  margin-bottom: 15px;
  padding: 4px;
}
.title:focus {
  border-color: #409eff;
}

效果如图:

标题文本框设计

此时 data 中的数据:

  data() {
    return {
      showDialog: false,
      categories: [],
      inputTag: "",
      inputTagVisible: false,
      showAddCategoryInput: false,
      article: {
        title: "",
        content: "",
        category: "",
        tags: [],
        tabloid: "",
        type: true,
        author: "",
        newCategory: "",
      },
    };
  },

当点击“提交”按钮的时候,调用 openDialog 方法,显示文章信息表单弹出框

// 断言 target 为非空
assertNotEmpty(target, msg) {
  if (!target) {
    this.$message({
      message: msg,
      type: "warning",
    });
    return false;
  }
  return true;
},
// 打开文章信息填写框
openDialog() {
  if (
    this.assertNotEmpty(this.article.title, "请填写文章标题") &&
    this.assertNotEmpty(this.article.content, "请填写文章内容")
  ) {
    this.showDialog = true;
  }
},

6、使用 el-dialog 组件做弹出框

<el-dialog :title="`发布文章:${article.title}`" :visible.sync="showDialog" width="30%">
  <el-form label-position="left" label-width="80px">
    <el-form-item label="标签:" style="width:fit-content">
      <el-tag
        :key="tag"
        v-for="tag in article.tags"
        closable
        :disable-transitions="false"
        @close="handleTagClose(tag)"
      >{{tag}}</el-tag>
      <el-input
        v-if="inputTagVisible"
        v-model="inputTag"
        ref="saveTagInput"
        size="small"
        @keyup.enter.native="handleTagInputConfirm"
        @blur="handleTagInputConfirm"
        class="input-new-tag"
      ></el-input>
      <el-button v-else class="button-new-tag" size="small" @click="showTagInput">+ 新标签</el-button>
    </el-form-item>
    <el-form-item label="分类:">
      <el-select v-model="article.category" placeholder="请选择">
        <el-option
          v-for="(category,index) in categories"
          :key="index"
          :label="category"
          :value="category"
        ></el-option>
      </el-select>
      <el-button type="text" @click="showAddCategoryInput = true" class="add-category-btn">自定义分类</el-button>
    </el-form-item>
    <el-collapse-transition>
      <el-form-item label="新分类:" v-show="showAddCategoryInput">
        <el-input v-model="article.newCategory" @keypress.enter.native="addCategory"></el-input>
      </el-form-item>
    </el-collapse-transition>
    <el-form-item label="摘要:">
      <el-input type="textarea" v-model="article.tabloid" rows="4"></el-input>
    </el-form-item>
    <el-form-item label="作者:">
      <el-input type="text" v-model="article.author"></el-input>
    </el-form-item>
    <el-form-item>
      <el-checkbox v-model="article.type">原创</el-checkbox>
    </el-form-item>
  </el-form>
  <span slot="footer">
    <el-button @click="handleCancel">取 消</el-button>
    <el-button type="primary" @click="handleSubmit">发布</el-button>
  </span>
</el-dialog>

说明:

  • 其中动态添加标签的功能参考:https://element.eleme.cn/#/zh-CN/component/tag
  • 实现了自定分类的功能

7、网络请求

新建@/api/category.js封装获取全部分类的方法

import request from '@/utils/request'

export function getAllCategories() {
  return request({
    url: '/categories',
    method: 'get',
  })
}

@/utils/request.js中配置post的默认请求头

service.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';

为post添加请求头

@/api/article.js添加添加文章的方法

export function postArticle(params) {
  return request({
    url: '/auth/articles',
    method: "post",
    data: {
      title: params.title,
      content: params.content,
      category: params.category,
      tags: params.tags.join(),
      tabloid: params.tabloid,
      type: params.type ? 1 : 0,
      author: params.author,
    }
  })
}

说明:

  • 注意对标签数组的处理

在 created 函数中获取所有分类

  created() {
    getAllCategories().then((res) => {
      this.categories = res.data.map((item) => item.name);
    });
  },

8、然后编写“发布”和“取消”两个按钮的回调函数

handleCancel() {
  this.showDialog = false;
},
handleSubmit() {
  if (
    this.assertNotEmpty(this.article.category, "分类不能为空") &&
    this.assertNotEmpty(this.article.tags.join(), "文章标签不能为空") &&
    this.assertNotEmpty(this.article.tabloid, "文章摘要不能为空") &&
    this.assertNotEmpty(this.article.author, "文章作者不能为空")
  ) {
    this.showDialog = false;
    postArticle(this.article).then((res) => {
      this.$notify({
        title: "提示",
        message: `文章《${this.article.title}》发布成功`,
        type: "success",
      });
      this.$router.push("/example/table");
    });
  }
},

说明:

  • this.$notify 为Element-UI提供的消息框,可参考官方文档:https://element.eleme.cn/#/zh-CN/component/notification
  • 文章提交成功之后,跳转到文章管理页面
效果图:

发布文章界面:

提交文章界面

文章发布成功:
文章发布成功

参考代码:https://gitee.com/qianyucc/QBlog2/tree/v-10.0

Logo

前往低代码交流专区

更多推荐