多级留言/评论的功能实现——Vue3前端篇

news2024/10/5 21:23:48

文章目录

  • 思路分析
  • 封装组件
    • 父组件
      • 模板
      • 逻辑
      • 样式
    • 子组件——二级留言
      • 模板
      • 逻辑
      • 样式
    • 子组件——三级留言以上
      • 模板
      • 逻辑
      • 样式
  • 留言组件的使用

写完论文了,来把评论的前端部分补一下。
前端的实现思路是自己摸索出来的,没找到可以符合自己需求的参考,有问题或者有优化的建议欢迎指正。

思路分析

当时写完后端的时候就在思考应该怎么处理响应数据才能做到多级评论的展示,感觉应该 不复杂,但是经验有限,写起来有些吃力。

本来我只用了一个组件,然后在里面实现多级的嵌套,但是发现这样使得单个文件比较臃肿,而且逻辑比较复杂。

于是我拆分了一下,两个组件,一个父组件、一个子组件。父组件只展示顶级留言,子组件展示所有子留言,但是这没有解决二级与三级以上留言的区分。

最终的版本,一个父组件,两个子组件。父组件同样只展示顶级留言,但是父组件中引入了两个子组件,分别展示了二级留言和三级以上留言,三级以上留言使用了递归来实现。

实现如图
在这里插入图片描述

封装组件

每一个组件都是单文件组件,模板、逻辑、样式都在同一个文件,但是这里为了让大家更清楚的浏览,将三个部分拆开展示。

父组件

模板

为了解读代码方便,将解释贴在了每段代码前方,建议按照从上至下的顺序去理解代码,根据这个顺序去看对应的逻辑实现。

难点:

  1. 父子组件传值
  2. 回复框的定位:控制回复框仅在当前点击的留言下方出现
<template>
  <div class="comments">
    <el-card>
      <template #header>
        <div class="comments-header">
          <h3>留言区</h3>
        </div>
      </template>

      <!-- 编辑区
      		1. 左侧:显示当前登录用户头像
      		2. 中间:输入框,使用 v-model 收集用户输入的内容 comment
      		3. 右侧:在 handlePublish 方法中请求新增留言接口
       -->
      <div class="editbox">
        <div class="editbox-left">
          <el-avatar :size="45" :src="userInfo.avatar" />
        </div>
        <div class="editbox-middle">
          <el-input
            placeholder="与其赞同别人的话语,不如自己畅所欲言..."
            v-model="comment"
          ></el-input>
        </div>
        <div class="editbox-right">
          <el-button @click="handlePublish(comment)">发布</el-button>
        </div>
      </div>

      <!-- 列表区
      		1. 遍历分页获取的留言列表,并设置唯一的 key 值
      		2. 顶级留言包括:头像、昵称、角色名标签、留言内容、发布时间
      		3. 点击 “回复” 会触发事件 handleReply,同时传入两个参数:当前被回复留言的根ID、当前被回复留言的直接父级ID
      			a. 这两个参数用于给【即将发布的留言】设置根ID与直接父级ID,做到 “回复框的定位” 
      			b. 对于二级留言,这两个值传入顶级留言本身的ID就行
       -->
      <div class="listbox" v-for="(item, index) in commentsList" :key="index">
        <!-- 顶级留言:这没什么好说的,就直接展示遍历的结果 -->
        <div class="top-level">
          <div class="listbox-top-user">
            <el-avatar :size="45" :src="item.userImg" />
            <p>
              <span>{{ item.createdBy }}</span>
              <span>{{ item.roleName }}</span>
            </p>
          </div>
          <div class="listbox-middle-root">{{ item.comment }}</div>
          <div class="listbox-bottom">
            <span>发布时间:{{ item.createdAt }}</span>
            <span @click="handleReply(item.id, item.id)">回复</span>
          </div>
        </div>
         
         <!-- 子留言区
        		1. 这里没有使用在二级组件中引入三级以上组件的方式,因为当时开发的时候感觉传值有点麻烦
        		2. 使用两个子组件同级的形式
         
	         子留言:二级
	          		1. 判断顶层留言是否存在二级子留言,是则引入 SecondComment 子组件
	          		2. 父组件传递参数:二级评论 item.children
	          		3. 处理 “回复” 功能,使用同一个方法实现(handleReply),这里的根ID和直接父ID是子组件传过来的
	          		4. handle-reply 是子组件中声明需要抛出的事件,@handle-reply 代表监听子组件的自定义事件
         -->
        <div v-if="item.children && item.children.length">
          <SecondComment
            :secondComments="item.children"
            @handle-reply="handleReply"
            style="margin-left: 0"
          />

          <!-- 子留言:三级
          		1. 因为使用的同级结构,所以需要先遍历每一个二级留言,判断其下是否存在子留言,是则引入 ChildComment 子组件。
          		2. 必须要遍历二级留言并设置唯一的 key !!无法直接获取 item.children.children !!!(原因有点忘了...)
          		3. 同样要给子组件传递参数:三级评论 child.children
          		4. 同时将二级留言的发表人昵称传递给子组件,用于非二级留言的子留言显示 “ @nickname ” 
          		5. 同样拥有 “回复” 功能,使用同一个方法实现(handleReply),这里的根ID和直接父ID是子组件传过来的
          		6. 子组件中声明的抛出事件(to-reply)不能与其他组件重复
           -->
          <template
            v-for="(child, childIndex) in item.children"
            :key="childIndex"
          >
            <template v-if="child.children && child.children.length">
              <ChildComment
                :childComments="child.children"
                :parentName="child.createdBy"
                @to-reply="handleReply"
                style="margin-left: 65px"
              />
            </template>
          </template>
        </div>

        <!-- 回复框
        		1. 使用一个变量 showReply 来控制显示隐藏
        		2. 同时使用变量 showReplyIndex 用来确定是在哪条留言下显示回复框,否则点击 “回复” 会在所有留言下都出现回复框
        		3. 当 handleReply 方法被触发时,改变 showReply 和 showReplyIndex 的值
        		4. 使用 replyComment 收集回复框输入的内容,当触发 handlePublish 方法时作为参数传进去
         -->
        <div
          class="reply-box-container"
          v-show="showReplyIndex === item.id && showReply"
        >
          <div class="replybox" id="reply-box">
            <div class="replybox-left">
              <el-avatar :size="30" :src="userInfo.avatar" />
            </div>
            <div class="replybox-middle">
              <el-input placeholder="回复" v-model="replyComment"></el-input>
            </div>
            <div class="replybox-right">
              <el-button @click="handlePublish(replyComment)">提交</el-button>
            </div>
          </div>
        </div>
      </div>
      <!-- 分页器:这也是一个单独的组件,此处不做深究,有机会会再出一篇封装分页组件的文章 -->
      <PageQuery
        :total="total"
        :pageNum="getCommentForm.pageNum"
        :pageSize="getCommentForm.pageSize"
        @page-size="handlePageSize"
        @page-num="handlePageNum"
      />
    </el-card>
  </div>
