[记录四] Vue(全家桶)+node+koa2+mysql+nginx+redis,博客全栈项目之web前端页面完结和路由的编写

导语:

暑假在家闲着无事,就琢磨着做一个web博客练练手,现在已经做完了,把过程分享出来给大家看看,分享一下学习经验。这是第二篇,主要讲node,webpack和vue-cli环境的搭建,使用vue全家桶,完成构建静态页面,写好路由。

本文的目录

  • 一,前端组件的完结
    • 1,顶部功能栏目
    • 2,顶部导航栏
    • 3,文章详情页面detail
  • 二,路由的编写

一,前端组件的完结

1,顶部功能栏目

[记录四] Vue(全家桶)+node+koa2+mysql+nginx+redis,博客全栈项目之web前端页面完结和路由的编写_第1张图片

<template>
  <div class="top">
    <div class="img_div">
      <img src="../../assets/logomin.jpg" class="img">
      <div class="text">轻松学算法div>
    div>
    <div class="tool">
      <div class="sign" @click="login" ref="sign" v-if="!islogin">登陆div>
      <div class="out" @click="logout" ref="out" v-if="islogin">退出div>
      <div class="more" @click="more">更多信息div>
    div>
  div>
template>

<script>

export default {
  methods: {
    more() {
      this.$emit('more')
    },
    login() {
      this.$emit('login')
    },
    logout() {
      this.$emit('logout')
    }
  },
  computed: {
    islogin(){
      return this.$store.getters.getIsLogin
    }
  },
}
script>

<style scoped>
.top{
  height: 50px;
  width: 100%;
  display: flex;
  background-color: #69d78a;
  position: fixed;
  top: 0;
  z-index: 1000;
}
.img_div{
  width: 180px;
  display: flex;
  margin: 5px 10px 5px 10px;
}
.img{
  height: 40px;
  width: 40px;
  border-radius: 20px;
}
.text{
  font-size: 14px;
  margin: 10px 0px 0px 20px;
  color: white;
}
.tool{
  display: flex;
  margin: 12px 10px 7px 50px;
  margin-left:auto;
}
.sign{
  margin-right: 10px;
  border: 1px white solid;
  padding: 4px 10px 5px 10px;
  border-radius: 15px;
  font-size: 14px;
  color: white;
}
.out{
  margin-right: 10px;
  border: 1px white solid;
  padding: 4px 10px 5px 10px;
  border-radius: 15px;
  font-size: 14px;
  color: white;
}
.more{
  border: 1px white solid;
  border-radius: 15px;
  padding: 4px 10px 5px 10px;
  font-size: 14px;
  color: white;
}
style>

2,顶部导航栏

[记录四] Vue(全家桶)+node+koa2+mysql+nginx+redis,博客全栈项目之web前端页面完结和路由的编写_第2张图片

<template>
  <div class="top-nav">
    <div class="img_div" >
      <van-icon name="arrow-left" size="24" @click="back" color="#ffffff"/>
      <div class="text" v-html="text">div>
    div>
  div>
template>

<script>

export default {
  props: {
    text: {
      type: String,
      default: ''
    }
  },
  methods: {
    back() {
      this.$emit('back')
    },
    like() {
      this.$emit('like')
    }
  },
  computed: {
    islogin(){
      return this.$store.getters.getIsLogin
    }
  },
}
script>

<style scoped>
.top-nav{
  height: 50px;
  width: 100%;
  display: flex;
  background-color: #69d78a;
  position: fixed;
  top: 0;
  z-index: 1000;
}
.img_div{
  width: 180px;
  display: flex;
  margin: 13px 10px 5px 10px;
}
.text{
  font-size: 14px;
  margin: 2px 0px 0px 20px;
  color: white;
}
.tool{
  display: flex;
  margin: 12px 10px 7px 50px;
  margin-left:auto;
}
style>

3,文章详情页面detail

在这里插入图片描述

<template>
  <div class="article-new">
    topnav>
    <scroll  :probe-type="probeType"
      :listen-scroll="listenScroll" ref="articleContentList"
      class="article-new-content"
    >
    <div>
      
