移动端项目 文章管理

在这里插入图片描述

一、创建组件配置路由

1.创建 views/article/index.vue 组件
2.将该页面配置到根级路由

{
  path: '/article/:articleId',
  name: 'article',
  component: () => import('@/views/article')
}

3.在 src\components\article-item\index.vue 中的文章列表中绑定

<van-cell class="article-item" :to="`/article/${article.art_id}`">
</van-cell>   

4.使用组件 Props 解耦合路由参数
由于文章列表的每一项的地址栏里是带articleId的
希望对路由参数进行解耦处理 就是说把参数放到组件的props中。
假如说在别的地方被重用,就可以通过父传子的方式来传这个参数。
步骤1.现在当前组件声明一个props来接收参数articleId

export default {
  name: 'ArticleIndex',
  props: {
    articleId: {
      type: [Number, String], //多类型 可能是字符串 可能是数字
      required: true
    }
  }
}

步骤2.路由传递props参数 在router.js中更改路由 开启props传参 。因此在子组件中就可以拿到刚刚传递的参数articleId

{
  path: '/article/:articleId',
  name: 'article',
  component: () => import('@/views/article'),
  // 开启 props 传参,说白了就是把路由参数映射到组件的 props 中
  props: true
}

二、页面布局部分 省略

使用到的vant组件有:

三、展示文章详情

主要内容:

  • 找到数据接口
  • 封装请求方法
  • 请求获取数据
  • 模板绑定
    1.新增接口方法,在api/article.js中
//获取文章
export const getArticleById = articleId =>{
	return request({
		method:'GET',
		url:`/v1_0/articles/${articleId}`
	})
}

2.导入import { getArticleById } from ‘@/api/article.js’ 获取文章详情

export default {
  name: 'ArticleIndex',
  props: {
    articleId: {
      type: [Number, String],
      required: true
    }
  },
  data () {
  return {
    article: {} // 文章详情
   }
  },
  created () {
    this.loadArticle()
  },
  methods: {
    async loadArticle () {
      try {
        const { data } = await getArticleById(this.articleId)
        console.log(data)
        this.article = data.data
      } catch (error) {
        console.log('获取数据失败', error)
      }
    }
  }
}

3.使用处理好以后的数据,使用模板进行绑定 略

四、处理内容加载状态

需求分析:

  • 在加载中时显示loading
  • 加载成功显示文章详情
  • 加载错误显示错误提示
    • 404 提示资源不存在
    • 其他的提示 加载失败 用户可以点击重新加载

1.在data中声明loading即errStatus状态

data () {
  return {
    article: {}, // 文章详情
    loading: true, // 加载中的 loading
    errStatus: 0 // 失败的状态码
  }
}

2.放到methods中

methods:{
	async loadArticle(){
		this.loading = true  //进来先显示加载
		try{
			const {data} = await getArticleById(this.articleId)
			this.article = data.data
		}catch(error){
			 if (error.response && error.response.status === 404) {
        this.errStatus = 404
     	 	 }
		}
		//无论是成功还是失败 都要关闭loading
		this.loading = false
	}
}

3.在页面上进行优化

 <!-- 加载完成-文章详情 -->
  <div class="article-detail" v-else-if="article.title"></div>

  <!-- 加载失败:404 -->
  <div class="error-wrap" v-else-if="errStatus === 404"></div>

  <!-- 加载失败:其它未知错误(例如网络原因或服务端异常) -->
  <div v-else class="error-wrap"></div>
</div>

五、正文样式 直接用下载的资源

@import './github-markdown.css';
module.exports = {
  plugins: {
    'postcss-pxtorem': {
      rootValue ({ file }) {
        return file.indexOf('vant') !== -1 ? 37.5 : 75
      },

      // rootValue: 75,

      // 配置要转换的 CSS 属性
      // * 表示所有
      propList: ['*'],
      exclude: 'github-markdown'
    }
  }
}

示例用法:

<div class="contain markdown-bode"></div>

六、图片点击预览

思路:

  • 从文章内容中获取到所有的 img DOM 节点
  • 获取文章内容中所有的图片地址
  • 遍历所有的img节点 给每个节点添加点击事件
  • 在点击事件处理函数中 调用ImagePreview 预览

1.ImagePreview组件的使用

import { ImagePreview } from 'vant'
ImagePreview(['xxx'])

2.封装 ImagePreview 预览图片方法

previewImage(){
	//获取所有的img节点
	const articleContent = this.$ref['article-content']
	const imgs = articleContent.querySelectorAll('img')
	const images = []
	imgs.forEach((item,index) => {
		//获取文章内容中所有的图片地址
		images.push(item.src)
		item.onclick = () =>{
			ImagePreview([
				images:images, //将数组赋给它
				startPosition: index
			])
		}
	})
}

3.最后在loadArticle()中添加一个定时器 让图片预览的操作放在最后执行

setTimeout(() => {
            this.previewImage()
        }, 0);

七、关注用户

思路:

  • 给按钮注册点击事件
  • 创建事件处理函数
  • 找到数据接口 封装请求方法 请求调用 视图更新