</template>

代码对应结构参考:
在这里插入图片描述

逻辑

<script setup>
import { ref, onMounted, reactive } from "vue";
import { getCommentListApi, postAddCommentApi } from "@/api/common";
import PageQuery from "@/components/common/PageQuery.vue";
import ChildComment from "@/components/front/ChildComment.vue";
import { useUserStore } from "@/stores/useUserStore";
import SecondComment from "@/components/front/SecondComment.vue";

const { userInfo } = useUserStore();
// 收集 “编辑区” 的输入内容
const comment = ref("");
// 收集 “回复框” 的输入内容
const replyComment = ref("");
// 存储请求回来的数据总数
const total = ref(0);
// 存储请求回来的留言列表
const commentsList = ref();
// 控制回复框的索引
const showReplyIndex = ref(0);
// 控制回复框的显示隐藏
const showReply = ref(false);

onMounted(() => {
  getCommentList();
});

// 接收父组件传过来的值——在别的文件中使用留言组件,则改文件为留言组件的父组件
const props = defineProps({
// 关联主体ID
  momentId: {
    type: Number,
    required: true,
  },
  postAddCommentForm: {
    type: Object,
    required: true,
  },
});

// 请求当前主体的评论列表
const getCommentForm = reactive({
  pageNum: 1,
  pageSize: 10,
  // ChildPageNum: 1,
  // ChildPageSize: 2,
  momentId: props.momentId,
});

/**
 * 获取留言列表
 */
const getCommentList = async () => {
  try {
    // 封装参数
    const res = await getCommentListApi(getCommentForm);
    total.value = res.data.total;
    commentsList.value = res.data.items;
  } catch (error) {}
};

/**
 * 显示 回复编辑框
 */
