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

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;…...

青藏高原东北部祁连山地区250m分辨率多年冻土空间分带指数图(2023)

时间分辨率&#xff1a;10年 < x < 100年空间分辨率&#xff1a;100m - 1km共享方式&#xff1a;开放获取数据大小&#xff1a;24.38 MB数据时间范围&#xff1a;近50年来元数据更新时间&#xff1a;2023-10-08 数据集摘要 多年冻土目前正在经历大规模的退化&#xff0c…...

[6-2] 定时器定时中断定时器外部时钟 江协科技学习笔记(41个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 V 30 31 32 33 34 35 36 37 38 39 40 41...

抖音视频去水印怎么操作

在抖音上保存或分享视频时&#xff0c;水印通常会自动添加。如果想去除水印&#xff0c;可以尝试以下方法&#xff0c;但请注意尊重原创作者的版权&#xff0c;仅限个人合理使用。 方法 1&#xff1a;使用第三方去水印工具&#xff08;手机/电脑均可&#xff09; 复制视频链接 …...

Java并发编程

Java并发编程的核心挑战 线程安全与数据竞争 线程安全的概念及其重要性数据竞争的产生原因及常见场景如何通过同步机制&#xff08;如锁、原子类&#xff09;避免数据竞争 // 示例&#xff1a;使用synchronized关键字实现线程安全 public class Counter {private int count …...

【ospf综合实验】

拓扑图&#xff1a;...

NVMe控制器之仿真平台搭建

本设计采用Verilog HDL语言进行实现并编写测试激励&#xff0c;仿真工具使用Mentor公司的QuestaSim 10.6c软件完成对关键模块的仿真验证工作&#xff0c;由于是基于Xilinx公司的Kintex UltraScale系列FPGA器件实现的&#xff0c;因此使用Xilinx公司的Vivado2019.1设计套件工具进…...

深入探究 InnoDB 的写失效问题

在 MySQL 数据库的世界中&#xff0c;InnoDB 存储引擎凭借其卓越的性能和可靠性&#xff0c;成为众多应用的首选。然而&#xff0c;如同任何复杂的系统一样&#xff0c;InnoDB 也面临着一些挑战&#xff0c;其中写失效问题便是一个值得深入探讨的关键议题。本文将带您全面了解 …...

边缘计算从专家到小白

“云-边-端”架构 “云” &#xff1a;传统云计算的中心节点&#xff0c;是边缘计算的管控端。汇集所有边缘的感知数据、业务数据以及互联网数据&#xff0c;完成对行业以及跨行业的态势感知和分析。 “边” &#xff1a;云计算的边缘侧&#xff0c;分为基础设施边缘和设备边缘…...

智能商品推荐系统技术路线图

智能商品推荐系统技术路线图 系统架构图 --------------------------------------------------------------------------------------------------------------- | 用户交互层 (Presentation Layer) …...

SpringMVC面试内容

SpringMVC运行流程 SpringMVC的运行流程SpringBoot Vue交互流程HTTP 的 GET 和 POST 区别跨域请求是什么&#xff1f;有什么问题&#xff1f;怎么解决?浏览器访问资源没有响应,怎么排查Cookie的理解Session的理解 Cookie和Session的区别 SpringMVC的运行流程 1、域名解析…...

Python 核心概念速查清单

本文大纲 1. 变量与字符串 (Variables and Strings) 变量 (Variables): 用于存储值。字符串 (String): 由单引号或双引号包围的字符序列。 示例:打印 “Hello world!” print("Hello world!")使用变量打印: msg = "Hello world!" print(msg)字符串拼接…...

Unity.UGUI DrawCall合批笔记

前言 昨天在通过FrameDebug查看DrawCall时&#xff0c;发现批次结果与理解中的不一致&#xff0c;又去补充了一下这方面知识&#xff0c;笔记记录下&#xff0c;只关乎UGUI。 基础场景 首先列一下无法合批的一些基础场景 1.图片无图集或图集不同&#xff0c;图片是运行时生成的…...

高精度加减

1、高精度加法 主要有以下几步&#xff1a; 输入处理&#xff1a;使用字符串来存储大整数&#xff0c;避免数值范围限制。对齐数字&#xff1a;确保两个数字的数位对齐&#xff08;前面补零&#xff09;。逐位相加&#xff1a;从最低位开始&#xff0c;逐位相加并处理进位。最…...

day21python打卡

知识点回顾&#xff1a; LDA线性判别PCA主成分分析t-sne降维 还有一些其他的降维方式&#xff0c;也就是最重要的词向量的加工&#xff0c;我们未来再说 作业&#xff1a; 自由作业&#xff1a;探索下什么时候用到降维&#xff1f;降维的主要应用&#xff1f;或者让ai给你出题&…...

DataBinding与Kotlin优化视图绑定

在 Android 开发中&#xff0c;DataBinding 与 Kotlin 的结合可以显著提升代码的简洁性和可维护性&#xff0c;彻底摆脱传统 findViewById 的繁琐操作。以下是如何通过 DataBinding 优化视图绑定的完整指南&#xff1a; 一、为何要告别 findViewById&#xff1f; 模板代码冗余…...

CDGP主观题题库与范例解答

本文共8400字,涉及数据建模、数据安全、主数据、数据架构等主观题解答范例 数据建模题目 初次访问网购网站的访客,如试图在网站上购物,则需要申请会员。申请会员时需要填写会员姓名、性别、身份证号码、联系电话、会员ID、密码等信息。会员申请成功后,通过会员ID和密码便…...

2.商户查询缓存

2.0 问题记录 2.0.1 为什么要给缓存 TTL 1. 防止内存泄漏&#xff1a;如果不设置过期时间&#xff0c;缓存数据会永久存在于 Redis 中&#xff0c;随着时间推移可能导致 Redis 内存耗尽。2. 数据一致性&#xff1a;设置合理的过期时间可以确保缓存不会长期存储过时数据&#…...

vs python“““标记注释报错,vs使用自带环境安装 python第三方库

文章目录 vs python"""标记注释报错vs使用自带环境安装 python第三方库 vs python"""标记注释报错 解决方法&#xff1a; 切换编码 文件-高级保存选项-编码处选择下拉菜单中的“Unicode(UTF-8带签名)-代码页65001”-确定 这里更详细&#xff1a;…...

区块链技术中的Java SE实战:从企业级应用到5大核心问题解析

区块链技术中的Java SE实战&#xff1a;从企业级应用到5大核心问题解析 问题1&#xff1a;如何在Java SE中实现区块链的基本数据结构&#xff1f; 回答1&#xff1a; 区块链的核心数据结构是链式区块&#xff0c;每个区块包含数据、哈希值以及前一个区块的哈希值。以下是一个…...

数据结构—(概述)

目录 一 数据结构&#xff0c;相关概念 1. 数据结构&#xff1a; 2. 数据(Data): 3. 数据元素(Data Element): 4. 数据项&#xff1a; 5. 数据对象(Data Object): 6. 容器&#xff08;container&#xff09;&#xff1a; 7. 结点&#xff08;Node&#xff09;&#xff…...

UE5 PCG学习笔记

https://www.bilibili.com/video/BV1onUdY2Ei3/?spm_id_from333.337.search-card.all.click&vd_source707ec8983cc32e6e065d5496a7f79ee6 一、安装PCG 插件里选择以下进行安装 移动目录后&#xff0c;可以使用 Update Redirector References&#xff0c;更新下&#xff0…...

Harness: 全流程 DevOps 解决方案,让持续集成如吃饭般简单

引言 在当今快速发展的软件开发世界中,高效的 DevOps 工具变得越来越重要。Harness 作为一个开源的运维平台,为开发和运维团队提供了从代码托管到 CI/CD 的全流程解决方案,同时实现自动化的开发环境和制品管理。这种集中化的工具可以显著减少运维难度,提高团队效率,真正解…...

Windows:Powershell的使用

文章目录 零、格式化输出命令1、Format-List&#xff08;别名&#xff1a;fl&#xff09; 一、服务管理SC命令二、软件管理命令三、权限管理命令1、Get-Acl2、Set-Acl 总结 零、格式化输出命令 1、Format-List&#xff08;别名&#xff1a;fl&#xff09; 可通过管道符传递对象…...

AIGC时代大模型幻觉问题深度治理:技术体系、工程实践与未来演进

文章目录 一、幻觉问题的多维度透视与产业冲击1.1 幻觉现象的本质特征与量化评估1.2 产业级影响案例分析 二、幻觉问题的根源性技术解剖2.1 数据污染的复合效应2.1.1 噪声数据类型学分析2.1.2 数据清洗技术实现 2.2 模型架构的先天缺陷2.2.1 注意力机制的局限性2.2.2 解码策略的…...

JMeter 中通过 WebSocket (WS) 协议发送和接收 Protocol Buffers (Proto) 消息

在 JMeter 中通过 WebSocket (WS) 协议发送和接收 Protocol Buffers (Proto) 消息&#xff0c;需要使用 JMeter WebSocket 插件&#xff0c;并结合 JSR223 脚本处理 Proto 的序列化和反序列化。以下是完整步骤&#xff1a; 1. 准备工作 1.1 安装 WebSocket 插件 下载插件&…...

PyQt5基础:QWidget类的全面解析与应用实践

在Python的GUI编程领域&#xff0c;PyQt5是一个强大且广泛应用的库。其中&#xff0c;QWidget类作为所有用户界面对象的基类&#xff0c;是构建丰富多样用户界面的基础。今天&#xff0c;我们就来深入了解QWidget类及其相关应用。 QWidget类概述 QWidget类是PyQt中所有窗口和…...

DA14585墨水屏学习

一、do_min_word void do_min_work(void) {timer_used_min app_easy_timer(APP_PERIPHERAL_CTRL_TIMER_DELAY_MINUTES, do_min_work);current_unix_time time_offset;time_offset 60;// if (isconnected 1)// {// GPIO_SetActive(GPIO_LED_PORT, GPIO_LED_PIN);// …...

AI日报 · 2025年5月10日|OpenAI“Stargate”超级数据中心项目掀起美国各州争夺战

1、OpenAI“Stargate”超级数据中心项目掀起美国各州争夺战 《华盛顿邮报》披露&#xff0c;OpenAI 与 Oracle、SoftBank 合作推进的“Stargate”项目&#xff08;首期投资 1000 亿美元&#xff0c;四年内总投资 5000 亿美元&#xff09;已收到超过 250 份选址提案&#xff…...

浅谈装饰模式

一、前言 hello大家好&#xff0c;本次打算简单聊一下装饰者模式&#xff0c;其实写有关设计模式的内容还是蛮有挑战性的&#xff0c;首先呢就是小永哥实力有限担心说不明白&#xff0c;其次设计模式是为了解决某些问题场景&#xff0c;在当前技术生态圈如此完善的情况下&#…...

《Python星球日记》 第54天:卷积神经网络进阶

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、深度CNN架构解析1. LeNet-5&#xff08;1998&#xff09;2. AlexNet&#x…...

R 语言科研绘图 --- 桑基图-汇总

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...

JDBC工具类

目录 引言 一、JDBC连接数据库步骤 1. 加载驱动 2. 获取连接&#xff08;URL 用户名 密码&#xff09; 3. 编写sql 4. 获取执行sql的stmt的对象 5. 执行sql 拿到结果集 6. 遍历结果集 7. 关闭资源&#xff08;先开的后关 后开的先关&#xff09; 二、JDBC工具类 版…...

【深度学习-Day 8】让数据说话:Python 可视化双雄 Matplotlib 与 Seaborn 教程

Langchain系列文章目录 01-玩转LangChain&#xff1a;从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块&#xff1a;四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain&#xff1a;从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...

InnoDB结构与表空间文件页的详解

目录 1.InnoDB的概览 表空间文件在哪里&#xff1f; 为什么要设计成内存结构和磁盘结构&#xff1f; 表空间与表空间文件关系&#xff1f; 用户数据如何在表空间文件存储&#xff1f; 2.页 如何设置页的大小&#xff1f; 页的结构及在表空间的位置&#xff1f; 页头包…...

计算机网络基础科普

IP地址是计算机网络中标识设备的唯一地址 IPv4&#xff08;32位&#xff09;IPv6&#xff08;128位&#xff09; 1.IPv4&#xff08;32位&#xff09; 简介&#xff1a;IPv4&#xff08;Internet Protocol version 4&#xff09;是互联网协议&#xff08;IP&#xff09;的…...

PostgreSQL 的 pg_advisory_lock_shared 函数

PostgreSQL 的 pg_advisory_lock_shared 函数详解 pg_advisory_lock_shared 是 PostgreSQL 提供的共享咨询锁函数&#xff0c;允许多个会话同时获取相同键值的共享锁&#xff0c;但排斥排他锁。 共享咨询锁 vs 排他咨询锁 锁类型共享锁 (pg_advisory_lock_shared)排他锁 (pg…...

Win11安装APK方法详解

1、官方win11系统 预览版 开发版 正式版 都行 2、同时你还需要开启主板 BIOS 虚拟化选项&#xff08;具体名称不同主板略有不同&#xff09; 这一步自行百度 开始&#xff1a;先去确定有没有开启虚拟化 任务管理器检查—— 虚拟化是否已经开启&#xff0c;如果没有自己去BIO…...

kafka的安装及简单使用

kafka 1、什么是kafka kafka是一个分布式事件流平台&#xff0c;核心功能有发布/订阅消息系统、实时处理数据流等&#xff0c;Kafka非常适合超大数据量场景。 2、kafka安装 &#xff08;1&#xff09;下载 在kafka官网下载二进制压缩包 &#xff08;2&#xff09;解压安…...

圆角边框 盒子阴影 文字阴影

一.圆角边框 在css3中&#xff0c;新增了圆角边框样式&#xff0c;这样我们的盒子就可以变成圆角了 1.border-radius border-radius属性用于设置元素的外边框圆角 border-radius&#xff1a;length&#xff1b; radius半径(圆的半径)原理&#xff1a;椭圆与矩形边框的交集形…...

LRU CPP实现

缓存结构&#xff1a; 使用一个双向链表&#xff08;std::list<int>&#xff09;保存缓存中的页面编号&#xff0c;越靠前的是最近访问的&#xff0c;越靠后的是最久未访问的。 使用一个哈希表&#xff08;std::unordered_map<int, list<int>::iterator>&am…...

C/C++复习-- C语言初始基础

C语言初始基础 本文结合代码实例与理论解析&#xff0c;系统讲解C语言的核心知识点&#xff0c;涵盖数据类型、控制结构、函数、指针、结构体等核心内容&#xff0c;并辅以常见错误分析与进阶技巧。通过对比文件一代码与文件二理论&#xff0c;帮助初学者构建完整的C语言知识框…...

小刚说C语言刷题—1078求恰好使s=1+1/2+1/3+…+1/n的值大于X时n的值

1.题目描述 求恰好使 s11/21/3⋯1/n 的值大于 X 时 n 的值。( 2≤x≤10 ) 输入 输入只有一行&#xff0c;包括 1个整数 X 。 输出 输出只有一行&#xff08;这意味着末尾有一个回车符号&#xff09;&#xff0c;包括 1 个整数。 样例 输入 2 输出 4 2.参考代码(C语言…...

深度学习篇---MediaPipe 及其人体姿态估计模型详解

文章目录 前言一、MediaPipe 核心特点跨平台支持实时性能模块化设计预训练模型 二、MediaPipe 人体姿态估计模型1. MediaPipe Pose (BlazePose)模型特点实时性能两种变体LiteHeavy 关键点定义技术细节检测器关键点预测器支持3D姿态估计 2. MediaPipe Holistic模型特点更全面的检…...

Embedding 的数学特性与可视化解析

一、向量空间的可视化解码 1.1 GloVe 词向量实例 取词向量维度 d 50 d50 d50 的 GloVe 嵌入示例&#xff1a; king_vec [[0.50451, 0.68607, -0.59517, -0.022801, 0.60046, -0.13498, -0.08813, 0.47377, -0.61798, -0.31012, -0.076666, 1.493, -0.034189, -0.98173, 0…...

“睿思 BI” 系统介绍

“睿思 BI” 商业智能系统是由成都睿思商智科技有限公司自主研发的企业数据分析系统&#xff0c;以下是对该系统的详细介绍&#xff1a; 功能模块 &#xff1a; • 数据集成与准备 &#xff1a;支持数据导入、数据填报、数据 ETL 等功能&#xff0c;可抽取企业在经营过程中产生…...

[ctfshow web入门] web69

信息收集 使用cinclude("php://filter/convert.base64-encode/resourceindex.php");读取的index.php if(isset($_POST[c])){$c $_POST[c];eval($c); }else{highlight_file(__FILE__); }解题 查目录 百度了一下有哪些打印函数&#xff0c;var_export能用 var_exp…...

AI赋能研究工作:我的深度学习助手使用体验(DeepResearch)

在过去一年多的时间里&#xff0c;AI工具在国内经历了数次大规模普及与质量波动。作为一名研究工作者&#xff0c;我一直在寻找稳定高效的AI解决方案来辅助日常工作。今天想分享一个让我受益良多的平台——GPTYOU.com 为什么它值得一试&#xff1f; 和市面上众多同类产品相比…...

Vue基础(8)_监视属性、深度监视、监视的简写形式

监视属性(watch)&#xff1a; 1.当被监视的属性变化时&#xff0c;回调函数(handler)自动调用&#xff0c;进行相关操作。 2.监视的属性必须存在&#xff0c;才能进行监视&#xff01;&#xff01; 3.监视的两种写法&#xff1a; (1).new Vue时传入watch配置 (2).通过vm.$watc…...

STM32硬件I2C驱动OLED屏幕

本文基于STM32硬件I2C驱动SSD1306 OLED屏幕&#xff0c;提供完整的代码实现及关键注意事项&#xff0c;适用于128x32或128x64分辨率屏幕。代码通过模块化设计&#xff0c;支持显示字符、数字、汉字及位图&#xff0c;并优化了显存刷新机制。 零、完整代码 完整代码: 1&#x…...