Vue3 进阶教程:一文详解 el-table 组件的二次封装技巧!

news2024/12/24 20:25:38

开发后台管理系统,在业务上接触的最多就是表单(输入)和表格(输出)了。对于使用 Vue 框架进行开发的同学来说,组件库 Element 是肯定会接触的,而其中的 el-table 和 el-form 更是管理系统中的常客。

然而,一旦项目的表格或表单多起来,每个不同的配置,以及多一个字段少一个字段,都要在 template 中重新写一大段组件代码,显得非常麻烦。或许你会考虑将这些代码封装起来,可是又会发现,封装的表格、表单大多数只在一处地方使用,还不如不封装呢。到底要如何封装,可以让每处使用 el-table 或 el-form, 都可以复用相同的组件,减少代码量的同时又具备高度的可定制性?

本文章将会按照从无到有的步骤,按照封装组件常用的思路来封装 el-table,并且实现封装完成的组件支持 el-table 的全配置。在封装的过程中,你将会看到:

  • 如何抽取组件。
  • 巧用属性透传。
  • v-html、component 组件、h 函数、动态组件的应用。
  • 具名插槽、作用域插槽。
  • v-bind 的妙用。
  • 实现插槽透传的方法。

一般的组件封装思路

以下是 el-table 在项目中常用的写法:el-table 接受一个数组 data 作为数据,在 el-table 元素中插入多个 el-table-column 组件,用于定义列的名称(label),数据来源(prop),以及其它列的定制配置(width 等)。在实际项目中,往往不止几行 column,甚至三四十行都有可能(不过一般超过十行,最好考虑把次要的信息放在详情中展示,而不是全部列在表格上,除非是业务需要在表格上浏览所有数据),而且每个 column 都可能会有不同的配置,比如排序、fix、不同宽度、插入增删改按钮等,这就使得一个表格的代码会变得又长又复杂,如果还要写其它业务功能,会大大地降低模板代码的可读性。

<template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="a" label="aName" width="180" /> <el-table-column prop="b" label="bName" width="180" /> <el-table-column prop="c" label="cName" width="180" /> <el-table-column prop="d" label="dName" width="180" /> <el-table-column prop="e" label="eName" width="180" /> <el-table-column prop="f" label="fName" width="180" /> <el-table-column prop="g" label="gName" width="180" /> <el-table-column prop="h" label="hName" width="180" /> <el-table-column prop="i" label="iName" width="180" /> </el-table> </template> <script lang="ts" setup> const tableData = new Array(9).fill({ a: "2016-05-03", b: "Tom", c: "No. 189, Grove St, Los Angeles", d: "No. 189, Grove St, Los Angeles", e: "2016-05-03", f: "Tom", g: "No. 189, Grove St, Los Angeles", h: "2016-05-03", i: "Tom", }); </script>
Copy

当然,这种情况,一般都会将它抽取为组件:

// CustomTable.vue <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="a" label="aName" width="180" /> <el-table-column prop="b" label="bName" width="180" /> <el-table-column prop="c" label="cName" width="180" /> <el-table-column prop="d" label="dName" width="180" /> <el-table-column prop="e" label="eName" width="180" /> <el-table-column prop="f" label="fName" width="180" /> <el-table-column prop="g" label="gName" width="180" /> <el-table-column prop="h" label="hName" width="180" /> <el-table-column prop="i" label="iName" width="180" /> </el-table> </template> <script lang="ts" setup> defineProps<{ tableData: Array<any>; }>(); </script>
Copy

然后在页面中使用:

// App.vue <template> <CustomTable :tableData="tableData"></CustomTable> </template> <script lang="ts" setup> import CustomTable from "./CustomTable.vue"; const tableData = new Array(9).fill({ a: "2016-05-03", b: "Tom", c: "No. 189, Grove St, Los Angeles", d: "No. 189, Grove St, Los Angeles", e: "2016-05-03", f: "Tom", g: "No. 189, Grove St, Los Angeles", h: "2016-05-03", i: "Tom", }); </script>
Copy

一般封装的过程到这里就结束了。可见,这种封装既将表格从页面中抽取出来方便单独维护,又提高了页面代码的可读性。然而,这种封装方式并没有解决开篇提到的书写重复代码的问题,而且还比没有封装多了一些操作,其实仍然是一种“体力活”。

封装表格数据Api