const handleReply = (rootCommentId, parentId) => {
  // 解决只在 当前点击项下 显示回复框
  showReplyIndex.value = rootCommentId;
  // 控制显示隐藏
  showReply.value = !showReply.value;

  const replyBox = document.querySelector(".reply-box-container");
  // 更新回复编辑框的属性,作为参数传给父组件
  // 这里使用到一个知识点:自定义属性
  // 因为需要实现绑定某回复框并使其含有rootCommentId和parentId,发送新增子留言请求时需要这两个参数
  replyBox.setAttribute("data-parent-comment-id", parentId);
  replyBox.setAttribute("data-root-comment-id", rootCommentId);
};

/**
 * 发布/回复 评论
 */
const handlePublish = async (comment) => {
  // 封装请求体:数据从父组件来
  const params = {
    comment: comment,
    momentId: props.postAddCommentForm.momentId,
    commentType: props.postAddCommentForm.commentType,
    rootCommentId: null,
    parentId: null,
    replyComment: "",
  };

  // 子评论 添加属性
  const replyBox = document.querySelector(".reply-box-container");
  if (replyBox) {
    // 获取根评论ID
    const rootCommentId = replyBox.getAttribute("data-root-comment-id");
    // 获取直接父评论ID
    const parentId = replyBox.getAttribute("data-parent-comment-id");

    params.rootCommentId = rootCommentId;
    params.parentId = parentId;
  }

  // 发送请求
  try {
    const res = await postAddCommentApi(params);
    ElMessage.success(res.msg);
    getCommentList();
    // 【问题】发布评论后,输入框中的值没有消失
  } catch (error) {
    console.log("🚀 ~ handlePublish ~ error:", error);
  }
};

/**
 * 分页器--当前页的数据量
 */
const handlePageSize = (pageSizeVal) => {
  getCommentForm.pageSize = pageSizeVal.pageSize;
  getCommentList();
};

/**
 * 分页器--切换页码
 */
const handlePageNum = (pageNumVal) => {
  getCommentForm.pageNum = pageNumVal.pageNum;
  getCommentList();
};
</script>

样式

<style lang="scss" scoped>
@import "@/assets/css/var.scss";

// 留言区
.comments {
  margin-top: 30px;
  margin-bottom: 100px;

  .el-card {
    width: 80%;
    margin: 20px auto;
  }

  .editbox,
  .listbox {
    margin: 0px 20px 20px 20px;
    display: flex;
  }

  // 编辑区
  .editbox {
    justify-content: space-between;
    align-items: center;
    .editbox-middle {
      width: 85%;
    }
  }

  // 列表展示区
  .listbox {
    flex-direction: column;
    border-bottom: 1px solid rgb(189, 187, 187);

    // 时间 + 回复
    .listbox-bottom {
      font-size: 12px;
      color: #9499a0;
      margin: 10px 0 10px 65px;
      display: flex;

      span {
        display: block;
        margin-right: 20px;
      }

       // 这里 color 换成普通颜色表示即可
      span:last-child:hover {
        cursor: pointer;
        color: $title-color;
      }
    }

    // 信息条
    .listbox-top-user {
      display: flex;

      // 个人信息
      p {
        margin-left: 20px;
        width: 100%;
        position: relative;

        span:first-child {
          color: $second-text;
        }
        // 身份标签
        span:last-child {
          margin-left: 5px;
          font-size: 8px;
          padding: 2px;
          background-color: $title-color;
          color: white;
          border-radius: 5px;
          position: absolute;
        }
      }
    }

    // 顶级评论
    .top-level {
      // 根评论内容
      .listbox-middle-root {
        margin-left: 65px;
      }
    }

    // 回复评论输入框
    .replybox {
      margin: 10px 0 20px 65px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      width: 60%;

      .replybox-middle {
        width: 75%;
      }
    }

    // 展示更多
    .view-more {
      margin-left: 65px;
      font-size: 12px;
      color: #9499a0;
    }

    .view-more span:hover,
    .view-less span:hover {
      cursor: pointer;
      color: $title-color;
    }

    // 展示更少
    .view-less {
      font-size: 12px;
      color: #9499a0;
      margin-left: 37px;
    }
  }
}
</style>

子组件——二级留言

模板

<!-- 二级评论 -->

<template>
  <div v-if="props.secondComments && props.secondComments.length">
    <div
      class="sub-reply-container"
      id="child-reply"
      v-for="(child, childIndex) in props.secondComments"
      :key="childIndex"
    >
      <div class="listbox-top-user">
        <el-avatar :size="30" :src="child.userImg" />
        <p>
          <span>{{ child.createdBy }}</span>
          <span>{{ child.roleName }}</span>
        </p>
      </div>
      <div class="listbox-middle-root">{{ child.comment }}</div>
      <div class="listbox-bottom">
        <span>发布时间:{{ child.createdAt }}</span>
        <!-- 回复的是二级评论 -->
        <span @click="handleReply(child.parentId, child.id)">回复</span>
      </div>
    </div>
  </div>
