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

Vue3新特性

Vue3新特性

  • 1、Composition API
    • 1.1 什么是 Composition API
    • 1.2 常用 Composition API
      • 1.2.1 setup
      • 1.2.2 ref
      • 1.2.3 reactive
      • 1.2.4 computed
      • 1.2.5 watchEffect、watchPostEffect、watchSyncEffect
      • 1.2.6 watch
  • 2、生命周期
    • 2.1 Vue3生命周期钩子
    • 2.2 vue2 和 vue3 关于生命周期的对比
  • 3、异步组件
  • 4、自定义指令
  • 5、Teleport
  • 6、自定义 Hooks

1、Composition API

1.1 什么是 Composition API

  • 函数式编程,逻辑复用途经–函数组合(组合式 Composition API)
  • 面对对象编程,逻辑复用的途径–继承(选项式 选项式 API )

函数式编程思想将组件 UI逻辑 和状态逻辑解耦,让组件得到更大的复用性

vue2 选项式API

export default {// data() 返回的属性将会成为响应式的状态// 并且暴露在 `this` 上data() {return {count: 0}},methods: {increment() {this.count++}},
}
</script>

Vue3 组合式(更拥抱这种写法)

<script setup>
import { ref, onMounted } from 'vue'
// 响应式状态
const count = ref(0)//或者const count = reactive({value:0})
// 用来修改状态、触发更新的函数
function increment() {count.value++
}
</script>

1.2 常用 Composition API

Q1: 说说你对 setup 的理解

  1. 组合式 API 的入口

Q2: ref 和 reactive 有什么区别?

  1. ref 内部使用了 reactive
  2. ref(obj) === reactive({ value: obj })

Q3: ref 和 shallowRef 的区别,以及 reactive 和 shallowReactive 的区别?

  1. shallow 表示浅层,这里均是指的响应值作用在第一层,即 .value,不过我们可以使用 triggerRef(xxx) 来在深层内容变更后,手动触发更新,需要注意的是 shallowReactive 没有对应方法

Q4: watchEffect 与 watch 的区别

  1. watch 是懒执行,属性改变的时候执行,而 watchEffect 是默认会执行一次,然后属性改变也会执行。
  2. watch 是需要传入侦听的数据源,而 watchEffect 是自动收集数据源作为依赖;
  3. watch 可以访问侦听状态变化前后的值,而 watchEffect 没有。

1.2.1 setup

setup() 钩子是在组件中使用组合式 API 的入口

<script setup>
import { ref, onMounted } from 'vue'
// 响应式状态
const count = ref(0)//或者const count = reactive({value:0})
// 用来修改状态、触发更新的函数
function increment() {count.value++
}
</script>

