当前位置: 首页 > article >正文

vue 组件函数式调用实战:以身份验证弹窗为例

通常我们在 Vue 中使用组件,是像这样在模板中写标签:

<MyComponent :prop="value" @event="handleEvent" />

而函数式调用,则是让我们像调用一个普通 JavaScript 函数一样来使用这个组件,例如:

MyComponentFunction({ prop: value }).then(result => { /* ... */ })

接下来我们就用一个实际的例子来看看这种函数式调用的写法是怎么写的。

我们来实现一个非常通用的功能,在系统中,如果某些操作需要进行身份验证才能进行下一步,我们就需要实现一个身份验证的弹框,只有验证了用户的账号密码的情况下,才能执行接下来的逻辑。

以下是这个AuthBox组件的部分,这里无需多言。

// src/components/AuthBox/src/AuthBox.vue
<template><el-dialogtitle="身份验证"v-model="state.dialogVisible"width="360px":custom-class="customClass"centeralign-centerdestroy-on-close:show-close="false":close-on-click-modal="false"@opened="handleOpened"@closed="handleClosed"><el-form ref="formRef" :model="state.formData" :rules="formRules" label-width="70px" :validate-on-rule-change="false"><el-form-item label="账号" prop="username"><el-inputref="usernameRef"v-model="state.formData.username"placeholder="请输入账号"@keyup.enter="handlePasswordFocus"/></el-form-item><el-form-item label="密码" prop="password"><el-inputref="passwordRef"v-model="state.formData.password"type="password"placeholder="请输入密码"@keyup.enter="handleConfirm"/></el-form-item></el-form><template #footer><div class="text-center"><el-button @click="handleCancel">取消</el-button><el-button type="primary" @click="handleConfirm">确认</el-button></div></template></el-dialog>
</template><script lang="ts" setup>
import { ref, reactive, nextTick, onMounted } from "vue";
import { ElDialog, ElForm, ElFormItem, ElInput, ElButton, ElMessage } from "element-plus";
import { AuthBoxState } from "./type";// 定义组件属性
const props = defineProps({// 自定义类名customClass: {type: String,default: ""},// 提示文本message: {type: String,default: ""}
});// 定义事件
const emits = defineEmits(["confirm", "cancel", "close", "vanish"]);// 组件状态
const state = reactive<AuthBoxState>({dialogVisible: false,formData: {username: "",password: ""}
});// 表单校验规则
const formRules = {username: [{ required: true, message: "请输入账号", trigger: "blur" }],password: [{ required: true, message: "请输入密码", trigger: "blur" }]
};// 表单引用
const formRef = ref();
const usernameRef = ref();
const passwordRef = ref();// 聚焦密码输入框
const handlePasswordFocus = () => {passwordRef.value.focus();
};// 确认按钮处理
const handleConfirm = () => {formRef.value.validate((valid: boolean) => {if (valid) {// 在实际应用中,这里可能会调用API进行验证// 这里我们简化为直接模拟验证通过// 触发confirm事件,传递表单数据emits("confirm", {username: state.formData.username,password: state.formData.password});// 关闭对话框state.dialogVisible = false;}});
};// 取消按钮处理
const handleCancel = () => {emits("cancel");state.dialogVisible = false;
};// 对话框打开后处理
const handleOpened = () => {// 对话框完全打开后才设置焦点,确保元素已渲染完成并可见usernameRef.value?.focus();
};// 对话框关闭处理
const handleClosed = () => {emits("close");// 组件消失,用于清理资源nextTick(() => {emits("vanish");});
};// 公开给外部的关闭方法
const doClose = () => {state.dialogVisible = false;
};// 初始化
const init = () => {// 重置表单state.formData.username = "";state.formData.password = "";// 显示对话框state.dialogVisible = true;
};// 组件挂载时初始化
onMounted(() => {init();
});// 暴露方法给父组件调用
defineExpose({doClose,state
});
</script>

接下来重点看看关于函数式调用的部分:

// src/components/AuthBox/index.tsimport { AppContext, ComponentPublicInstance, createVNode, render } from "vue";
import AuthBoxConstructor from "./src/AuthBox.vue";
import { AuthBoxData, AuthBoxOptions, AuthBoxState, Callback, IAuthBox } from "./src/type";/*** 实例映射表 - 存储所有通过函数式调用创建的AuthBox实例** Key: 组件实例的代理对象(vm),包含doClose方法* Value: 包含options、callback、Promise的resolve和reject函数** 作用: 让我们能够在异步事件(如用户点击确认)发生时,找到对应的Promise并解析它*/
const instanceMap = new Map<ComponentPublicInstance<{ doClose: () => void }>,{options: AuthBoxOptions;callback: Callback | undefined;resolve: (res: any) => void;reject: (reason?: any) => void;}
>();/*** 获取组件应该挂载到的DOM元素** @param props - 组件的props* @returns 挂载目标DOM元素,默认为document.body*/
const getAppendToElement = (props: AuthBoxOptions): HTMLElement => {// 这里简化处理,始终返回document.body// 在实际应用中,可以根据props.appendTo来自定义挂载位置return document.body;
};/*** 创建临时容器元素** @returns 新创建的div元素*/
const genContainer = (): HTMLDivElement => {return document.createElement("div");
};/*** 初始化组件实例** @param props - 传递给组件的属性* @param container - 临时容器元素* @param appContext - Vue应用上下文(可选)* @returns 创建的组件实例*/
const initInstance = (props: AuthBoxOptions, container: HTMLElement, appContext: AppContext | null = null) => {// 1. 使用组件构造函数和props创建虚拟节点const vnode = createVNode(AuthBoxConstructor, props);// 2. 如果提供了应用上下文,则设置到vnode上//    (这确保组件能访问到应用的全局组件、插件等)if (appContext) {vnode.appContext = appContext;}// 3. 将虚拟节点渲染到临时容器中render(vnode, container);// 4. 将容器中渲染好的DOM元素移动到目标挂载点(通常是body)getAppendToElement(props).appendChild(container.firstElementChild!);// 5. 返回组件实例return vnode.component;
};/*** 显示AuthBox对话框** @param options - 配置选项* @param appContext - 应用上下文(可选)* @returns 创建的组件实例代理对象*/
const showAuthBox = (options: AuthBoxOptions, appContext?: AppContext | null) => {// 1. 创建临时容器const container = genContainer();// 2. 设置组件销毁时的回调// 当组件通过transition动画完全消失后触发options.onVanish = () => {// 2.1 从DOM中彻底移除组件//     (将null渲染到container会清除其中的内容)render(null, container);// 2.2 从实例映射表中移除组件实例//     (防止内存泄漏)instanceMap.delete(vm);};// 3. 设置用户点击确认按钮的回调options.onConfirm = (userData: { username: string; password: string }) => {// 3.1 获取该组件实例对应的Promise解析函数const currentInstance = instanceMap.get(vm)!;// 3.2 创建返回数据const resolveData: AuthBoxData = {username: userData.username,password: userData.password,action: "confirm"};// 3.3 解析Promise,传递结果数据//     (这会使得await AuthBox()或.then()收到结果)currentInstance.resolve(resolveData);};// 4. 设置用户点击取消按钮的回调options.onCancel = () => {const currentInstance = instanceMap.get(vm)!;const resolveData: AuthBoxData = {username: "",password: "",action: "cancel"};currentInstance.resolve(resolveData);};// 5. 设置对话框关闭的回调options.onClose = () => {const currentInstance = instanceMap.get(vm)!;const resolveData: AuthBoxData = {username: "",password: "",action: "close"};currentInstance.resolve(resolveData);};// 6. 初始化并创建组件实例const instance = initInstance(options, container, appContext)!;// 7. 获取组件实例的代理对象//    (这是我们与组件交互的接口)const vm = instance.proxy as ComponentPublicInstance<{doClose: () => void;} & AuthBoxState>;// 8. 返回代理对象return vm;
};/*** AuthBox函数 - 用于函数式调用AuthBox组件** 用法:* const result = await AuthBox({ title: '登录', message: '请输入您的账号和密码' });* if (result.action === 'confirm') {*   console.log('用户名:', result.username);*   console.log('密码:', result.password);* }** @param options - AuthBox配置选项* @param appContext - Vue应用上下文(可选)* @returns Promise,解析为AuthBoxData*/
async function AuthBox(options: AuthBoxOptions, appContext?: AppContext | null): Promise<AuthBoxData>;
function AuthBox(options: AuthBoxOptions, appContext: AppContext | null = null): Promise<AuthBoxData> {// 1. 创建并返回一个新的Promise//    (这是函数式调用的核心,让我们可以使用await或.then()获取结果)return new Promise((resolve, reject) => {// 2. 获取应用上下文(优先使用传入的,否则使用预设的)const finalAppContext = appContext ?? (AuthBox as IAuthBox)._context;// 3. 显示AuthBox对话框,获取组件实例代理const vm = showAuthBox(options, finalAppContext);// 4. 将组件实例与Promise的resolve/reject函数关联起来//    (这样在事件回调中就能找到对应的Promise进行解析)instanceMap.set(vm, {options,callback: undefined, // 保留字段,便于扩展resolve,reject});});
}/*** 关闭所有通过AuthBox函数创建的对话框*/
AuthBox.close = () => {// 1. 遍历实例映射表中的所有组件实例instanceMap.forEach((_, vm) => {// 2. 调用每个实例的doClose方法关闭对话框vm.doClose();});// 3. 清空实例映射表//    (作为安全措施,确保不留下任何引用)instanceMap.clear();
};// 初始化应用上下文为null
(AuthBox as IAuthBox)._context = null;// 导出函数
export default AuthBox as IAuthBox;

下面我们就重点分析看一下,这个 indes.ts 做了什么:

  1. 导入依赖
import { AppContext, ComponentPublicInstance, createVNode, render } from "vue";
import AuthBoxConstructor from "./src/AuthBox.vue";
import { AuthBoxData, AuthBoxOptions, AuthBoxState, Callback, IAuthBox } from "./src/type";
  • vue:从 Vue 中导入了核心的 AppContext (应用上下文)、ComponentPublicInstance (组件公共实例类型)、createVNode (创建虚拟DOM节点) 和 render (渲染虚拟DOM) 函数。
  • AuthBoxConstructor:这是实际的 AuthBox.vue 组件。我们将其作为构造函数来创建组件实例。
  • ./src/type:从类型定义文件中导入了与 AuthBox 组件相关的各种类型,这里就不放出来了,根据自己实际业务来写就行。
  1. instanceMap:实例映射表
const instanceMap = new Map<ComponentPublicInstance<{ doClose: () => void }>,{options: AuthBoxOptions;callback: Callback | undefined;resolve: (res: any) => void;reject: (reason?: any) => void;}
>();
  • 作用:这是一个关键的数据结构。由于我们可以通过函数调用创建多个 AuthBox 实例,instanceMap 用于存储每一个动态创建的 AuthBox 组件实例 (vm) 以及与之关联的配置项 (options) 和 Promise 的 resolve / reject 函数。
  • 键 (Key)ComponentPublicInstance<{ doClose: () => void }>,表示 AuthBox 组件的实例代理对象。这个代理对象上预期有一个 doClose 方法,用于关闭对话框。
  • 值 (Value):一个对象,包含:
    • options: 调用 AuthBox 时传入的配置。
    • callback: 一个可选的回调函数 (这里标记为 undefined,保留了扩展性)。
    • resolve: Promise 的 resolve 函数。当用户在 AuthBox 中完成操作 (如点击确认) 时,我们会调用这个函数来解决 (fulfill) Promise,并传递结果。
    • reject: Promise 的 reject 函数。如果发生错误或需要中断操作,会调用此函数。
  • 为什么需要它?AuthBox 组件内部发生事件 (如用户点击按钮) 时,我们需要一种方式找到当初调用它时创建的那个 Promise,以便能将结果传递回去。instanceMap 就是通过组件实例这个桥梁来找到对应的 Promise 控制函数的。
  1. getAppendToElement:获取挂载目标
const getAppendToElement = (props: AuthBoxOptions): HTMLElement => {return document.body;
};
  • 作用:决定 AuthBox 组件的 DOM 元素最终应该被插入到页面的哪个位置。
  • 实现:这里简化了处理,固定返回 document.bodyAuthBox 会被挂载到 <body> 元素的末尾。
  • 扩展性:在实际应用中,可以根据需要来自定义挂载位置。
  1. genContainer:创建临时容器
const genContainer = (): HTMLDivElement => {return document.createElement("div");
};
  • 作用:创建一个临时的 <div> 元素。
  • 为什么需要临时容器? Vue 的 render 函数需要一个容器元素来渲染虚拟节点。我们先将组件渲染到这个临时容器中,然后再将容器内的实际 DOM 元素(即 AuthBox 的根元素)移动到由 getAppendToElement 指定的最终挂载点。
  1. initInstance:初始化组件实例
const initInstance = (props: AuthBoxOptions, container: HTMLElement, appContext: AppContext | null = null) => {// 1. 使用组件构造函数和props创建虚拟节点const vnode = createVNode(AuthBoxConstructor, props);// 2. 如果提供了应用上下文,则设置到vnode上if (appContext) {vnode.appContext = appContext;}// 3. 将虚拟节点渲染到临时容器中render(vnode, container);// 4. 将容器中渲染好的DOM元素移动到目标挂载点(通常是body)getAppendToElement(props).appendChild(container.firstElementChild!);// 5. 返回组件实例return vnode.component;
};
  • 作用:这个函数负责创建 AuthBox 组件的 Vue 实例并将其渲染到 DOM 中。
  • 步骤
    1. 创建虚拟节点 (VNode):使用 createVNode(AuthBoxConstructor, props)AuthBoxConstructor 是导入的 .vue 文件,props 是传递给组件的属性。
    2. 设置应用上下文 (appContext):如果调用时传入了 appContext,则将其设置到 vnode.appContext。它能确保动态创建的组件实例可以访问到主 Vue 应用实例中注册的全局组件、指令、插件以及 provide/inject 等。
    3. 渲染到临时容器:调用 render(vnode, container),将虚拟节点转换成真实的 DOM 元素,并插入到 container(由 genContainer 创建的 div)中。
    4. 移动到最终挂载点getAppendToElement(props).appendChild(container.firstElementChild!)。这一步是将 container 中的第一个子元素 (即 AuthBox 组件的根 DOM 元素) 移动到 document.body (或 getAppendToElement 返回的其他元素) 中。
    5. 返回组件实例vnode.component 是实际的 Vue 组件实例对象,我们可以通过它访问组件的属性和方法。
  1. showAuthBox:显示对话框并处理回调
const showAuthBox = (options: AuthBoxOptions, appContext?: AppContext | null) => {const container = genContainer(); // 1. 创建临时容器// 2. 设置组件销毁时的回调options.onVanish = () => { // Linter Error: Property 'onVanish' does not exist on type 'AuthBoxOptions'.render(null, container); // 从DOM中彻底移除instanceMap.delete(vm);  // 从实例映射表中移除};// 3. 设置用户点击确认按钮的回调options.onConfirm = (userData: { username: string; password: string }) => { // Linter Errorconst currentInstance = instanceMap.get(vm)!;const resolveData: AuthBoxData = { /* ... */ action: "confirm" };currentInstance.resolve(resolveData);};// 4. 设置用户点击取消按钮的回调options.onCancel = () => { // Linter Errorconst currentInstance = instanceMap.get(vm)!;const resolveData: AuthBoxData = { /* ... */ action: "cancel" };currentInstance.resolve(resolveData);};// 5. 设置对话框关闭的回调 (例如点击遮罩层或右上角关闭按钮)options.onClose = () => { // Linter Errorconst currentInstance = instanceMap.get(vm)!;const resolveData: AuthBoxData = { /* ... */ action: "close" };currentInstance.resolve(resolveData);};const instance = initInstance(options, container, appContext)!;const vm = instance.proxy as ComponentPublicInstance< /* ... */ >; // 7. 获取组件实例代理return vm; // 8. 返回代理对象
};
  • 作用:这是实际处理 AuthBox 显示逻辑和事件回调的核心函数。
  • 步骤与解释
    1. 创建容器:调用 genContainer()
    2. 设置 options.onVanish
      • 这个回调函数会在 AuthBox 组件从界面上完全消失时被调用。
      • 内部逻辑:
        • render(null, container): 这是 Vue 中卸载组件并从 DOM 中移除其内容的方法。
        • instanceMap.delete(vm): 从 instanceMap 中删除对此实例的引用,防止内存泄漏。
    3. 设置 options.onConfirm
      • 当用户在 AuthBox 组件内部点击“确认”按钮时,AuthBox 组件会触发这个回调,并传入用户数据 (userData)。
      • 内部逻辑:
        • instanceMap.get(vm)!: 通过组件实例 vminstanceMap 中获取之前存储的 Promise resolve 函数。
        • 构造 resolveData:包含用户名、密码和操作类型 (action: "confirm")。
        • currentInstance.resolve(resolveData): 调用 Promise 的 resolve 函数,将 resolveData 作为结果传递出去。这将使得等待此 Promise 的 await AuthBox(...) 调用得到结果。
    4. 设置 options.onCancel
      • 当用户点击“取消”按钮时触发。
      • 逻辑与 onConfirm 类似,但 action"cancel",并且通常不包含用户输入数据。
    5. 设置 options.onClose
      • 当对话框因其他方式关闭(如点击遮罩层、按下 Esc 键,或组件内部调用关闭逻辑)时触发。
      • 逻辑与 onCancel 类似,action"close"
    6. 初始化实例:调用 initInstance(options, container, appContext) 创建并挂载 AuthBox 组件。注意,这里的 options 对象已经被我们动态添加了 onVanish, onConfirm, onCancel, onClose 这些回调处理函数。AuthBox.vue 组件内部在合适的时机(如用户点击、组件卸载)就会调用这些通过 props 传递进来的函数。
    7. 获取组件代理 vminstance.proxy 是组件实例的代理对象,通过它来调用组件的方法或访问其数据 (如果组件暴露了 doClose 方法和 AuthBoxState 中的状态)。
    8. 返回代理对象 vm:将 vm 返回。
  1. AuthBox 主函数 (函数式调用的入口)
async function AuthBox(options: AuthBoxOptions, appContext?: AppContext | null): Promise<AuthBoxData>;
function AuthBox(options: AuthBoxOptions, appContext: AppContext | null = null): Promise<AuthBoxData> {return new Promise((resolve, reject) => {const finalAppContext = appContext ?? (AuthBox as IAuthBox)._context;const vm = showAuthBox(options, finalAppContext);instanceMap.set(vm, {options,callback: undefined,resolve,reject});});
}
  • 作用:这是最终暴露给用户调用的函数。它使得我们可以像 const result = await AuthBox({ }); 这样使用。
  • 实现逻辑
    1. 返回 Promise:核心在于 return new Promise((resolve, reject) => { ... });。这使得 AuthBox 函数的调用结果可以被 await 或者通过 .then() 方法处理。
    2. 确定应用上下文const finalAppContext = appContext ?? (AuthBox as IAuthBox)._context;
      • 优先使用调用时直接传入的 appContext
      • 如果没传,则尝试使用 (AuthBox as IAuthBox)._context。这是一个预设的或全局设置的 appContext (见后续解释)。
    3. 显示 AuthBoxconst vm = showAuthBox(options, finalAppContext); 调用我们之前定义的 showAuthBox 函数,传入用户配置和确定的应用上下文。这将创建、挂载组件,并返回组件实例代理 vm
    4. 存储到 instanceMapinstanceMap.set(vm, { options, callback: undefined, resolve, reject });
      • 它将当前创建的组件实例 vm 与新创建的 Promise 的 resolvereject 函数关联起来,并存储到 instanceMap 中。
      • 这样,当 showAuthBox 中设置的 onConfirm, onCancel, onClose 等回调被 AuthBox.vue 组件内部触发时,它们可以通过 vminstanceMap 中找到对应的 resolve (或 reject) 函数,从而完成 Promise,将数据传递给 AuthBox 函数的调用者。
  1. AuthBox.close:关闭所有实例
AuthBox.close = () => {instanceMap.forEach((_, vm) => {vm.doClose(); // 调用每个实例的doClose方法});instanceMap.clear(); // 清空映射表
};
  • 作用:提供一个静态方法,用于关闭所有当前通过 AuthBox 函数打开的对话框实例。
  • 实现
    1. 遍历 instanceMap 中的所有组件实例代理 (vm)。
    2. 调用每个 vm 上的 doClose() 方法。这要求 AuthBox.vue 组件通过 defineExpose 暴露了一个名为 doClose 的方法,用于执行关闭自身的逻辑(比如设置一个内部状态让组件隐藏,然后触发过渡动画,最终触发 onVanish)。
    3. instanceMap.clear(): 清空映射表。

以上就是这个 index.ts 的详细解释,相信你能明白vue中的组件是如何通过函数式调用的了,这样的调用方式非常的方便。

相关文章:

vue 组件函数式调用实战:以身份验证弹窗为例

通常我们在 Vue 中使用组件&#xff0c;是像这样在模板中写标签&#xff1a; <MyComponent :prop"value" event"handleEvent" />而函数式调用&#xff0c;则是让我们像调用一个普通 JavaScript 函数一样来使用这个组件&#xff0c;例如&#xff1a;…...

多线程面试题总结

基础概念 进程与线程的区别 进程:操作系统资源分配的基本单位,有独立内存空间线程:CPU调度的基本单位,共享进程资源对比: 创建开销:进程 > 线程通信方式:进程(IPC)、线程(共享内存)安全性:进程更安全(隔离),线程需要同步线程的生命周期与状态转换 NEW → RUNNABLE …...

Kafka 与 RabbitMQ、RocketMQ 有何不同?

一、不同的诞生背景&#xff0c;塑造了不同的“性格” 名称 背景与目标 产品定位 Kafka 为了解决 LinkedIn 的日志收集瓶颈&#xff0c;强调吞吐与持久化 更像一个“可持久化的分布式日志系统” RabbitMQ 出自金融通信协议 AMQP 的实现&#xff0c;强调协议标准与广泛适…...

【比赛真题解析】篮球迷

本次给大家分享一道比赛的题目:篮球迷。 洛谷链接:U561543 篮球迷 题目如下: 【题目描述】 众所周知,jimmy是个篮球迷。众所周知,Jimmy非常爱看NBA。 众所周知,Jimmy对NBA冠军球队的获奖年份和队名了如指掌。 所以,Jimmy要告诉你n个冠军球队的名字和获奖年份,并要求你…...

【MATLAB源码-第277期】基于matlab的AF中继系统仿真,AF和直传误码率对比、不同中继位置误码率对比、信道容量、中继功率分配以及终端概率。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 在AF&#xff08;放大转发&#xff09;中继通信系统中&#xff0c;信号的传输质量和效率受到多个因素的影响&#xff0c;理解这些因素对于系统的优化至关重要。AF中继通信的基本架构由发射端、中继节点和接收端组成。发射端负…...

webRtc之指定摄像头设备绿屏问题

摘要&#xff1a;最近发现&#xff0c;在使用navigator.mediaDevices.getUserMedia({ deviceId: ‘xxx’}),指定设备的时候&#xff0c;video播放总是绿屏&#xff0c;发现关闭浏览器硬件加速不会出现&#xff0c;但显然这不是一个最好的方案; 播放后张这样 修复后 上代码 指定…...

2023年03月青少年软件编程(图形化)等级考试四级编程题

求和 1.准备工作 &#xff08;1&#xff09;保留舞台中的小猫角色和白色背景。 2.功能实现 &#xff08;1&#xff09;计算1&#xff5e;100中&#xff0c;可以被3整除的数之和&#xff1b; &#xff08;2&#xff09;说出被3整除的数之和。 标准答案&#xff1a; 参考程序&…...

ensp的华为小实验

1.先进行子网划分 2.进行接口的IP地址配置和ospf的简易配置&#xff0c;先做到全网小通 3.进行ospf优化 对区域所有区域域间路由器进行一个汇总 对区域1进行优化 对区域2.3进行nssa设置 4.对ISP的路由进行协议配置 最后ping通5.5.5.5...

ragflow报错:KeyError: ‘\n “序号“‘

环境&#xff1a; ragflowv 0.17.2 问题描述&#xff1a; ragflow报错&#xff1a;KeyError: ‘\n “序号”’ **1. 推荐表&#xff08;输出json格式&#xff09;** [{"},{},{"},{} ]raceback (most recent call last): May 08 20:06:09 VM-0-2-ubuntu ragflow-s…...

Java大数据可视化在城市空气质量监测与污染溯源中的应用:GIS与实时数据流的技术融合

随着城市化进程加速&#xff0c;空气质量监测与污染溯源成为智慧城市建设的核心议题。传统监测手段受限于数据离散性、分析滞后性及可视化能力不足&#xff0c;难以支撑实时决策。2025年4月27日发布的《Java大数据可视化在城市空气质量监测与污染溯源中的应用》一文&#xff0c…...

FHE与后量子密码学

1. 引言 近年来&#xff0c;关于 后量子密码学&#xff08;PQC, Post-Quantum Cryptography&#xff09; 的讨论愈发热烈。这是因为安全专家担心&#xff0c;一旦有人成功研发出量子计算机&#xff0c;会发生什么可怕的事情。由于 Shor 算法的存在&#xff0c;量子计算机将能够…...

Flask 调试的时候进入main函数两次

在 Flask 开启 Debug 模式时&#xff0c;程序会因为自动重载&#xff08;reloader&#xff09;的机制而启动两个进程&#xff0c;导致if __name__ __main__底层的程序代码被执行两次。以下说明其原理与常见解法。 Flask Debug 模式下自动重载机制 Flask 使用的底层服务器 Wer…...

cv_area_center()

主题 用opencv实现了halcon中area_center算子的功能&#xff0c; 返回region的面积&#xff0c;中心的行坐标和中心的列坐标 代码很简单 def cv_area_center(region):area[]row []col []for re in region:retval cv2.moments(re)area.append(retval[m00])row.append(int(r…...

CSS: 选择器与三大特性

标签选择器 标签选择器就是选择一些HTML的不同标签&#xff0c;由于它们的标签需求不同&#xff0c;所以CSS需要设置标签去选择它们&#xff0c;为满足它们的需求给予对应的属性 基础选择器 标签选择器 <!DOCTYPE html> <head><title>HOME</title>…...

2505d,d的借用检查器

void func(scope ref int*) {}unique(int*) a ...; assert(a !is null);unique(int*) b a; assert(a is null); assert(b !is null);func(b); // ok用live作为检查器,不必有断定了. int* a ...; int* b a; // 所有权转至b *a 3; // 不能再用a.编译器保证约束指针. live…...

力扣-2.两数相加

题目描述 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都…...

M0基础篇之ADC

本节课使用到的例程 一、Single模式例程基本配置的解释 在例程中我们只使用到了PA25这一个通道&#xff0c;因此我们使用的是Single这个模式&#xff0c;也就是我们在配置模式的时候使用的是单一转换。 进行多个通道的测量我们可以使用Sequence这个模式。 二、Single模式例程基…...

Nginx安全防护与HTTPS部署

一、安全防护与HTTPS概念 一、安全防护与HTTPS概念 为什么要隐藏版本号&#xff1f; 当访问网站时&#xff0c;能从响应标头查看到server的信息&#xff0c;这里面就包含了是什么web应用及其版本为你提供的服务。如果不隐藏server的版本&#xff0c;会导致别有用心的人知晓…...

C语言_程序的段

在 C 语言程序中,内存通常被分为多个逻辑段,每个段存储不同类型的数据。理解这些段的结构和功能,有助于你更高效地编写、调试和优化程序。以下是 C 语言程序中主要的内存段及其特点: 1. 代码段(Text Segment) 存储内容:编译后的机器指令(程序代码)。特性: 只读:防止…...

OSPF综合实验实验报告

OSPF综合实验实验报告 一、实验拓扑 二、实验要求 1.R5为ISP&#xff0c;其上只能配置IP地址&#xff1b;R4作为企业边界路由器&#xff0c; 出口公网地址需要通过PPP协议获取&#xff0c;并进行chap认证 2&#xff0c;整个OSPF环境IP基于172.16.0.0/16划分&#xff1b; 3&…...

vue3+ant design vue + Sortable实现多级表格列拖动

1、最近遇到个需求&#xff0c;需使用vue3ant design vue Sortable实现多级表格的表头允许用户拖拽移动。即当用户拖拽一级表头时&#xff0c;其对应的子级表头及数据应同步移动&#xff0c;并且只允许一级非固定表头允许拖拽。 2、代码 <a-table:data-source"rowDat…...

基于开源链动2+1模式AI智能名片S2B2C商城小程序的分销价格管控机制研究

摘要&#xff1a;本文聚焦开源链动21模式AI智能名片S2B2C商城小程序在分销体系中的价格管控机制&#xff0c;通过解析其技术架构与商业模式&#xff0c;揭示平台如何通过"去中心化裂变中心化管控"双轨机制实现价格统一。研究显示&#xff0c;该模式通过区块链存证技术…...

阿里云 SLS 多云日志接入最佳实践:链路、成本与高可用性优化

作者&#xff1a;裘文成&#xff08;翊韬&#xff09; 摘要 随着企业全球化业务的扩展&#xff0c;如何高效、经济且可靠地将分布在海外各地的应用与基础设施日志统一采集至阿里云日志服务 (SLS) 进行分析与监控&#xff0c;已成为关键挑战。 本文聚焦于阿里云高性能日志采集…...

体育培训的实验室管理痛点 质检LIMS如何重构体育检测价值链

在竞技体育与全民健身并行的时代背景下&#xff0c;体育培训机构正面临双重挑战&#xff1a;既要通过科学训练提升学员竞技水平&#xff0c;又需严格把控运动安全风险。作为实验室数字化管理的核心工具&#xff0c;质检LIMS系统凭借其标准化流程管控与智能化数据分析能力&#…...

第二节:Vben Admin 最新 v5.0 对接后端登录接口(上)

文章目录 前言一、登录页面调整二、登录表单调整三、后端接口(Python)对接对接准备1. Flask项目介绍2. User模型创建3. 迁移模型4. Token创建5. 编写蓝图6. 注册蓝图四、测试登录总结前言 这里是Vben Admin V5版本实战体验,上一节我们前端已正常运行,但是没有实现登录。本节…...

设计模式【cpp实现版本】

文章目录 设计模式1.单例模式代码设计1.饿汉式单例模式2.懒汉式单例模式 2.简单工厂和工厂方法1.简单工厂2.工厂方法 3.抽象工厂模式4.代理模式5.装饰器模式6.适配器模式7.观察者模式 设计模式 1.单例模式代码设计 ​ 为什么需要单例模式&#xff0c;在我们的项目设计中&…...

阿维塔汽车CAN总线数据适配技术解析与免破线数据采集实践

在智能电动汽车快速迭代的背景下&#xff0c;阿维塔凭借其高度集成的电子电气架构成为行业焦点。昨天我们经过实测&#xff0c;适配了该车型CAN总线数据适配的核心技术&#xff0c;从硬件接口定位、无损伤接线方案到关键动力系统数据解码进行系统性剖析&#xff0c;为智能诊断、…...

用纯HTML和CSS仿写知乎登录页面

这是知乎的官方的登录页面 这是我的登录页面&#xff0c;使用 HTML CSS 进行编写。我觉得这是一个供前端新手练手的一个不错的小项目&#xff0c; 在这个系列&#xff0c;我将会用 HTML CSS 编写各大知名网站的登录界面&#xff0c;欢迎大家交流探讨。 源码展示: body{ba…...

数据库故障排查全攻略:从实战案例到体系化解决方案

一、引言&#xff1a;数据库故障为何是技术人必须攻克的 "心腹大患" 在数字化时代&#xff0c;数据库作为企业核心数据资产的载体&#xff0c;其稳定性直接决定业务连续性。据 Gartner 统计&#xff0c;企业每小时数据库 downtime 平均损失高达 56 万美元&#xff0…...

MySQL如何优雅的执行DDL

一、概述 在MySQL中&#xff0c;DDL&#xff08;数据定义语言&#xff09;语句用于定义和管理数据库结构&#xff0c;包括创建、修改和删除数据库对象&#xff08;如表、索引等&#xff09;。执行DDL操作时&#xff0c;需要谨慎处理&#xff0c;以避免对生产环境的稳定性和性能…...