</template>

逻辑

<script setup>
// 接收父组件传过来的值:二级留言
const props = defineProps({
  secondComments: {
    type: Array,
    default: [],
  },
});

// 声明需要抛出的事件
const emit = defineEmits(["handle-reply"]);

const handleReply = (rootCommentId, parentId) => {
  // 【注意】这里不以对象形式包裹发送,会导致嵌套;因为父组件中回复一级评论与子级评论共用一个传值方法
  emit("handle-reply", rootCommentId, parentId);
};
</script>

样式

<style lang="scss" scoped>
@import "../../assets/css/_var.scss";

.sub-reply-container {
  margin: 20px 0 0 65px;

  .listbox-top-user {
    display: flex;

    p {
      margin-left: 10px;
      width: 100%;

      // 姓名条
      span:first-child {
        color: $second-text;
      }

      // 身份标签
      span:nth-child(2) {
        margin-left: 5px;
        font-size: 8px;
        padding: 2px;
        background-color: $title-color;
        color: white;
        border-radius: 5px;
        position: relative;
        bottom: 4px;
      }
    }
  }

  .listbox-middle-root,
  .listbox-bottom {
    margin-left: 38px;
  }

  .listbox-bottom {
    font-size: 12px;
    color: #9499a0;
    margin: 10px 0 10px 35px;
    display: flex;

    span {
      display: block;
      margin-right: 20px;
    }

    span:last-child:hover {
      cursor: pointer;
      color: $title-color;
    }
  }
}
</style>

子组件——三级留言以上

模板

<!-- 三级及以上评论 -->
<template>
  <div class="sub-reply-container" v-if="childComments && childComments.length">
    <div class="sub-reply" v-for="(child, index) in childComments" :key="index">
      <!-- 渲染内容 -->
      <div class="listbox-top-user">
        <el-avatar :size="30" :src="child.userImg" />
        <p>
          <span>{{ child.createdBy }}</span>
          <span>{{ child.roleName }}</span>
          回复
          <span>@{{ parentName }}</span>
        </p>
      </div>
      <div class="listbox-middle-root">{{ child.comment }}</div>
      <div class="listbox-bottom">
        <span>发布时间:{{ child.createdAt }}</span>
        <span @click="handleReply(child.rootCommentId, child.id)">回复</span>
      </div>

      <!-- 递归地渲染子评论的子评论:调用自己 -->
      <ChildComment
        :childComments="child.children"
        :parentName="child.createdBy"
        @to-reply="handleReply"
      />
    </div>
  </div>
</template>

逻辑

<script setup>
// 接收父组件传过来的值
const props = defineProps({
  childComments: {
    type: Array,
    default: [],
  },
  parentName: {
    type: String,
    reequire: true,
  }
});
const childComments = props.childComments;
const parentName = props.parentName;

// console.log("🚀 ~ parentName:", parentName);
// console.log("🚀 ~ childComments:", childComments);

// 声明需要抛出的事件
const emit = defineEmits(["to-reply"]);

const handleReply = (rootCommentId, parentId) => {
  // 【注意】这里不以对象形式包裹发送,会导致嵌套;父组件中回复一级评论与子级评论共用一个传值方法
  emit("to-reply", rootCommentId, parentId);
};
</script>

样式

<style lang="scss" scoped>
@import "../../assets/css/_var.scss";

.listbox-top-user {
  display: flex;

  p {
    margin-left: 10px;
    width: 100%;

    // 姓名条
    span:first-child {
      color: $second-text;
    }

    // 身份标签
    span:nth-child(2) {
      margin-left: 5px;
      font-size: 8px;
      padding: 2px;
      background-color: $title-color;
      color: white;
      border-radius: 5px;
      position: relative;
      bottom: 4px;
    }

    // 父级姓名条
    span:last-child {
      color: #0c9dd2;
    }
  }
}

.listbox-middle-root,
.listbox-bottom {
  margin-left: 38px;
}

.listbox-bottom {
  font-size: 12px;
  color: #9499a0;
  margin: 10px 0 10px 35px;
  display: flex;

  span {
    display: block;
    margin-right: 20px;
  }

  span:last-child:hover {
    cursor: pointer;
    color: $title-color;
  }
}
</style>