<script >
import { h, ref } from 'vue'export default {setup(props, { expose }) {const count = ref(0)const increment = () => ++count.value// 透传 Attributes(非响应式的对象,等价于 $attrs)console.log(context.attrs)// 插槽(非响应式的对象,等价于 $slots)console.log(context.slots)// 触发事件(函数,等价于 $emit)console.log(context.emit)// 暴露公共属性(函数)console.log(context.expose)expose({increment})return () => h('div', count.value)}
}
</script>

1.2.2 ref

ref 函数 用于定义一个响应式对象

<script setup>
import { ref, onMounted } from 'vue'
// 声明一个 ref 来存放该元素的引用
// 必须和模板里的 ref 同名
const input = ref(null)
onMounted(() => {input.value.focus()
})
</script><template><input ref="input" />
</template>

1.2.3 reactive

用法同 ref

const obj = reactive({ count: 0 })
obj.count++

1.2.4 computed

const count = ref(1)
const plusOne = computed(() => count.value + 1)console.log(plusOne.value) // 2plusOne.value++ // 错误

或者通过对象 get、set 指定的方式

const count = ref(1)
const plusOne = computed({get: () => count.value + 1,set: (val) => {count.value = val - 1}
})plusOne.value = 1
console.log(count.value) // 0

1.2.5 watchEffect、watchPostEffect、watchSyncEffect

后两者是前者的语法糖,就是将第二个参数中的 flush,指定为对应值,分别为:flush?: 'pre' | 'post' | 'sync' // 默认:'pre'

初始化 执行顺序:watchEffect,watchSyncEffect,watchPostEffect
变化时 执行顺序:watchSyncEffect,watchEffect,watchPostEffect

监听回调又叫监听副作用。

简单使用

const count = ref(0)watchEffect(() => console.log(count.value))
// -> 输出 0count.value++
// -> 输出 1

具有清除与停止侦听的功能

const stop = watchEffect(async (onCleanup) => {const { response, cancel } = doAsyncWork(id.value)// `cancel` 会在 `id` 更改时调用// 以便取消之前// 未完成的请求onCleanup(cancel)data.value = await response
})// 什么时候需要停止的话,那就
stop()

1.2.6 watch

先来简单回顾一下vue2.x版本中watch的使用

watch: {dataName (val, oldVal){console.log("改变前的数据-" + oldVal, "改变后的数据-" + val)}
}

Vue3中的watch
watch 自定义监听

watch 函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是懒执行的,也就是说仅在侦听的源变更时才执行回调。

<template><button @click="change">count is: {{ state.count }}</button>
</template><script>
import { reactive, watch } from 'vue'
export default {setup () {let state = reactive({count: 0})let change = () => state.count++;watch(state, () => {console.log(state, '改变')})return { state, change }}
}
</script>

注意上面的代码,第一个参数传入的 state 对象,第二个参数是回调函数,只要 state 中任意的属性发生改变都会执行回调函数,和 vue2 的区别是不要写 deep 属性,默认就是深度监听了。
监听state 对象,没有旧的值,只有新的值

现在是监听整个对象,当然我们也可以监听对象上的某个属性,注意下面代码的写法:第一个是回调函数,第二个参数也是回调函数
监听state 对象上的某个属性,有旧的值,有新的值

<template><button @click="change">count is: {{ state.count }}</button>
</template><script>
import { reactive, watch } from 'vue'
export default {setup () {let state = reactive({count: 0})let change = () => state.count++;watch(() => state.count, (oldVlaue, newValue) => {//() => state.count, getter方式console.log(oldVlaue, newValue, '改变')})return { state, change }}
}
</script>

上面都是以创建响应式对象函数reactive()方式定义的数据,下面再看看使用ref()初始化的数据怎样实现数据监听

<template><button @click="change">count is: {{ count }}</button>
</template><script>
import { reactive, watch } from 'vue'
export default {setup () {let count = ref(0)let change = () => count.value++;watch(count, () => {console.log(count.value '改变')})return { count , change }}
}
</script>

当侦听多个来源时,回调函数接受两个数组,分别对应来源数组中的新值和旧值:

watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {/* ... */
})

2、生命周期

2.1 Vue3生命周期钩子

  • setup() : 开始创建组件之前,在 beforeCreatecreated 之前执行,创建的是 data
    method
  • onBeforeMount() : 组件挂载到节点上之前执行的函数;
  • onRenderTracked() : 响应式的收集依赖;追踪,订阅
  • onMounted() : 组件挂载完成后执行的函数;
  • onRenderTriggered() : 响应式的触发依赖变更,发布
  • onBeforeUpdate(): 组件更新之前执行的函数;
  • onUpdated(): 组件更新完成之后执行的函数;
  • onBeforeUnmount(): 组件卸载之前执行的函数;
  • onUnmounted(): 组件卸载完成后执行的函数;
  • onActivated(): 被包含在 <keep-alive> 中的组件,会多出两个生命周期钩子函数,被激活时执行;
  • onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行;
  • onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数。

PS: 使用<keep-alive> 组件会将数据保留在内存中,比如我们不想每次看到一个页面都重新加载数据,就可以使用<keep-alive> 组件解决。

在这里插入图片描述

2.2 vue2 和 vue3 关于生命周期的对比

在这里插入图片描述

3、异步组件

当我们的项目达到一定的规模时,对于某些组件来说,我们并不希望一开始全部加载,而是需要的时候进行加载;这样的做得目的可以很好的提高用户体验。
一般用于分割代码,按需加载

为了实现这个功能,Vue3中为我们提供了一个方法,即defineAsyncComponent,这个方法可以传递两种类型的参数,分别是函数类型对象类型

传递工厂函数作为参数

<template><logo-img /><hello-world msg="Welcome to Your Vue.js App" />
</template><script setup>
import LogoImg from './components/LogoImg.vue'
import HelloWorld from './components/HelloWorld.vue'
</script>

现在我们就将组件修改为异步组件,示例代码如下:

<template><logo-img /><hello-world msg="Welcome to Your Vue.js App" />
</template><script setup>
import { defineAsyncComponent } from 'vue'
import LogoImg from './components/LogoImg.vue'// 简单用法
const HelloWorld = defineAsyncComponent(() =>import('./components/HelloWorld.vue'),
)
</script>

传递对象类型作为参数

defineAsyncComponent方法也可以接收一个对象作为参数,该对象中有如下几个参数:

  • loader:同工厂函数;
  • loadingComponent:加载异步组件时展示的组件;
  • errorComponent:加载组件失败时展示的组件;
  • delay:显示loadingComponent之前的延迟时间,单位毫秒,默认200毫秒;
  • timeout:如果提供了timeout,并且加载组件的时间超过了设定值,将显示错误组件,默认值为Infinity(单位毫秒);
  • suspensible:异步组件可以退出控制,并始终控制自己的加载状态。具体可以参考文档;
  • onError:一个函数,该函数包含4个参数,分别是error、retry、fail和attempts,这4个参数分别是错误对象、重新加载的函数、加载程序结束的函数、已经重试的次数。
 <template><logo-img /><hello-world msg="Welcome to Your Vue.js App" />
</template><script setup>
import { defineAsyncComponent } from 'vue'
import LogoImg from './components/LogoImg.vue'
import LoadingComponent from './components/loading.vue'
import ErrorComponent from './components/error.vue'// 定义一个耗时执行的函数,t 表示延迟的时间, callback 表示需要执行的函数,可选
const time = (t, callback = () => {}) => {return new Promise(resolve => {setTimeout(() => {callback()resolve()}, t)})
}
// 记录加载次数
let count = 0
const HelloWorld = defineAsyncComponent({// 工厂函数loader: () => {return new Promise((resolve, reject) => {;(async function () {await time(300) //模拟异步const res = await import('./components/HelloWorld.vue')if (++count < 3) {// 前两次加载手动设置加载失败reject(res)} else {// 大于3次成功resolve(res)}})()})},loadingComponent: LoadingComponent,errorComponent: ErrorComponent,delay: 0,timeout: 1000,suspensible: false,onError(error, retry, fail, attempts) {// 注意,retry/fail 就像 promise 的 resolve/reject 一样:// 必须调用其中一个才能继续错误处理。if (attempts < 3) {// 请求发生错误时重试,最多可尝试 3 次console.log(attempts)retry()} else {fail()}},
})
</script>

通常会与 Suspense 配合
用Suspense 包一下异步组件,用来在组件树中协调对异步依赖的处理。该特性目前还不是稳定版本,后续可能会有变更。

4、自定义指令

  • 自定义指令着眼于组件,围绕组件去做增强
  • composition api着眼于状态,围绕数据做功能增强

我们都知道指令是为了增强组件的,我们常见的指令有:v-if、v-show、v-model、v-bind:value、v-on:click 等。

自定义指令其实非常简单,我们需要始终关注以下几个问题:

  1. 指令的钩子函数,有点类似生命周期函数钩子
  2. 指令钩子函数中的参数
  3. 指令的逻辑处理

注册自定指令,有点像封装了一个组件,封装在外部。有点类似vue2的mixin(功能复用),不过比mixin好很多,没mixin那么多缺点。
自定义指令关注组件或者本身dom(如 v-if,作用于dom节点)。composition api更关注状态

自定义指令 v-focus 、v-drag案例

<template><input v-focus /><div class="heyi" v-drag></div>
</template><script setup lang="ts">
// 注册自定义指令
import { vDrag } from "../directives/vDrag";
import { vFocus } from "../directives/vFocus";
</script><style scoped>
.heyi {width: 100px;height: 100px;background-color: red;
}
</style>

vDrag组件

import { Directive } from "vue";//ts// mixin  xxxxxxexport const vDrag: Directive = {mounted(el) {//el,当前domel.draggable = true;el.addEventListener("dragstart", () => {console.log("dragstart");});},
};

vFocus组件

import { Directive } from "vue";// mixin  xxxxxxexport const vFocus: Directive = {//tsmounted(el) {el.focus();},
};

指令钩子:

const myDirective = {// 在绑定元素的 attribute 前// 或事件监听器应用前调用created(el, binding, vnode, prevVnode) {// 下面会介绍各个参数的细节},// 在元素被插入到 DOM 前调用beforeMount(el, binding, vnode, prevVnode) {},// 在绑定元素的父组件// 及他自己的所有子节点都挂载完成后调用mounted(el, binding, vnode, prevVnode) {},// 绑定元素的父组件更新前调用beforeUpdate(el, binding, vnode, prevVnode) {},// 在绑定元素的父组件// 及他自己的所有子节点都更新后调用updated(el, binding, vnode, prevVnode) {},// 绑定元素的父组件卸载前调用beforeUnmount(el, binding, vnode, prevVnode) {},// 绑定元素的父组件卸载后调用unmounted(el, binding, vnode, prevVnode) {}
}

5、Teleport

该特性允许你将组件内的某个子组件挂载到任意 HTML 节点上,这个特性像极了 React 中的 createPortal。
整个vue应用都是挂载到根节点,然后下面子组件挂到父组件上行成一棵树。
假设我现在某一个组件想挂到别的地方去,而不是父组件上,就使用Teleport

假设不用Teleport

<template><div class="heyi"></div>
</template><script setup lang="ts"></script><style scoped>
.heyi {width: 100px;height: 100px;background-color: red;position: absolute;left: 0;top: 0;
}
</style>

打开控制台查看,会发现 <div class="heyi"></div> 挂在我们的vue实例 #app底下,也就是正常的父级dom下面

使用了Teleport

<template><Teleport to="body"><div class="heyi"></div></Teleport>
</template><script setup lang="ts"></script><style scoped>
.heyi {width: 100px;height: 100px;background-color: red;position: absolute;left: 0;top: 0;
}
</style>

打开控制台查看,会发现 <div class="heyi"></div> 挂在body地下,不再是#app底下

  • Teleport 组件创建
    • 首先会在在主视图里插入注释节点或者空白文本节点
    • 接着获取目标元素节点
    • 最后调用mount方法创建子节点往目标元素插入 Teleport 组件的子节点

Teleport通常用来创建模态框modal

  • 弹出层
  • Popover 等
  • tooltip

6、自定义 Hooks

假设我们需要封装一个计数器,该计数器用于实现数字的增加或者减少,并且我们可以指定数字可最大和最小值

使用:(负责视图)

<template><div><p>{{ current }} [max: 10; min: 1;]</p><div class="contain"><button @click="inc()">Inc()</button><button @click="dec()" style="margin-left: 8px">Dec()</button><button @click="set(3)" style="margin-left: 8px">Set(3)</button><button @click="reset()" style="margin-left: 8px">Reset()</button></div></div>
</template><script lang="ts" setup>import { useCounter } from './useCounter'const [current, { inc, dec, set, reset }] = useCounter(20, { min: 1, max: 10 })
</script>

useCounter就是自定义 Hooks(负责状态)

import { Ref, readonly, ref } from 'vue'// 判断是否为数字
const isNumber = (value: unknown): value is number => typeof value === 'number'export interface UseCounterOptions {/***  Min count*/min?: number/***  Max count*/max?: number
}export interface UseCounterActions {/*** Increment, default delta is 1* @param delta number* @returns void*/inc: (delta?: number) => void/*** Decrement, default delta is 1* @param delta number* @returns void*/dec: (delta?: number) => void/*** Set current value* @param value number | ((c: number) => number)* @returns void*/set: (value: number | ((c: number) => number)) => void/*** Reset current value to initial value* @returns void*/reset: () => void
}export type ValueParam = number | ((c: number) => number)function getTargetValue(val: number, options: UseCounterOptions = {}) {const { min, max } = optionslet target = valif (isNumber(max)) {target = Math.min(max, target)}if (isNumber(min)) {target = Math.max(min, target)}return target
}function useCounter(initialValue = 0,options: UseCounterOptions = {},
): [Ref<number>, UseCounterActions] {const { min, max } = optionsconst current = ref(getTargetValue(initialValue, {min,max,}),)const setValue = (value: ValueParam) => {const target = isNumber(value) ? value : value(current.value)current.value = getTargetValue(target, {max,min,})return current.value}const inc = (delta = 1) => {setValue(c => c + delta)}const dec = (delta = 1) => {setValue(c => c - delta)}const set = (value: ValueParam) => {setValue(value)}const reset = () => {setValue(initialValue)}return [readonly(current),{inc,dec,set,reset,},]
}export default useCounter

总结:Composition API的优点:将组件 UI逻辑 和状态逻辑解耦,让组件得到更大的复用性

相关文章:

Vue3新特性

Vue3新特性 1、Composition API1.1 什么是 Composition API1.2 常用 Composition API1.2.1 setup1.2.2 ref1.2.3 reactive1.2.4 computed1.2.5 watchEffect、watchPostEffect、watchSyncEffect1.2.6 watch 2、生命周期2.1 Vue3生命周期钩子2.2 vue2 和 vue3 关于生命周期的对比…...

一套功能齐全、二开友好的即时通讯IM工具,提供能力库和UI库,支持单聊、频道和机器人(附源码)

前言 在当今数字化时代&#xff0c;即时通讯(IM)和实时音视频(RTC)功能已成为众多应用的标配。然而&#xff0c;现有的解-决方案往往存在一些痛点&#xff0c;如架构落后、成本高昂、数据安全性和隐私保护不足&#xff0c;以及二次开发和部署的复杂性。 为了解决这些问题&…...

MySQL:JOIN 多表查询

多表查询 在关系型数据库中&#xff0c;表与表之间是有联系的&#xff0c;它们通过 外键 联系在一起&#xff0c;所以在实际应用中&#xff0c;经常使用多表查询。多表查询就是同时查询两个或两个以上的表。 MySQL多表查询是数据库操作中非常重要的一部分&#xff0c;它允许你…...

【机器学习】必会算法模型之:一文掌握 密度聚类,建议收藏。

密度聚类 1、引言2、密度聚类2.1 定义2.2 核心原理2.3 实现步骤2.4 算法公式2.5 代码示例 3、总结 1、引言 在机器学习的无监督学习领域&#xff0c;聚类是一项基础而重要的任务。 聚类算法通过将数据点分组&#xff0c;使同一组内的数据点具有更大的相似性&#xff0c;而组间…...

代码:前端与数据库交互的登陆界面

<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>登录</title> </head> <body>…...

发电机基础知识:负载组

什么是发电机负载组&#xff1f; 简单地说&#xff0c;负载组是一种可以产生人工电力负载的设备&#xff0c;用于测试发电机并验证发电机组的性能&#xff0c;包括相关组件&#xff0c;以确保通过使发电机发动机达到适当的工作温度和压力来满足适当的负载。 它是如何工作的&a…...

内网安全:各类密码的抓取

Mimikatz在线读取SAM文件 离线读取SAM文件 在线读取lsass进程 离线读取lsass进程 BrowserGhost浏览器密码抓取 Sharp-HackBrowserData浏览器密码抓取 SharpDecryptPwd数据库密码抓取 LaZagne各类密码的抓取 Windows其他类型抓NTLM Hash工具 sam文件和lsass进程就是Wind…...

前端面试题汇总2

1. CSS 中两个 .class1 .class2 从哪个开始解析 在 CSS 中&#xff0c;选择器 .class1 .class2 表示所有 class 为 class1 的元素中的 class 为 class2 的子元素。浏览器解析这个选择器时&#xff0c;从右向左解析。也就是说&#xff0c;浏览器首先找到所有 class 为 class2 的…...

分布式服务框架zookeeper+消息队列kafka

一、zookeeper概述 zookeeper是一个分布式服务框架&#xff0c;它主要是用来解决分布式应用中经常遇到的一些数据管理问题&#xff0c;如&#xff1a;命名服务&#xff0c;状态同步&#xff0c;配置中心&#xff0c;集群管理等。 在分布式环境下&#xff0c;经常需要对应用/服…...

服务攻防-应用协议cve

Cve-2015-3306 背景&#xff1a; ProFTPD 1.3.5中的mod_copy模块允许远程攻击者通过站点cpfr和site cpto命令读取和写入任意文件。 任何未经身份验证的客户端都可以利用这些命令将文件从文件系统的任何部分复制到选定的目标。 复制命令使用ProFTPD服务的权限执行&#xff0c;…...

Springcloud之gateway的使用详解

官网地址&#xff1a;https://docs.spring.io/spring-cloud-gateway/docs/4.0.4/reference/html/ 1.网关入门 helloword 网关不依赖start-web 导入的pom&#xff1a; <!--gateway--> <dependency><groupIdorg.springframework.cloud</groupId><arti…...

中望CAD 建筑 v2024 解锁版下载、安装教程 (超强的CAD三维制图)

前言 中望CAD建筑版是一款国产CAD制图软件&#xff0c;专注于建筑设计领域。中望CAD建筑版拥有丰富多样的建筑图块和图案&#xff0c;完美兼容各类建筑图纸。同时&#xff0c;它提供了绘图标准规范&#xff0c;使绘图更加规范和专业。更值得一提的是&#xff0c;该软件还具备智…...

windows edge自带的pdf分割工具(功能)

WPS分割pdf得会员&#xff0c;要充值&#xff01;网上一顿乱找&#xff0c;发现最简单&#xff0c;最好用&#xff0c;免费的还是回到Windows。 Windows上直接在edge浏览器打开PDF&#xff0c;点击 打印 按钮,页面下选择对应页数 打印机 选择 另存为PDF&#xff0c;然后保存就…...

HTML5实现好看的天气预报网站源码

文章目录 1.设计来源1.1 获取天气接口1.2 PC端页面设计1.3 手机端页面设计 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_4…...

比较(八)利用python绘制指示器

比较&#xff08;八&#xff09;利用python绘制指示器 指示器&#xff08;Indicators&#xff09;简介 指示器是一系列相关图的统称&#xff0c;主要用于突出展示某一变量的实际值与目标值的差异&#xff0c;例如常见的数据delta、仪表盘、子弹图、水滴图等。 快速绘制 基于p…...

【体外诊断】ARM/X86+FPGA嵌入式计算机在医疗CT机中的应用

体外诊断 信迈科技提供基于Intel平台、AMD平台、NXP平台的核心板、2.5寸主板、Mini-ITX主板、4寸主板、PICO-ITX主板&#xff0c;以及嵌入式准系统等计算机硬件。产品支持GAHDMI等独立双显&#xff0c;提供丰富串口、USB、GPIO、PCIe扩展接口等I/O接口&#xff0c;扩展性强&…...

力扣 28找到字符串中第一个匹配项的下标 KMP算法

思路&#xff1a; 朴素匹配有很多步骤是多余的 KMP算法能够避免重复匹配 KMP算法主要是根据子串生成的next数组作为回退的依据&#xff0c;它记录了模式串与主串(文本串)不匹配的时候&#xff0c;模式串应该从哪里开始重新匹配。 这里讲一下为什么用模式串的最大公共前后缀…...

JavaScript(10)——匿名函数

匿名函数 没有名字的函数&#xff0c;无法直接使用。 使用方式: 函数表达式立即执行函数 函数表达式 将匿名函数赋值给一个变量&#xff0c;并且通过变量名称进行调用 let fn function(){ 函数体 } 调用&#xff1a; fn() 立即执行函数 语法&#xff1a; (function () {…...

图片上传成功却无法显示:静态资源路径配置问题解析

1、故事的背景 最近&#xff0c;有个学弟做了一个简单的后台管理页面。于是他开始巴拉巴拉撘框架&#xff0c;写代码&#xff0c;一顿操作猛如虎&#xff0c;终于将一个简单的壳子搭建完毕。但是在实现功能&#xff1a;点击头像弹出上传图片进行头像替换的时候&#xff0c;卡壳…...

【转盘案例-弹框-修改Bug-完成 Objective-C语言】

一、我们来看示例程序啊 1.旋转完了以后,它会弹一个框,这个框,是啥, Alert 啊,AlertView 也行, AlertView,跟大家说过,是吧,演示过的啊,然后,我们就用iOS9来做了啊,完成了以后,我们要去弹一个框, // 弹框 UIAlertController *alertController = [UIAlertContr…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...