基于Spring Boot+Vue的博客系统 04——展示一篇文章

废弃说明:
这个专栏的文章本意是记录笔者第一次搭建博客的过程,文章里里有很多地方的写法都不太恰当,现在已经废弃,关于SpringBoot + Vue 博客系列,笔者重新写了这个系列的文章,不敢说写的好,但是至少思路更加清晰,还在看SpringBoot + Vue 博客系列文章的朋友可以移步:https://blog.csdn.net/li3455277925/category_10341110.html,文章中有错误的地方或者大家有什么意见或建议都可以评论或者私信交流。

1. 实现MarkDown to HTML
  • 因为存入数据库中的文章内容为markdown格式,要像展示在网页上必须将markdown转换为HTML,这里用到一个开源项目:showdownjs

项目地址为:https://github.com/showdownjs/showdown

  • 使用npm install showdown命令安装
  • 新建/src/components/page/articleDetails.vue文件,在文件中导入showdown,在vue生命周期created函数中使用将markDown转换为html并存在变量content中,再渲染到页面中,代码如下:
<template>
  <b-container class="main">
    <!-- 文章标题 -->
    <h2  class="title">这是文章的标题</h2>
    <!-- 文章描述 -->
    <h6 class="description"></h6>
    <!-- 文章内容 -->
    <div v-html="content"></div>
    <!-- 标签 -->
    <div class="tag-box"></div>
</template>
<script>
import showdown from "showdown";
export default {
  name: "articleDetails",
  data() {
    return {
      content: null
    };
  },
  methods: {
  created() {
    let converter = new showdown.Converter();
    let text = "- 列表 \n - 列表 ";
    this.content = converter.makeHtml(text);
  }
};
</script>
2. 实现评论以及二级评论
  • 由于展示二级评论的时候需要用到动画,vue的动画效果比较繁琐,而且对CSS3要求比较高,所以这里使用JQuery实现的简单的动画。在/static/目录下新建js文件夹,存放js文件,将下载的JQuery放在文件夹下。在index.html中引入。

JQuery官网:https://jquery.com/
另外Vue和JQuery一起使用时有一些注意事项:https://blog.csdn.net/qq_39692256/article/details/82835096

  • 动画使用JQuery中的slideDown()slideUp()方法实现,并且给每条评论添加唯一的id,避免出现点击一条评论的图标所有评论的二级评论都展开的情况。
  • 代码实现:
<template>
  <b-container class="main">
    <!-- 文章标题 -->
    <h2  class="title">这是文章的标题</h2>
    <!-- 文章描述 -->
    <h6 class="description"></h6>
    <!-- 文章内容 -->
    <div v-html="content"></div>
    <!-- 标签 -->
    <div class="tag-box"></div>
    <!-- 评论回复 -->
    <hr />
    <h5>总共有4条评论</h5>
    <hr />
    <!-- 一级评论列表 start -->
    <b-media>
      <template v-slot:aside>
        <b-img width="60" height="60" src="/static/images/no-name.png"></b-img>
      </template>
      <h6 thumbnail class="commentator-name">匿名用户</h6>
      <p>一级评论1</p>
      <p>
        <i class="icon iconfont icon-dianzan1 link-icon"></i>
        <i class="icon iconfont icon-pinglun link-icon" @click="showOrHideSecondLevelComments(1)"></i>2
      </p>
      <div id="second-level-comment-1" style="display:none;">
        <!-- 二级评论列表 start -->
        <b-media>
          <template v-slot:aside>
            <b-img width="60" height="60" src="/static/images/no-name.png"></b-img>
          </template>
          <h6 thumbnail class="commentator-name">匿名用户</h6>
          <p>二级评论1</p>
        </b-media>
        <!-- 二级评论 end -->
        <hr />
        <b-textarea placeholder="请输入评论内容......"></b-textarea>
        <b-button class="pull-right" variant="success">提交</b-button>
      </div>
    </b-media>
    <!-- 一级评论列表 end -->
    <hr />
    <b-media>
      <template v-slot:aside>
        <b-img width="60" height="60" src="/static/images/no-name.png"></b-img>
      </template>
      <h6 thumbnail class="commentator-name">匿名用户</h6>
    </b-media>
    <b-textarea placeholder="请输入评论内容......"></b-textarea>
    <b-button variant="success" class="pull-right">提交</b-button>
  </b-container>
</template>

<script>
import showdown from "showdown";
export default {
  name: "articleDetails",
  data() {
    return {
      content: null
    };
  },
  methods: {
    showOrHideSecondLevelComments(id) {
      let element = $("#second-level-comment-" + id);
      let display = element.css("display");
      if (display == "none") {
        element.slideDown();
      } else {
        element.slideUp();
      }
    }
  }
};
</script>
3. 预览
  • 在路由中注册articleDetails组件
import Vue from 'vue'
import Router from 'vue-router'
import mainPage from "@/components/page/mainPage"
import articleDetails from "@/components/page/articleDetails"

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'mainPage',
      component: mainPage
    },
    {
      path:'/articleDetails',
      name:"articleDetails",
      component:articleDetails
    }
  ]
})
  • 完整代码:
