手拉手带你用 vite2 + vue3 + elementPlus 做个博客尝尝鲜(四)

简介: 这里主要是体验一下 vite2 + vue3 做项目是什么样子的,重点在于 vite2 + vue3 方面的介绍,博客只是一个例子,所以博客的功能比较弱,只实现了几个最基本的功能。

博文内容 + 讨论

<template>
  <el-row :gutter="12">
    <el-col :span="5">
      <!--分组-->
      <blogGroup :isDetail="true"/>
    </el-col>
    <el-col :span="18">
      <!--显示博文-->
      <h1>{{blogInfo.title}}</h1>
      ({{dateFormat(blogInfo.addTime).format('YYYY-MM-DD')}})
      <v-md-preview :text="blogInfo.concent"></v-md-preview>
      <hr>
      <!--讨论列表-->
      <discussList :id="id"/>
      <!--讨论表单-->
      <discussForm :id="id"/>
    </el-col>
  </el-row>
</template>
【引入的代码略】
// 组件的属性,博文ID
const props = defineProps({
  id: String
})
// 管理
const { getArtcileById } = blogManage()
// 表单的model
const blogInfo = reactive({})
getArtcileById(props.id).then((data) => {
  Object.assign(blogInfo, data)
})

这个代码就很简单了,因为只实现了基本的发讨论和显示讨论的功能,其他暂略。

看看效果:

50.png


好吧,这个讨论做的蛮敷衍的,其实有好多想法,只是篇幅有限,以后再介绍。

组件级别的代码

虽然在vue里面,除了js文件,就是vue文件了,但是我觉得还是应该细分一下。比如上面都是是页面级的代码,下面这些是“组件”级别的代码了。

1

博文分组

多次提到的博文分组。

<template>
  <!--分组,分为显示状态和编辑状态-->
  <el-card shadow="hover"
    v-for="(item, index) in blogGroupList"
    :key="'grouplist_' + index"
  >
    <template #header>
      <div class="card-header">
        <span>{{item.label}}</span>
        <span class="button"></span>
      </div>
    </template>
    <div
      class="text item"
      style="cursor:pointer"
      v-for="(item, index) in item.children"
      :key="'group_' + index"
      @click="changeGroup(item.value)"
    >
      {{item.label}}
    </div>
  </el-card>
</template>

暂时先用 el-card 来实现,后期会改成 NavMenu 来实现。

【引入的代码略】
// 组件的属性
const props = defineProps({
  isDetail: Boolean
})
/** 
* 博文的分组列表
*/
const blogGroupList = reactive([
  {
    value: '1000',
    label: '前端',
    children: [
      {  value: '1001', label: 'vue基础知识',  },
      {  value: '1002', label: 'vue组件',     },
      {  value: '1003', label: 'vue路由',     }
    ]
  },
  {  value: '2000',  label: '后端',
     children: [
      { value: '2001', label: 'MySQL',     },
      { value: '2002', label: 'web服务',    }
    ]
  }
])
// 选择分组
const { setCurrentGroupId } = blogStateManage()
const router = useRouter()
const changeGroup = (id) => {
  setCurrentGroupId(id)
  // 判断是不是要跳转
  // 首页、编辑页不跳,博文详细页面调整 
  if (props.isDetail) {
    // 跳转到列表页
    router.push({ name: 'groups', params: { groupId: id }})
  }
}

分组数据暂时写死了,没有做成可以维护的方式,以后再完善。

2

博文列表,编辑用

<template>
  <!--添加标题-->
  <el-card shadow="hover">
    <template #header>
      <div class="card-header">
        <el-button @click="addNewArticle" >添加新文章</el-button>
        <span class="button"></span>
      </div>
    </template>
    <div
      class="text item"
      style="cursor:pointer"
      v-for="(item, index) in blogList"
      :key="'article_' + index"
      @click="changeArticle(item.ID)"
    >
      {{item.ID}}:{{item.title}} ({{dateFormat(item.addTime).format('YYYY-MM-DD')}})
    </div>
    <el-empty description="该分类里面还没有文章呢。" v-if="blogList.length === 0"></el-empty>
  </el-card>
</template>

用 el-card 做个列表,上面是 添加博文的按钮,下面是博文列表,单击可以进行修改。

【引入的代码略】
// 博文列表
const blogList = reactive([])
// 博文管理
const { addNewBlog, getBlogListByGroupId } = blogManage()
// 状态管理
const { getBlogState, setEditArticleId } = blogStateManage()
// 博文的状态
const blogState = getBlogState()
// 更新列表
const load = () => {
  getBlogListByGroupId(blogState.currentGroupId).then((data) => {
    blogList.length = 0
    blogList.push(...data)
  })
}
load()
// 监控选择的分组的ID
watch(() => blogState.currentGroupId, () => {
  load()
})
// 添加新文章,仅标题、时间
const addNewArticle = () => {
  const newArticle = blogForm()
  // 选择的分组ID
  newArticle.groupId = blogState.currentGroupId
  // 用日期作为默认标题
  newArticle.title = dayjs(new Date()).format('YYYY-MM-DD')
  addNewBlog(newArticle).then((id) => {
    // 设置要编辑的文章ID
    setEditArticleId(id)
    // 通知列表
    newArticle.ID = id
    blogList.unshift(newArticle)
  })
}
// 选择要编辑的文章
const changeArticle = (id) => {
  setEditArticleId(id)
}

