vue中如何实现组件通信
1. 父子组件通信
1. props和emits
我们最常见的组件通信就是父子组件数据通信。父子组件实现数据通信需要使用props和emit两个api。
在父组件中我们通过props将数据绑定给子组件,在子组件中我们可以通过props对象来收集到父组件传递的数据。
在子组件想要修改的props中的数据时,我们可以使用emit对象来触发一个自定义事件,在父组件中监听这个自定义事件并修改数据。(Vue中数据必须保证单向数据流,父组件的数据不能由子组件直接修改,而是通过通知父组件的收段让父组件来修改数据)
1.script setup实现
在script setup语法糖中,我们可以使用defineProps和defineEmits两个宏函数来创建props和emit对象。
<script setup>// 创建props和emit对象const props = defineProps({message: {type: String,default: 'hello'}})const emit = defineEmits(['change'])
</script>
defineProps注意事项:
- 这两个宏函数在script setup语法糖中会隐式导入,并不需要我们手动导入。
- defineProps函数接收一个对象或者数组作为参数:
- 为对象时,该对象中的属性即为父组件绑定的props名称,属性值可以是一个该数据对应的类型构造函数或者是一个包含该数据类型的对象配置对象,如上代码。(这里的配置对象下面会详解)
- 为数组时,该数组每一项均为对应的props名称字符串。
- 在3.5以后的版本中,如果父组件的传递的props是响应式的,那我们在子组件中接解构props获取的值仍然是响应式的。可以通过watch和watchEffect来监听props的变化。我们能在setup中访问一个props解构的值时,其本质上是自动为调用的props.变量名.
const props = defineProps(['foo'])watchEffect(() => {// 在 3.5 之前只运行一次// 在 3.5+ 中在 "foo" prop 变化时重新执行console.log(foo) }) watchEffect(() => {// `foo` 由编译器转换为 `props.foo`console.log(props.foo) })
- 在模板中我们可以使用小驼峰命名法(camelCase)为props命名,也可以是使用短横线命名法(kebab-case),但为了和 HTML保持一致,推荐使用短横线命名法。
- 上面我们说到的配置对象中,除了type属性外,还可以按照如下的方式编写:
defineProps({// 1. 基础类型检查// (给出 `null` 和 `undefined` 值则会跳过任何类型检查)propA: Number,// 2. 多种可能的类型propB: [String, Number],// 3. 必传,且为 String 类型propC: {type: String,required: true},// 4.必传但可为 null 的字符串propD: {type: [String, null],required: true},// 5.Number 类型的默认值propE: {type: Number,default: 100},// 6.对象类型的默认值propF: {type: Object,// 对象或数组的默认值// 必须从一个工厂函数返回。// 该函数接收组件所接收到的原始 prop 作为参数。default(rawProps) {return { message: 'hello' }}},// 7.自定义类型校验函数// 在 3.4+ 中完整的 props 作为第二个参数传入propG: {validator(value, props) {// The value must match one of these stringsreturn ['success', 'warning', 'danger'].includes(value)}},// 8.函数类型的默认值propH: {type: Function,// 不像对象或数组的默认,这不是一个// 工厂函数。这会是一个用来作为默认值的函数default() {return 'Default function'}} })
当 prop 的校验失败后,Vue 会抛出一个控制台警告 (在开发模式下)。
defineEmits注意事项:
- 该函数接收一个数组作为参数,数据每一项是事件名称,函数返回一个emit实例。
- 该函数必须放在script setup的顶级作用作用域中才能使用
- 在触发事件时,我们需要使用emit函数触发一个自定义事件,并传递参数。
const emit = defineEmits(['change']) emit('change', 'hello')
2.setup函数中实现
setup函数中我们可以通过setup函数的两个参数来获取到props和emit对象。
- setup 函数传递两个参数,第一个参数就是父组件传入的props对象,第二个参数一个上下文对象,该上下文对象后续还会说到。
- props对象还需要通过选项式的写法来声明,才能使用。选项的值与上面的defineProps函数接收的参数一致。
export default {props: ['foo'],setup(props,context) {// setup() 接收 props 作为第一个参数console.log(props.foo)} }
- context上挂载了emit对象,该对象本质是一个函数,与使用defineEmits函数创建的emit对象一致。
3.在template模板中使用
- 前面两个api都可以在template中直接通过关键是调用。
- props和emit对象通过 p r o p s 和 props和 props和emit来调用。
注意
如果子组件注册的事件与原生事件相同,则子组件只会触发注册事件,不会再响应原生事件。
2. defineModel(3.2+)
相信大家都知道Vue3中的v-model指令本质上是props名为modelValue和emit事件名为update:modelValue的组合。
因此在Vue3.2 版本之后,官方直接将这个组合封装到了defineModel宏函数中,以后再为组件绑定v-mode时,我们只需要在子组件中通过defineModel函数来声明即可。减少了代码量。
同时可以实现父子组件的数据通信.
- 这个宏函数接收一个配置参数
参数 | 默认值 | 描述 |
---|---|---|
required | false | 是否必传,如果为true,则父组件必须绑定v-model的值 |
defaultProp | undefined | 默认的值,当父组件传递的值为undefined时会使用 |
- 该函数返回一个ref对象,并且如果在父组件中使用这个子组件,为子组件绑定一个v-model时,这个v-model的值就会被绑定给这个ref对象的value属性。一但这个ref变化就会触发父组件的数据更新,父组件数据主动更新也会触发子组件的更新。(这个宏函数的本质就是modelValue与update:modelValue的进一步封装)
3. 组件实例
在Vue中我们可以通过变量来绑定组件实例,在特定的生命周期函数中我们就可以通过变量来获取到组件实例对象。因此,我们就可以拿到组件暴露出来的属性与方法,从而时间组件间的数据通信。
步骤:
- 父组件通过ref绑定来获取到子组件实例
- 子组件主动暴露某些属性与方法
- 父组件通过变量获取到子组件的属性与方法
<!-- 父组件 --><script setup> import { useTemplateRef, onMounted } from 'vue' import Child from './Child.vue'const childRef = useTemplateRef('child')onMounted(() => {// childRef.value 将持有 <Child /> 的实例 }) </script><template><Child ref="child" /> </template><!-- 子组件 --> <script setup> import { ref } from 'vue'const a = 1 const b = ref(2)// 像 defineExpose 这样的编译器宏不需要导入 defineExpose({a,b }) </script>
注意事项:
- 在最新版本的Vue中(3.5+)我们可以使用useTemplateRef hook函数来创建一个ref对象,并通过ref绑定到组件上。在3.5之前可以直接使用ref函数来创建。
- 在子组件使用script setup语法糖时,默认的组件实例是不会暴露任何的属性与方法(子组件私有),因此如果需要在父组件中获取到子组件属性与方法就需要使用defineExpose函数来暴露。该函数接收一个作为参数,每一个属性就是一个暴露的属性名称。
- 如果不使用script setup语法糖,此时访问到的就是整个子组件实例对象,包括props,data等等。此时访问到的就是子组件中的this上下文。
2. 依赖注入
上面我们提到数据通信方法仅限于父子组件之间,如果两个组件嵌套层级过深,子级组件如果想要访问父级组件的数据,就需要一层一层的传递props,这样显然是不合理的。因此Vue提供了依赖注入的方式来实现跨组件通信。
1.provide(提供)
我们可以在数据提供的组件中通过provide函数来提供数据,该函数接收两个参数:
-
第一个参数被称为注入名,可以是一个字符串或是一个 Symbol。后代组件会用注入名来查找期望注入的值。一个组件可以多次调用 provide(),使用不同的注入名,注入不同的依赖值。
-
第二个参数是提供的值,值可以是任意类型,包括响应式的状态.
<script setup> import { provide } from 'vue'provide(/* 注入名 */ 'message', /* 值 */ 'hello!') </script><!-- 如果不使用 <script setup>,请确保 provide() 是在 setup() 同步调用的: --> <script> import { provide } from 'vue'export default {setup() {provide(/* 注入名 */ 'message', /* 值 */ 'hello!')} } </script>
注意事项:
- 该函数无论在那种写法下都需要显示的导入,且必须爱setup中才能使用。
- 该函数在Vue全局的app实例上默认是挂载的,因此我们可以通过app.provide来提供数据,这样所有的Vue组件均可以访问到该数据。(该方法也被称为应用级Provide)
import { createApp } from 'vue'const app = createApp({})app.provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
2. Inject (注入)
上面在父级组件中通过provide函数提供了数据,那么在子级组件中如何获取到该数据呢?Vue提供了inject函数来获取到父级组件提供的数据。
<script setup>
import { inject } from 'vue'const message = inject('message')
</script>
该函数接受两个参数:
- 第一个参数就是注入数据的名称,可以为字符串或 Symbol。
- 第二个参数是默认值,当没有任何的组件提供该数据时,会使用这个默认值。
注意事项:
- 该函数无论在那种写法下都需要显示的导入,且必须爱setup中才能使用。
- 在一些场景中,默认值可能需要通过调用一个函数或初始化一个类来取得。为了避免在用不到默认值的情况下进行不必要的计算或产生副作用,我们可以使用工厂函数来创建默认值。同时需要为该函数提供第三个参数并设置为true,代表第二个参数是一个工厂函数。
- 和响应式数据配合使用,这里可以注入一个ref响应式数据,通过在提供数据的时候为该数据提供一个修改的函数,作为一个对象的setter,这样就可以在子组件中修改该数据。
<!-- 在供给方组件内 --> <script setup> import { provide, ref } from 'vue'const location = ref('North Pole')function updateLocation() {location.value = 'South Pole' }provide('location', {location,updateLocation }) </script>
<!-- 在注入方组件 --> <script setup> import { inject } from 'vue'const { location, updateLocation } = inject('location') </script><template><button @click="updateLocation">{{ location }}</button> </template>
3. 全局状态状态管理
如果我们的应用及其复杂,那么我们可能需要一个全局的状态管理来帮助我们更好的组织代码。
所谓的全局状态管理就是将应用中需要共享的数据抽取出来,在任意组件中都可以访问到这些数据。
1.VueX
VueX是一个专门为Vue.js设计的状态管理工具,它采用集中式存储管理应用的所有组件的状态。并且以响应的规则保证状态以一种可预测的方式发生变化。
基本使用:
-
安装VueX
npm install vuex --save
-
创建store实例
import { createStore } from 'vuex' const store = createStore({state() {return { count: 0 }},mutations: {increment(state) {state.count++}},actions: {},getters: {}modules: {} })
-
在Vue实例中注册store
import { createApp } from 'vue' import App from './App.vue' import store from './store' const app = createApp(App) app.use(store) app.mount('#app')
-
在组件中访问store
<template><div>{{ count }}</div><button @click="increment">+</button> </template> <script setup>import { useStore } from 'vuex'const store = useStore()</script>
注意事項:
- 虽然vuex仍然可以作为vue3的全局状态管理,但官方不在推荐使用vuex,而是推荐使用pinia。因此这里只是简单的介绍一下vuex的使用。
2.Pinia
pinia为Vue3官方推荐的状态管理工具,基本使用和vuex类似。
1. 基本使用
-
安装
npm install pinia --save
-
创建pinia实例
import { createPinia } from 'pinia' const pinia = createPinia() export default pinia
-
创建store hook函数
import { defineStore } from 'pinia' export const useStore = defineStore("main",{state: () => {return { count: 0 }},getters: {},actions: {} })
-
在Vue实例中注册pinia
import { createApp } from 'vue' import App from './App.vue' import pinia from './pinia' const app = createApp(App) app.use(pinia) app.mount('#app')
-
在组件中访问store
<template><div>{{ count }}</div> </template> <script setup>import { useStore } from './store'const store = useStore() </script>
2.pinia各部分解析
(1).pinia创建
- 在vue中我们如果需要使用pinia,就需要创建一个pinia实例,然后将实例挂载到app上。
- 这里的创建pinia实例需要使用createPinia函数,该函数会返回一个pinia实例。使用时需要从pinia导入这个函数。
(2).store hook函数
我们需要在pinia中存放数据就需要由store,pinia提供了hook函数方式来创建store。我们首选需要从pinia中导入defineStore函数,该函数接收两个参数。
- 第一个 参数是个字符串,用来定义store的名称。
- 第二个参数可以是一个对象,也可以是一个工厂函数。
- 如果是对象,则该对象中需要定义state,getters,actions三个属性。其中state属性是一个函数,用来定义state数据,getters属性是一个对象,用来定义getters(计算属性),actions属性是一个对象,用来定义actions(方法)。(state定义的数据均为响应式数据)
- 如果为函数,急需要在该函数中返回一个对象,该对象的属性就会被作为store的属性。这里返回的对象的属性值一般是响应式数据。可以通过ref,computed等来定义。如果属性值为ref对象,则会被自动解包。同时作为store的state存在,如果是computed对象,则会被自动处理为getters(也会自动解包)。如果是一个函数,则会被自动处理为action。
- defineStore函数会返回一个hook函数,该函数可以用来创建store实例。调用这个函数不需要传入任何参数,该函数会返回一个store实例。
- 因此我们一般把这些hook函数通过一个文件统一导出,便于在组件中导入使用。
(3).组件内部使用
我们将hook函数导入之后,直接通过无参调用,即可得到有个store实例,可以在组件中直接调用对应的属性获取到数据。
3. 数据持久化
pinia本身的数据是存于内存当中,当再次刷新页面时,数据就会丢失。如果我们需要将数据持久化,可以使用pinia的插件来实现。pinia-plugin-persist
- 安装pinia-plugin-persist
npm install pinia-plugin-persist --save
- 在pinia实例中注册插件
import { createPinia } from 'pinia' import piniaPluginPersist from 'pinia-plugin-persist' const pinia = createPinia() pinia.use(piniaPluginPersist) export default pinia
- 在store中开启持久化
import { defineStore } from 'pinia' export const useStore = defineStore("main",{state: () => {return { count: 0 }},getters: {},actions: {},persist: {enabled: true,strategies: [{key: 'main',storage: localStorage,paths: ['count']}]} })
- persist属性是一个对象,该对象中需要定义enabled和strategies两个属性。
- enabled属性是一个布尔值,用来开启或关闭持久化。
- strategies属性是一个数组,用来定义持久化的策略。该数组中可以定义多个策略,每个策略都是一个对象,该对象中需要定义key,storage和paths三个属性。
- key属性是一个字符串,用来定义持久化的key。
- storage属性是一个对象,用来定义持久化的存储方式。可以是localStorage,sessionStorage,cookie等。
- paths属性是一个数组,用来定义需要持久化的属性。如果不定义,则默认持久化所有属性。
- 如果需要持久化所有属性,则可以不定义paths属性。
如果defineStore函数中定义的是工厂函数,则该函数会接受第三个参数,该参数是一个对象,该对象中需要定义persist属性。属性的值和上面一样。同时persist属性可以简写,接收一个布尔值作为值,表示开启或关闭持久化。其缓存策略默认会使用localStorage。key默认会使用store的名称。paths默认会使用所有属性。
拓展: 这个插件通过指定保存策略的不同,也可以在uniapp中使用。
相关文章:

vue中如何实现组件通信
1. 父子组件通信 1. props和emits 我们最常见的组件通信就是父子组件数据通信。父子组件实现数据通信需要使用props和emit两个api。 在父组件中我们通过props将数据绑定给子组件,在子组件中我们可以通过props对象来收集到父组件传递的数据。 在子组件想要修改的pr…...

C/C++:内存管理
文章目录 前言一、内存分区1. 内存划分情况2. 最大内存计算 二、malloc/calloc/realloc 与 free1. malloc2. calloc3. realloc4. free5. 差异对比6. 失败处理 三、内存分配题目1. 题目2. 内存区域划分 四、C内存管理方式1. new 与 delete2. new/delete操作内置类型3. new和dele…...

jmeter学习(4)提取器
同线程组https://blog.csdn.net/vikeyyyy/article/details/80437530 不同线程组 在JMeter中,正则表达式提取的参数可以跨线程组使用。 通过使用Beanshell后置处理器和属性设置函数,可以将提取的参数设置为全局变量,从而在多个线程组之间共享…...

移动端的每日任务,golang后端数据库应该怎么设计
推荐学习文档 golang应用级os框架,欢迎stargolang应用级os框架使用案例,欢迎star案例:基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识,这里有免费的golang学习笔…...

1、Spring Boot 3.x 集成 Eureka Server/Client
一、前言 基于 Spring Boot 3.x 版本开发,因为 Spring Boot 3.x 暂时没有正式发布,所以很少有 Spring Boot 3.x 开发的项目,自己也很想了踩踩坑,看看 Spring Boot 3.x 与 2.x 有什么区别。自己与记录一下在 Spring Boot 3.x 过程…...

Vue根实例、实例总结
在Vue.js框架中,根实例和实例扮演着至关重要的角色。以下是对Vue根实例和实例的总结: Vue根实例 定义与创建: Vue根实例是Vue.js应用的核心。每个Vue应用都是通过用Vue函数创建一个新的Vue实例开始的,这个实例被称为根实例。根实…...

微服务架构:Spring Cloud的服务注册与发现、配置管理、服务网关、熔断器、分布式追踪
微服务架构是一种将应用程序构建为一组小型、自治的服务的方法,每个服务都运行在其独立的进程中,服务间通过轻量级通信机制(通常是HTTP API)进行通信。Spring Cloud是一套基于Spring Boot的微服务解决方案,它提供了一系…...

Spring Boot实现的大学生就业市场解决方案
1系统概述 1.1 研究背景 如今互联网高速发展,网络遍布全球,通过互联网发布的消息能快而方便的传播到世界每个角落,并且互联网上能传播的信息也很广,比如文字、图片、声音、视频等。从而,这种种好处使得互联网成了信息传…...

Ubuntu上安装Git:简单步骤指南
Git是目前世界上最流行的版本控制系统,广泛用于软件开发中。无论你是开发者还是版本控制的新手,Git都是你不可或缺的工具。本文将为你介绍如何在Ubuntu操作系统上安装Git。 什么是Git? Git是一个开源的分布式版本控制系统,由Lin…...

新闻推荐系统:Spring Boot的架构优势
4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式,是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示: 图4-1系统工作原理…...

谷歌收录批量查询,谷歌收录批量查询的简单方法
谷歌收录批量查询是网站管理员和SEO优化人员常见的需求,以下提供几种简单且高效的批量查询方法: 一、使用Google Search Console(谷歌搜索控制台) 注册并验证网站: 首先,确保你已经在Google Search Conso…...

HarmonyOS NEXT应用开发(一、打造最好用的网络通信模块组件)
随着HarmonyOS NEXT 的发布,越来越多的开发者开始关注如何在这个新平台上高效地进行应用开发。其中网络通信模块的封装尤为关键。纵观HarmonyOS的众多三方网络库及封装,竟没有一个简单好用的。虽然有个axios的鸿蒙版,但有点儿重了也不是很好用…...

Windows Ubuntu下搭建深度学习Pytorch训练框架与转换环境TensorRT
Windows Ubuntu下搭建深度学习Pytorch训练框架与转换环境TensorRT JetBrains2024(IntelliJ IDEA、PhpStorm、RubyMine、Rider……)安装包Anaconda Miniconda安装.condarc 文件配置镜像源查看conda的配置和源(channel)自定义conda虚拟环境路径conda常用命…...

如何选择合适的BI工具及集成
目录 1 BI工具介绍 1.1 BI工具介绍 1.2 大数据平台与BI工具的集成 2 选择BI工具的考虑因素 2.1 可视化与分析能力 2.2 易用性与学习曲线 2.3 数据源与连接性 2.4 定制化与扩展性 3 案例分析 3.1 案例一:某零售行业的应用 3.2 案例二:某金融企业的应用 3.3 案例三:…...

STM32的串行外设接口SPI
一、SPI简介 1.SPI总线特点 (1)四条通信线 SPI需要SCK、MISO、MOSI、NSS四条通信线来完成数据传输 ,每增加一个从机,多一条NSS通信线。 (2)多主多从 SPI总线允许有多个主机和多个从机。 (3&…...

函数重载
一、概念 C 允许在同一作用域中存在几个功能类似的同名函数,但这些同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同 int Add(int left, int right) {return leftright; }double Add(double left, double right) {return leftright; }long Add(long left, l…...

单例模式:Python中的“独一无二”模式
引言 单例模式是一种常用的设计模式,它确保一个类只有一个实例,并提供一个全局访问点。这种模式在需要控制资源消耗、管理共享资源或者协调系统组件时非常有用。例如,数据库连接、配置文件管理、日志记录等场景。 基础语法介绍 单例模式的…...

C++和OpenGL实现3D游戏编程【连载12】——游戏中音效的使用
🔥C++和OpenGL实现3D游戏编程【目录】 1、游戏中音效的使用 前面我们实现了图片纹理的显示功能,是不是感觉到非常的简单。那么今天我们就继续说下游戏声音的实现。音效也是游戏的灵魂,只有搭配了美妙动听的音效以后,游戏才能令人耳目一新,与玩家产生良好的效果。 音效文…...

Hive数仓操作(八)
一、Hive中的分桶表 1. 分桶表的概念 分桶表是Hive中一种用于提升查询效率的表类型。分桶指的是根据指定列的哈希值将数据划分到不同的文件(桶)中。 2. 分桶表的原理 哈希分桶:根据分桶列计算哈希值,对哈希值取模,将…...

【C++打怪之路Lv6】-- 内存管理
🌈 个人主页:白子寰 🔥 分类专栏:C打怪之路,python从入门到精通,数据结构,C语言,C语言题集👈 希望得到您的订阅和支持~ 💡 坚持创作博文(平均质量分82)&#…...

408知识点自检(二)
一、细节题 边界对齐长度是由什么决定的?64位计算机边界按几字节对齐?单周期cpu、多周期cpu、基本流水线cpu、超标量cpu的cpi分别是多少?中断的处理优先级和响应优先级分别由谁决定?动态分区管理需要用什么重定位方式?…...

C语言复习概要(二)
本文目录 C语言中的数组与函数详解1. 引言2. 数组2.1. 什么是数组?语法:示例: 2.2. 数组的初始化示例 1:在声明时初始化示例 2:部分初始化示例 3:运行时赋值 2.3. 数组的访问与修改示例: 2.4. 多…...

小程序原生-利用setData()对不同类型的数据进行增删改
1. 声明和绑定数据 wxml文件 <view> {{school}} </view> <view>{{obj.name}}</view> <view id"{{id}}" > 绑定属性值 </view> <checkbox checked"{{isChecked}}"/> <!--算数运算--> <view>{{ id …...

.NET Core 集成 MiniProfiler性能分析工具
前言: 在日常开发中,应用程序的性能是我们需要关注的一个重点问题。当然我们有很多工具来分析程序性能:如:Zipkin等;但这些过于复杂,需要单独搭建。 MiniProfiler就是一款简单,但功能强大的应用…...

【JAVA开源】基于Vue和SpringBoot的旅游管理系统
本文项目编号 T 063 ,文末自助获取源码 \color{red}{T063,文末自助获取源码} T063,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析5.4 用例设计 六、核…...

信息学奥赛一本通 1885:【14NOIP提高组】寻找道路 | 洛谷 P2296 [NOIP2014 提高组] 寻找道路
【题目链接】 洛谷 P2296 [NOIP2014 提高组] 寻找道路 ybt 1885:【14NOIP提高组】寻找道路 【题目考点】 1. 图论:广搜 2. 图论:反图 【解题思路】 设path数组,path[i]表示顶点i出发到终点t是否有路径。 先求path数组&#…...

JVM 基础、GC 算法与 JProfiler 监控工具详解
目录 1、引言 1.1 JVM内存与本地内存 1.2 JVM与JDK的关系 2、JVM基础 2.1 JVM(Java Virtual Machine) 2.2 Java与JVM的关系 2.3 JVM的内存结构 2.3.1 堆内存 2.3.2 栈内存 2.3.3 方法区 2.3.4 本地方法栈 2.3.5 程序计数器(PC寄存…...

nodejs安装及环境配置
一、下载 进入官网https://nodejs.org/en/download/prebuilt-installer下载node.js安装包,选择对应版本的node,这里我选择的是14.21.3版本 二、安装 1、下载完成后,双击“node-v14.21.3-x64.msi”,开始安装Node.js 2、勾选复…...

无人机电力巡检:点亮电力巡检新视野!
一、无人机电力巡查的优势 提高巡检效率:无人机可以搭载高清摄像头、红外热像仪等先进设备,实时拍摄和传输图像,帮助巡检人员快速发现潜在问题,如电线破损、绝缘子污损、设备过热等,从而大大缩短了巡检周期。 降低人…...

详细介绍:API 和 SPI 的区别
文章目录 Java SPI (Service Provider Interface) 和 API (Application Programming Interface) 的区别详解目录1. 定义和目的1.1 API (Application Programming Interface)1.2 SPI (Service Provider Interface) 2. 使用场景2.1 API 的应用场景2.2 SPI 的应用场景 3. 加载和调…...