一、文章详情——创建组件并配置路由
// 1.创建文件,src/views/article/index.vue
文章详情
// 2.在src/router/index.vue中将文章详情页配置到一级路由
const routes = [
.....
{
path: '/article/:articleId',
name: 'article',
component: () => import('@/views/article'),
props: true,// 动态路径参数的解耦:将路由动态参数映射到组件的 props 中,更推荐这种做法
}
];
// 3.配置跳转路由,在src/components/article-item/index.vue中
.....
// 4.页面布局
加载中 这是文章标题
黑马头条号
14小时前
关注 这是文章内容
正文结束 写评论
该资源不存在或已删除!
内容加载失败!
点击重试 .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;
}
.van-icon {
font-size: 40px;
.van-info {
font-size: 16px;
background-color: #e22829;
}
}
}
}
二、获取文章数据
// 1.封装请求,在src/api/article.js中
export const getArticleById = (articleId) => {
return request({
method: 'GET',
url: `/v1_0/articles/${articleId}`,
})
};
// 2.获取文章信息,在src/views/article/index.vue中
// 2.1.导入请求方法
import { getArticleById } from '@/api/article'export default {
name: 'ArticlePage',
components: {},
props: {
articleId: {
type: String,
required: true
}
},
data () {
return {
article: {} // 2.2.定义变量来储存数据
}
},
computed: {},
watch: {},
created () {
// 2.4. 调用方法
this.loadArticle()
},
mounted () {},
methods: {
// 2.3. 定义获取数据请求方法
async loadArticle () {
try {
// 2.3.1 发送请求
const { data } = await getArticleById(this.articleId)
console.log(data)
// 2.3.3 成功赋值
this.article = data.data
console.log(this.article)
} catch (err) {
// 2.3.2 失败处理
console.log(err)
this.$toast("获取数据失败");
}
}
}
}
// 3.渲染数据到页面{{ article.title }}
{{ article.aut_name }}
{{ article.pubdate | relativeTime }}正文结束
三、处理加载情况
// 1. 在src/views/article/index.vue中的data中定义变量data() {
return {
...
loading: true, // 加载中的 loading 状态
errStatus: 0, // 失败的状态码
};
},
// 2.在src/views/article/index.vue中
async loadArticle () {
// 2.1 展示 loading 加载中
this.loading = true
try {
const { data } = await getArticleById(this.articleId)// if (Math.random() > 0.5) {
//JSON.parse('dsankljdnskaljndlkjsa')
// }// 赋值
this.article = data.data} catch (err) {
if (err.response && err.response.status === 404) {
this.errStatus = 404
}
}
// 2.2无论成功还是失败,都需要关闭 loading
this.loading = false
},
// 3.在在src/views/article/index.vue中判断 ... ... ... ...
四、处理内容的样式
// 1. 将github-markdown-css样式文件放到src/views/article中,与index.vue同级// 2.在src/views/article/index.vue中引用@import "./github-markdown.css";
....// 3.添加到标签中
正文结束
// 4.postcss.config.js文件中添加忽略
module.exports = {
plugins: {....
propList: ['*'],
// 配置不要转换的样式资源
exclude: 'github-markdown'// 添加忽略文件
}
}
}// 5.注意,一定要重启项目,否则不会起作用
五、点击图片预览
// 1. 使用vant组件库中的 ImagePreview 图片预览 组件// 2. 增加ref属性, 在src/views/article/index.vue中// 3.导入ImagePreview 图片预览 组件插件,在src/views/article/index.vue中
import { ImagePreview } from 'vant' // 4.
methods: {
async loadArticle() {
this.loading = true;
try {
const { data } = await getArticleById(this.articleId);
// console.log(data);
data.data.content = data.data.content.replaceAll('https://images.weserv.nl/?url=','')
this.article = data.data;
// 初始化图片点击预览
console.log(this.$refs["article-content"]);
// 这里没有内容
// 这个时候其实找不到 这个refs引用的,原因是因为v-if的渲染其实需要时间,我们视图还没有立即更新完成。
// 使用定时器,延迟更新( setTimeout 0 会把要做的事情放在异步队列的最后面执行! )
setTimeout(() => {
console.log(this.$refs["article-content"]);
// 这里有内容
this.previewImage();
}, 0);
} catch (err) {
// this.$toast("获取数据失败");
if (err.response && err.response.status === 404) {
this.errStatus = 404;
}
}
this.loading = false;
},
previewImage() {
// 得到所有的 img 节点
const articleContent = this.$refs["article-content"];
// 获取到了容器节点
const imgs = articleContent.querySelectorAll("img");
// 获取所有 img 地址
const images = [];
imgs.forEach((img, index) => {
images.push(img.src);
// 给每个 img 注册点击事件,在处理函数中调用预览
img.onclick = () => {
ImagePreview({
// 预览的图片地址数组
images,
// 起始位置,从 0 开始
startPosition: index,
});
};
});
},
},
【项目分析六】
推荐阅读
- 项目分析五
- 项目分析七
- vue.js|vue-cli3.0 使用postcss-plugin-px2rem(推荐)和 postcss-pxtorem(postcss-px2rem)自动转换px为rem 的配置方法;
- 大数据项目总结|基于Java+springmvc+vue 健康管理系统
- Java毕业设计|基于Java+SpringMvc+vue+element实现博物馆平台系统
- vue|Vue基础知识点(一)
- vuejs|vue-router原理与源码分析
- 前端面试总结|vue核心面试题(vue中模板编译原理)
- Vue|Vue2的核心原理剖析