为了后面演示方便,先将表格数据的 api 封装起来。

// src/api/index.ts export function getData() { return new Promise((resolve) => { setTimeout(() => { resolve({ data: new Array(9).fill({ a: "2016-05-03", b: "Tom", c: "No. 189, Grove St, Los Angeles", d: "No. 189, Grove St, Los Angeles", e: "2016-05-03", f: "Tom", g: "No. 189, Grove St, Los Angeles", h: "2016-05-03", i: "Tom", }), }); }, 200); }); }
Copy

同时,组件的位置也改为 src/components/custom-table/index.vue

// App.vue <template> <CustomTable :tableData="tableData"></CustomTable> </template> <script lang="ts" setup> import CustomTable from "./components/custom-table/index.vue"; import { getData } from "./api/index"; import { onMounted, ref } from "vue"; const tableData = ref<any>([]); onMounted(() => { getData().then((res: any) => { tableData.value = res.data; }); }); </script>
Copy

v-for 复用 el-table-column

先回到最初的代码,来解决 el-table-column 复用的问题。首先暂时不考虑 el-table-column 定制化属性的需求,先把下面的代码量减少,如何实现?很简单,使用 v-for:

// src\components\custom-table\index.vue <template> <el-table :data="tableData" style="width: 100%"> <el-table-column v-for="column in tableHeaders" :key="column" :prop="column" :label="column + 'Name'" width="180" ></el-table-column> </el-table> </template> <script lang="ts" setup> import { computed } from "vue"; const prop = defineProps<{ tableData: Array<any>; }>(); const tableHeaders = computed(() => Object.keys(prop.tableData[0] || {})); </script>
Copy

这里,我们使用数据的 key 作为列名,数据有多少个字段,就可以显示多少列,当数据的列数发生改变时,还不需要修改任何代码。

自定义列名和列的属性

自定义列名

然而,数据的 key 作为列名的情况很少(至少在我们这里,一般是使用中文作为列名的),这就需要我们使用可定制的列名,并且,如果我们不想展示某些字段,上面的写法也是做不到的(它会显示数据的所有字段)。

这时候,我们只需要一个映射(mapper)就可以解决这些问题。该对象的每一个属性对应每一列的 prop、key,值对应列的列名 label。

// App.vue // 定义新的Header结构,key为column的prop/key,value为column的label const tableHeaderMapper = { a: "列a", b: "列b", c: "列c", d: "列d", e: "列e", f: "列f", g: "列g", h: "列h", i: "列i", };
Copy

遍历并绑定:

// src\components\custom-table\index.vue <template> <el-table :data="tableData" style="width: 100%"> <el-table-column v-for="(value, key) in tableHeaders" :key="key" :prop="key" :label="value" ></el-table-column> </el-table> </template> <script lang="ts" setup> export type Mapper<T> = { [P in keyof T as string]?: string; }; defineProps<{ tableData: Array<any>; tableHeaders: Mapper<any>; }>(); </script>
Copy

使用:

<CustomTable :tableData="tableData" :table-headers="tableHeaderMapper"></CustomTable>
Copy

v-bind 绑定所有属性

在 Vue 中,可以使用 v-bind 直接绑定对象,简化很多代码:

<el-table-column :key="key" :prop="key" :label="value" ></el-table-column>
Copy

等同:

<el-table-column v-bind="{key:key,prop:key,label:value}" ></el-table-column>
Copy

所以,我们其实可以这样定义 tableHeaders!

const tableHeaderMapper = { a: { label: "列a", key: "a", prop: "a" }, ... };
Copy

改写组件代码:

// src\components\custom-table\index.vue // v-bind 直接绑定一个对象 <template> <el-table :data="tableData" style="width: 100%"> <el-table-column v-for="column in tableHeaders" v-bind="column" ></el-table-column> </el-table> </template> <script lang="ts" setup> export type Mapper<T> = { [P in keyof T as string]?: object; // 从string类型改为object类型 }; defineProps<{ tableData: Array<any>; tableHeaders: Mapper<any>; }>(); </script>
Copy

如果觉得重复写 key、prop 太冗余,又或者想兼容之前自定义列名的写法,可以在自定义组件中对 tableHeaders 进行处理,生成 newTableHeaders。

