vue项目day05

87 阅读6分钟

vue项目day05

1653912454732.png

1653912494799.png

4、完成收藏文章功能
  • 功能一:实现收藏按钮的效果
    • 已收藏:显示红色
    • 未收藏:显示黑马
    • 这里我们使用动态行内样式来完成这个功能,然后我们还需要知道如何来判断当前文章是否已收藏,那如何判断呢?答:后端文章详情接口中返回了一个has_star属性,当这个属性值为true表示已收藏,false表示未收藏。 +
  • 功能二:实现收藏功能
    • 用户角度分析:点击收藏按钮,实现收藏效果
    • 程序员角度分析:给收藏按钮绑定点击事件 声明事件处理函数,然后再事件处理函数中调用收藏接口实现收藏功能
    • 拆解步骤:
      • 1、给收藏按钮绑定点击事件 声明事件处理函数
      • 2、封装“收藏”接口函数
      • 3、引入接口函数,并在事件处理函数中调用接口实现收藏功能

1653912519921.png

1653912541011.png

8、评论列表

1、创建commentList.vue组件

2、配置路由

3、布局

4、实现功能

1、渲染评论列表

用户角度分析:用户点击文章详情页面中的 “评论数量”或者“更多跟帖”按钮,跳转到评论列表页面,进入页面就可以立刻看到评论的数据。

程序员角度分析:在文章详情页面,给“更多跟帖”和“评论数量”绑定点击事件,并通过事件处理函数跳转到评论列表页面,然后在created中调用接口,请请并保存数据,渲染数据。

拆解步骤:

  • 1、在文章详情页面,给“更多跟帖”和“评论数量”绑定点击事件,并通过事件处理函数跳转到评论列表页面
  • 2、封装 “获取评论列表”的接口函数
  • 3、评论列表页面引入接口函数,并在created中调用 接口,请求并保存数据
  • 4、根据数据渲染

1653912579637.png

2、渲染评论中的嵌套评论内容

问题1:嵌套评论的内容是如何产生的?答:是通过回复评论产生的,那么数据中如何体现出来呢?答:通过parent属性,当parent为null的时候表示改评论为直接评论,当parent为对象的时候,表示存在嵌套评论。

  • 1、把嵌套评论的结构实现出来
  • 2、根据parent判断,然后进行渲染

1653912606345.png

1653912640169.png

1653912685386.png

1653912722097.png

1653912746623.png

3、递归组件的使用

问题:评论内容有多层嵌套,且第二层以及第三层之后的所有嵌套都是一样的结构和样式,因此我们可以把嵌套评论内容部分封装起来,然后使用递归组件渲染内容。

封装src/commentItem.vue递归组件

<template>
    <div class="commentItem">
        <div class="top">
            <div class="left">
                <span>{{item.user.nickname}}</span> &nbsp;&nbsp;&nbsp;
                <span>2分钟前</span>
            </div>
            <span>回复</span>
        </div>
        <!-- 第二层嵌套 start
        递归组件:自己调用了自己,但是一定要有结束的判断
         -->
        <commentItem v-if="item.parent" :item="item.parent"></commentItem>
        <!-- 第二层嵌套 end -->
        <div class="bottom">{{item.content}}</div>
    </div>
</template>

<script>
export default {
    // props: ["item"]
    // name属性相当于通过components注册了该组件,name的值就是注册的组件名
    name: "commentItem", 
    props: {
        item: {
            type: Object, // 规定传入的item的数据类型
            required: true // 规定使用组件时,item为必传
        }
    }
}
</script>
<style lang="less" scoped>
.commentItem {
  border: 1px solid #ccc;
  padding: 5px;
  margin-top: 10px;
  .top {
    font-size: 12px;
    color: #aaa;
    display: flex;
    justify-content: space-between;
  }
  .bottom {
    font-size: 13px;
    line-height: 40px;
  }
}
</style>

1653912777747.png

1653912798704.png

2、发表评论
  • 1、点击底部输入框,显示文本域。
