赞
踩
目录
- // 配置动态路由,文章详情
- {
- path: '/article/:articleId',
- name: 'article',
- component: () => import('@/views/article/')
- }
在components/article-item.vue列表项组件中添加路由导航 to=" " 跳转至对应页面
在article/index.vue组件中获取动态路由参数:
方式一:this.$route.params.xxx
方式二:props 传参,推荐
采用方式二示范:router.js 给路由开启一个props: true
- {
- path: '/article/:articleId',
- name: 'article',
- component: () => import('@/views/article/'),
- // 动态路由传参:将动态路由参数映射到组件的props中,无论是访问还是维护都很方便
- props: true
- }
article/index.vue组件中用props申明接收:
- props: {
- articleId: {
- type: Number,
- required: true
- }
- },
使用github上正文内容封装好的样式,引入 import './github-markdown.css',直接拿过来用即可 github-markdown.css
api/article.js 封装数据接口
- // 获取文章详情
- export const getArticleById = articleId => {
- return request({
- method: 'GET',
- url: `/app/v1_0/articles/${articleId}`
- })
- }
article/index.vue
加载接口配置: import { getArticleById } from "@/api/article";
页面初始化时加载方法,请求相应数据:
- created() {
-
- this.loadArticle();
-
- },
-
- methods: {
-
- async loadArticle() {
-
- const { data } = await getArticleById(this.articleId);
-
- console.log(data);
-
- }
-
- }
会报错:
解决:后端返回数据中的大数字问题
Js能够准确表示的整数范围在-2^53到2^53之间,不包含两个端点,超过这个范围则无法精确表示该值
后端返回的数据一般是JSON格式的字符串,若不做任何处理直接获取字符串的指定数据比较麻烦,所以要转换为js对象。
'{"id":"234894235395435","name":"jack","age": 18}'
转换为:
JSON.parse( '{"id":"234894235395435","name":"jack","age": 18}' )
可以看出超出安全整数范围的id无法精确表示这个问题并不是axios的错,解决办法是json-bigint
json-bigint是第三方包:
1.安装 npm i json-bigint
2.在utils/request.js中配置
- const request = axios.create({
- baseURL: 'http://ttapi.research.itcast.cn/', // 接口的基准路径
- transformResponse: [function (data) {
- // 后端返回的数据可能不是json格式字符串
- // 如果不是,那么 jsonbig.parse调用会报错
- // 所以用try-catch来捕获民异常,处理异常的发生
- try {
- // 如果转换成功,则直接把结果返回
- return JSONbig.parse(data)
- } catch (err) {
- console.log('转换失败', err)
- // 如果转换失败了,则进入这里
- // 把数据原封不动的直接返回给请求使用
- return data
- }
- // axios默认在内部使用JSON.parse来转换处理原始数据
- // return JSON.parse(data)
- }]
- })
点击文章里的图片可以对图片进行预览,大致步骤如下:
获取文章内容DOM容器,要用ref属性
先绑定ref属性
- <div
- class="markdown-body"
- v-html="article.content"
- ref="article-content"
- ></div>
获取DOM容器
const articleContent = this.$refs['article-content']
得到所有的img标签
- const imgs = articleContent.querySelectorAll("img");
- console.log(imgs);
从方面打印出来的数据看出: 数组为空,这是因为数据改变影响视图更新(DOM数据)不是立即的,如 this.article = data.data;已经改变了数据,但页面上未及时更新视图效果
所以如果需要在修改数据之后马上操作被该数据影响的视图DOM,需要把得到所有的img标签的代码放到$nextTick中,$nextTick是Vue提供的一个方法
- this.$nextTick(() => {
- const imgs = articleContent.querySelectorAll("img");
- console.log(imgs);
- });
加了$nextTick()方法之后,效果如下:
在事件处理函数中调用ImagePreview()预览
该部分完整代码:
- methods: {
- async loadArticle() {
- const { data } = await getArticleById(this.articleId);
- console.log(data);
- this.article = data.data;
- this.$nextTick(() => {
- this.handlerPreviewImage();
- });
- },
- handlerPreviewImage() {
- // 进行图片预览操作
- // 1.获取文章内容DOM容器,要用ref属性
- const articleContent = this.$refs["article-content"];
- // 2.得到所有的img标签
- // 数据改变影响视图更新(DOM数据)不是立即的
- // 所以如果需要在修改数据之后马上操作被该数据影响的视图DOM,
- // 需要把得到所有的img标签的代码放到$nextTick中,
- // $nextTick是Vue提供的一个方法
- const imgs = articleContent.querySelectorAll("img");
- const imgPaths = []; // 收集所有图片的路径
-
- // 3.循环img列表,给img注册点击事件
- imgs.forEach((img, index) => {
- imgPaths.push(img.src);
- img.onclick = function() {
- // 4.在事件处理函数中调用ImagePreview()预览
- ImagePreview({
- images: imgPaths, // 预览图片路径列表
- startPosition: index // 起始位置
- });
- };
- });
- }
- }
1.api/user.js中配置关注用户、取消关注用户的数据接口
- // 关注用户
- export const addFollow = userId => {
- return request({
- method: 'POST',
- url: '/app/v1_0/user/followings',
- data: {
- target: userId
- }
- })
- }
- // 取消关注用户
- export const deleteFollow = userId => {
- return request({
- method: 'DELETE',
- url: `/app/v1_0/user/followings/${userId}`
- })
- }
这两个接口都需要传用户id,即userId
“关注”按钮绑定onFollow事件,绑定:loading事件
- @click="onFollow"
- :loading="isFollowLoading"
处理onFollow事件函数
- async onFollow() {
- this.isFollowLoading = true;
- // 已关注,则取消关注
- if (this.article.is_followed) {
- await deleteFollow(this.article.aut_id);
- } else {
- // 没有关注,则添加关注
- await addFollow(this.article.aut_id);
- }
- this.article.is_followed = !this.article.is_followed;
- this.isFollowLoading = false;
- }
配置数据接口
- // 收藏文章
- export const addCollect = articleId => {
- return request({
- method: 'POST',
- url: '/app/v1_0/article/collections',
- data: {
- target: articleId
- }
- })
- }
- // 取消收藏文章
- export const deleteCollect = articleId => {
- return request({
- method: 'DELETE',
- url: `/app/v1_0/article/collections/${articleId}`
- })
- }
收藏与取消收藏的点击事件
- // 收藏与取消收藏
- async onCollect() {
- // this.isCollectLoading = true;
- this.$toast.loading({
- message: "操作中...",
- forbidClick: true // 禁止背景点击
- });
- // 已收藏,则取消收藏
- if (this.article.is_collected) {
- await deleteCollect(this.articleId);
- } else {
- // 没有收藏,则添加收藏
- await addCollect(this.articleId);
- }
- this.article.is_collected = !this.article.is_collected;
- // this.isCollectLoading = false;
- this.$toast.success(`${this.article.is_collected ? "" : "取消"}收藏成功`);
- }
配置数据接口
- // 点赞文章
- export const addLike = articleId => {
- return request({
- method: 'POST',
- url: '/app/v1_0/article/likings',
- data: {
- target: articleId
- }
- })
- }
- // 取消点赞文章
- export const deleteLike = articleId => {
- return request({
- method: 'DELETE',
- url: `/app/v1_0/article/likings/${articleId}`
- })
- }
点赞与取消点赞的点击事件
- // 对文章点赞或取消点赞
- async onLike() {
- this.$toast.loading({
- message: "操作中...",
- forbidClick: true // 禁止背景点击
- });
- if (this.article.attitude === 1) {
- // 取消点赞
- await deleteLike(this.article.art_id);
- this.article.attitude = -1;
- } else {
- // 添加点赞
- await addLike(this.article.art_id);
- this.article.attitude = 1;
- }
- this.$toast.success(
- `${this.article.attitude === 1 ? "" : "取消"}点赞成功`
- );
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。