vue之评论

在这里插入图片描述

在这里插入图片描述

评论组件 artical.vue

  • 功能:
    • 先获取用户信息
    • 获取文章 数据
    • 获取评论数据
    • 发表评论
      • 发表评论后,调用子组件中的 获取最新评论方法
    • 点击回复 拿到父评论的id 并且给评论的数据对象,添加父评论的id
    • 点击回复的 时候 输入框聚焦 需要使用 ref 拿到子组件的节点 然后调用子组件中的 input表单节点下 使用focus方法
    • 这边引入了 评论头部组件 评论每一项item组件
<template>
  <div>
    <!-- 显示video -->
    <div class="a_video" v-if="detail">
      <video controls :src="detail.content"></video>
    </div>
    <!-- 可折叠 当前video信息 -->
    <van-collapse v-model="activeNames">
      <van-collapse-item :title="detail.name" name="1">
        <div v-if="detail.category">分类: {{ detail.category.title }}</div>
        <div v-if="detail.userinfo">{{ detail.date }} {{ detail.userinfo.name }}</div>
      </van-collapse-item>
    </van-collapse>
    <!-- 收藏等 -->
    <div class="collect">
      <span>收藏</span>
      <span>缓存</span>
      <span>分享</span>
    </div>
    <!-- 推荐列表 -->
    <div>
      <artical-detail v-for="(item,index) in commomList" :key="index" :detailitem="item"></artical-detail>
    </div>

    <!-- 评论 -->
    <comment-title @publishComment="publishComment" ref="commentIpt"></comment-title>
    <comment @reviewClcik="reviewClcik" ref="commentPublish"></comment>
  </div>
</template>

<script>
import Vue from "vue";
import { Collapse, CollapseItem } from "vant";

Vue.use(Collapse);
Vue.use(CollapseItem);

import ArticalDetail from "@/components/comtent/ArticalDetail";
import CommentTitle from "@/components/comtent/CommentTitle";
import Comment from "@/components/comtent/Comment";
export default {
  name: "Article",
  data() {
    return {
      detail: [],
      activeNames: ["1"],
      userinfo: {},
      commomList: [],
      publishInfo: {
        comment_user: "",
        comment_content: "",
        comment_date: "",
        parent_id: null,
        comment_id: null
      }
    };
  },
  // 由于使用的同一个 组件 这个方法 只是最初的时候 触发 需要监听
  created() {
    this.getArticle();
    this.getcommomList();
    this.getUser();
  },
  watch: {
    $route() {
      this.getArticle();
      this.getcommomList();
    }
  },
  methods: {
    // 获取用户信息
    async getUser() {
      const { data } = await this.$request.get(
        "/user/" + localStorage.getItem("id")
      );
      this.userinfo = data[0];
    },
    // 获取 文章 数据
    async getArticle() {
      const res = await this.$request.get("/article/" + this.$route.params.id);
      this.detail = res.data[0];
    },
    // 获取 评论列表
    async getcommomList() {
      const res = await this.$request.get("/commend");
      this.commomList = res.data;
    },
    // 发表评论
    async publishComment(val) {
      let date = new Date();
      let m = date.getMonth() + 1;
      let d = date.getDate();
      m = m < 10 ? "0" + m : m;
      d = d < 10 ? "0" + d : d;
      this.publishInfo.comment_user = this.userinfo.name;
      this.publishInfo.comment_content = val;
      this.publishInfo.comment_date = m + "-" + d;
      this.publishInfo.comment_id = this.$route.params.id;
      //把当前 发表评论写入数据库
      this.$request.post(
        "/comment_post/" + localStorage.getItem("id"),
        this.publishInfo
      );
      //发表评论后 需要调用 该组件下 中的一个拿到最新的排评论的方法
      this.$refs.commentPublish.getComment();
      // console.log("当前", this.publishInfo);
      // console.log("当前res", res);
    },
    // 点击回复 拿到 父id
    reviewClcik(id) {
      // console.log("父id", id);
      this.parent_id = id;
      this.$refs.commentIpt.focusIpt();
    }
  },
  components: {
    ArticalDetail,
    CommentTitle,
    Comment
  }
};
</script>
<style  lang="scss" scoped>
.a_video {
  width: 100%;
  height: 2rem;

  video {
    width: 100%;
    height: 100%;
  }
}
.collect {
  span {
    margin: 0 10px;
  }
  span:nth-child(1) {
    margin-left: 20px;
  }
}
</style>

评论头部组件 CommentTitle.vue

  • 功能:
    • 父组件 引用的时候 点击回复,使得当前input表单 聚焦
    • 点击发表评论的时候,需要触发父组件的方法,并且传递当前的表单的内容,到父组件(自定义事件后,接受参数,操作数据)

