vue黑马头条

4.8、文章收藏

该功能和关注用户的处理思路几乎一样,建议由学员自己编写。

封装组件

处理视图

功能处理

思路:

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

下面是具体实现。

1、封装组件

创建src/components/collect-article/index.vue

<template>
	<van-button icon="star-o"></van-button>
</template>
<script>
	export default {
        name:'CollectArticle',
        props:{},
        data(){
            return{
                
            }
        },
        methods:{},
        created(){}
    }
</script>
<style scoped lang="less">
</style>

src/views/article/index.vue中导入注册,使用组件

import CollectArticle from '@/components/collect-article'

components:{
    // ...其他注册
    CollectArticle
}
<collect-article  class="btn-item"/>

2、处理视图

在父组件article/index.vue中通过v-model 绑定文章的收藏状态

<collect-article  
     class="btn-item" 
     v-model="article.is_collected" 
/>

子组件中collect-article/index.vue 中定义props接收,且去渲染视图

props:{
    // 接收文章收藏状态
    value:{
        type:Boolean,
        required:true    
    }
}

<van-button 
    icon="value ? 'star' : 'star-o'" 
    :class="{ collected: value }"
></van-button>

<style scoped lang="less">
.collected {
  .van-icon {
    color: #ffa500;
  }
}
</style>

3、功能处理

在 api/article.js 添加封装数据接口

/**
 * 收藏文章
 */
export const addCollect = target => {
  return request({
    method: 'POST',
    url: '/v1_0/article/collections',
    data: {
      target
    }
  })
}

/**
 * 取消收藏文章
 */
export const deleteCollect = target => {
  return request({
    method: 'DELETE',
    url: `/v1_0/article/collections/${target}`
  })
}

<template>
  <van-button
    :icon="value ? 'star' : 'star-o'"
    :class="{ collected: value }"
    :loading="loading"
    @click="onCollect"
  />

3、父组件传递文章id给子组件,书写处理函数

article/index.vue中传递文章id

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

collect-article/index.js 定义props接收; 定义loading变量, 导入请求方法,书写事件函数,完成功能

<script>
import { addCollect, deleteCollect } from '@/api/article'

export default {
  name: 'CollectArticle',
  components: {},
  props: {
    // 接收文章收藏状态
    value: {
      type: Boolean,
      required: true
    },
    // 接收文章id  
    articleId: {
      type: [Number, String, Object],
      required: true
    }
  },
  data () {
    return {
      // 加载中效果  
      loading: false
    }
  },
  methods: {
    async onCollect () {
      this.loading = 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 (err) {
        this.$toast.fail('操作失败,请重试!')
      }
      this.loading = false
    }
  }
}

拓展: 升级讨论一下v-model的名称问题,默认是自定义属性value 和 自定义事件input,但是这个名称不太语义化!希望用更加语义化的名称来实现v-model同样的效果

export default {
  name: 'CollectArticle',
  // 配置 v-model 对应的自定义属性名和自定义事件名称  
  model:{
      prop:'isCollected',
      event:'updateCollect'
  }
}

// 接收文章收藏状态
//value: {
isCollected:{
    type: Boolean,
    required: true
},

<template>
  <van-button
    :icon="isCollected ? 'star' : 'star-o'"
    :class="{ collected: isCollected }"
    :loading="loading"
    @click="onCollect"
  />

async onCollect () {
    this.loading = true
    try {
        if (this.isCollected) {
            // 已收藏,要取消收藏
            await deleteCollect(this.articleId)
        } else {
            // 没有收藏,要添加收藏
            await addCollect(this.articleId)
        }
        // 更新视图
        // 自定义事件修改数据并不是立即的
        this.$emit('updateCollect', !this.isCollected)

        this.$toast.success(!this.isCollected ? '收藏成功' : '取消收藏')
    } catch (err) {
        this.$toast.fail('操作失败,请重试!')
    }
    this.loading = false
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值