3

讨论列表

<el-card shadow="hover"
    v-for="(item, index) in discussList"
    :key="'bloglist_' + index"
  >
    <template #header>
      <div class="card-header">
        {{item.discusser}}
        <span class="button">({{dateFormat(item.addTime).format('YYYY-MM-DD')}})</span>
      </div>
    </template>
    <!--简介-->
    <div class="text item" v-html="item.concent"></div>
    <hr>
    <i class="el-icon-circle-check"></i>&nbsp;{{item.agreeCount}}&nbsp;&nbsp;
  </el-card>
  <!--没有找到数据-->
  <el-empty description="没有讨论呢,抢个沙发呗。" v-if="discussList.length === 0"></el-empty>

还是用 el-card 做个列表,el-empty 做一个没有讨论的提示。

【引入的代码略】
// 组件的属性
const props = defineProps({
  id: String
})
// 管理
const { getDiscussListByBlogId } = blogManage()
// 获取状态
const { getBlogState } = blogStateManage()
const blogState = getBlogState()
// 表单的model
const discussList = reactive([])
getDiscussListByBlogId(props.id).then((data) => {
  discussList.push(...data)
})
watch(() => blogState.isReloadDiussList, () => {
  getDiscussListByBlogId(props.id).then((data) => {
    discussList.length = 0
    discussList.push(...data)
  })
})

因为功能比较简单,所以代码也很简单,获取讨论数据绑定显示即可,暂时没有实现分页功能。

4

讨论表单

<el-form
    style="width:400px;"
    label-position="top"
    :model="dicussModel"
    label-width="80px"
  >
  <el-form-item label="昵称">
    <el-input v-model="dicussModel.discusser"></el-input>
  </el-form-item>
  <el-form-item label="内容">
    <el-input type="textarea" v-model="dicussModel.concent"></el-input>
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="submit">发表讨论</el-button>
    <el-button>取消</el-button>
  </el-form-item>
</el-form>

用 el-form 做个表单。

【引入的代码略】
// 组件的属性
const props = defineProps({
  id: String
})
// 管理
const { addDiuss } = blogManage()
// 获取状态
const { getBlogState, setReloadDiussList } = blogStateManage()
const blogState = getBlogState()
// 表单的model
const dicussModel = reactive(discuss())
// 发布讨论
const submit = () => {
  dicussModel.blogId = props.id // 这是博文ID
  addDiuss(dicussModel).then((id) => { // 可以想象成 axios 的提交
      // 通知列表
    setReloadDiussList()
  })
}

分成多个组件,每个组件的代码就可以非常少了,这样便于维护。发布讨论的函数,先使用blogManage的功能提交数据,回调函数里面,使用的状态管理的功能提醒讨论列表刷新数据。

源码

https://gitee.com/naturefw/vue3-blog


52.png


52.png



在线演示

https://naturefw.gitee.io/vue3-blog

本文作者:自然框架

个人网址:jyk.cnblogs.com

声明:本文为 脚本之家专栏作者 投稿,未经允许请勿转载。


相关文章
|
1天前
|
JavaScript 定位技术 API
在 vue3 中使用高德地图
在 vue3 中使用高德地图
8 0
|
1天前
vue3 键盘事件 回车发送消息,ctrl+回车 内容换行
const textarea = textInput.value.textarea; //获取输入框元素
9 3
|
4天前
|
JavaScript 前端开发 CDN
vue3速览
vue3速览
14 0
|
4天前
|
设计模式 JavaScript 前端开发
Vue3报错Property “xxx“ was accessed during render but is not defined on instance
Vue3报错Property “xxx“ was accessed during render but is not defined on instance
|
4天前
|
JavaScript 前端开发 安全
Vue3官方文档速通(下)
Vue3官方文档速通(下)
15 0
|
4天前
|
JavaScript API
Vue3 官方文档速通(中)
Vue3 官方文档速通(中)
20 0
|
4天前
|
缓存 JavaScript 前端开发
Vue3 官方文档速通(上)
Vue3 官方文档速通(上)
26 0
|
4天前
Vue3+Vite+Pinia+Naive后台管理系统搭建之五:Pinia 状态管理
Vue3+Vite+Pinia+Naive后台管理系统搭建之五:Pinia 状态管理
8 1
|
4天前
Vue3+Vite+Pinia+Naive后台管理系统搭建之三:vue-router 的安装和使用
Vue3+Vite+Pinia+Naive后台管理系统搭建之三:vue-router 的安装和使用
10 0
|
4天前
Vue3+Vite+Pinia+Naive后台管理系统搭建之二:scss 的安装和使用
Vue3+Vite+Pinia+Naive后台管理系统搭建之二:scss 的安装和使用
8 0