// src\components\custom-table\index.vue <template> <el-table :data="tableData" style="width: 100%"> <el-table-column v-for="column in newTableHeader" v-bind="column" ></el-table-column> </el-table> </template> <script lang="ts" setup> import { ref, onMounted, onBeforeUpdate } from "vue"; export type Mapper<T> = { [P in keyof T as string]?: string | object; }; const prop = defineProps<{ tableData: Array<any>; tableHeaders: Mapper<any>; }>(); const newTableHeader = ref<any>({}); const genNewTableHeader = () => { newTableHeader.value = { ...prop.tableHeaders }; const rawAttr = prop.tableHeaders; for (let key in rawAttr) { let column = rawAttr[key]; if (typeof column === "string") { Reflect.set(newTableHeader.value, key, { key: key, prop: key, label: column, }); } // 其实此时一定是对象了,此处判断是用于ts类型收窄 if (typeof column === "object") { // 设置默认的key if (!Reflect.has(column, "key")) { Reflect.set(column, "key", key); } if (!Reflect.has(column, "label")) { Reflect.set(column, "label", key); } // 设置默认的prop,如果该列是多选项,则不需要prop if ( !Reflect.has(column, "prop") && !( Reflect.has(column, "type") && Reflect.get(column, "type") == "selection" ) ) { Reflect.set(column, "prop", key); } } } console.log(newTableHeader.value); }; onMounted(genNewTableHeader); onBeforeUpdate(genNewTableHeader); </script>
Copy

使用:

// App.vue const tableHeaderMapper = { a: { label: "列a", width: "200", }, b: "列b", c: "列c", d: "列d", e: "列e", f: "列f", g: "列g", h: "列h", i: "列i", };
Copy

到这里,对 el-tabl 的封装已经相对完善了,我们不需要书写复杂的 el-table-column,只需传入 tableData 和 tableHeaders,就可以自由定制我们的表格列了。

表格透传

我们解决了表格列属性问题,现在,如果我们还想要表格属性和表格列属性一样可以自由传入,如何实现?

属性、样式、事件透传

Vue 天然支持属性、样式、事件透传,我们直接在 CustomeTable 上书写我们想要的 el-table 属性或事件即可!

// App.vue <template> <CustomTable :tableData="tableData" :table-headers="tableHeaderMapper" v-loading="loading" ></CustomTable> </template> <script lang="ts" setup> ... const loading = ref(false); onMounted(() => { loading.value = true; getData().then((res: any) => { tableData.value = res.data; loading.value = false; }); }); </script>
Copy

插槽透传

仔细观察 el-table 属性,发现它还支持三个插槽:默认插槽、append、empty。我们的 CustomTable 也要支持!

先回顾以下我们的 CustomTable。在 custom-table/index. vue 中,我们并没有书写 slot 标签,所以在 App. vue 中往 CustomTable 插入标签是不会被渲染的,所以我们需要给 CustomTable 添加 slot 插槽,要添加什么样的插槽呢?和 el-table 提供同名的插槽,并在 custom-table/index. vue 中的 el-table 中插入。即,CustomTable 提供插槽,App. vue 写入插槽,CustomTable 读取到插槽,并把插槽的内容写入 el-table 中。插槽的内容是这样传递的:App. vue -> CustomTable -> el-table。

在 CustomTable 中开始写插槽前,会发现,我们已经使用了 el-table 的插槽,将我们 v-for 生成的 column 插入到 el-table 的默认插槽中了。这个时候,我们需要改变我们的写法:将 column 的生成也拆分为组件!然后传入给 CustomTable,而 CustomTable 的职责则变为:只负责从 App. vue 传递插槽给 el-table。符合单一职责的封装原则!

// 新的CustomTable,只负责传递插槽 <template> <el-table :data="tableData" style="width: 100%"> <slot></slot> </el-table> </template> <script lang="ts" setup> defineProps<{ tableData: Array<any>; }>(); </script>
Copy

新建 src/components/custom-column/index. vue,修改少许代码。