发表评论有以下几种情况:
1、直接对文章发表评论
2、点击最外层的回复按钮,进行评论
3、点击第一层嵌套的回复按钮,进行评论
4、点击递归组件生成的嵌套的回复按钮,进行评论

1653912826010.png

  • 1、直接对文章发表评论

    • 用户角度分析:点击底部输入,显示文本域,输入评论内容,点击发送按钮,进行评论。
    • 程序员角度分析:给底部输入框绑定事件,控制文本域的显示,收集用户输入的评论内容,给“发送”绑定点击事件,在事件处理函数中调用接口进行发表评论。
    • 拆解步骤:
      • 1、给底部输入框绑定事件,控制文本域的显示,
      • 2、声明变量,v-model双向绑定文本域
      • 3、给“发送”按钮绑定点击事件,并声明事件处理函数
      • 4、封装“发表评论”的接口函数
      • 5、在事件处理函数中调用“发表评论”接口,实现发表功能。
  • 2、点击最外层的回复按钮,进行评论

    • 用户角度分析:用户点击回复按钮,显示底部文本域,输入评论内容,点击发送按钮,发表成功了。
    • 程序员角度分析:给回复按钮绑定点击事件,并声明事件处理函数,控制底部文本域的显示,收集用户输入的评论内容,给发送按钮绑定点击事件,调用接口实现发表评论。
    • 拆解步骤:
      • 1、给回复按钮绑定点击事件,并声明事件处理函数
      • 2、事件处理函中控制底部文本域的显示
      • 3、收集用户输入的评论内容 ---- 上一个功能已经实现了
      • 4、给发送按钮绑定点击事件,并声明事件处理函数。 --- 上一个功能已经实现了
      • 5、封装接口函数,调用接口函数。 ---- 上一个功能已经实现了
        • 注意:此刻我们是回复评论,因此接口需要添加多一个参数,这个参数就是parent_id。
  • 3、点击第一层嵌套的回复按钮,进行评论

    • 用户角度分析:用户点击回复按钮,显示底部文本域,输入评论内容,点击发送按钮,发表成功了。
    • 程序员角度分析:给回复按钮绑定点击事件,在事件处理函数中控制底部组件文本域的显示,收集用户输入的评论内容,给发送按钮绑定点击事件,调用接口实现发表评论。
    • 拆解步骤:
      • 1、给回复按钮绑定点击事件,并声明事件处理函数
      • 2、在函数中控制底部组件文本域的显示,以及把回复评论的id传递给子组件
        • 因为控制底部组件文本域的显示已经在父组件中实现了,因此我们可以在commentItem组件中通过子传父,通知父组件控制底部组件文本域的显示即可,
        • 因为id传递给底部组件也已经在父组件中实现了,因为,我们可以在commentItem组件中通过子传父,把id传递给父组件,父组件再传递底部组件。

1653912845037.png

1653912883898.png

1653912943769.png

1653912999335.png

  • 4、点击递归组件生成的嵌套的回复按钮,进行评论

    • 用户角度分析:用户点击回复按钮,显示底部文本域,输入评论内容,点击发送按钮,发表成功了。

    • 程序员角度分析:给回复按钮绑定点击事件,在事件处理函数中控制底部组件文本域的显示,收集用户输入的评论内容,给发送按钮绑定点击事件,调用接口实现发表评论。

    • 因为递归组件生成的回复按钮,已经在上一个功能中绑定了自定义事件,并且进行了父传子,因此我们只需在父组件commentItem组件中绑定自定义事件,并在事件处理函数中进行子传父即可

    • 在commentItem组件中添加如下代码即可

      <template>
          <div class="commentItem">
      .....
              <!-- 第二层嵌套 start
              递归组件:自己调用了自己,但是一定要有结束的判断
      			添加 @replyEvent="replyFn"事件完成,递归组件生成的回复按钮功能
               -->
              <commentItem v-if="item.parent" :item="item.parent" 
                           @replyEvent="replyFn"></commentItem>
      ....
      </template>
      

1653913037227.png