导语:
暑假在家闲着无事,就琢磨着做一个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.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接口。
你们的赞就是对我最大的鼓励。谢谢~