文章正文包括各种数据:段落、标题、列表、链接、图片、视频等资源。
将样式文件下载到项目中
复制这段css :https://github.com/sindresorhus/github-markdown-css/blob/main/github-markdown.css
放到src/views/article/github-markdown.css
配置不要转换样式文件中的字号
如果有问题,可以直接复制这个:https://juejin.cn/post/6999569568385466376/
以下是完整代码:src/views/article/index.vue
<template>
<div class="article-container">
<van-nav-bar class="page-nav-bar" left-arrow title="黑马头条"></van-nav-bar>
<div class="main-wrap">
<div v-if="loading" class="loading-wrap">
<van-loading color="#3296fa" vertical>加载中</van-loading>
</div>
<div v-else-if="article.title" class="article-detail">
<h1 class="article-title">{{article.title}}</h1>
<van-cell class="user-info" center :border="false">
<van-image class="avatar" slot="icon" round fit="cover" :src="article.aut_photo" />
<div slot="title" class="user-name">{{article.aut_name}}</div>
<div slot="label" class="publish-date">{{article.pubdate | relativeTime}}</div>
<fllow-user class="follow-btn" :userId="article.aut_id" v-model="article.is_followed" />
</van-cell>
<div class="article-content markdown-body" v-html="article.content" ref="article-content"></div>
<van-divider>正文结束</van-divider>
<comment-list :source="article.art_id" :list="CommentLists" @onload_success="commentCount = $event.total_count" @replay-comment="onReplay"></comment-list>
<div class="article-bottom">
<van-button class="comment-btn" type="default" round size="small" @click="isPropShow = true">写评论</van-button>
<van-icon name="comment-o" :info="commentCount" color="#777" />
<collect-article v-model="article.is_collected" :articleId="article.art_id"></collect-article>
<like-article v-model="article.attitude" :articleId="article.art_id"></like-article>
<van-icon name="share" color="#777777"></van-icon>
<van-popup v-model="isPropShow" position="bottom">
<comment-post :target="article.art_id" @post-success="onPostSuccess"></comment-post>
</van-popup>
</div>
</div>
<div v-else-if="errorStatus === 404" class="error-wrap">
<van-icon name="failure" />
<p class="text">该资源不存在或已删除!</p>
</div>
<div v-else class="error-wrap">
<van-icon name="failure" />
<p class="text">内容加载失败!</p>
<van-button class="retry-btn" @click="loadArticlesByid">点击重试</van-button>
</div>
</div>
<van-popup v-model="isReplayShow" position="bottom" style="height:100%">
<comment-replay v-if="isReplayShow" :comment="commentReplays" @close="isReplayShow = false"></comment-replay>
</van-popup>
</div>
</template>
<script>
import { getArticleById } from '@/api/article'
import { ImagePreview } from 'vant'
import fllowUser from '@/components/follow'
import CollectArticle from '@/components/collect-article'
import LikeArticle from '@/components/like-item'
import CommentList from './components/comment-list'
import CommentPost from './components/comment-post'
import CommentReplay from './components/comment-replay'
export default {
name: 'ArticleIndex',
components: { fllowUser, CollectArticle, LikeArticle, CommentList, CommentPost, CommentReplay },
provide: function () {
return {
articleId: this.articleId
}
},
props: {
articleId: {
type: [Number, String, Object],
required: true
}
},
data() {
return {
article: {},
loading: true,
errorStatus: 0,
isLoading: false,
commentCount: 0,
isPropShow: false,
CommentLists: [],
isReplayShow: false,
commentReplays: {}
}
},
computed: {},
watch: {},
created() {
this.loadArticlesByid()
},
mounted() { },
methods: {
async loadArticlesByid() {
this.loading = true
try {
const { data } = await getArticleById(this.articleId)
console.log(data);
this.article = data.data
setTimeout(() => {
this.previewImage()
}, 0);
} catch (error) {
if (error.response && error.response.status === 404) {
this.errorStatus = 404
}
}
this.loading = false
},
previewImage() {
const container = this.$refs['article-content']
const imgs = container.querySelectorAll('img')
const images = []
imgs.forEach((img, index) => {
images.push(img.src)
img.onclick = () => {
ImagePreview({
images,
startPosition: index,
})
}
});
},
onPostSuccess(data) {
this.isPropShow = false
this.CommentLists.unshift(data.new_obj)
},
onReplay(comment) {
this.commentReplays = comment
this.isReplayShow = true
}
}
}
</script>
<style scoped lang="less">
@import './github-markdown.css';
.article-container {
.main-wrap {
position: fixed;
left: 0;
right: 0;
top: 92px;
bottom: 88px;
overflow-y: scroll;
background-color: #fff;
}
.article-detail {
.article-title {
font-size: 40px;
padding: 50px 32px;
margin: 0;
color: #3a3a3a;
}
.user-info {
padding: 0 32px;
.avatar {
width: 70px;
height: 70px;
margin-right: 17px;
}
.van-cell__label {
margin-top: 0;
}
.user-name {
font-size: 24px;
color: #3a3a3a;
}
.publish-date {
font-size: 23px;
color: #b7b7b7;
}
.follow-btn {
width: 170px;
height: 58px;
}
}
.article-content {
padding: 55px 32px;
/deep/ p {
text-align: justify;
}
}
}
.loading-wrap {
padding: 200px 32px;
display: flex;
align-items: center;
justify-content: center;
background-color: #fff;
}
.error-wrap {
padding: 200px 32px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #fff;
.van-icon {
font-size: 122px;
color: #b4b4b4;
}
.text {
font-size: 30px;
color: #666666;
margin: 33px 0 46px;
}
.retry-btn {
width: 280px;
height: 70px;
line-height: 70px;
border: 1px solid #c3c3c3;
font-size: 30px;
color: #666666;
}
}
.article-bottom {
position: fixed;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: space-around;
align-items: center;
box-sizing: border-box;
height: 88px;
border-top: 1px solid #d8d8d8;
background-color: #fff;
.comment-btn {
width: 282px;
height: 46px;
border: 2px solid #eeeeee;
font-size: 30px;
line-height: 46px;
color: #a7a7a7;
}
/deep/ .van-icon {
font-size: 40px;
.van-info {
font-size: 16px;
background-color: #e22829;
}
}
}
}
</style>