Vue 中 v-model 的三种使用方式对比与实践
在 Vue 3 中,v-model 是组件双向数据绑定的核心特性。随着 Vue 的版本演进,v-model 的使用方式也在不断优化。本文将基于您提供的代码示例,详细分析三种不同的 v-model 实现方式:基础用法、useVModel Hook(@vueuse/core组件库) 用法和 defineModel 宏用法。
1. 基础 v-model 用法
基础用法是 Vue 3.4 版本之前的标准实现方式,需要手动处理 props 和 emits。
子组件实现 (myChild.vue):
<template><div><ElButton @click="setValue">点击数字增加</ElButton></div>
</template><script setup lang="ts">
import { ref } from "vue";
import { ElButton } from "element-plus";const props = defineProps<{ count: number }>();
const emits = defineEmits(["update:count"]);const setValue = () => {emits("update:count", props?.count + 1);
};
</script>
父组件使用:
<template><div class="w-fuu h-full"><div class="text-center">3.4之前的v-model用法</div><div class="mb-2">{{ count }}---数值</div><myChild v-model:count="count" /></div>
</template><script setup lang="ts">
import { ref } from "vue";
import myChild from "./components/myChild.vue";const count = ref(0);
</script>
特点:
-
需要显式定义 props 和 emits
-
通过
emit('update:xxx')
触发更新 -
兼容性好,适用于所有 Vue 3 版本
-
代码相对冗长
2. useVModel Hook 用法
useVModel 是一种自定义 Hook(@vueuse/core组件库) 的封装方式,简化了双向绑定的实现。
useVModel源码 :
import type { Ref, UnwrapRef, WritableComputedRef } from 'vue'
import { computed, getCurrentInstance, nextTick, ref, watch } from 'vue'
import type { ToRefs } from 'vue';export type CloneFn<F, T = F> = (x: F) => T;export function isDef<T = unknown>(val?: T): val is T {return typeof val !== 'undefined';
}function cloneFnJSON<T>(source: T): T {return JSON.parse(JSON.stringify(source));
}export interface UseVModelOptions<T, Passive extends boolean = false> {/*** When passive is set to `true`, it will use `watch` to sync with props and ref.* Instead of relying on the `v-model` or `.sync` to work.** @default false*/passive?: Passive;/*** When eventName is set, it's value will be used to overwrite the emit event name.** @default undefined*/eventName?: string;/*** Attempting to check for changes of properties in a deeply nested object or array.* Apply only when `passive` option is set to `true`** @default false*/deep?: boolean;/*** Defining default value for return ref when no value is passed.** @default undefined*/defaultValue?: T;/*** Clone the props.* Accepts a custom clone function.* When setting to `true`, it will use `JSON.parse(JSON.stringify(value))` to clone.** @default false*/clone?: boolean | CloneFn<T>;/*** The hook before triggering the emit event can be used for form validation.* if false is returned, the emit event will not be triggered.** @default undefined*/shouldEmit?: (v: T) => boolean;
}export function useVModel<P extends object,K extends keyof P,Name extends string
>(props: P,key?: K,emit?: (name: Name, ...args: any[]) => void,options?: UseVModelOptions<P[K], false>
): WritableComputedRef<P[K]>;export function useVModel<P extends object,K extends keyof P,Name extends string
>(props: P,key?: K,emit?: (name: Name, ...args: any[]) => void,options?: UseVModelOptions<P[K], true>
): Ref<UnwrapRef<P[K]>>;export function useVModel<P extends object,K extends keyof P,Name extends string,Passive extends boolean
>(props: P,key?: K,emit?: (name: Name, ...args: any[]) => void,options: UseVModelOptions<P[K], Passive> = {}
) {const {clone = false,passive = false,eventName,deep = false,defaultValue,shouldEmit,} = options;const vm = getCurrentInstance();const _emit =emit ||vm?.emit ||vm?.$emit?.bind(vm) ||vm?.proxy?.$emit?.bind(vm?.proxy);let event: string | undefined = eventName;if (!key) {key = 'modelValue' as K;}event = event || `update:${key!.toString()}`;const cloneFn = (val: P[K]) =>!clone ? val : typeof clone === 'function' ? clone(val) : cloneFnJSON(val);const getValue = () =>isDef(props[key!]) ? cloneFn(props[key!]) : defaultValue;const triggerEmit = (value: P[K]) => {if (shouldEmit) {if (shouldEmit(value)) _emit(event, value);} else {_emit(event, value);}};if (passive) {const initialValue = getValue();const proxy = ref<P[K]>(initialValue!);let isUpdating = false;watch(() => props[key!],(v) => {if (!isUpdating) {isUpdating = true;(proxy as any).value = cloneFn(v) as UnwrapRef<P[K]>;nextTick(() => (isUpdating = false));}});watch(proxy,(v) => {if (!isUpdating && (v !== props[key!] || deep)) triggerEmit(v as P[K]);},{ deep });return proxy;} else {return computed<P[K]>({get() {return getValue()!;},set(value) {triggerEmit(value);},});}
}export function useVModels<P extends object, Name extends string>(props: P,emit?: (name: Name, ...args: any[]) => void,options?: UseVModelOptions<any, true>,
): ToRefs<P>
export function useVModels<P extends object, Name extends string>(props: P,emit?: (name: Name, ...args: any[]) => void,options?: UseVModelOptions<any, false>,
): ToRefs<P>
export function useVModels<P extends object, Name extends string, Passive extends boolean>(props: P,emit?: (name: Name, ...args: any[]) => void,options: UseVModelOptions<any, Passive> = {},
): ToRefs<P> {const ret: any = {};for (const key in props) {ret[key] = useVModel(props,key,emit,options as Parameters<typeof useVModel>[3],);}return ret;
}
子组件实现 (ProRadiuSelectSecond.vue):
<template><div class="radio"><divv-for="item in option":key="item?.value":class="{ item_radio: true, active: item.value == checked }"@click="seletItem(item)">{{ item.label }}</div></div>
</template><script lang="ts" setup>
import { useVModel } from "@/utils/useVModel";
import { ref } from "vue";defineOptions({ name: "ProRadiuSelectSecond" });const props = defineProps<{option: { label: string; value: number }[];checked?: number | string;
}>();const emit = defineEmits(["update:checked"]);const checked = useVModel(props, "checked", emit);const seletItem = (val: any) => {if (checked.value == val.value) {checked.value = undefined;return;}checked.value = val.value;
};
</script><style scoped lang="less">样式忽略
@import url("./index.less");
</style>
父组件使用:
<template><div><h1 class="mb-4">useVmodelHooks使用</h1><ProRadiuSelectSecond :option="myOptions" v-model:checked="selset" /></div>
</template><script lang="ts" setup>
import { ref } from "vue";
import { ProRadiuSelectSecond } from "@/components/ProComponents/index";const selset = ref(1);const myOptions = [{label: "香蕉a",value: 1,},{label: "榴莲a",value: 2,},{label: "西瓜a",value: 3,},
];
</script>
特点:
-
封装了 props 和 emits 的处理逻辑
-
提供更简洁的响应式变量访问
-
需要额外引入 useVModel 工具函数
-
适合在需要复用 v-model 逻辑的场景
3. defineModel 宏用法 (Vue 3.4+)
defineModel 是 Vue 3.4 引入的新特性,极大简化了双向绑定的实现。
子组件实现 (ProRadiuSelect.vue):
<template><div class="radio"><divv-for="item in option":key="item?.value":class="{ item_radio: true, active: item.value == checked }"@click="seletItem(item)">{{ item.label }}</div></div>
</template><script lang="ts" setup>
import { ref } from "vue";defineOptions({ name: "ProRadiuSelect" });const checked = defineModel('checked');const props = defineProps<{ option: { label: string; value: number }[] }>();const seletItem = (val: any) => {if (checked.value == val.value) {checked.value = undefined;return;}checked.value = val.value;
};
</script><style scoped lang="less">
@import url("./index.less");
</style>
父组件使用:
<template><div><h1 class="mb-4" >v-model使用</h1><ProRadiuSelect :option="myOptions" v-model:checked="selset" /></div>
</template><script lang="ts" setup>
import { ref, watch } from "vue";
import { ProRadiuSelect } from "@/components/ProComponents/index";const selset = ref();watch(selset, (newVal, oldVal) => {console.log("newVal:", newVal, "oldVal:", oldVal);
});const myOptions = [{label: "香蕉",value: 1,},{label: "榴莲",value: 2,},{label: "西瓜",value: 3,},
];
</script>
特点:
-
代码最简洁,一行代码即可实现双向绑定
-
内置类型推断,开发体验好
-
需要 Vue 3.4 或更高版本
-
未来 Vue 官方推荐的方式
三种方式对比
特性 | 基础用法 | useVModel Hook | defineModel 宏 |
---|---|---|---|
代码简洁度 | 低 | 中 | 高 |
Vue 版本要求 | 所有 | 所有 | 3.4+ |
类型支持 | 需要手动 | 需要手动 | 自动推断 |
额外依赖 | 无 | 需要 | 无 |
未来兼容性 | 高 | 中 | 高 |
最佳实践建议
总结
Vue 3 中的 v-model 实现方式经历了从基础用法到 Hook 封装,再到现在的 defineModel 宏的演进过程。随着 Vue 的不断发展,双向绑定的实现变得越来越简洁和高效。开发者应根据项目实际情况选择合适的方式,在保证代码质量的同时提升开发效率。
-
新项目:如果使用 Vue 3.4+,优先选择
defineModel
宏,它提供了最简洁的语法和最佳的类型支持。 -
旧项目升级:
-
如果需要保持兼容性,可以使用
useVModel
Hook 作为过渡方案 -
逐步将基础用法迁移到
defineModel
-
使用uni或taro开发小程序时,不太推荐使用defineModel,兼容性较差
-
-
复杂场景:当需要处理复杂的双向绑定逻辑时,可以考虑使用
useVModel
进行自定义封装。 -
类型安全:无论使用哪种方式,都应该优先使用 TypeScript 以获得更好的类型检查和开发体验。
相关文章:
Vue 中 v-model 的三种使用方式对比与实践
在 Vue 3 中,v-model 是组件双向数据绑定的核心特性。随着 Vue 的版本演进,v-model 的使用方式也在不断优化。本文将基于您提供的代码示例,详细分析三种不同的 v-model 实现方式:基础用法、useVModel Hook(vueuse/core…...
Adminer:一个基于Web的轻量级数据库管理工具
Adminer 是一个由单个 PHP 文件实现的免费数据库管理工具,支持 MySQL、MariaDB、PostgreSQL、CockroachDB、SQLite、SQL Server、Oracle、Elasticsearch、SimpleDB、MongoDB、Firebird、Clickhouse 等数据库。 Adminer 支持的主要功能如下: 连接数据库服…...
Linux笔记---内核态与用户态
用户态(User Mode) 权限级别:较低,限制应用程序直接访问硬件或关键系统资源。 适用场景:普通应用程序的运行环境。 限制:无法执行特权指令(如操作I/O端口、修改内存管理单元配置等)…...
MFC 编程中 OnInitDialog 函数
核心作用 对话框初始化入口 :创建完成后第一个执行的函数。是对话框的起点。控件操作安全期 :此时所有控件已创建完成。可以安全地进行控件的初始化、属性设置等操作。界面布局最佳时机 :窗口显示前完成初始化设置。可以进行布局调整、数据初…...
Java高频面试之并发编程-18
hello啊,各位观众姥爷们!!!本baby今天又来报道了!哈哈哈哈哈嗝🐶 面试官:详细说说synchronized synchronized 是 Java 中实现线程同步的核心关键字,用于解决多线程环境下的资源竞争…...
深入探究AKS Workload Identity
Azure Kubernetes 服务 (AKS) 提供了一项名为 Workload Identity 的强大功能,它可以增强安全性并简化在 Kubernetes 集群中运行的应用程序的身份验证。以下是 Workload Identity 在 AKS 环境中的工作原理概述: AKS 中的 Workload Identity 允许 Pod 无需…...
【MySQL基础】MySQL基础:MySQL基本操作与架构
MySQL学习: https://blog.csdn.net/2301_80220607/category_12971838.html?spm1001.2014.3001.5482 前言: 这里是MySQL学习的第一篇,本篇主要是讲解一些MySQL的基础操作,但这并不是重点,本篇我们主要是要理解MySQL…...
【线下沙龙】NineData x Apache Doris x 阿里云联合举办数据库技术Meetup,5月24日深圳见!
5月24日下午,NineData 将联合 Apache Doris、阿里云一起,在深圳举办数据库技术Meetup。本次技术沙龙聚焦「数据实时分析」与「数据同步迁移」 两大核心领域,针对企业数据战略中的痛点,特邀行业资深技术大咖,结合多年技…...
【Unity网络编程知识】Unity的 UnityWebRequest相关类学习
1、UnityWebRequest类介绍 UnityWebRequest是一个unity提供的一个模块化的系统类,用于构成HTTP请求和处理HTTP响应,它主要目标是让unity游戏和Web服务端进行交互,它将之前WWW的相关功能都集成在了其中,所以新版本中都建议使用unit…...
STM32实战指南——DHT11温湿度传感器驱动开发与避坑指南
知识点1【DHT11的概述】 1、概述 DHT是一款温湿度一体化的数字传感器(无需AD转换)。 2、驱动方式 通过单片机等微处理器简单的电路连接就能实时采集本地湿度和温度。DHT11与单片机之间采用单总线进行通信,仅需要一个IO口。 相对于单片机…...
SVG 与 Canvas 技术调研对比
在 画布 中进行 大量矩形框绘制 时,SVG 和 Canvas 都是可行的技术方案,但它们适用于不同的场景,技术特性也有明显区别。下面我从性能、灵活性、可维护性、适用场景等方面做一个系统性的对比,帮助你做出更合适的选择。 ᾞ…...
Ubuntu 远程桌面配置指南
概述: 本文主要介绍在Ubuntu 22.04中通过VNC实现远程连接的方法。首先需安装图形化界面和VNC工具x11vnc,设置开机启动服务;然后在Windows客户端用VNC Viewer通过局域网IP和端口5900连接。 总结: 一、VNC配置与安装 安装图形化界面 在Ubuntu 22.04中需先安装: sudo apt …...
146. LRU 缓存
一、题目 二、思路 题目要求 O(1) 的平均时间复杂度运行 -> 使用Map空间换时间 Map<Integer, Node>Map 通过 key 直接找到对应节点 getNode(key) -> Node记得只要查过该节点之后就应该把该节点放到最前面 pushFront(Node)put 元素后,在map中添加&…...
微信学习之导航功能
先看这个功能的效果: 然后开始学习吧。 一、我们这里用的是vant的Grid控件,首先我们导入: { "usingComponents": {"van-search": "vant/weapp/search/index","my-swiper":"../../components…...
MySQL替换瀚高数据库报错: TO_DAYS()不存在(APP)
文章目录 环境症状问题原因解决方案报错编码 环境 系统平台:中标麒麟(海光)7,中标麒麟(飞腾)7 版本:4.5 症状 MySQL替换为瀚高数据库进行应用系统适配报错:TO_DAYS()不…...
FPGA:高速接口JESD204B以及FPGA实现
本文将先介绍JESD204B高速接口的基本概念和特性,然后详细说明如何基于Xilinx Kintex-7系列FPGA实现JESD204B高速接口。 一、JESD204B高速接口介绍 JESD204B是由JEDEC(固态技术协会)制定的一种高速串行通信标准,主要用于数据转换器…...
HarmonyOS Navigation组件深度解析与应用实践
HarmonyOS Navigation组件深度解析与应用实践 一、组件架构与核心能力 HarmonyOS Navigation组件作为路由导航的根视图容器,采用三层架构设计: 标题层:支持主副标题配置,提供Mini/Free/Full三种显示模式内容层:默认…...
C#中的ThreadStart委托
ThreadStart 委托: ThreadStart 是 .NET 中的一个内置委托类型,表示无参数且无返回值的方法。其定义如下: public delegate void ThreadStart(); 通常用于定义线程的入口方法。 List<ThreadStart>: 这是一个泛型集合&…...
Spring boot 集成 Knife4j
knife4j官网:https://doc.xiaominfo.com/docs/quick-start 1. 引入Knife4j相关依赖 <!-- knife4j--> <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version…...
基于Java在高德地图面查询检索中使用WGS84坐标的一种方法-以某商场的POI数据检索为例
前言 随着移动互联网的飞速发展,基于位置的服务(LBS)需求日益增长,越来越多的应用需要从地图中检索特定区域内的地理信息,例如商业场所、公共服务设施等。商场作为城市商业活动的重要载体,其周边的地理信息…...
6K型护套连接器DLJ0601(2000)-00
6K型护套连接器DLJ0601(2000)-00简介 6K型护套连接器DLJ0601(2000)-00是一种用于电气连接的组件,广泛应用于工业设备、通信系统和电子设备中。该连接器设计紧凑,具有高可靠性和耐用性,适用于多种环境条件下的电气连接需求。 主要特点 高可…...
Hexo的Next主题的Config文件内方便修改的参数(Chat-Gpt)
这是对 Hexo 的 Next 主题 _config.yml 文件各部分配置项的中文解释,帮助你更方便地进行定制: 🚀 核心设置 cache / minify cache.enable: 启用缓存,加快生成速度。minify: 是否压缩生成的 HTML/CSS/JS。 custom_file_path 自…...
【three】给立方体的每个面加载不同贴图
效果图: 主要代码: initCube() {let _this thisconst geometry new Three.BoxGeometry(1, .3, .5)let TextureLoader new Three.TextureLoader()let mater1TextureLoader.load(require(/assets/images/bg2.jpg),function (texture){console.log(tex…...
vscode怎么关闭自动定位文件
关闭自动定位文件功能 方式1 在设置中搜索: explorer.autoReveal 方式2 直接在settings.json中增加"explorer.autoReveal": false 添加类似jetbrains IDE的文件定位功能 可以直接安装插件市场搜索niushuaibing.vs-location, 安装后会有文件定位按钮, 点击后即可…...
2025-5-19Vue3快速上手
1、toRefs和toRef 当解构一个响应式对象(如 reactive 创建的对象)时,直接解构会失去响应性,此时可用 toRefs或toRef 保持响应性 toRef 的核心作用是将对象的属性转换为 ref,保持与原属性的双向绑定,无论原…...
HDMI 屏幕 电脑HDMI HDMI采集卡的关系
一、HDMI接口方向性原理 普通设备的HDMI接口方向: 电脑的HDMI接口:无论是显卡还是主板上的HDMI,均为输出端(信号源),只能向外发送视频信号,无法接收输入信号。 显示器的HDMI接口:均…...
JESD204 ip核使用与例程分析(二)
JESD204 ip核使用与例程分析(二) JESD204时钟方案专用差分时钟对例程分析jesd204_0_transport_layer_demapperjesd204_0_sig_chkjesd204_0_clockingjesd204_0 ip核port寄存器AXI-LITE寄存器配置jesd204_phy ip核JESD204时钟方案 图3-1所示为最通用、灵活的时钟解决方案。在图…...
如何使用VCS+XA加密verilog和spice网表
如果要交付verilog,但是需要对方进行VCS仿真,那么可以用以下方法: 一、基于编译指令的局部加密 适用场景:需精确控制加密范围(如仅加密核心算法或敏感逻辑)。 实现步骤: 代码标注…...
Grafana之Dashboard(仪表盘)
在前面的小节中介绍了Grafana中4中常用的可视化面板的使用,通过在面板中使用PromQL表达式,Grafana能够方便的将Prometheus返回的数据进行可视化展示。例如,在展示主机CPU使用率时,我们使用了如下表达式: 1 - (avg(ira…...
AOSP 中常见的键值对存储方式全解析(适用于系统开发与应用开发)
在 Android 系统开发(AOSP)中,键值对(Key-Value)存储是一种基础且广泛使用的数据持久化方式。从系统属性、用户设置,到应用配置,都依赖于这种结构的存储方式。本文将全面梳理 AOSP 中主流的键值…...
集合进阶2
Java不可变集合、Stream流与方法引用深度解析 一、不可变集合(Immutable Collections)进阶指南 1.1 不可变集合核心特性 防御性编程:防止外部修改数据(如传递集合给第三方库时)线程安全:天然支持多线程读…...
eMMC深度解析:嵌入式多媒体卡的硬件电路设计要点
一、eMMC 技术深度解析 1.定义与背景 eMMC(Embedded Multi Media Card)是一种专为嵌入式系统设计的非易失性存储解决方案,它将 NAND 闪存、主控芯片和接口协议封装在一个 BGA(Ball Grid Array)封装中。其核心目标是简…...
【SPIN】PROMELA语言编程入门同步机制(SPIN学习系列--4)
同步机制 PROMELA 不包含信号量、锁或监控器等常见的同步原语,而是通过语句的**可执行性(executability)**概念来建模同步机制。计算机系统的架构限制了同步机制的设计:本章主要介绍适用于共享内存系统的同步机制,第7…...
整数的个数
【描述】 给定k(1< k < 100)个正整数,其中每个数都是大于等于1,小于等于10的数。写程序计算给定的k个正整数中,1,5和10出现的次数。 【输入】 输入有两行:第一行包含一个正整数kÿ…...
AWS EKS IP 耗尽:原因、解决方案和最佳实践
想象一下,您的 AWS EKS 集群在生产环境中运行顺畅,所有 CI/CD 管道运行正常,服务优雅地扩展,一切都像自动驾驶模式一样。——直到有一天,新的 Pod 无法启动。 您深入研究 kubectl get pods 命令,发现一堆 P…...
艾默生流量计与Profibus DP主站转Modbus RTU/TCP网关通讯案例
艾默生流量计与Profibus DP主站转Modbus RTU/TCP网关通讯案例 在现代工业自动化控制系统中,艾默生流量计因其高精度、稳定性和易用性而备受青睐。然而,为了实现与不同协议设备之间的无缝通信,经常需要借助专业的通讯网关进行协议转换。本文将…...
Python测试单例模式
单例模式的核心思想 单例模式确保一个类只有一个实例,并提供一个全局访问点。这在需要控制资源访问(如配置文件、数据库连接等)时非常有用。 一个简单的示例: import threading import timeclass Singleton:instance Nonelock…...
Linux架构篇、第五章_06Jenkins 触发器全面解析与实战指南
Linux架构篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:jenkins触发器的介绍与使用 版本号: 1.0,0 作者: laowang 日期: 2025.05.16 适用环境:rocky9.5 文档说明 本文档为《jenkins 触发器的介绍与…...
如何快速更换电脑浏览器ip:教程与注意事项
无论是为了访问地域限制内容、保护隐私,还是解决网络问题,快速更换浏览器IP地址的需求日益增多。以下是快速更换电脑浏览器IP地址的几种常用方法及注意事项,结合了多种场景下的解决方案: 一、快速更换浏览器IP的方法 1. 代理服务…...
《黑马前端ajax+node.js+webpack+git教程》(笔记)——ajax教程(axios教程)
黑马程序员前端AJAX入门到实战全套教程,包含学前端框架必会的(ajaxnode.jswebpackgit),一套全覆盖 文章目录 框架前置导学AJAX-Day01-01.AJAX入门与axios使用什么是AJAX如何使用AJAX使用axios获取数据案例axios语法尝试获取数据代…...
超级管理员租户资源初始化与授权管理设计方案
背景说明 在多租户系统中,资源(如功能模块、系统菜单、服务能力等)需按租户维度进行授权管理。超级管理员在创建新租户时,需要初始化该租户的资源授权信息。 两种可选方案 方案描述方案 A:前端传入选中的资源列表创…...
【Python训练营打卡】day30 @浙大疏锦行
DAY 30 模块和库的导入 知识点回顾: 1. 导入官方库的三种手段 2. 导入自定义库/模块的方式 3. 导入库/模块的核心逻辑:找到根目录(python解释器的目录和终端的目录不一致) 作业:自己新建几个不同路径文件尝试下如何…...
微前端记录
微前端 实习过程中,做了些微前端方向的调研,记录下 微前端将前端拆分为独立的可以单独运行,测试,部署的代码, 具有技术栈无关,多团队,多业务线协作的特点。 前端现有的页面,分为单页…...
词嵌入基础
一 前言 最近在学习NLP方面知识,在此记录一下词嵌入的技术。 二 词袋法 1.理论 就是统计一个句子或文章中,词语出现的次数。这方法有去重词袋法,无去重词袋法。 a 原理与案例 chinese_docs ["我爱自然语言处理","自然语…...
CSS之网页元素的显示与隐藏(旧土豆网遮罩案例)
网页元素的显示与隐藏。 很多网页的侧边栏都会出现广告,我们点击关闭时,广告会消失不见,但若重新刷新网页页面,则广告会重新出现。网页的广告并非是真的被删除了,而是被暂时的隐藏起来了。 • display • visibil…...
关于 Web 漏洞原理与利用:2. XSS(跨站脚本攻击)
一、原理: 用户输入未过滤被执行 攻击者输入的内容,如果没有被正确处理(过滤/转义),被网页原样输出到浏览器中,那么这些内容就可能会被浏览器当成代码执行,这就是 XSS(跨站脚本攻击…...
【TTS回顾】深度剖析 TTS 合成效果的客观评估与主观评价
如何评估合成音色的效果 当我们面对一个新发布的 TTS 模型,或者在多个模型之间进行选择时,一个核心问题摆在我们面前:如何科学、全面地评估一个 TTS 模型的合成效果? 仅仅凭感觉“听一听”显然不够客观和系统。我们需要一套行之有效的评估方法和指标体系,来衡量 AI “说话…...
WPF点击按钮弹出一个窗口
一、基本方法:直接实例化并显示窗口 1. 普通窗口(无参数) 适用场景:简单的弹出窗口,无需传递数据。 private void Button_Click(object sender, RoutedEventArgs e) { var newWindow new MyWindow(); // 实例化…...
WPF中的ObjectDataProvider:用于数据绑定的数据源之一
ObjectDataProvider是WPF(Windows Presentation Foundation)中一种强大而灵活的数据绑定源,它允许我们将对象实例、方法结果甚至是构造函数的返回值用作数据源。通过本文,我将深入探讨ObjectDataProvider的工作原理、使用场景以及如何在实际应用中发挥其…...
Java POJO接收前端null值设置
在 Java 中,若要让 price 字段接收前端传递的 null 值,只需确保以下几点: 1. 使用包装类型 Double 你的 price 字段已经是包装类型 Double(而不是基本类型 double),这天然支持 null 值。基本类型 double …...