1.封装请求方法

//添加关注
export const addFollow = target => {
  return request({
    method: 'POST',
    url: '/v1_0/user/followings',
    data: {
      target
    }
  })
}

// 取消关注
export const deleteFollow = target => {
  return request({
    method: 'DELETE',
    url: `/v1_0/user/followings/${target}`
  })
}

2.给按钮绑定点击事件

<van-button 
	v-if="article.is_followed" 
	class="follow-btn" 
	type="info" 
	color="#3296fa" 
	round size="small" 
	icon="plus" 
	@click="onFollow">
 	 关注
</van-button>

<van-button 
	v-else 
	class="articlefollow-btn" 
	round 
	size="small" 
	@click="onFollow">
  	已关注
</van-button>


methods:{
	onFollow(){}
}

3.事件处理函数

import { addFollow, deleteFollow } from '@/api/user'
async onFollow(){
	try{
		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
	}catch(error){
		console.log(error)
		let message = '操作失败,请重试'
    	if (error.response && error.response.status === 400) {
    	  message = '你不能关注你自己!'
    	}
    	this.$toast(message)
	}
}

4.添加loading效果

<van-button :loading="followLoading" v-if="is_followed" class="follow-btn" type="info" color="#3296fa" round size="small" icon="plus" @click="onFollow">
  关注
</van-button>

<van-button :loading="followLoading" v-else class="follow-btn" round size="small" @click="onFollow">
  已关注
</van-button>


data() {
  return {
    // .....
    followLoading: false // loading 状态显示与否
  }
},
methods:{
	// 关注和取消关注
	async onFollow() {
  		this.followLoading = true
  		try {
  		  // ...
 		 } catch (error) {
 		   // ...
 		 }
 	 	this.followLoading = false
	}
}

4.在 components\follow-user\index.vue 中声明封装以后的组件
导入父组件中:

import FollowUser from '@/components/follow-user/index.vue'
//将is_followed传入子组件 
<follow-user
  class="follow-btn"
  @update-is_followed="article.is_followed = $event"
  :is-followed="article.is_followed"
  :user-id="article.aut_id"
/>

子组件:

<template>
  <van-button
    v-if="isFollowed"
    @click="onFollow"
    class="follow-btn"
    type="info"
    color="#3296fa"
    round
    size="small"
    icon="plus"
    :loading="loading"
  >关注</van-button>
  <van-button :loading="loading" @click="onFollow" v-else class="follow-btn" round size="small">已关注</van-button>
</template>

<script>
import { addFollow, deleteFollow } from '@/api/user.js'
export default {
  name: 'FollowUser',
  props: {
    isFollowed: {
      type: Boolean,
      required: true
    }
  },
  data() {
    return {
      loading: false // loading 状态显示与否
    }
  },
methods: {
  // 关注和取消关注
  async onFollow() {
    this.followLoading = true
    try {
      if (this.isFollowed) {
        // 已关注,取消关注
        await deleteFollow(this.userId)
      } else {
        await addFollow(this.userId)
      }
      // this.article.is_followed = !this.article.is_followed
      this.$emit('update-is_followed', !this.isFollowed)
    } catch (error) {
      let message = '操作失败,请重试'
      if (error.response && error.response.status === 400) {
        message = '你不能关注你自己!'
      }
      this.$toast(message)
    }
    this.followLoading = false
  }
}
</script>

<style lang="less" scoped>
</style>

八、文章收藏

思路同关注用户部分
1.封装组件components\collect-article\index.vue
将子组件导入父组件并挂载 在页面中使用

2.处理视图 将id和是否选中传给子组件

<collect-article v-model="article.is_collected" :article-id="article.art_id" />

子组件props接收

  props: {
    value: {
      type: Boolean,
      required: true
    },
    articleId: {
      type: [Number, String, Object],
      required: true
    }
  }

使用传递的数据渲染页面

<template>
  <van-icon :color="value ? '#ffa500' : ''" :name="value ? 'star' : 'star-o'" />
</template>

3.功能处理
思路 和关注相同:

  • 给收藏按钮注册点击事件
  • 如果已经收藏了,则取消收藏
  • 如果没有收藏,则添加收藏

(1).在 api/article.js 添加封装收藏文章和取消收藏文章两个数据接口
(2).给收藏按钮注册点击事件 @click=“onCollect”
(3).处理收藏的业务逻辑

methods: {
  async onCollect() {
    this.$toast.loading({
      duration: 0, // 持续展示 toast
      message: '操作中...',
      forbidClick: true // 是否禁止背景点击
    })

    try {
      if (this.value) {
        // 已收藏
        await deleteCollect(this.articleId)
      } else {
        // 没有收藏
        await addCollect(this.articleId)
      }
      // 更新视图
      this.$emit('input', !this.value)
      // 收藏成功以后的提示
      this.$toast.success(!this.value ? '收藏成功' : '取消收藏')
    } catch (error) {
      this.$toast.fail('操作失败,请重试!')
    }
  }
}

九、文章点赞

思路和收藏和关注相同

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值