两个子组件没有太多额外说明,其实把父组件看懂了,子组件挺简单的,关键地方我都写了注释。有疑问可以在评论区提出,看到会回复的。

留言组件的使用

在药材详情页中使用:

  <!-- 留言区
  		使用时只需要传两个参数:评论类型、当前关联主体ID(就是谁被留言了,就传谁的ID)
   -->
  <Comment 
    :momentId="getMedicineId" 
    :postAddCommentForm="postAddCommentForm"
  />

相关代码

import { useRoute } from "vue-router";
import { reactive } from "vue";
import Comment from "@/components/front/Comment.vue";

const route = useRoute();
// 接收通过路由跳转传过来的资讯ID,默认变为字符串
const getMedicineId = Number(route.query.medicineId);

// 请求发布评论的请求体
const postAddCommentForm = reactive({
  comment: "",
  momentId: Number(getMedicineId),
  commentType: 1,
  rootCommentId: null,
  parentId: null,
  replyComment: "",
});
// 其实,这里好像可以不用封成一个对象了,单独把 commentType 传过去就行,感兴趣的同学可以试试(记得相应的把留言组件中接收的地方也改一下)

在方剂下进行留言, commentType设置为2;在资讯下进行留言, commentType设置为3;同时传入主体ID即可完成整个留言组件的调用。

以上实现均为个人思考后做出来了,代码还有欠缺,也有优化的地方,大佬路过莫喷。但是欢迎大家提出建议!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1695728.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++的类和对象

C面向对象的三大特性&#xff1a;封装&#xff0c;继承&#xff0c;多态 万事万物皆可为对象&#xff0c;有其相应的属性和行为 一、封装 1.1 封装的意义 将属性和行为作为一个整体&#xff0c;表现生活中的事物 将属性和行为加以权限控制 在设计类的时候&#xff0c;属性…

需求分析部分图形工具

描述复杂的事物时,图形远比文字叙述优越得多,它形象直观容易理解。前面已经介绍了用于建立功能模型的数据流图、用于建立数据模型的实体-联系图和用于建立行为模型的状态图,本节再简要地介绍在需求分析阶段可能用到的另外3种图形工具。 1 层次方框图 层次方框图用树形结…

开源模型应用落地-LangSmith试炼-入门初体验-数据集评估(三)

一、前言 LangSmith是一个用于构建生产级 LLM 应用程序的平台&#xff0c;它提供了调试、测试、评估和监控基于任何 LLM 框架构建的链和智能代理的功能&#xff0c;并能与LangChain无缝集成。通过使用LangSmith帮助开发者深入了解模型在不同场景下的表现&#xff0c;让开发者能…

论文阅读_管理模型的记忆_MemGPT

1 2 3 4 5 6 7 8 9英文名称: MemGPT: Towards LLMs as Operating Systems 中文名称: MemGPT&#xff1a;将LLMs打造成操作系统 链接: https://arxiv.org/abs/2310.08560 代码: https://github.com/cpacker/MemGPT 作者: Charles Packer, Sarah Wooders, Kevin Lin, Vivian Fang…

推荐10款优秀的组件库(一)

1.Ant Desgin UI 网址&#xff1a; https://ant-design-mobile.antgroup.com/zh Ant Design - 一套企业级 UI 设计语言和 React 组件库 "Ant Design Mobile"是一个在线的移动端Web体验平台&#xff0c;让你探索移动端Web的体验极限。 添加图片注释&#xff0c;不…

安全设计 | 安全设计不得马虎!微软STRIDE威胁建模方法让你事半功倍,快速发现应用安全隐患!

STRIDE威胁建模方法最早发表于2006年11月的《MSDN杂志》&#xff0c;作者是微软的工程师Shawn Hernan、Scott Lambert 、Tomasz Ostwald 和 Adam Shostack。那我们为什么要进行威胁建模&#xff1f; 如何使用数据流图对系统进行威胁建模&#xff1f;如何减轻威胁&#xff1f;接…

STM32F1之OV7725摄像头

目录 1. 摄像头简介 2. OV7725 摄像头简介 3. OV7725 引脚 4. OV7725 功能框架图 5. SCCB时序 5.1 SCCB 的起始、停止信号及数据有效性 5.2 SCCB 数据读写过程 1. 摄像头简介 在各类信息中&#xff0c;图像含有最丰富的信息&#xff0c;作为机…

从0开始学统计-蒙彼利埃尔悖论与条件概率