<template>
  <div>
    <p>
      <span>评论</span>
      <span>(4080)</span>
    </p>
    <div>
      <img :src="userinfo.user_img" alt />
      <input
        type="text"
        placeholder="请输入评论"
        ref="publishIpt"
        @focus="focusInput"
        v-model="commentVal"
      />
      <button @click="publish">发表</button>
    </div>
  </div>
</template>

<script>
export default {
  name: "CommentTitle",
  data() {
    return {
      userinfo: {},
      commentVal: null
    };
  },
  created() {
    if (localStorage.getItem("token")) {
      this.myUserInfo();
    }
  },
  methods: {
    async myUserInfo() {
      const { data } = await this.$request.get(
        "/user/" + localStorage.getItem("id")
      );
      // console.log("res111", data[0]);
      this.userinfo = data[0];
    },
    focusInput() {
      if (
        !this.userinfo &&
        !localStorage.getItem("token") &&
        localStorage.getItem("id")
      ) {
        this.$msg.fail("请登录");
        return;
      }
    },
    //发表评论
    publish() {
      // console.log("发表", this.commentVal);
      this.$emit("publishComment", this.commentVal);
      this.commentVal = "";
    },
    // 发表评论的聚焦 在父组件的 引用子组件的时候 使用 ref的方式 拿到该子组件节点 调用该方法!
    focusIpt() {
      // console.log("ref", this.$refs.publishIpt);
      this.$refs.publishIpt.focus();
    }
  },
  components: {}
};
</script>
<style  lang="scss" scoped>
</style>

评论组件 Comment.vue

  • 功能:
    • 这边写死的数据,理论需要接口的数据,若是遇到这种数据,需要递归的方式去处理
    • 先获取数据,然后采用递归方式处理数据
    • 点击回复的时候,触发父组件引用子组件的 回复事件
    • 这边引入了 二级评论的组件
<!--  -->
<template>
  <div class="comment" v-if="commentChildList">
    <div class="comment_item" v-for="(item,idx) in commentChildList" :key="idx">
      <div class="comment_title">
        <div class="comment_img">
          <img v-if="item.userinfo" :src="item.userinfo.user_img" alt />
          <img v-else src="../../assets/default_img.jpg" alt />
        </div>
      </div>
      <div class="comment_info">
        <div class="comment_user">
          <span v-if="item.userinfo.name">{{ item.userinfo.name }}</span>
          <span v-else>匿名</span>
          <span>{{ item.comment_date }}</span>
        </div>
        <div class="comment_con">
          {{ item.comment_content }}
          <span style="color:red" @click="reviewClcik(item.comment_id)">回复</span>
        </div>
        <!-- 二级评论等 把二级评论 传递进去 渲染 -->
        <comment-child :commentChild="item.child"></comment-child>
      </div>
    </div>
  </div>
</template>

