Gin blog I

Kesa...大约 4 分钟Frontendvuego-gin-blog

本节将实现前端页面的如下功能:

  • 文章列表
  • 文章添加, 修改和删除
  • 文章内容展示

1. 初始化

1.1 采用模板

vue-admin-templateopen in new window 为模板创建仓库 gin-blogopen in new window , clone 到本地

gh repo clone dreamjz/gin-blog

安装依赖

yarn install --registry=https://registry.npm.taobao.org

启动

yarn run dev

项目正常启动并能进入 dashboard

1.2 获取完全项目

vue-element-adminopen in new window 项目 clone 到本地

gh repo clone PanJiaChen/vue-element-admin

安装依赖

yarn install --registry=https://registry.npm.taobao.org

启动

yarn run dev

项目正常启动并能进入 dashboard

1.3 添加文章编辑页和文章列表页

vue-element-adminopen in new window 中的文章页相关的组件拷贝至 gin-blogopen in new window

src/views/router/index.js添加路由

{
    path: '/article',
    component: Layout,
    redirect: '/article/list',
    name: 'Article',
    meta: {
      title: 'Article',
      icon: 'el-icon-s-help'
    },
    children: [
      {
        path: 'create',
        component: () => import('@/views/article/create'),
        name: 'CreateArticle',
        meta: { title: 'Create Article', icon: 'edit' }
      },
      {
        path: 'edit/:id(\\d+)',
        component: () => import('@/views/article/edit'),
        name: 'EditArticle',
        meta: {
          title: 'Edit Article',
          noCache: true,
          activeMenu: '/example/list'
        },
        hidden: true
      },
      {
        path: 'list',
        component: () => import('@/views/article/list'),
        name: 'ArticleList',
        meta: { title: 'Article List', icon: 'list' }
      }
    ]
  },

更新 src/store/index.js, 实现自动导入 modules

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'

Vue.use(Vuex)

// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context('./modules', true, /\.js$/)

// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  // set './app.js' => 'app'
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  const value = modulesFiles(modulePath)
  modules[moduleName] = value.default
  return modules
}, {})

const store = new Vuex.Store({
  modules,
  getters
})

export default store

配置src/mock/index.js mock server

const article = require('./article')
const mocks = [...user, ...article]

启动项目即可看到文章编辑页和文章列表页

2. 添加文章浏览页

经过上述步骤,成功添加了文章列表和编辑页面,但是作为一个 blog 应用还需要一个浏览文章内容的页面

我的个人网站使用 vuepress 进行构建,其使用了 markdown-it 进行 markdown 文件的渲染,下面也使用markdown-it 来渲染文章内容

2.1 创建 MDContent组件

yarn add markdown-it --save

创建 src/components/Markdown/index.vue

<template>
  <component :is="mdHtml" class="md-content" />
</template>

<script>
import MarkdownIt from 'markdown-it'

export default {
  name: 'Markdown',
  props: {
    content: {
      type: String,
      default: ''
    }
  },
  data: () => ({
    md: null
  }),
  computed: {
    mdHtml: function() {
      const res = this.md.render(this.content)
      return {
        template: '<div>' + res + '</div>'
      }
    }
  },
  created() {
    this.md = new MarkdownIt()
  }
}
</script>

这里使用了动态插件,方便后续的扩展,同时需要配置 vue 的动态渲染

修改 vue.config.js

module.exports = {
  runtimeCompiler: true
}

2.2 文章内容页

创建src/views/article/content.vue

<template>
  <div>
    <Markdown :content="content" />
  </div>
</template>

<script>
import Markdown from '@/components/Markdown'
export default {
  name: 'ArticleContent',
  comments: {
    Markdown
  },
  data: () => ({
    content: ''
  }),
  created() {
    this.content = `# Test \n ## 1. H1`
  }
}
</script>