1.什么叫均衡可比&#xff1f; "均衡可比"指的是在进行比较时&#xff0c;确保所比较的对象或情况具有相似的特征和条件&#xff0c;以保持比较的公正性和准确性。这个概念通常应用于研究设计和数据分析中&#xff0c;以确保比较结果的可信度和有效性。 在研究中&a…

HTML静态网页成品作业(HTML+CSS)——企业酒店官网网页(5个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有5个页面。 二、作品演示 三、代…

SpringCloud系列(26)--OpenFeign超时控制

前言&#xff1a;在上一章节中我们简单的介绍了如何使用OprnFeign去调用微服务&#xff0c;因为消费侧和服务侧是两个不同的微服务&#xff0c;这样可能会出现超时的现象&#xff0c;例如服务侧需要3秒处理任何才能返回结果&#xff0c;但消费侧可能2秒就断开连接了&#xff0c…

C++代码错误解决1(函数模板)

1、代码如下 //示例函数模板的使用 #include <iostream> #include <string> using namespace std; template <typename T>//函数模板 T max(T a,T b) {return a>b?a:b; } int main() {int a,b;cout<<"input two integers to a&b:"…

文章解读与仿真程序复现思路——电力系统保护与控制EI\CSCD\北大核心《计及温控厌氧发酵和阶梯碳交易的农村综合能源低碳经济调度》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

如何处理时间序列的缺失数据

您是否应该删除、插入或估算&#xff1f; 世界上没有完美的数据集。每个数据科学家在数据探索过程中都会有这样的感觉&#xff1a; df.info()看到类似这样的内容&#xff1a; 大多数 ML 模型无法处理 NaN 或空值&#xff0c;因此如果您的特征或目标包含这些值&#xff0c;则在…

自己手写一个单向链表【C风格】

//单链表 #include <iostream> #define MAX_SIZE 20 #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0typedef int ElemType;//元素的类型 typedef int Status;//返回状态typedef struct Node {ElemType data;//链表中保存的数据struct Node* next;//指向下…

【字典树(前缀树) 异或 离线查询】1707. 与数组中元素的最大异或值

本文涉及知识点 字典树&#xff08;前缀树&#xff09; 位运算 异或 离线查询 LeetCode1707. 与数组中元素的最大异或值 给你一个由非负整数组成的数组 nums 。另有一个查询数组 queries &#xff0c;其中 queries[i] [xi, mi] 。 第 i 个查询的答案是 xi 和任何 nums 数组…

自定义一个复杂的React Table表格组件-06

前面基本了解了组件的基本用法&#xff0c;在本节会实现一个更高级的例子。另外需要注意本节代码是采用V15版本的createClass()、React.DOM和JSX实现的&#xff0c;有时间的同学可以改成类实现的方式。 html的世界中最复杂的UI控制就是表格了&#xff0c;原因是table它依赖本地…

Vitis HLS 学习笔记--控制驱动TLP-处理deadlock

目录 1. 简介 2. 代码解析 2.1 HLS kernel代码 2.2 查看接口报告 2.3 TestBench 2.4 Dataflow 报告 3. Takeaways 4. 总结 1. 简介 本文是对《Hardware Acceleration Tutorials: FIFO Sizing for Performance and Avoiding Deadlocks》实验内容的详细解释。 首先需要…

AI视频教程下载:用提示工程在GPT商店构建10个GPTs

你将学到什么&#xff1f; 深入了解ChatGPT平台和GPT商店的生态系统。 开发为多样化应用定制GPT模型的专业知识。 掌握高效内容生成的AI自动化技术。 学习高级提示工程以优化ChatGPT输出。 获取构建AI驱动的数字营销和广告解决方案的技能。 了解如何为SEO写作和优化创建专…

从0开始学统计-多个婴儿连续夭折是谋杀吗?

1.什么是小概率事件&#xff1f; 小概率事件是指在一次随机试验中发生概率非常低的事件。一般来说&#xff0c;小概率事件的发生概率远低于一定的阈值&#xff0c;通常取0.05或0.01。在统计学中&#xff0c;这些阈值被称为显著性水平&#xff08;significance level&#xff0…

CIC滤波器

CIC滤波器结构简单&#xff0c;没有乘法器&#xff0c;只有加法器、积分器和寄存器&#xff0c;适合工作在高抽样率条件下&#xff0c;而且CIC滤波器是一种基于零点相消的FIR滤波器。 CIC滤波器分为单级和多级滤波器。 1.在单极滤波器中&#xff1a; 当CIC滤波器的长度M远大于…