// 抽取为CustomColumn <template> <el-table-column v-for="column in newTableHeader" v-bind="column" ></el-table-column> </template> <script lang="ts" setup> import { ref, onMounted, onBeforeUpdate } from "vue"; export type Mapper<T> = { [P in keyof T as string]?: string | object; }; const prop = defineProps<{ tableHeaders: Mapper<any>; }>(); const newTableHeader = ref<any>({}); const genNewTableHeader = () => { newTableHeader.value = { ...prop.tableHeaders }; const rawAttr = prop.tableHeaders; for (let key in rawAttr) { let column = rawAttr[key]; if (typeof column === "string") { Reflect.set(newTableHeader.value, key, { key: key, prop: key, label: column, }); } // 其实此时一定是对象了,此处判断是用于ts类型收窄 if (typeof column === "object") { // 设置默认的key if (!Reflect.has(column, "key")) { Reflect.set(column, "key", key); } if (!Reflect.has(column, "label")) { Reflect.set(column, "label", key); } // 设置默认的prop,如果该列是多选项,则不需要prop if ( !Reflect.has(column, "prop") && !( Reflect.has(column, "type") && Reflect.get(column, "type") == "selection" ) ) { Reflect.set(column, "prop", key); } } } console.log(newTableHeader.value); }; onMounted(genNewTableHeader); onBeforeUpdate(genNewTableHeader); </script>
Copy

使用:

// App.vue <template> <CustomTable :tableData="tableData" v-loading="loading"> <CustomColumn :table-headers="tableHeaderMapper"></CustomColumn> </CustomTable> </template> <script lang="ts" setup> import CustomColumn from "./components/custom-column/index.vue"; ...
Copy

上面我们只是支持传递默认插槽,现在我们让 CustomTable 将所有插槽原封不动传给 el-table,实现“插槽透传“!

// src\components\custom-table\index.vue <template> <el-table :data="tableData" style="width: 100%"> <template v-for="slot in Object.keys($slots)" #[slot]> <slot :name="slot"></slot> </template> </el-table> </template> <script setup lang="ts"> defineProps<{ tableData: Array<any>; }>(); </script>
Copy

Vue 中并没有实现插槽透传的方法,我们做的其实是插槽传递,而非透传,但对于组件的使用者来说,这种传递方法看起来和透传无异!

到了这一步,我们的 CustomTable 的基础功能就算封装完成啦!支持 el-tabled 的所有属性和插槽。如有需要,可以在 CustomTable 的基础上进行修改,设计出我们自己的专属 Table!

在列中插入子元素

表格列中重要的一个内容,就是插入各种按钮(增删改)、图片、进度条以及其它元素,来实现表格的可操作性、数据可视化。在 el-table-column 中,我们想插入元素,直接使用插槽即可。然而,这里并不能完全照搬表格的插槽传递的方法,因为你很快就会发现,CustomColumn 只有一个,而 el-table-column 却有很多个,我怎么知道插入 CustomColumn 的插槽是属于哪个 el-table-column 的!

非插槽写法 v-html

如何在不同的 column 插入元素?很快我们就会想起我们是如何在不同 column 中定义不同的列名,对,tableHeaders!我们可以给 tableHeaders 定义一个属性,只要写到这个属性中,就插入到对应的列的位置上!我们暂且称这个属性为 inner。