<div class="title">[两万字]面试官:听说你很懂集合源码,接我二十道问题div> <div class="imformation"> <div class="time">2020-06-28div> <div class="viewnum">浏览量:{{hits}}div> div> <div class="author"> <div class="imgdiv"> <img src="../../assets/logo.png" class="img"> div> <div class="authorimformation"> <div class="authorname">小米粥div> <div class="experience">码龄:3年div> div> div> div>
<van-skeleton title :row="3" class="mysklenton"/> div> <div class="hr">div>
div>
<van-skeleton title :row="3" class="mysklenton"/> div> <div class="hrweight">div> commentarea>
<van-skeleton title :row="3" class="mysklenton"/> div> <div class="hrweight">div> div> scroll> comment> div> template> <script> import comment from "@/base/comment/comment" import commentarea from "@/base/commentarea/commentarea" import topnav from '@/components/top-nav/top-nav' import { commentItem } from "@/common/js/comment" import { createTime } from "@/common/js/time" import { Icon, Skeleton } from 'vant'; import marked from 'marked' import hljs from "highlight.js"; import javascript from 'highlight.js/lib/languages/javascript'; import 'highlight.js/styles/vs2015.css' import { getdetail, getcomments, postcomments, addhit, addgood, addlike, sublike, subgood } from "@/api/article" import scroll from '@/base/scroll/scroll' import Vue from 'vue'; Vue.use(Skeleton); export default { data() { return { articleContent: '', articleTitle: '', text: '最新文章', showbasic: false, showmacked: false, showcommentarea: false, commentcontent: [], articleid: 0, hits: 0, likes: 0, goods: 0, infogood: false, //点赞登陆的时候就已经拿到全部的id了,还没做 infolike: false //收藏 } }, methods: { back() { this.$router.back() }, getlogin() { if (!this.$store.getters.getIsLogin) { //检验登陆 console.log('未登录') return 0 } else { return 1 } }, _getdetail(id) { getdetail(id).then(res => { if (res.data.errno == 0) { console.log(res) this.articleContent = res.data.data.content this.showbasic = true this.showmacked = true this.showcommentarea = true this.articleTitle = res.data.data.title this.hits = res.data.data.hits this.likes = res.data.data.likes this.goods = res.data.data.goods addhit(id, this.hits).then(res => { if (res.data.errno == 0) { console.log(res) } }) if (!this.getlogin()) { //检验登陆 return } let mygood = this.$store.getters.getCurrentUser.goods.split(',') if (mygood.indexOf(this.$route.params.id)> -1) { this.infogood = true } let mylike = this.$store.getters.getCurrentUser.likes.split(',') if (mylike.indexOf(this.$route.params.id)> -1) { this.infolike = true } } }) }, _getcomments(id) { getcomments(id).then(res => { if (res.data.errno == 0) { this.articleid = res.data.data.id let mysqlcomment = JSON.parse(res.data.data.content) for (let i in mysqlcomment) { this.commentcontent.push(mysqlcomment[i]) } } }) }, commentsubmit(content) { if (!this.getlogin()) { //检验登陆 return } if (content == '') { console.log('不能评论为空') return } let userinfo = this.$store.getters.getCurrentUser //登陆后用户的信息 const nowtime = Date.now() //获取当前时间戳 let item = commentItem(userinfo.avatar, userinfo.username, content, createTime(nowtime)) //comment(avatar, username, content, time) this.commentcontent.push(item) //评论 console.log(this.commentcontent) //打印已经评论的总评论 let dataStr=JSON.stringify(this.commentcontent) //转化为json字符串,准备上传到数据库 let data = new FormData() data.append('comments', dataStr) data.append('id', this.articleid) postcomments(data).then(res => { console.log(res) }) }, like() { if (!this.getlogin()) { //检验登陆 return } if (!this.infolike) { let idstr = '' console.log(this.$store.getters.getCurrentUser.likes) if (this.$store.getters.getCurrentUser.likes == "") { idstr = this.$store.getters.getCurrentUser.likes + `${this.$route.params.id}` } else { idstr = this.$store.getters.getCurrentUser.likes + `,${this.$route.params.id}` } addlike(this.$route.params.id, idstr, this.likes).then(res => { console.log(res) let info = this.$store.getters.getCurrentUser info.likes = idstr this.$store.commit('updateUserStatus',info); this.likes += 1 this.infolike = true }) } else { let mylike = this.$store.getters.getCurrentUser.likes.split(',') mylike.splice(mylike.indexOf(this.$route.params.id)) let idstr = '' for (let i in mylike) { if (mylike.length - 1> i){ idstr += `${mylike[i]},` } else { idstr += `${mylike[i]}` } } sublike(this.$route.params.id, idstr, this.likes).then(res => { console.log(res) let info = this.$store.getters.getCurrentUser info.likes = idstr this.$store.commit('updateUserStatus',info); this.likes -= 1 this.infolike = false }) } }, good() { if (!this.getlogin()) { //检验登陆 return } if (!this.infogood) { let idstr = '' if (this.$store.getters.getCurrentUser.goods == '') { idstr = this.$store.getters.getCurrentUser.goods + `${this.$route.params.id}` } else { idstr = this.$store.getters.getCurrentUser.goods + `,${this.$route.params.id}` } addgood(this.$route.params.id, idstr, this.goods).then(res => { console.log(res) let info = this.$store.getters.getCurrentUser info.goods = idstr this.$store.commit('updateUserStatus',info); this.goods += 1 this.infogood = true }) } else { let mygood = this.$store.getters.getCurrentUser.goods.split(',') mygood.splice(mygood.indexOf(this.$route.params.id)) let idstr = '' for (let i in mygood) { if (mygood.length - 1> i){ idstr += `${mygood[i]},` } else { idstr += `${mygood[i]}` } } subgood(this.$route.params.id, idstr, this.goods).then(res => { console.log(res) let info = this.$store.getters.getCurrentUser info.goods = idstr this.$store.commit('updateUserStatus',info); this.goods -= 1 this.infogood = false }) } } }, created() { this.listenScroll = true this.probeType = 3 }, mounted() { marked.setOptions({ renderer: new marked.Renderer(), highlight: function (str, lang) { // 此处判断是否有添加代码语言 if (lang && hljs.getLanguage(lang)) { try { // 得到经过highlight.js之后的html代码 const preCode = hljs.highlight(lang, str, true).value // 以换行进行分割 const lines = preCode.split(/\n/) // 添加自定义行号 let html = lines.map((item, index) => { if (index < 9) { return `
  • ${index + 1}| ${index + 1}">${item}
  • `
    } else if (9 <= index < 99) { return `
  • ${index + 1}| ${index + 1}">${item}
  • `
    } else { return `
  • ${index + 1}| ${index + 1}">${item}
  • `
    } }).join('') html = '
      ' + html + '
    '
    // 添加代码语言 if (lines.length) { html += '' + lang + ''
    } return '
    ' +
                  html +
                  '
    '
    } catch (__) {} } // 未添加代码语言,此处与上面同理 const preCode = md.utils.escapeHtml(str) const lines = preCode.split(/\n/).slice(0, -1) let html = lines.map((item, index) => { return '
  • + (index + 1) + '">' + item + '
  • '
    }).join('') html = '
      ' + html + '
    '
    return '
    ' +
    html +
    '
    '
    }, pedantic: false, gfm: true, tables: true, breaks: false, sanitize: false, smartLists: true, smartypants: false, xhtml: false } ); this._getdetail(this.$route.params.id) this._getcomments(this.$route.params.id) }, computed: { compiledMarkdown: function() { return marked(this.articleContent, {}); //第一个参数是你的markdown文本 第二个参数是选项 }, str: function() { let arr = this.$route.path.split('/') console.log(arr) let str = `当前路径为:${arr[1]}>${arr[2]}` return str }, }, components: { scroll, topnav, comment, commentarea } }
    script> <style scoped> style>

    使用了mark去解析.md,并且使用highlight.js把代码部分进行高亮化处理,使得代码阅读变得更加舒服。

    二,路由的编写

    import Vue from 'vue'
    import Router from 'vue-router'
    import home from '@/components/home/home'
    import article from '@/components/article/article'
    import me from '@/components/me/me'
    import article_group from '@/components/article_group/article_group'
    import article_detail from '@/components/article_detail/article_detail'
    import article_new from '@/components/article_new/article_new'
    import like from '@/components/like/like'
    import imformation from '@/components/imformation/imformation'
    Vue.use(Router)
    
    export default new Router({
      mode: 'history',
      routes: [
        {
          path: '/',
          redirect: '/home'
        },
        {
          path: '/home',
          name: 'home',
          component: home,
          children: [
            {
              path: ':id',
              component: article_new,
            }
          ]
        },
        {
          path: '/article',
          name: 'article',
          component: article,
          children: [
            {
              path: ':id',
              component: article_group,
              children: [
                {
                  path: ':id',
                  component: article_detail
                }
              ]
            }
          ]
        },
        {
          path: '/me',
          name: 'me',
          component: me,
          children: [
            {
              path: 'like',
              component: like,
              children: [
                {
                  path: ':id',
                  component: article_detail
                }
              ]
            },
            {
              path: 'imformation',
              component: imformation
            }
          ]
        }
      ]
    })
    
    

    前端主要是三个主界面,以及一些子组件的构成,运用children子路由,去写好整个应用的路由关系。并且使用路由传参,让子路由拿到信息去调用api接口。

    在这里插入图片描述

    你们的赞就是对我最大的鼓励。谢谢~

    你可能感兴趣的:(html/css,js,node,javascript,vue.js,html,node.js,css)