关注用户
思路:
- 给按钮注册点击事件
- 在事件处理函数中
- 如果已关注,则取消关注
- 如果没有关注,则添加关注
给关注按钮绑定点击事件,如果已关注则取消关注,如果没有关注,则是关注,账号登录的状态下,未登录则提示关注失败,跳转到登录页面
已关注v-if="article.is_followed" 关注v-else
找到数据接口,封装接口,请求调用,视图更新
async onFollow () {
// 如果没有登录,就不允许操作
if(!this.$store.state.user) return this.$toast('请登录!')
// 开启按钮的 loading 状态
this.isFollowLoading = truetry {
// 如果已关注,则取消关注
const authorId = this.article.aut_id
if (this.article.is_followed) {
await deleteFollow(authorId)
} else {
// 否则添加关注
await addFollow(authorId)
}// 更新视图
this.article.is_followed = !this.article.is_followed
} catch (err) {
if(err && err.response.status === 400){
this.$toast('你不能关注自己')
}else{
this.$toast.fail('操作失败')
}
}// 关闭按钮的 loading 状态
this.isFollowLoading = false
}
v-model 的使用
回顾`v-model`, 双向绑定数据的!
<tempatel>
<div>
<input v-model="msg"> {{msg}}
<hr/>
<input :value="msg" @input="msg=$event.target.value"> {{msg}}
<hr>
<!--
总结: v-model 是 value属性和input事件的语法糖!
-->
</div>
</tempatel>
<script>
export default {
data(){
return {
msg:"呵呵!"
}
}
}
</script>
运用场景:当我们的父组件通过`props`传递某个数据给子组件,且子组件需要通过自定义事件`$emit`去修改该数据,也就是父子之间共同操作同一个变量数据,我们可以使用`v-model`指令
文章收藏
封装组件
处理视图
功能处理
思路:
- 给收藏按钮注册点击事件
- 如果已经收藏了,则取消收藏
- 如果没有收藏,则添加收藏
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`同样的效果
// 配置 v-model 对应的自定义属性名和自定义事件名称
model:{
prop:'isCollected',
event:'updateCollect'
}
// 接收文章收藏状态
//value: {
isCollected:{
type: Boolean,
required: true
},
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
}
展示文章评论列表
创建组件
获取数据并展示
步骤:
- 封装接口
- 请求获取数据
- 处理模板
async onLoad () {
try {
// 1. 请求获取数据
const { data } = await getComments({
type: 'a', // 评论类型,a-对文章(article)的评论,c-对评论(comment)的回复
source: this.source.toString(), // 源id,文章id或评论id,【可能有大数字,所以执行一下toString 方法】
offset: this.offset, // 评论数据的偏移量,值为评论id,表示从此id的数据向后取,不传表示从第一页开始读取数据
limit: this.limit // 获取的评论数据个数,不传表示采用后端服务设定的默认每页数据量
})// 2. 将数据添加到列表中(一定要注意是追加数据,否则列表高度不增加,形成死循环)
const { results } = data.data
this.list.push(...results)// 3. 将 loading 设置为 false
this.loading = false// 4. 判断是否还有数据
if (results.length) {
// 有就更新获取下一页的数据页码
this.offset = data.data.last_id
} else {
// 没有就将 finished 设置结束
this.finished = true
}
} catch (err) {
this.error = true
this.loading = false
}
}
展示文章评论总数量
`onLoad`事件函数里面 触发自定义
// 2. 将数据添加到列表中
const { results } = data.data
this.list.push(...results)
// 把文章评论的总数量传递到外部
this.$emit('onload-success', data.data) // <========== 增加这一句
// 3. 将 loading 设置为 false
this.loading = false
默认情况下只有滚动到了评论列表区域才会触发`onLoad`事件,所以我们需要再`created`里面主动触发一次,保证一开始就触发
created () {
this.onLoad()
}