当前位置: 代码迷 >> 综合 >> [记录四] Vue(全家桶)+node+koa2+mysql+nginx+redis,博客全栈项目之web前端页面完结和路由的编写
  详细解决方案

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

热度:55   发布时间:2024-02-13 07:10:42.0

导语:

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

本文的目录

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

一,前端组件的完结

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,顶部导航栏

在这里插入图片描述

<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 @back= "back" :text= "text"></topnav><scroll :probe-type="probeType":listen-scroll="listenScroll" ref="articleContentList"class="article-new-content"><div><div class="basicmessage" v-if= "showbasic"><div class="title">[两万字]面试官:听说你很懂集合源码,接我二十道问题</div><div class="imformation"><div class="time">2020-06-28</div><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><div class="sklentondiv" v-if= "!showbasic"><van-skeleton title :row="3" class="mysklenton"/><!-- <van-skeleton title avatar class="mysklentonavatar"/> --></div><div class="hr"></div><div v-html="compiledMarkdown" class="macked" v-if= "showmacked"></div><div class="sklentondiv" v-if= "!showmacked"><van-skeleton title :row="3" class="mysklenton"/><!-- <van-skeleton title avatar class="mysklentonavatar"/> --></div><div class="hrweight"></div><commentarea v-if= "showcommentarea" :list= "commentcontent"></commentarea><div class="sklentondiv" v-if= "!showcommentarea"><van-skeleton title :row="3" class="mysklenton"/><!-- <van-skeleton title avatar class="mysklentonavatar"/> --></div><div class="hrweight"></div></div></scroll><comment @commentsubmit= "commentsubmit" @like= "like" @good= "good" :infogood= "infogood" :infolike= "infolike":goodnum= 'goods' :likenum= "likes"></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.contentthis.showbasic = truethis.showmacked = truethis.showcommentarea = truethis.articleTitle = res.data.data.titlethis.hits = res.data.data.hitsthis.likes = res.data.data.likesthis.goods = res.data.data.goodsaddhit(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.idlet 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.getCurrentUserinfo.likes = idstrthis.$store.commit('updateUserStatus',info);this.likes += 1this.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.getCurrentUserinfo.likes = idstrthis.$store.commit('updateUserStatus',info);this.likes -= 1this.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.getCurrentUserinfo.goods = idstrthis.$store.commit('updateUserStatus',info);this.goods += 1this.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.getCurrentUserinfo.goods = idstrthis.$store.commit('updateUserStatus',info);this.goods -= 1this.infogood = false})}}},created() {this.listenScroll = truethis.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 `<li> ${index + 1}| <span class="line-num" data-line="${index + 1}"></span>${item}</li>`} else if (9 <= index < 99) {return `<li>${index + 1}| <span class="line-num" data-line="${index + 1}"></span>${item}</li>`} else {return `<li>${index + 1}| <span class="line-num" data-line="${index + 1}"></span>${item}</li>`}}).join('')html = '<ol>' + html + '</ol>'// 添加代码语言if (lines.length) {html += '<b class="name">' + lang + '</b>'}return '<pre class="hljs myhljs"><code>' +html +'</code></pre>'} catch (__) {}}// 未添加代码语言,此处与上面同理const preCode = md.utils.escapeHtml(str)const lines = preCode.split(/\n/).slice(0, -1)let html = lines.map((item, index) => {return '<li><span class="line-num" data-line="' + (index + 1) + '"></span>' + item + '</li>'}).join('')html = '<ol>' + html + '</ol>'return '<pre class="hljs"><code>' +html +'</code></pre>'},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接口。

在这里插入图片描述

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

  相关解决方案