const tableHeaderMapper = { a: { label: "列a", width: "200", inner: xxx },
Copy

接下来就是如何读取 inner 并插入了,我们很容易就想起 v-html:

// CustomColumn <template> <el-table-column v-for="column in newTableHeader" v-bind="column"> <div v-if="column.inner" v-html="column.inner"></div> </el-table-column> </template>
Copy

inner 的值为字符串:

const tableHeaderMapper = { a: { label: "列a", inner: "<h1>hello</h1>", },
Copy

在字符串中写 html,显然不是很方便,而一说到字符串中写 html,我们自然而然就会想到 jsx!那么这里我们能否接受 jsx 呢?显然不能,但是可以接受一个返回组件的函数吗?可以一试!

const tableHeaderMapper = { a: { label: "列a", inner: h('h1','function component!'), },
Copy

直接运行,可以看到对应列显示:


其实就是输出一个组件对象。如何应用这个对象?不妨试试 component。

// CustomColumn <template> <el-table-column v-for="column in newTableHeader" v-bind="column"> <div v-if="typeof column.inner == 'string'" v-html="column.inner"></div> <component v-else :is="column.inner"></component> </el-table-column> </template>
Copy

浏览页面:

好极了。

既然支持 h 渲染函数,能否支持导入的组件?

const tableHeaderMapper = { a: { label: "列a", width: "200", inner: CustomButton,
Copy

component 也是支持的:

插槽写法

如何在 CustomColumn 的插槽中区分不同的插槽?其实也很简单,规定一个格式,使用不同的后缀即可。比如,a 列的插槽为 default-a,b 列的插槽为 default-b。我们可以使用 useSlots 读取传入 CustomColumn 中的所有插槽,并使用正则进行匹配。

const slots = useSlots(); const slotKeys = Object.keys(slots); for(let key of keys){ const res = key.match(/^(\S+)-(\S+)/); console.log(res); }
Copy

假设传入:

<CustomColumn :table-header="tableHeaderMapper"> <template #default-a> I am slot of a </template> </CustomColumn>
Copy

输出:

const slots = useSlots() // { 'default-a': V_node } const slotKeys = Object.keys(slots); // ['default-a'] for(let key of keys){ const res = key.match(/^(\S+)-(\S+)/); console.log(res); // ['default-a','default','a'] }
Copy

根据 res 的值,我们可以很快确定插槽是属于哪一列的、哪一种类型的插槽。

插槽能够区分和读取了,接下来如何插入?

试想一下我们之前是如何插入列的 inner 属性的,很快就有思路了。

// CustomColumn <template> <el-table-column v-for="column in newTableHeader" v-bind="column"> <template v-for="(value, key) in column.slot" #[key]> <slot :name="value"> <div v-if="column.inner && String(key) == 'default'"> <div v-if="typeof column.inner == 'string'" v-html="column.inner" ></div> <component v-else :is="column.inner"></component> </div> </slot> </template> <!-- <div v-if="typeof column.inner == 'string'" v-html="column.inner"></div> --> <!-- <component v-else :is="column.inner"></component> --> </el-table-column> </template> <script lang="ts" setup> import { ref, onMounted, onBeforeUpdate, useSlots } from "vue"; ... const slots = useSlots(); const newTableHeader = ref<any>({}); const genNewTableHeader = () => { newTableHeader.value = { ...prop.tableHeaders }; const rawAttr = prop.tableHeaders; for (let key in rawAttr) { ... if (typeof column === "object") { // 设置默认的key ... // 设置默认的prop,如果该列是多选项,则不需要prop ... // 处理插槽 const slotKeys = Object.keys(slots); for (let key of slotKeys) { const res = key.match(/^(\S+)-(\S+)/); // 查找不到则res为null if (res && res[2] == Reflect.get(column, "key")) { if (!Reflect.has(column, "slot")) { Reflect.set(column, "slot", {}); } Reflect.set(Reflect.get(column, "slot"), res[1], res[0]); } } } } console.log(newTableHeader.value); }; ... </script>
Copy

这里我们预先处理 slots,和 inner 属性类似,在渲染 column 时,如果有 inner 就渲染 inner。我们在 column 对象(column 对象位于 newTableHeaders 上)上绑定了一个 slot 属性,在渲染 column 时,如果有 slot 就渲染 slot。

兼容 inner 和 slot:因为 inner 也是渲染在 default 上,所以上面的代码需要将 inner 注释掉,以免冲突。这里我选择在 slot 存在的情况下,忽略 inner(你也可以选择其它处理方式,比如二者存在时,都渲染出来,或者存在 inner,就忽略slot)。

// CustomColumn <template> <el-table-column v-for="column in newTableHeader" v-bind="column"> <template v-for="(value, key) in column.slot" #[key]> <slot :name="value"> <div v-if="column.inner && String(key) == 'default'"> <div v-if="typeof column.inner == 'string'" v-html="column.inner" ></div> <component v-else :is="column.inner"></component> </div> </slot> </template> <template v-if="!column.slot" #default> <div v-if="column.inner"> <div v-if="typeof column.inner == 'string'" v-html="column.inner"></div> <component v-else :is="column.inner"></component> </div> </template> </el-table-column> </template>
Copy

插槽作用域

在点击按钮时(修改列、删除列),我们需要得到点击对应列的信息,该信息是通过插槽作用域实现的。

// CustomColumn <template> <el-table-column v-for="column in newTableHeader" v-bind="column"> <template v-for="(value, key) in column.slot" #[key]="scope"> <slot :name="value" v-bind="scope"> <div v-if="column.inner && String(key) == 'default'"> <div v-if="typeof column.inner == 'string'" v-html="column.inner" ></div> <component v-else :is="column.inner"></component> </div> </slot> </template> <template v-if="!column.slot" #default> <div v-if="column.inner"> <div v-if="typeof column.inner == 'string'" v-html="column.inner"></div> <component v-else :is="column.inner"></component> </div> </template> </el-table-column> </template>
Copy

这里使用 template 的 #插槽 =“xxx”读取了 el-table-column 提供的列信息并保存 xxx 为 scope,然后又使用 v-bind 将 scope 通过 slot 的属性传递给 CustomColumn 的使用者。

// App.vue 使用scope可以读取对应的列的信息 <template> <CustomTable :tableData="tableData" v-loading="loading"> <template #empty>暂无数据</template> <CustomColumn :table-headers="tableHeaderMapper"> // 使用scope.$index读取该列在表格中的索引 <template #default-a="scope"> I am slot of a {{ scope.$index }}</template> </CustomColumn> </CustomTable> </template>
Copy

关于 scope 对象的取值可以查阅 Element 的文档(Table 表格 | Element Plus)

总结

本文章通过通俗易懂、循序渐进的方法,介绍了如何对 el-table 进行基础性的二次封装,让我们使用表格的代码量减到最少的同时,又具备极高的可定制性和可维护性。同时,又在封装的过程中掌握了 v-for、v-if、v-else、v-html、v-slot 等内置指令的用法、属性透传和插槽的概念。

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

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

相关文章

华为云征文|华为云Flexus X实例docker部署srs6并调优,协议使用webrtc与rtmp

华为云征文&#xff5c;华为云Flexus X实例docker部署srs6并调优&#xff0c;协议使用webrtc与rtmp 什么是华为云Flexus X实例 华为云Flexus X实例云服务是新一代开箱即用、体验跃级、面向中小企业和开发者打造的高品价比云服务产品。Flexus云服务器X实例是新一代面向中小企业…

MES系统如何实现产品追溯功能

MES系统&#xff08;Manufacturing Execution System&#xff0c;制造执行系统&#xff09;的产品追溯功能是现代制造业中不可或缺的一部分&#xff0c;它通过记录和分析生产过程中产生的数据&#xff0c;实现了对产品、原材料、设备等信息的追踪和溯源。以下是对MES系统产品追…

网络安全的历史

如今&#xff0c;网络安全几乎成为各大公司和利益相关者关注的焦点。但在早期&#xff0c;网络安全的概念非常模糊。 直到多年以后&#xff0c;由于网络攻击和危险实体威胁的频繁发生&#xff0c;网络安全的发展才受到重视。这些措施的发展成为了网络安全的演变。 网络安全起…

基于django框架下个人着装助理系统/基于python的服装服装搭配系统

摘要 随着科学技术的发展和人们生活质量的改善&#xff0c;人们对于着装的要求也会越来越高。为了能够更好的管理着装&#xff0c;个人着装助理系统被开发处理方便人们对着装的管理。 本个人着装助理系统采用编程语言Python&#xff0c;开源框架Django实现系统的架构&#xff…

分类任务实现模型集成代码模版

分类任务实现模型&#xff08;投票式&#xff09;集成代码模版 简介 本实验使用上一博客的深度学习分类模型训练代码模板-CSDN博客&#xff0c;自定义投票式集成&#xff0c;手动实现模型集成&#xff08;投票法&#xff09;的代码。最后通过tensorboard进行可视化&#xff0…

Java之初始泛型

1 包装类 在Java中&#xff0c;由于基本类型不是继承自Object&#xff0c;为了在泛型代码中可以支持基本类型&#xff0c;Java给每个基本类型都对应了一个包装类型。 1.1 基本数据类型和对应的包装类 基本数据类型包装类byteByteshortShortintIntegerlongLongfloatFloatdoub…

RAG最佳实践:用 ElasticSearch 打造AI搜索系统与RAG 应用全流程详解!

前面一篇文章《RAG 向量数据库:掌握 Elasticsearch 作为向量数据库的终极指南》中,介绍了使用ElasticSerach作为向量数据的安装和使用指南。 今天这篇文章将介绍如何使用 Elasticsearch 搭建AI搜索系统和RAG应用系统。 Elasticsearch 搭建 AI 搜索系统 在 Elasticsearch 中…

游泳耳机哪个牌子的好?四大口碑精品游泳耳机专业推荐!

在追求健康生活的同时&#xff0c;游泳成为了许多人选择的锻炼方式。它不仅能够帮助人们塑造身材&#xff0c;还能有效缓解压力。而在游泳过程中&#xff0c;音乐的陪伴无疑能让人更加享受这段时光。因此&#xff0c;一款适合游泳时使用的耳机&#xff0c;成为了游泳爱好者们不…

java程序CUP持续飙高

1.top 2.定位进程中使用CPU最高的线程 top -Hp 70688 3.将线程ID转为十六进制 printf "0x%x\n" 28760 4.jstack工具跟踪堆栈定位代码 jstack 70688 | grep 0x7058 -A 10

尺度和位置敏感的红外小目标检测

Infrared Small Target Detection with Scale and Location Sensitivity 在本文中&#xff0c;着重于以更有效的损失和更简单的模型结构来提升检测性能。 问题一 红外小目标检测&#xff08;IRSTD&#xff09;一直由基于深度学习的方法主导。然而&#xff0c;这些方法主要集中…

python-春游

[题目描述] 老师带领同学们春游。已知班上有 N 位同学&#xff0c;每位同学有从 0 到 N−1 的唯一编号。到了集合时间&#xff0c;老师确认是否所有同学都到达了集合地点&#xff0c;就让同学们报出自己的编号。到达的同学都会报出自己的编号&#xff0c;不会报出别人的编号&am…

单链表应用

基于单链表实现通讯录项目 //Contact.c #define _CRT_SECURE_NO_WARNINGS 1 #include"contact.h" #include"list.h"//初始化通讯录 void InitContact(contact** con) {con NULL;} //添加通讯录数据 void AddContact(contact** con) {PeoInfo info;printf…

无主灯设计:吊顶之问与光影艺术的探索

在现代家居设计中&#xff0c;照明不仅仅是为了满足基本的照明需求&#xff0c;更是一种艺术和情感的表达。随着无主灯设计越来越受到人们的青睐&#xff0c;许多业主开始考虑一个问题&#xff1a;进行无主灯设计时&#xff0c;是否一定需要吊顶呢&#xff1f;本文将深入探讨这…

2017年系统架构师案例分析试题五

目录 案例 【题目】 【问题 1】(5 分) 【问题 2】(16 分) 【问题 3】(4 分) 【答案】 【问题 1】解析 【问题 2】解析 【问题 3】答案 相关推荐 案例 阅读以下关于 Web 系统架构设计的叙述&#xff0c;在答题纸上回答问题 1 至问题 3。 【题目】 某电子商务企业因发…

小波神经网络的时间序列的短时交通流量预测

小波神经网络的时间序列的短时交通流量预测 通过小波分析进行负荷序列分 解, 获得不同频率负荷分量规律 ; 由粒子群算法进行粒子群适应度排序 , 提升算法收敛速度和收敛能力 ; 为避免算法陷入局部 收敛性, 引入混沌理论来增强全局搜索能力 。 预测结果

linux 系统如何进行nfs(第五节)

网上的截图&#xff1a; 自己的操作&#xff1a; 首先是 在虚拟机中的操作。 然后是在开发板上的操作。 已经是没有问题了。

AI绘画【Stable Diffusion】抽卡必备!时间管理大师Agent Scheduler插件,一键设置任务,让你的休息时间充分利用起来!

大家好&#xff0c;我是灵魂画师向阳 相信大家在玩 Stable Diffusion 的时候一直有一个痛点&#xff0c;每次出图抽卡时都只能等待上一次抽卡结束&#xff0c;才能继续下一次抽卡&#xff1b; 特别是当我们想抽大量的卡来测试不同的模型&#xff0c;不同的参数的效果时&#…

大学生社团管理系统

一、项目概述 Hi&#xff0c;大家好&#xff0c;今天分享的项目是《大学生社团管理系统》。 随着校园文化的不断丰富&#xff0c;大学里各种社团越来越多&#xff0c;社团活动也越来越频繁&#xff0c;社团管理就显得繁琐&#xff0c;传统的人工管理方式比较麻烦&#xff0c;…

Client客户端模块

一.Client模块介绍 二.Client具体实现 1.消费者/订阅者模块 2.信道管理模块 3.异步线程模块 4.连接管理模块 这个模块同样是针对muduo库客户端连接的二次封装&#xff0c;向用户提供创建channel信道的接口&#xff0c;创建信道后&#xff0c;可以通过信道来获取指定服务。 三…