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

导语:

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

微信搜索 【web小馆】,回复 ”全栈博客项目“,即可获取 项目源码和后续的实战文章教程。

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

一,前端组件的完结
1,顶部功能栏目

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

<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前端页面完结和路由的编写

<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

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

<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.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 `<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接口。

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

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

微信搜索【web小馆】,回复全栈博客项目,即可获取项目源码和后续的实战文章教程。每天用最简单朴实的语言,潜移默化的提升你的计算机基础知识和前端技术。小米粥,一个专注的web全栈工程师,我们下期再见!

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

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

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

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » [记录四] Vue(全家桶)+node+koa2+mysql+nginx+redis,博客全栈项目之web前端页面完结和路由的编写
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