<template>
  <b-container class="main">
    <!-- 文章标题 -->
    <h2  class="title">这是文章的标题</h2>
    <!-- 文章描述 -->
    <h6 class="description">
      <b-badge variant="info">原创</b-badge>&nbsp;&nbsp;
      <i class="icon iconfont icon-riqi"></i>&nbsp;2019-10-12
      &nbsp;&nbsp;
      <i class="icon iconfont icon-gaojian-zuozhe"></i>&nbsp;芊雨
      &nbsp;&nbsp;
      <i class="icon iconfont icon-yuedu"></i>&nbsp;20
      &nbsp;&nbsp;
      <i class="icon iconfont icon-fenlei"></i>&nbsp;学习经验
    </h6>
    <!-- 文章内容 -->
    <div v-html="content"></div>
    <!-- 标签 -->
    <div class="tag-box">
      <b-link class="tag" variant="info">
        <i class="icon iconfont icon-tag"></i>java
      </b-link>
      <b-link class="tag" variant="info">
        <i class="icon iconfont icon-tag"></i>java
      </b-link>
      <b-link class="tag" variant="info">
        <i class="icon iconfont icon-tag"></i>java
      </b-link>
    </div>
    <!-- 评论回复 -->
    <hr />
    <h5>总共有4条评论</h5>
    <hr />
    <!-- 一级评论列表 start -->
    <b-media>
      <template v-slot:aside>
        <b-img width="60" height="60" src="/static/images/no-name.png"></b-img>
      </template>
      <h6 thumbnail class="commentator-name">匿名用户</h6>
      <p>一级评论1</p>
      <p>
        <i class="icon iconfont icon-dianzan1 link-icon"></i>
        <i class="icon iconfont icon-pinglun link-icon" @click="showOrHideSecondLevelComments(1)"></i>2
      </p>
      <div id="second-level-comment-1" style="display:none;">
        <!-- 二级评论列表 start -->
        <b-media>
          <template v-slot:aside>
            <b-img width="60" height="60" src="/static/images/no-name.png"></b-img>
          </template>
          <h6 thumbnail class="commentator-name">匿名用户</h6>
          <p>二级评论1</p>
        </b-media>
        <!-- 二级评论 end -->
        <hr />
        <b-textarea placeholder="请输入评论内容......"></b-textarea>
        <b-button class="pull-right" variant="success">提交</b-button>
      </div>
    </b-media>
    <!-- 一级评论列表 end -->
    <hr />
    <b-media>
      <template v-slot:aside>
        <b-img width="60" height="60" src="/static/images/no-name.png"></b-img>
      </template>
      <h6 thumbnail class="commentator-name">匿名用户</h6>
    </b-media>
    <b-textarea placeholder="请输入评论内容......"></b-textarea>
    <b-button variant="success" class="pull-right">提交</b-button>
    <!-- 回顶部按钮 -->
    <i class="icon iconfont icon-huidingbu" @click="backTop()"></i>
  </b-container>
</template>

<script>
import showdown from "showdown";
export default {
  name: "articleDetails",
  data() {
    return {
      content: null
    };
  },
  methods: {
    showOrHideSecondLevelComments(id) {
      let element = $("#second-level-comment-" + id);
      let display = element.css("display");
      if (display == "none") {
        element.slideDown();
      } else {
        element.slideUp();
      }
    },
    //回到顶部
    backTop() {
      let back = setInterval(() => {
        if (document.body.scrollTop || document.documentElement.scrollTop) {
          document.body.scrollTop -= 50;
          document.documentElement.scrollTop -= 50;
        } else {
          clearInterval(back);
        }
      });
    }
  },
  created() {
    let converter = new showdown.Converter();
    let text =
      "- 列表 \n - 列表 \n - 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n- 列表 \n - 列表 \n";
    this.content = converter.makeHtml(text);
  }
};
</script>

<style scoped>
.main {
  margin-top: 10px;
  padding: 20px 10px;
  border-radius: 5px;
  background-color: #fff;
  /* 防止当文章内容较少的时候,出现上下颜色不一致的问题 */
  min-height: 100%;
  /* 解决元素浮动后从父元素溢出的问题 */
  overflow: auto;
}
.title,
.description {
  text-align: center;
}
.tag-box {
  margin-left: 10px;
  display: flex;
  flex-direction: row;
  justify-content: left;
}
.tag {
  text-decoration: none;
  margin-left: 5px;
}
.commentator-name {
  font-weight: bold;
  text-align: left;
}
.link-icon {
  margin-right: 5px;
}
.link-icon:hover {
  color: #337ab7;
}
textarea {
  margin: 10px 0;
}

/* 回顶部按钮 start */
.icon-huidingbu:before {
  font-size: 25px;
}
.icon-huidingbu {
  text-align: center;
  width: 37px;
  height: 37px;
  position: fixed;
  left: 92%;
  top: 80%;
}
.icon-huidingbu:hover {
  border-radius: 6px;
  background-color: #495057;
  color: #eee;
}
/* 回顶部按钮 end */
</style>
  • 在浏览器中输入:http://localhost:8080/#/articleDetails
  • 效果:
    效果预览
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值