src/router/index.js 添加为 article 的子路由

      {
        path: 'content',
        component: () => import('@/views/article/content'),
        name: 'ArticleContent',
        meta: { title: 'Article Content', icon: 'content' },
        hidden: false
      },

启动项目,可以看到新增菜单Article Content 并且渲染测试数据

Test
1. H1

2.3 从文章列表进入

上述步骤成功创建了文章内容页并渲染如测试内容,下面将实现从文章列表点击标题进入其内容页面的功能

修改路由,使其可以获取文章 ID并隐藏其菜单栏

// src/router/index.js
      {
        path: 'content/:id(\\d+)',
        component: () => import('@/views/article/content'),
        name: 'ArticleContent',
        meta: { title: 'Article Content', icon: 'content' },
        hidden: true
      },

修改src/views/article/content.vue,使其在 created 时通过fetchArticle API 获取文章内容

<template>
  <div>
    <MDContent :content="content" />
  </div>
</template>

<script>
import MDContent from '@/components/MDContent'
import { fetchArticle } from '@/api/article'

const defaultForm = {
  status: 'draft',
  title: '', // 文章题目
  content: '', // 文章内容
  content_short: '', // 文章摘要
  source_uri: '', // 文章外链
  image_uri: '', // 文章图片
  display_time: undefined, // 前台展示时间
  id: undefined,
  platforms: ['a-platform'],
  comment_disabled: false,
  importance: 0
}

export default {
  name: 'ArticleContent',
  components: {
    MDContent
  },
  data() {
    return {
      artileForm: Object.assign({}, defaultForm),
      content: ''
    }
  },
  created() {
    const id = this.$router.params && this.$router.params.id
    this.fetchData(id)
  },
  methods: {
    fetchData(id) {
      fetchArticle(id)
        .then((response) => {
          this.artileForm = response.data
          this.content = this.artileForm.content
        })
        .catch((err) => {
          console.log(err)
        })
    }
  }
}
</script>

修改src/views/article/list.vue, 实现点击标题跳转至内容页

      <el-table-column min-width="300px" label="Title">
        <template slot-scope="{ row }">
          <router-link :to="'/article/content/' + row.id" class="link-type">
            <span>{{ row.title }}</span>
          </router-link>
        </template>
      </el-table-column>

启动应用,从文章列表进入内容页,发现文章内容中的 html 没有被解析而是直接以文本形式渲染

<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>

因为 markdown-it 的默认选项中 html 为 false , 修改 MDContent.vuemarkdown-it的配置

  created() {
    this.md = new MarkdownIt({
      html: true
    })
  }

再次启动应用,发现内容被正常渲染并且图片也正显示了

3. 添加删除按钮

回到文章列表页,可以看到只有编辑按钮,下面就在其旁边添加一个删除按钮

修改 src/views/article/list.vue,在编辑按钮所在单元格添加删除按钮

      <el-table-column align="center" label="Actions" width="230">
        <template slot-scope="scope">
          <router-link :to="'/article/edit/' + scope.row.id">
            <el-button class="edit-btn" type="primary" size="small" icon="el-icon-edit">
              Edit
            </el-button>
          </router-link>
          <el-button class="del-btn" type="primary" size="small" icon="el-icon-delete" @click="deleteArticle($index)">
            Delete
          </el-button>
        </template>
      </el-table-column>

在 methods 中添加删除函数 deleteArticle

    deleteArticle(index) {
      this.list.splice(index, 1)
    }

设置样式

.el-button {
  margin-right: 10px;
}

.edit-btn, .del-btn {
  width: 85px;
}

这样前端的部分就完成了,接下来完成服务端的实现

Reference

  1. vue-element-adminopen in new window official docs
  2. #316open in new window vue-element-admin github issue
  3. vue configopen in new window vue cli docs
  4. Vue单页面应用中的Markdown渲染 open in new window youxam
  5. markdown-itopen in new window official docs
上次编辑于:
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.2