理解按需自动导入 unplugin-auto-import unplugin-vue-components

在这里插入图片描述

文章目录

  • unplugin-auto-import
    • 基础使用
      • 构建工具引入插件
      • 配置插件
    • import:配置自动导入规则
      • 使用预设
      • 自动引入第三方库
      • 自动导入 TypeScript 类型
      • vue 预设的自动导入配置
    • dts:让编辑器环境识别 ts 类型
    • eslintrc:解决 eslint 检查错误
    • dirs:配置本地目录文件自动导入
  • unplugin-vue-components
    • 基本使用
    • 导入流行库组件
    • 自动引入自己的本地组件
    • 自定义解析器 resolvers,实现组件库按需导入
    • 开源库的解析器写法(参考)
      • element-plus
      • vant

unplugin-auto-import

Auto import APIs on-demand for Vite, Webpack, Rspack, Rollup and esbuild. With TypeScript support. Powered by unplugin.

基础使用

项目中的 js 模块可以使用 unplugin-auto-import 来自动引入。

比如 vue 的一些 api,ref,reactive 等,可以不用手动导入。但要明白插件只是帮助我们在编译时自动添加 import,而不是代码中可以没有 import 导入。

看看 element-plus 的自动引入配置:

import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";export default defineConfig(({ command }) => {return {plugins: [vue(),AutoImport({resolvers: [ElementPlusResolver({ importStyle: "sass" })],eslintrc: {enabled: true}}),Components({resolvers: [ElementPlusResolver({ importStyle: "sass" })]})]}
}

安装:

pnpm i -D unplugin-auto-import

构建工具引入插件

因为上面是 vite 中使用,因此引入 unplugin-vue-components 的 vite 插件版本unplugin-vue-components/vite

其他常见构建工具引入:webpack、vue cli

// webpack.config.js & vue.config.js
module.exports = {/* ... */plugins: [require('unplugin-auto-import/webpack').default({ /* options */ }),],
}

配置插件

AutoImport({// targets to transforminclude: [/\.[tj]sx?$/, // .ts, .tsx, .js, .jsx/\.vue$/,/\.vue\?vue/, // .vue/\.md$/, // .md],// global imports to registerimports: [// presets'vue','vue-router',// custom{'@vueuse/core': [// named imports'useMouse', // import { useMouse } from '@vueuse/core',// alias['useFetch', 'useMyFetch'], // import { useFetch as useMyFetch } from '@vueuse/core',],'axios': [// default imports['default', 'axios'], // import { default as axios } from 'axios',],'[package-name]': ['[import-names]',// alias['[from]', '[alias]'],],},// example type import{from: 'vue-router',imports: ['RouteLocationRaw'],type: true,},],// Enable auto import by filename for default module exports under directoriesdefaultExportByFilename: false,// Auto import for module exports under directories// by default it only scan one level of modules under the directorydirs: [// './hooks',// './composables' // only root modules// './composables/**', // all nested modules// ...],// Filepath to generate corresponding .d.ts file.// Defaults to './auto-imports.d.ts' when `typescript` is installed locally.// Set `false` to disable.dts: './auto-imports.d.ts',// Auto import inside Vue template// see https://github.com/unjs/unimport/pull/15 and https://github.com/unjs/unimport/pull/72vueTemplate: false,// Custom resolvers, compatible with `unplugin-vue-components`// see https://github.com/antfu/unplugin-auto-import/pull/23/resolvers: [/* ... */],// Inject the imports at the end of other importsinjectAtEnd: true,// Generate corresponding .eslintrc-auto-import.json file.// eslint globals Docs - https://eslint.org/docs/user-guide/configuring/language-options#specifying-globalseslintrc: {enabled: false, // Default `false`filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`globalsPropValue: true, // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')},
})

上面的配置很完整,但我们一般关注其中几个就可以了。

import:配置自动导入规则

使用预设

对于一些常见的库,插件已经内置了它的自动导入规则,如:vue、vue-router、pinia、react 等。

在 imports 数组里添加字符串就代表使用预设:

AutoImport({imports: ["vue", "vue-router", "pinia"],
}

自动引入第三方库

有些库没有预设,我们也想自动导入该怎么办?比如 axios、loadsh、vueuse。

使用对象语法,自定义导入规则:包名: 数组

AutoImport({imports: ["vue",// 自定义导入规则{'包名 ikun': [// 命名导入,相当于会自动添加 import { sing } from "ikun";'sing',// 设置别名导入,自动添加 import { sing as singFromIkun } from "ikun";['sing', 'singFromIkun'],],},]
})

注意:对于默认导出的库,export default,自定义导入规则要写成别名导入的形式,导入的字段为 default。

比如 axios,我们正常使用是这样导入:

import axios from "axios"

因为 axios 库是 export default 默认导出的,所以我们不会 import { axios } from "axios";
对于这种默认导出,AutoImport 自动导入规则要写成别名导入:

AutoImport({imports: ["vue",// 自定义导入规则{'包名 ikun': [// 命名导入,相当于会自动添加 import { sing } from "ikun";'sing',// 设置别名导入,自动添加 import { sing as singFromIkun } from "ikun";['sing', 'singFromIkun'],],'axios': [// default imports['default', 'axios'], // import { default as axios } from 'axios',],},]
})

说白了,压根没有import axios from "axios";的写法,它只是import { default as axios} from "axios";的语法糖。因此在这种编译配置的情况下,需要严格按照规范来定义。

补充一个自动导入 vueuse:

AutoImport({imports: ["vue",{'@vueuse/core': [// named imports'useMouse', // import { useMouse } from '@vueuse/core',// alias['useFetch', 'useMyFetch'], // import { useFetch as useMyFetch } from '@vueuse/core',]}]
})

自动导入 TypeScript 类型

上面都是 js 引入,如果是在 ts 中这样引入,会没有类型,vue-tsc 类型检查过不了,build 构建失败。

导入 ts 类型的规则:

{from: 'vue-router',imports: ['RouteLocationRaw'],type: true,
}

其实上面这种写法才是导入规则的完整写法包名: 数组字符串这些都是简写,就和 webpack loader 配置一样。
这个对象就是在模拟import { xxx } from "xxx";,多了一个 type 为 true,就是标明了导入的为类型,等价于:import type { Xxx as Hhh} from "xxx";

这时候就要注意 type 的位置了:

AutoImport({imports: ["vue",// {//     axios: ["default", "axios"]// },{from: "axios",imports: [["default", "axios"], "AxiosStatic"],type: true}],
})

如上述写法就是错误的,它编译后就是:

import type { default as axios, AxiosStatic} from "axios";

显然 axios 不是类型,正确写法应该是:

import { default as axios, type AxiosStatic} from "axios";

那怎么把 type 和 AxiosStatic 类型绑定到一起,编译出正确的 import 语句呢?

AxiosStatic 继续写成对象形式即可:

AutoImport({imports: [// {//     axios: ["default", "axios"]// },// {//     from: "axios",//     imports: [["default", "axios"], "AxiosStatic"],//     type: true// }{from: "axios",imports: [ ["default", "axios"], {name: "AxiosStatic",type: true}],} ]
})

vue 预设的自动导入配置

可以看到 vue 自动导入配置的预设,内部写法就是如上诉一样:

  • https://github.com/unjs/unimport/blob/main/src/presets/vue.ts
{"from": "vue","imports": ["EffectScope","computed","createApp","customRef","defineAsyncComponent","defineComponent","effectScope","getCurrentInstance","getCurrentScope","h","inject","isProxy","isReactive","isReadonly","isRef","markRaw","nextTick","onActivated","onBeforeMount","onBeforeUnmount","onBeforeUpdate","onDeactivated","onErrorCaptured","onMounted","onRenderTracked","onRenderTriggered","onScopeDispose","onServerPrefetch","onUnmounted","onUpdated","provide","reactive","readonly","ref","resolveComponent","shallowReactive","shallowReadonly","shallowRef","toRaw","toRef","toRefs","toValue","triggerRef","unref","useAttrs","useCssModule","useCssVars","useSlots","watch","watchEffect","watchPostEffect","watchSyncEffect",{"name": "Component","type": true},{"name": "ComponentPublicInstance","type": true},{"name": "ComputedRef","type": true},{"name": "ExtractDefaultPropTypes","type": true},{"name": "ExtractPropTypes","type": true},{"name": "ExtractPublicPropTypes","type": true},{"name": "InjectionKey","type": true},{"name": "PropType","type": true},{"name": "Ref","type": true},{"name": "VNode","type": true},{"name": "WritableComputedRef","type": true}]
}

dts:让编辑器环境识别 ts 类型

配置 import 后能自动导入 ts 类型了,但那是在编译时才会导入,在 vscode 编辑器里写代码时,类型可没导入。在 ts 看来,你使用了未定义的变量,会报错。

这其实就和之前按需引入 elmessage 的问题一样:
按需引入 ElMessage,没有样式且类型检查失败

这时就需要对自动导入的内容进行类型声明:

AutoImport({dts: true // or a custom path
})

开启dts配置后,就会自动生成auto-imports.d.ts文件,进行全局类型声明。默认生成在根目录。
另外要确保tsconfig.json中 include 配置项包含了这个类型声明文件,好让 ts 读取里面的类型。

各种开源组件库按需引入的时候,就默认就打开了这个配置,所以根目录会出现这么个文件。

上面 axios 配置,自动生成的类型声明:

/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
export {}
declare global {const axios: typeof import('axios')['default']
}
// for type re-export
declare global {// @ts-ignoreexport type { AxiosStatic } from 'axios'
}

eslintrc:解决 eslint 检查错误

ts 通过了禁止使用未定义变量的检查,但 eslint 检查未通过。eslint 的检查中也会认为你使用了未定义的变量。解决办法自然是在 eslint 的配置中声明一下这些是全局变量,可以未导入直接用。

unplugin 官方认为如果使用了 ts,就不必再让 eslint 来检查是否使用未定义的变量了,建议把no-undef这条规则关掉。

💡 When using TypeScript, we recommend to disable no-undef rule directly as TypeScript already check for them and you don’t need to worry about this.

如果开着双重保险,就要让 eslint 识别自动导入的内容为全局变量:

  1. 开启配置,在项目根目录生成全局变量文件 .eslintrc-auto-import.json
AutoImport({eslintrc: {enabled: true, // <-- this},
})
{"globals": {"AxiosStatic": true,"axios": true}
}
  1. 在 eslint 校验规则中继承它。
// .eslintrc.js
module.exports = {extends: ['./.eslintrc-auto-import.json',],
}

dirs:配置本地目录文件自动导入

比如项目中有一个 utils 文件夹,如果想自动引入里面的文件,则可以用 dirs 来配置

AutoImport({// Auto import for module exports under directories// by default it only scan one level of modules under the directorydirs: [// './hooks',// './composables' // only root modules// './composables/**', // all nested modules// ..."./src/utils/**"]
})

unplugin-vue-components

https://github.com/unplugin/unplugin-vue-components

unplugin-vue-components 这玩意是用来专门引入 vue SFC 文件的,相当于 unplugin-auot-import 的一个子集。作者都是 antfu。

基本使用

// vite.config.ts
import Components from 'unplugin-vue-components/vite'export default defineConfig({plugins: [Components({ /* options */ }),],
})
// webpack.config.js & vue.config.js
module.exports = {/* ... */plugins: [require('unplugin-vue-components/webpack').default({ /* options */ }),],
}
Components({// relative paths to the directory to search for components.dirs: ['src/components'],// valid file extensions for components.extensions: ['vue'],// Glob patterns to match file names to be detected as components.// When specified, the `dirs` and `extensions` options will be ignored.globs: ['src/components/*.{vue}'],// search for subdirectoriesdeep: true,// resolvers for custom componentsresolvers: [],// generate `components.d.ts` global declarations,// also accepts a path for custom filename// default: `true` if package typescript is installeddts: false,// Allow subdirectories as namespace prefix for components.directoryAsNamespace: false,// Collapse same prefixes (camel-sensitive) of folders and components// to prevent duplication inside namespaced component name.// works when `directoryAsNamespace: true`collapseSamePrefixes: false,// Subdirectory paths for ignoring namespace prefixes.// works when `directoryAsNamespace: true`globalNamespaces: [],// auto import for directives// default: `true` for Vue 3, `false` for Vue 2// Babel is needed to do the transformation for Vue 2, it's disabled by default for performance concerns.// To install Babel, run: `npm install -D @babel/parser`directives: true,// Transform path before resolvingimportPathTransform: v => v,// Allow for components to override other components with the same nameallowOverrides: false,// filters for transforming targetsinclude: [/\.vue$/, /\.vue\?vue/],exclude: [/[\\/]node_modules[\\/]/, /[\\/]\.git[\\/]/, /[\\/]\.nuxt[\\/]/],// Vue version of project. It will detect automatically if not specified.// Acceptable value: 2 | 2.7 | 3version: 2.7,// Only provide types of components in library (registered globally)types: []
})

导入流行库组件

该插件内置了大多数流行库解析器,可以直接开箱即用。
并且会在根目录生成一个ui库组件以及指令路径components.d.ts文件

// vite.config.js
import { defineConfig } from 'vite'
import Components from 'unplugin-vue-components/vite'
import {ElementPlusResolver,AntDesignVueResolver,VantResolver,HeadlessUiResolver,ElementUiResolver
} from 'unplugin-vue-components/resolvers'export default defineConfig({plugins: [Components({// ui库解析器,也可以自定义resolvers: [ElementPlusResolver(),AntDesignVueResolver(),VantResolver(),HeadlessUiResolver(),ElementUiResolver()]})]
})
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}declare module 'vue' {export interface GlobalComponents {ABreadcrumb: typeof import('ant-design-vue/es')['Breadcrumb']AButton: typeof import('ant-design-vue/es')['Button']RouterLink: typeof import('vue-router')['RouterLink']RouterView: typeof import('vue-router')['RouterView']SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']SwitchTheme: typeof import('./src/components/SwitchTheme/SwitchTheme.vue')['default']}
}

自动引入自己的本地组件

默认情况下,自己写的组件放在src/components路径下是会被自动引入的。
比如上面 components.d.ts 文件中的 SvgIcon 和 SwitchTheme 就是自己写的组件。

当然,也可以进一步配置自动引入的情况:

// vite.config.js
import { defineConfig } from 'vite'
import Components from 'unplugin-vue-components/vite'export default defineConfig({plugins: [Components({// 指定组件位置,默认是src/componentsdirs: ['src/components'],// ui库解析器// resolvers: [ElementPlusResolver()],extensions: ['vue'],// 配置文件生成位置dts: 'src/components.d.ts'})]
})

自定义解析器 resolvers,实现组件库按需导入

如果是自己开发的组件库,为了让它支持自动按需导入,就需要自己编写解析器。

Components({resolvers: [// example of importing Vant(componentName) => {// where `componentName` is always CapitalCaseif (componentName.startsWith('Van'))return { name: componentName.slice(3), from: 'vant' }},],
})

resolvers 数组里可以传入一个函数,这个函数会在编译时不断执行。
函数接收组件名,并返回一个和 unplugin-auto-import 插件中 imports 配置一样的配置对象,这个对象就是 import 语句的描述对象,最终依据它生成导入语句。

  • 注意:组件名会自动转成大驼峰写法。

因此所谓的解析器,功能就是根据组件名映射成 import 导入语句。

假设组件库的前缀为 ikun,比如按钮组件: ikun-button

  1. 在 SFC 中使用了组件
<!-- 在 SFC 中使用了组件 -->
<ikun-button>按钮</ikun-button>
  1. 解析器中都能拿到大驼峰格式的组件名
const IkunResolver = componentName => {console.log(componentName) // IkunButton// 组件名有很多,通过前缀过滤出本组件库的组件名if (componentName.startsWith("Ikun")) {// import 引入规则对象:// 等价于 import { IkunButton } from "ikun-ui";return {name: componentName,from: "ikun-ui"}}return null
}
  1. 使用组件库的 resolver
Components({resolvers: [IkunResolver()],
})

还有一个细节问题:组件库中组件的样式可能是单独一个文件的,不一定在 .vue 文件中。
比如这样:

ikun-button
|
|—— style
|		|—— index.css
|			
|—— index.vue

上面的 import 配置对象写法只会引入 SFC 文件,并不会引入样式文件。

解决办法:副作用配置项。引入组件的副作用是会引入另一个文件,我们让这个文件是样式文件。

  • sideEffects
const IkunResolver = componentName => {if (componentName.startsWith("Ikun")) {// 等价于:// import { IkunButton } from "ikun-ui";// import "ikun-ui/ikun-button/style/index.css";return {name: componentName,from: "ikun-ui",sideEffects: `ikun-ui/${componentName}/style/index.css`}}return null
}

开源库的解析器写法(参考)

element-plus

// src/core/resolvers/element-plus.ts
function getSideEffectsLegacy(partialName, options) {const { importStyle } = options;if (!importStyle)return;if (importStyle === "sass") {return ["element-plus/packages/theme-chalk/src/base.scss",`element-plus/packages/theme-chalk/src/${partialName}.scss`];} else if (importStyle === true || importStyle === "css") {return ["element-plus/lib/theme-chalk/base.css",`element-plus/lib/theme-chalk/el-${partialName}.css`];}
}
function getSideEffects2(dirName, options) {const { importStyle, ssr, nightly } = options;const themeFolder = nightly ? "@element-plus/nightly/theme-chalk" : "element-plus/theme-chalk";const esComponentsFolder = nightly ? "@element-plus/nightly/es/components" : "element-plus/es/components";if (importStyle === "sass") {return ssr ? [`${themeFolder}/src/base.scss`, `${themeFolder}/src/${dirName}.scss`] : [`${esComponentsFolder}/base/style/index`, `${esComponentsFolder}/${dirName}/style/index`];} else if (importStyle === true || importStyle === "css") {return ssr ? [`${themeFolder}/base.css`, `${themeFolder}/el-${dirName}.css`] : [`${esComponentsFolder}/base/style/css`, `${esComponentsFolder}/${dirName}/style/css`];}
}
function resolveComponent(name, options) {if (options.exclude && name.match(options.exclude))return;if (!name.match(/^El[A-Z]/))return;if (name.match(/^ElIcon.+/)) {return {name: name.replace(/^ElIcon/, ""),from: "@element-plus/icons-vue"};}const partialName = kebabCase(name.slice(2));const { version, ssr, nightly } = options;if (compare(version, "1.1.0-beta.1", ">=") || nightly) {return {name,from: `${nightly ? "@element-plus/nightly" : "element-plus"}/${ssr ? "lib" : "es"}`,sideEffects: getSideEffects2(partialName, options)};} else if (compare(version, "1.0.2-beta.28", ">=")) {return {from: `element-plus/es/el-${partialName}`,sideEffects: getSideEffectsLegacy(partialName, options)};} else {return {from: `element-plus/lib/el-${partialName}`,sideEffects: getSideEffectsLegacy(partialName, options)};}
}
function resolveDirective(name, options) {if (!options.directives)return;const directives2 = {Loading: { importName: "ElLoadingDirective", styleName: "loading" },Popover: { importName: "ElPopoverDirective", styleName: "popover" },InfiniteScroll: { importName: "ElInfiniteScroll", styleName: "infinite-scroll" }};const directive = directives2[name];if (!directive)return;const { version, ssr, nightly } = options;if (compare(version, "1.1.0-beta.1", ">=") || nightly) {return {name: directive.importName,from: `${nightly ? "@element-plus/nightly" : "element-plus"}/${ssr ? "lib" : "es"}`,sideEffects: getSideEffects2(directive.styleName, options)};}
}
var noStylesComponents = ["ElAutoResizer"];
function ElementPlusResolver(options = {}) {let optionsResolved;async function resolveOptions() {if (optionsResolved)return optionsResolved;optionsResolved = __spreadValues({ssr: false,version: await getPkgVersion("element-plus", "2.2.2"),importStyle: "css",directives: true,exclude: void 0,noStylesComponents: options.noStylesComponents || [],nightly: false}, options);return optionsResolved;}return [{type: "component",resolve: async (name) => {const options2 = await resolveOptions();if ([...options2.noStylesComponents, ...noStylesComponents].includes(name))return resolveComponent(name, __spreadProps(__spreadValues({}, options2), { importStyle: false }));elsereturn resolveComponent(name, options2);}},{type: "directive",resolve: async (name) => {return resolveDirective(name, await resolveOptions());}}];
}

vant

// src/core/resolvers/vant.ts
var moduleType = isSSR ? "lib" : "es";
function getSideEffects4(dirName, options) {const { importStyle = true } = options;if (!importStyle || isSSR)return;if (importStyle === "less")return `vant/${moduleType}/${dirName}/style/less`;if (importStyle === "css")return `vant/${moduleType}/${dirName}/style/index`;return `vant/${moduleType}/${dirName}/style/index`;
}
function VantResolver(options = {}) {return {type: "component",resolve: (name) => {if (name.startsWith("Van")) {const partialName = name.slice(3);return {name: partialName,from: `vant/${moduleType}`,sideEffects: getSideEffects4(kebabCase(partialName), options)};}}};
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/239978.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用PE信息查看工具和Dependency Walker工具排查因为库版本不对导致程序启动报错问题

目录 1、问题说明 2、问题分析思路 3、问题分析过程 3.1、使用Dependency Walker打开软件主程序&#xff0c;查看库与库的依赖关系&#xff0c;查看出问题的库 3.2、使用PE工具查看dll库的时间戳 3.3、解决办法 4、最后 VC常用功能开发汇总&#xff08;专栏文章列表&…

链表常见题型(1)

1.反转链表 1.1反转链表 如果我们想要反转链表&#xff0c;那应该有head的next指针指向空&#xff0c;其余结点的next指针反过来&#xff0c;指向它的上一个结点&#xff0c;那我们在执行该操作的时候就需要定义变量cur(current)表示我们当前遍历到的结点&#xff0c;变量pre(…

【后台报错】插入时sql报错,varchar撑爆

后台的一个报错。按照正常的需要复现&#xff0c;或者查一下日志。但是凭借多年经验和大胆猜测&#xff0c;以及对自己代码要自信 引用一下文章 目测7*15 105项。每个id有9个数字加上分隔符刚好十个。大概就是超过了定义的一千的varchar长度。直接改数据库就好了。 简单粗暴…

【金猿CIO展】乖宝宠物CIO王天刚:以数据为核心,转变业务模式

‍ 王天刚 本文由乖宝宠物CIO王天刚撰写并投递参与“数据猿年度金猿策划活动——2023大数据产业年度趋势人物榜单及奖项”评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 随着社会经济的快速发展&#xff0c;“宠物经济”悄然崛起&#xff0c;宠物在家中的角色地位有时…

c语言:计算1+2+3……+n的和|练习题

一、题目 输入一个数n&#xff0c;计算123……n的和 二、代码截图【带注释】 三、源代码【带注释】 #include int main() { int num0; printf("请输入要运算的数:"); scanf("%d",&num); sumResult(num);//相加结果函数 } //计算打印…

【智能家电】东胜物联离在线语音方案为厨电企业赋能,实现厨房智能化控制

近年来&#xff0c;我国厨电市场蓬勃发展。据行业统计数据显示&#xff0c;至今年6月&#xff0c;市场规模已达356亿元&#xff0c;同比增长8.8%。随着数字科技、物联网和人工智能的兴起&#xff0c;厨电产品正在朝着更智能、多功能化的方向迅速发展。 为此厨电厂商正在积极布…

EarMaster Pro 7 简体中文破解版 v7.2.0.42 电脑版

软件介绍 EarMaster破解版一款功能强大的专业级别多媒体音乐教育学习软件&#xff0c;EarMaster破解版提供了大量音乐相关的学习内容&#xff0c;用户在这里可以学习基础的和弦、音阶、节奏&#xff0c;也可以提升自己的音感&#xff0c;如果基础已经很扎实了&#xff0c;还可…

加拿大 ANUSPLIN 网格气候数据集

ANUSPLIN 网格气候数据集 加拿大 ANUSPLIN 网格气候数据集是使用澳大利亚国立大学样条 (ANUSPLIN) 模型生成的基于站点的插值数据集。它由加拿大农业和农业食品部生产&#xff0c;覆盖加拿大全境。该数据集提供 1950 年至 2015 年期间每日和每月时间步长的最高气温、最低气温和…

OpenFeign 万字教程详解

OpenFeign 万字教程详解 目录 一、概述 1.1.OpenFeign是什么&#xff1f;1.2.OpenFeign能干什么1.3.OpenFeign和Feign的区别1.4.FeignClient 二、OpenFeign使用 2.1.OpenFeign 常规远程调用2.2.OpenFeign 微服务使用步骤2.3.OpenFeign 超时控制2.4.OpenFeign 日志打印2.5.O…

【小黑嵌入式系统第十二课】μC/OS-III程序设计基础(二)——系统函数使用场合、时间管理、临界区管理、使用规则、互斥信号量

上一课&#xff1a; 【小黑嵌入式系统第十一课】μC/OS-III程序设计基础&#xff08;一&#xff09;——任务设计、任务管理&#xff08;创建&基本状态&内部任务&#xff09;、任务调度、系统函数 文章目录 一、系统函数使用场合1.1 时间管理1.1.1 控制任务的执行周期1…

CSS新手入门笔记整理:CSS3弹性盒模型

特点 子元素宽度之和小于父元素宽度&#xff0c;所有子元素最终的宽度就是原来定义的宽度。子元素宽度之和大于父元素宽度&#xff0c;子元素会按比例来划分宽度。在使用弹性盒子模型之前&#xff0c;必须为父元素定义“display:flex;”或“display:inline-flex;”。 弹性盒子…

一款基于.NET Core的快速开发框架、支持多种前端UI、内置代码生成器

前言 经常看到有小伙伴在技术群里问有没有什么好用且快速的开发框架推荐的&#xff0c;今天就给大家分享一款基于MIT License协议开源、免费的.NET Core快速开发框架、支持多种前端UI、内置代码生成器、一款高效开发的利器&#xff1a;WalkingTec.Mvvm框架&#xff08;简称WTM…

CyclicBarrier实战应用——实现异步多线程业务处理,异常情况回滚全部子线程

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; CyclicBarrier实战应用——实现异步多线程业务处理&#xff0c;异常情况…

Linux笔记本电脑投屏到电视,用网页浏览器就能投屏到电视!

Linux系统的电脑如果要投屏到安卓电视屏幕上&#xff0c;可以使用投屏工具AirDroid Cast的网页版和TV版一起实现。 首先&#xff0c;在Linux系统的电脑里用chrome浏览器或edge浏览器打开网址webcast.airdroid.com。这个网址就是AirDroid Cast的网页版。你可以看到中间白色框框的…

Canal使用详解

Canal介绍 Canal是阿里巴巴开发的MySQL binlog增量订阅&消费组件&#xff0c;Canal是基于MySQL二进制日志的高性能数据同步系统。在阿里巴巴集团中被广泛使用&#xff0c;以提供可靠的低延迟增量数据管道。Canal Server能够解析MySQL Binlog并订阅数据更改&#xff0c;而C…

cilium原理之ebpf尾调用与trace

背景 在深入剖析cilium原理之前&#xff0c;有两个关于epbf的基础内容需要先详细介绍一下&#xff1a; 1. ebpf尾调用 尾调用类似于程序之间的相互跳转&#xff0c;但它的功能更加强大。 2. trace 虽然之前使用trace_printk输出日志&#xff0c;但这个函数不能多用&#x…

使用StableDiffusion进行图片Inpainting原理

论文链接&#xff1a;RePaint: Inpainting using Denoising Diffusion Probabilistic Models代码链接&#xff1a;RePaint Inpainting任务是指在任意一个二进制的掩码指定的图片区域上重新生成新的内容&#xff0c;且新生成的内容需要和周围内容保持协调。当前SOTA模型用单一类…

高级算法设计与分析(四) -- 贪心算法

系列文章目录 高级算法设计与分析&#xff08;一&#xff09; -- 算法引论 高级算法设计与分析&#xff08;二&#xff09; -- 递归与分治策略 高级算法设计与分析&#xff08;三&#xff09; -- 动态规划 高级算法设计与分析&#xff08;四&#xff09; -- 贪心算法 高级…

FATFS文件系统

文件系统是为了存储和管理数据&#xff0c;而在存储设备上建立的一种组织结构。 Windows常用的文件系统&#xff1a; 1、FAT12 2、FAT16 3、FAT32 4、exFAT 5、NTFS FAT&#xff1a;File Alloction Table 文件分配表 在小型的嵌入式存储设备大多…

Ubuntu 常用命令之 ping 命令用法介绍

&#x1f4d1;Linux/Ubuntu 常用命令归类整理 ping命令是一种网络诊断工具&#xff0c;用于测试主机之间网络的连通性。它发送ICMP Echo Request消息到指定的网络主机&#xff0c;并等待接收ICMP Echo Reply。通过这种方式&#xff0c;我们可以知道两台主机之间的网络是否畅通…