Vue2中watch与Vue3中watch对比和踩坑
上一节说到了 computed计算属性对比 ,虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch
选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
Vue2 watch用法
Vue2 中的 watch 是一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch()
,遍历 watch 对象的每一个 property。
Vue2 存在两种监听方式,分别是简单监听和复杂监听
简单监听:监听的是一个回调函数,当监听的值发生改变时,才会执行监听动作。
<template><h2>当前求和值为:{{ sum }}</h2><button @click="sum++">点击加1</button>
</template><script>export default {name: "TestComponent",data() {return {sum:1}},watch:{sum(newValue, oldValue) {console.log('sum的值变化了',newValue, oldValue);}},
};
</script>
上面的是一个最简单的监听动作,只有在点击按钮 sum 的值变化之后,监听器 watch 才会触发。同时,我们还可以将这个方法放到 methods 中,通过方法名的方式在 watch 中实现监听效果
watch:{sum:'sumAdd'},methods: {sumAdd(newValue, oldValue) {console.log('sum的值变化了',newValue, oldValue);}},
深度监听:监听的是一个包含选项的对象。除了包含简单监听的功能之外,还包含深度监听、初始化监听等。
首先,我们可以通过对象形式来实现简单监听的效果,还是按照上面的例子,例如:
// 其余代码一致
watch:{sum:{handler(newValue, oldValue) {console.log('sum的值变化了',newValue, oldValue);}}
},
通过对象形式实现深度监听 -- deep:true 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深,也就是说即使监听的是一个对象形式的数据,只要对象内部属性发生变化,都能被监听到。
watch:{sum:{handler(newValue, oldValue) {console.log('sum的值变化了',newValue, oldValue);},deep:true}
},
通过对象形式实现初始化监听 -- immediate:true 该回调将会在侦听开始之后被立即调用,也就是说在组件初始化时,就会监听一次,在数据改变之后继续监听
watch:{sum:{handler(newValue, oldValue) {console.log('sum的值变化了',newValue, oldValue);},immediate:true}
},
完整的对象监听:深度监听+初始化监听
watch:{sum:{handler(newValue, oldValue) {console.log('sum的值变化了',newValue, oldValue);},deep: true,immediate:true}
},
在Vue3 中使用 Vue2 的watch
和 在 Vue3 中使用 Vue2 的computed 计算属性一样,直接使用 watch 配置项即可。
<template><h2>当前求和值为:{{ sum }}</h2><button @click="sum++">点击加1</button>
</template><script>
import { ref } from "vue";export default {name: "TestComponent",watch: {sum: {handler(newValue, oldValue) {console.log("sum的值变化了", newValue, oldValue);},deep: true,immediate: true,},},setup() {let sum = ref(1);return {sum,};},
};
</script>
当页面第一次渲染时,监听器就执行了一次,这对应的是 -- immediate: true
点击按钮之后,页面渲染,同时监听器也会同步触发。
Vue3 中 watch的基本使用
和 computed 一样,组合式api在使用时,需要先引入,再使用。
Vue3 中的 watch 是一个函数,接收三个参数,
- 第一个参数是需要被监听的数据( 单个数据,数组格式的多个数据),
- 第二个参数是回调函数,用来处理监听之后的动作
- 第三个参数则是监听配置项( 深度监听、初始化监听 )。
但是和 computed 不一样的是 在 setup 中定义的监听器不需要使用变量接收且 return 返回的,因为 监听是一种行为,而计算属性则是一个值。
<template><h2>当前求和值为:{{ sum }}</h2><button @click="sum++">点击加1</button>
</template><script>
//组合式api需要先引入再使用
import { ref ,watch} from "vue";export default {name: "TestComponent",setup() {let sum = ref(1);// 不用接收,不用返回,因为监听是动作,计算属性、响应式数据、函数都是值watch(sum, (newValue, oldValue) => {console.log("sum的值变化了", newValue, oldValue);})return {sum,};},
};
</script>
Vue3 中 watch 的复杂使用方式
上面说的Vue3 中 watch 的简单使用方式,其实就是监听单个 ref 定义的响应式数据。但是 Vue3 中的 watch 可以分为好几种情况:
情况一:通过 watch 监听 ref 定义的单个基础类型响应式数据,也就是上面的例子
情况二:通过 watch 监听 ref 定义的多个基础类型响应式数据,例如
<template><h2>当前求和值为:{{ sum }}</h2><button @click="sum++">点击加1</button><br><h2>当前msg值为:{{ msg }}</h2><button @click="msg += '!'">点击加!</button>
</template><script>
import { ref ,watch} from "vue";export default {name: "TestComponent",setup() {let sum = ref(1);let msg = ref('你好啊')watch(sum, (newValue, oldValue) => {console.log("sum的值变化了", newValue, oldValue);})watch(msg, (newValue, oldValue) => {console.log("msg的值变化了", newValue, oldValue);})return {sum,msg};},
};
</script>
但是这么写很明显太麻烦了,我想监听多个,那我就需要写多个 watch 监听函数,还不如 Vue2的配置项直接定义一个对象来的方便,所以Vue3 也提供了简便写法,那就是通过数组形式一次性监听多个数据:
// 通过 [sum,msg] 一次性监听多个数据
watch([sum,msg], (newValue, oldValue) => {console.log("sum或msg的值变化了", newValue, oldValue);
})
同时,我们改变 sum和msg,发现返回的 newValue 和 oldValue 分别是两个数组
- 第一步:改变 sum ,newValue 数组中 sum 值改变,msg值不变,oldValue 数组中的值就是 sum 和 msg 的初始值
- 第二步:改变 msg,newValue 数组中 sum 值不变,msg值改变变,oldValue 数组中的值就是 sum 和 msg 的上一次的值
情况三:通过 watch 中的 immediate: true 初始化监听 ref 定义的基础类型响应式数据
watch(sum, (newValue, oldValue) => {console.log("sum的值变化了", newValue, oldValue);
},{immediate: true})
可以发现,初始化监听成功,在组件初始化, sum 未发生改变时 监听动作就已经执行了。
情况四:通过 watch 监听 ref 定义的对象类型的响应式数据 -- 存在bug( 无法正确获取 oldValue )
我们用 ref 定义一个响应式对象数据,但是这两有两个点需要注意:
- 通过 ref 定义的对象数据,其实底层还是通过 reactive 来实现响应式的
- 通过 ref 定义的数据是一个 RefImpl对象,在 js 代码中使用时,不会自动解包,需要 .value
<template><p>{{person.name}}</p><p>{{person.age}}</p><button @click="person.name += '~'">更改name</button><button @click="person.age++">更改age</button>
</template>export default {name: "TestComponent",setup() {let person = ref({name: "al",age: 28,});watch(person.value, (newValue, oldValue) => {console.log("person的值变化了", newValue, oldValue);});return {person,};},
};
然后我们就会发现下面这么问题:
- 当更改 name 属性时,newValue 中的 name 改变了,但是 oldValue 中的 name 也同步变了
- 当更改 age 属性时,newValue 中的 age改变了,但是 oldValue 中的 age也同步变了
这和我们想的也太不一样了啊,不是说好了 oldValue 是上一次的值么,怎么还同步更新了呢? 这其实就是 Vue3 的监听bug,暂时官方也没有给出具体的解决办法,但是其实我们在开发过程中也确实不太关注 oldValue 的值。
但是如果你一定想要监听的话,建议把对象拆成单个 ref ,或者把你需要监听的对象中的某个属性单独拆成一个 ref,例如:上面的例子中,我现摘指向单独监听 age,那我就不把age 塞到 person 对象里面了,单独拎出来使用 ref定义。
let person = ref({name: "al",
});let age = ref(28)watch(age.value, (newValue, oldValue) => {console.log("age的值变化了", newValue, oldValue);
});
如果你觉得 reactive 可以解决这个问题,你也不妨试一试通过 reactive 定义的响应式数据能否达到你想要的效果。
关于 reactive 和 ref 的原理及对比请参考之前的博文 -- Vue2与Vue3响应式原理对比 里面通过源码详细解释了 ref 和 reactive 定义对象数据的底层关系
情况五:深度监听 ref 定义的对象形式的响应式数据 -- 默认开启 deep:true。监听整个对象。可通过配置关闭( 但是在 Vue3.2之前的版本,好像是不能进行配置更改的 )
其实我们按照上面的例子,将数据嵌套多几层,然后改变数据
let person = ref({name: "al",age: 28,job:{j1: {work: '前端',salary:1}}
});watch(person.value, (newValue, oldValue) => {console.log("person.salary的值变化了", newValue, oldValue);
});
然后改变数据
<template><p>{{ person.job.j1.work }}</p><p>{{ person.job.j1.salary }}</p><button @click="person.job.j1.salary++">涨薪</button>
</template>
我们可以发现,此时 深度嵌套的值也能被监听到。但是 在 Vue2 中监听深度嵌套数据时,我们是需要配置 deep:true 才能实现的 ,但是在 Vue3 中不用开启 deep:true 就可以直接实现深度监听了。
所以我们可以大胆假设,在 Vue3 中,deep:true 是默认开启的,如果我们进行配置关闭,那会有什么结果呢?
watch(person.value, (newValue, oldValue) => {console.log("person.salary的值变化了", newValue, oldValue);
},{deep:false}); // 关闭深度监听
关闭之后我们可以发现,无法监听到深度嵌套数据的改变了。
但是,有一个问题需要说明,因为我的 Vue 版本是 "vue": "^3.2.13" 所以看起来配置 是生效的。但是如果好像是3.2以下的版本,这个配置是不生效的,只能默认开启 deep:true。
情况六:监听 ref 定义的对象形式的响应式数据 -- 只监听嵌套对象中的某个基础属性
<template><p>工作:{{ person.age }}</p><button @click="person.age++">改变年龄</button>
</template>let person = ref({name: "al",age: 28,
});watch(person.value.age, (newValue, oldValue) => {console.log("person.age改变了", newValue, oldValue);
});
但是点击按钮之后,我们发现 控制台上并没有打印出数据,按理来说这是肯定不可能的,Vue肯定会放开这个口子供开发者使用,所以我们需要从使用语法中查找问题。
// 之前watch 的第一个参数,要么是 变量,要么是数组。
// 但是在这里,我们需要使用一个函数,通过函数的返回值来表明我们需要监听对象中的那个属性
watch(() => person.value.age, (newValue, oldValue) => {console.log("person.age改变了", newValue, oldValue);
});
然后我们就会发现,控制台上已经可以正常打印正确数据了。
情况七:监听 ref 定义的对象形式的响应式数据 -- 只监听嵌套对象中的某些属性
按照情况二和情况七的结合,我们可以大致上了解监听嵌套对象中的某些属性应该怎么做。
// 通过 数组模式和函数返回模式相结合,实现了监听对象中某些属性
watch([() => person.value.name,() => person.value.age], (newValue, oldValue) => {console.log("name或age改变了", newValue, oldValue);
});
情况八:监听 ref定义的对象形式的响应式数据 -- 深度监听嵌套对象中的值为复杂类型数据的属性
之前的几种监听情况大致上可以分为
- 监听 ref 定义的基础类型数据
- 监听 ref 定义的对象类型数据 --
- 监听的是整个对象( 包括深度嵌套对象 )
- 监听的是对象( 包括深度嵌套对象 )中的某个属性 -- 基础类型属性
- 监听的是对象( 包括深度嵌套对象 )中的某几个属性 -- 都是基础类型属性
如果我们现在监听的是 深度嵌套对象中某个值为复杂类型数据的属性时,那需要怎么做呢?
我们还是用之前的数据来进行测试
let person = ref({name:'al',job:{j1: {work: '前端',salary:1}}
});
然后我们按照 情况六的模式来进行监听
<template><p>工作:{{ person.job.j1.salary }}</p><button @click="person.job.j1.salary++">涨薪</button>
</template>// 监听属性通过函数返回
watch(() => person.value.job, (newValue, oldValue) => {console.log("job中的数据该变了", newValue, oldValue);
});
发现此时并没有监听成功。按理来说这也不应该啊,我是按照之前的情况实现的啊,只不过是把监听的数据类型该变了,怎么就不行了呢?
此时我们回忆一下,在我们监听完整的对象时,默认开启 deep:true 。但我们监听的是整个对象,而不是对象中的某个属性。
如果我们监听的是对象中的某个对象属性时,这一套就不适用了,所以我们需要手动配置 deep:true
watch(() => person.value.job, (newValue, oldValue) => {console.log("name或age改变了", newValue, oldValue);
},{deep: true});
此时改变 salary 后,控制台上能打印出数据,表atch功
watch 监听 ref 与 reactive 定义的数据使用方式区别
在之前的例子中我们定义数据都是使用的 ref, 虽然我有说 ref 定义的对象类型实际上底层还是通过 reactive 来实现响应式,但在 watch 监听时,使用方式还是存在区别的。
分别用 ref 和 reactive 定义深层嵌套的响应式数据
let person1 = ref({job: {j1: {work: "前端",salary: 1,},},
});let person2 = reactive({job: {j2: {work: "后端",salary: 2,},},
});
然后使用 watch 分别监听。这里我们就可以看出区别在哪了。
watch(person1.value,(newValue, oldValue) => {console.log("j1中salary改变了", newValue, oldValue);},
);watch(person2,(newValue, oldValue) => {console.log("j2salary改变了", newValue, oldValue);},
);
ref 定义的数据需要解包,而 reactive 定义的数据则可以直接使用。这一点可以在 之前的博文 ref函数与reactive函数的对比 中可以详细了解一下。
这是因为,通过 ref 转化的复杂数据,是一个 refImpl实例对象,其中 value属性的值才是真的响应式数据,是通过 reactive 方法中的 Proxy 代理对象实现响应式。这相比 reactive 直接转化就多了一层 refImpl 实例。所以在 js脚本中使用数据时,需要 .value 解包。
然后,我们参考一下情况八,其实对于 ref 定义的深层嵌套对象我们也可以通过手动配置 deep:true 的形式来实现深度监听
watch(person1,(newValue, oldValue) => {console.log("j1中salary改变了", newValue, oldValue);},{ deep: true }
);
总结
- Vue3 中能够使用 Vue2 的模式来实现 watch监听 动作
- Vue3 中的 watch 因为是组合式api,所以也需要先引入再使用,和 computed 一致
- Vue3 中的 watch 是一个函数,接收三个参数: 参数一:需要监听的数据,参数类型可以是变量,数组或函数
参数二:监听的回调函数,接收两个参数,分别代表新值和旧值
参数三:一个对象,包含复杂监听的配置,例如深度监听 ( dep:true ),初始化监听( immediate: true ) - Vue3 中 setup 中的 watch 不需要使用变量接收,也不用返回,因为 watch 监听是动作,而 computed 计算属性最终返回的是值
- Vue3 的watch 存在几种情况需要注意:
- 通过 ref 定义的简单类型数据,可以直接实现监听,无bug -- 情况一 & 情况二 & 情况三
- 通过 ref 或 reactive 定义的复杂类型数据在监听时存在bug:
- 无法正确获得 oldValue -- 情况四
- 监听的是完整对象,则强制开启深度监听 -- 情况五
- 监听的是对象中的某个基础数据类型属性,则需要通过函数返回该属性 -- 情况六 & 情况七
- 监听的是对象中的某个值为复杂类型数据的属性,则需要通过函数返回,且需要手动配置 deep:true 实现深度监听 -- 情况八
- Vue3 中的watch 在监听 ref 和 reactiv定义的响应式数据时,使用方式是存在区别的,那就是 ref 定义的数据,在使用时是需要解包的,而 reactive 则是不需要。
相关文章:

Vue2中watch与Vue3中watch对比和踩坑
上一节说到了 computed计算属性对比 ,虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时&#…...

在Java程序中执行Linux命令
在Java中执行Linux命令通常涉及到使用Java的运行时类 (java.lang.Runtime) 或者 ProcessBuilder 类来启动一个外部进程 1. 使用 Runtime.exec() Runtime.exec() 方法可以用来执行一个外部程序。它返回一个 Process 对象,可以通过这个对象与外部程序交互࿰…...

微信小程序在不同移动设备上的差异导致原因
在写小程序的时候用了rpx自适应单位,但是还是出现了在不同机型上布局不统一的问题,在此记录一下在首页做一个输入框,在测试的时候,这个输入框在不同的机型上到处跑,后来排查了很久都不知道为什么会这样 解决办法是后 …...

快速体验fastllm安装部署并支持AMD ROCm推理加速
序言 fastllm是纯c实现,无第三方依赖的高性能大模型推理库。 本文以国产海光DCU为例,在AMD ROCm平台下编译部署fastllm以实现LLMs模型推理加速。 测试平台:曙光超算互联网平台SCNet GPU/DCU:异构加速卡AI 显存64GB PCIE&#…...

报错:java: javacTask: 源发行版 8 需要目标发行版 1.8
程序报错: Executing pre-compile tasks... Loading Ant configuration... Running Ant tasks... Running before tasks Checking sources Copying resources... [gulimail-coupon] Copying resources... [gulimail-common] Parsing java… [gulimail-common] java…...

【数据结构篇】~单链表(附源码)
【数据结构篇】~链表 链表前言链表的实现1.头文件2.源文件 链表前言 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 1、链式机构在逻辑上是连续的,在物理结构上不一定连续 2、结点一般是从…...

旋转图像(LeetCode)
题目 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 解题 def rotate(matrix):n len(matrix)# 矩阵转置for i in range(n):for…...

入门 - vue中v-model的实现原理和完整用法详解
v-model介绍 v-model是vue的双向绑定的指令,能将页面上控件输入的值同步更新到相关绑定的data属性,也会在更新data绑定属性时候,更新页面上输入控件的值。在view层,model层相互需要数据交互,即可使用v-model。 双向绑…...

【区块链+金融服务】港融区域股权服务平台 | FISCO BCOS应用案例
中国证监会在 2020 年启动了区块链建设试点工作,提出建设基于区块链的场外市场登记系统和交易报告库,利 用区块链去中心化、不易篡改、安全稳定等技术特点,构建区域性股权市场数字化信任机制,为区域性股权市场 提供基础支撑设施。…...

Nginx反向代理和前后端分离项目打包部署
Nginx反向代理 Nginx的定位:主要用于做反向代理,一般都是用它来做前端页面的服务器,动态资源代理到后端服务器。这样做的好处是可以避免跨域请求带来的不便。 使用Nginx主要是对Nginx中的nginx.conf文件进行配置: 虚拟主机配置…...

Spring 中ApplicationContext
ApplicationContext 是 Spring 框架中最重要的接口之一,用于提供 Spring IoC 容器的功能。它是一个比 BeanFactory 更高级的容器,负责管理 Spring bean 的生命周期,同时提供对各种企业服务的集成,例如事件传播、国际化、弱引用等。…...

python之时间 datetime、date、time、timedelta、dateutil
在 Python 中,处理日期和时间的常用库是 datetime。此外,还有一些第三方库如 pytz 和 dateutil 可以帮助处理时区和日期解析。 1. 使用 datetime 模块 导入模块 from datetime import datetime, date, time, timedelta获取当前日期和时间 now datet…...

【机器学习第11章——特征选择与稀疏学习】
机器学习第11章——特征选择与稀疏学习 11.特征选择与稀疏学习11.1子集搜索与评价子集搜索子集评价 11.2 过滤式选择11.3 包裹式选择11.4 嵌入式选择11.5 稀疏表示与字典学习稀疏表示字典学习 11.6 压缩感知 11.特征选择与稀疏学习 11.1子集搜索与评价 特征:描述物…...

LeetCode-day43-3137. K 周期字符串需要的最少操作次数
LeetCode-day43-3137. K 周期字符串需要的最少操作次数 题目描述示例示例1:示例2: 思路代码 题目描述 给你一个长度为 n 的字符串 word 和一个整数 k ,其中 k 是 n 的因数。 在一次操作中,你可以选择任意两个下标 i 和 j&#x…...

基于springboot的智能家居系统
TOC springboot198基于springboot的智能家居系统 研究背景与现状 时代的进步使人们的生活实现了部分自动化,由最初的全手动办公已转向手动自动相结合的方式。比如各种办公系统、智能电子电器的出现,都为人们生活的享受提供帮助。采用新型的自动化方式…...

【从问题中去学习k8s】k8s中的常见面试题(夯实理论基础)(七)
本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》:python零基础入门学习 《python运维脚本》: python运维脚本实践 《shell》:shell学习 《terraform》持续更新中:terraform_Aws学习零基础入门到最佳实战 《k8…...

C:每日一练:单身狗(2.0版本)
前言: 今天在刷题的时候突然看到一道题,疑似一位故题。仔细一看,欸!这不是就是单身狗的升级版吗?我想那必须再安排一篇,不过由于本篇文章与上一篇单身狗文章所涉及的知识点基本相同,所以还请大…...

打破接口壁垒:适配器模式让系统无缝对接
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许不兼容的接口之间协同工作。主要用途是将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的对象可以一起工作。 一、适配器模式的组成 目标接口(…...

U-Boot 命令使用
U-Boot 是一种常用的引导加载程序,用于引导嵌入式系统。它提供了一系列命令以进行系统配置、引导操作和调试。 以下是一些常见的 U-Boot 命令及其用法: bootm:从指定的内存地址启动操作系统映像。 用法:bootm [addr] bootz&…...

谷歌的高级指令有哪些
今天会分享一些组合用法,这样就能节省许多时间可以放在跟进客户上面(本文只介绍谷歌的搜索指令,并无推广) part one 谷歌常用的搜索引擎指令: 1、Inurl,在网址中 2、Intext,在网页内容中 3、…...

Redis操作--RedisTemplate(一)介绍
一、介绍 1、简介 RedisTemplate 是 Spring Data Redis 提供的一个高级抽象,由 Spring 官方提供的方便操作 Redis 数据库的一个工具类,支持模板设计模式,使得操作 Redis 更加符合 Spring 的编程模型。还支持序列化机制,可以处理…...

GitLab环境搭建
GitLab环境搭建 一、环境搭建 1、更新系统软件包: sudo yum update2、安装docker sudo yum install -y yum-utils device-mapper-persistent-data lvm2 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo yum install do…...

Socket编程TCP 基础
一.什么是Socket(套接字) 定义:就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程&#x…...

JAVA中的Iterator与ListIterator
Java中的Iterator类是Java集合框架中的一个重要接口,它用于遍历集合中的元素。Iterator提供了三个基本操作:检查是否有下一个元素、获取下一个元素以及移除元素。下面将详细介绍Iterator类及其使用方法,并提供相应的代码例子和中文注释。 一、…...

高校疫情防控web系统pf
TOC springboot365高校疫情防控web系统pf 第1章 绪论 1.1 课题背景 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。所以各行…...

复现nnUNet2并跑通自定义数据
复现nnUNet2并跑通自定义数据 1. 配置环境2. 处理数据集2.1 创建文件夹2.2 数据集格式转换2.3 数据集预处理 3. 训练4. 改进模型4.1 概要4.2 加注意力模块 1. 配置环境 stage1:创建python环境,这里建议python3.10 conda create --n nnunet python3.10 …...

Educational Codeforces Round 169 (Rated for Div. 2)(ABCDE)
A. Closest Point 签到 #define _rep(i,a,b) for(int i(a);i<(b);i) int n,m; int q[N]; void solve() {cin>>n;_rep(i,1,n)cin>>q[i];if(n!2)cout<<"NO\n";else if(abs(q[1]-q[2])!1)cout<<"YES\n";else cout<<"…...

成为Python砖家(2): str 最常用的8大方法
str 类最常用的8个方法 str.lower()str.upper()str.split(sepNone, maxsplit-1)str.count(sub[, start[, end]])str.replace(old, new[, count])str.center(width[, fillchar])str.strip([chars])str.join(iterable) 查询方法的文档 根据 成为Python砖家(1): 在本地查询Pyth…...

深入理解JVM运行时数据区(内存布局 )5大部分 | 异常讨论
前言: JVM运行时数据区(内存布局)是Java程序执行时用于存储各种数据的内存区域。这些区域在JVM启动时被创建,并在JVM关闭时销毁。它们的布局和管理方式对Java程序的性能和稳定性有着重要影响。 目录 一、由以下5大部分组成 1.…...

JAVA根据表名获取Oracle表结构信息
响应实体封装 import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor;/*** author CQY* version 1.0* date 2024/8/15 16:33**/ Data NoArgsConstructor AllArgsConstructor Builder public class OracleTableInfo …...