<script>
import CommentChild from "../comtent/CommentChild";
export default {
  name: "Comment",
  data() {
    return {
      commentChildList: null,
      list: [
        {
          comment_id: 76,
          user_id: 42,
          comment_date: "05-14",
          comment_content: "你好",
          parent_id: null,
          userinfo: {
            gender: "1",
            id: 42,
            name: "黄民泽",
            user_desc: "Mr.Huang",
            user_img:
              "http://112.74.99.5:3000/upload/fad74f638b1cbc452378fb4e3496faed"
          }
        },
        {
          comment_id: 78,
          user_id: 42,
          comment_date: "05-14",
          comment_content: "你也好",
          parent_id: "76",
          userinfo: {
            gender: "0",
            id: 43,
            name: "小红帽",
            user_desc: "888",
            user_img:
              "http://112.74.99.5:3000/upload/d7747f9ee313f4eee2a105f5ad166889"
          }
        },
        {
          comment_id: 79,
          user_id: 42,
          comment_date: "05-14",
          comment_content: "你也是",
          parent_id: "78",
          userinfo: {
            gender: "0",
            id: 43,
            name: "小红帽",
            user_desc: "888",
            user_img:
              "http://112.74.99.5:3000/upload/d7747f9ee313f4eee2a105f5ad166889"
          }
        },
        {
          comment_id: 80,
          user_id: 42,
          comment_date: "05-14",
          comment_content: "你也一样",
          parent_id: "79",
          userinfo: {
            gender: "0",
            id: 43,
            name: "小红帽",
            user_desc: "888",
            user_img:
              "http://112.74.99.5:3000/upload/d7747f9ee313f4eee2a105f5ad166889"
          }
        },
        {
          comment_id: 81,
          user_id: 42,
          comment_date: "05-14",
          comment_content: "大家都好",
          parent_id: "80",
          userinfo: {
            gender: "0",
            id: 43,
            name: "小红帽",
            user_desc: "888",
            user_img:
              "http://112.74.99.5:3000/upload/d7747f9ee313f4eee2a105f5ad166889"
          }
        },
        {
          comment_id: 82,
          user_id: 391,
          comment_date: "05-14",
          comment_content: "大家都一样",
          parent_id: "81",
          userinfo: {
            gender: "0",
            id: 43,
            name: "小红帽",
            user_desc: "888",
            user_img:
              "http://112.74.99.5:3000/upload/d7747f9ee313f4eee2a105f5ad166889"
          }
        },
        {
          comment_id: 83,
          user_id: 42,
          comment_date: "05-14",
          comment_content: "",
          parent_id: null,
          userinfo: {
            gender: "0",
            id: 43,
            name: "小红帽",
            user_desc: "888",
            user_img:
              "http://112.74.99.5:3000/upload/d7747f9ee313f4eee2a105f5ad166889"
          }
        }
      ]
    };
  },
  created() {
    this.getComment();
  },
  methods: {
    async getComment() {
      //需要发起请求 拿到评论的数据
      // const { data } = await this.$request.get(
      //   "/comment/" + this.$route.params.id
      // );
      // console.log("评论", data);
      // this.commentChildList =  this.getCommentChild(data);

      //使用的是 死数据 进行渲染的
      this.commentChildList = await this.getCommentChild(this.list);
      console.log("plun", this.commentChildList);
    },
    async getCommentChild(data) {
      function fun(temp) {
        let arr1 = [];
        for (let i = 0; i < data.length; i++) {
          //遍历 假如数据中 parent_id 为null 那么就是代表为 一级评论
          if (data[i].parent_id == temp) {
            arr1.push(data[i]);
            data[i].child = fun(data[i].comment_id);
          }
        }
        return arr1;
      }
      return fun(null);
    },
    reviewClcik(id) {
      // console.log("id", id);
      this.$emit("reviewClcik", id);
      
    }
  },
  components: {
    CommentChild
  }
};
</script>
<style  lang="scss" scoped>
.comment_item {
  display: flex;
  margin-bottom: 10px;
  .comment_title {
    display: flex;
    align-items: center;
    height: 0.4rem;
    padding: 0 10px;

    .comment_img {
      width: 0.35rem;
      height: 0.35rem;
      img {
        width: 100%;
        height: 100%;
      }
    }
  }
  .comment_user {
    height: 0.35rem;
    margin-left: 10px;
  }
  .comment_info {
    display: flex;
    flex-direction: column;
  }
  .comment_con {
    width: 100%;
    display: flex;
    justify-content: space-between;
    margin-top: 10px;
  }
  .comment_child {
    margin-left: 40px;
  }
}
</style>

二级评论组件 ComemntChild.vue

  • 功能:
    • 接受父组件 传递来的二级评论数据等 然后渲染数据
    • 还有实现组件的递归 假如有三级评论等 就传入数据,继续递归下去
<!--  -->
<template>
  <div class="comment-child">
    <div class="comment-box" v-for="(item,idx) in commentChild" :key="idx">
      <div class="comment_title">
        <div class="comment_img">
          <img v-if="item.userinfo" :src="item.userinfo.user_img" alt />
          <img v-else src="../../assets/default_img.jpg" alt />
        </div>
      </div>
      <div class="comment_info">
        <div class="comment_user">
          <span v-if="item.userinfo.name">{{ item.userinfo.name }}</span>
          <span v-else>匿名</span>
          <span>{{ item.comment_date }}</span>
        </div>
        <div
          class="comment_con"
          v-if="temp"
          @click="commentClild(item.comment_id)"
        >回复 XXX {{ item.comment_content }}</div>
        <div class="comment_con" v-else @click="commentClild(item.comment_id)">
          回复 某某
          <!-- <span style="color:#333">{{ item.parent_user_info.name }}</span> -->
          {{ item.comment_content }}
        </div>
      </div>
      <!-- 组件的递归 -->
      <div style="padding-left:30">
        <comment-child :commentChild="item.child" :temp="true"></comment-child>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "CommentChild",
  props: ["commentChild", "temp"],
  data() {
    return {};
  },
  methods: {
    commentClild(id) {
      console.log("二级", id);
    }
  },
  components: {}
};
</script>
<style  lang="scss" scoped>
.comment-box {
  display: flex;
  flex-direction: column;
}
.comment-child {
  margin-top: 10px;
}
.comment_item {
  display: flex;
  margin-bottom: 10px;
  .comment_title {
    display: flex;
    align-items: center;
    height: 0.4rem;
    padding: 0 10px;

    .comment_img {
      width: 0.35rem;
      height: 0.35rem;
      img {
        width: 100%;
        height: 100%;
      }
    }
  }
  .comment_user {
    height: 0.35rem;
    margin-left: 10px;
  }
  .comment_info {
    display: flex;
    flex-direction: column;
  }
  .comment_con {
    margin-top: 5px;
  }
  .comment_child {
    margin-left: 0px;
  }
}
</style>
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值