基于原子化思想的 Vue3 组件库 UnoCSS UI

news2024/10/7 14:27:51

UnoCSS UI

  • 项目地址
  • 前言
  • Monorepo 项目架构
    • UnoCSS UI 的模块设计
    • PNPM Monorepo 常用操作: --filter, -w
    • Monorepo 中的依赖管理
    • 项目整体结构
  • 基于原子化 CSS 的组件封装方式
    • 原子化 CSS 基础
      • 原子化 VS 内联样式
      • 原子化 VS class
    • 原子化对组件封装的影响
    • @unocss-ui/components 项目结构
    • @unocss-ui/preset
      • safelist
      • theme
  • example
  • demo
  • TODO

项目地址

Github 地址:https://github.com/cherryful/unocss-ui

example 预览地址:https://cherryful.github.io/unocss-ui/

前言

UnocssUI 是一个基于 UnoCSS0 带有原子化思想的现代化 Vue3 组件库,它的特点是简单,每个组件的实现之间没有任何依赖(只在 一个 .vue 文件实现),非常适合用来学习组件库的封装,同时它也在快速的迭代与建设中。

从该项目中你或许可以学习到:

  • 基于 PNPM 的 Monorepo 项目架构:如何组织组件库的目录结构
  • 基于原子化 CSS 的组件封装方式:原子化 CSS 极大的简化了组件的封装
  • 一种倾向于简洁的编码思想:可以减少编码的心智负担
  • 开发带有动态调试功能的文档:这是一种非常灵活的文档展现形式

很多思想与方式都是个人参考很多开源项目 + 自己的理解所得到的,如果有问题或者更好的方案,欢迎交流


在开始前,先简单看一下组件库的使用方式:

需要安装三个依赖:unocss,unocss-ui,@unocss/reset

pnpm add unocss unocss-ui @unocss/reset

使用方式一:在 main.ts 进行全局注册,后续在 .vue 中使用无需引入

// 注意顺序
import '@unocss/reset/tailwind.css'
import 'unocss-ui/style.css' // 目前,无论使用哪种方式都必须引入组件库的 CSS 文件
import 'uno.css'

import unocssui from 'unocss-ui'
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).use(unocssui).mount('#app')

使用方式二:不进行全局注册,需要在 .vue 页面文件中单独引入:

// App.vue
<script setup>
import { UButton } from 'unocss-ui'
</script>

<template>
	<UButton> Hello </UButton>
</template>

方式二 TODO:后续实现按需引入并打包的功能(非常重要)

Monorepo 项目架构

Monorepo 是现在比较流行的一种前端项目架构,简单来说就是:一个仓库内包含多个开发项目(模块)。

  • 整个项目的根目录下有一个 package.json
  • 子目录下可能还会有 package.json 即子模块
  • 基于 PNPM 的 Monorepo 由 pnpm-workspace.yaml 文件来指定哪些目录可能为子模块

参考文档:https://www.pnpm.cn/pnpm-workspace_yaml

本项目的 pnpm-workspace.yaml 内容如下:

# pnpm-workspace.yaml
packages:
  - 'packages/*'
  - example
  - demo

其含义是指 packages 目录下的所有目录,及根目录下的 example 和 demo 可以为子模块。

在这里插入图片描述

即该项目总共有 5 个子模块,加上根模块,共计 6 个模块,在拉取本项目并执行 pnpm install 时也会提示。

在这里插入图片描述

UnoCSS UI 的模块设计

在 UnoCSS UI 项目中,最外层的根模块是 unocss-ui-monorepo,其中包含了以下子模块:

  • example:用于开发组件时进行实时预览,以及作为一个示例项目展示
  • demo:用于测试打包后的组件包是否正常(不能用来做开发时预览,因为导入的是打包后的 package)
  • @unocss-ui/components:组件的源码
  • @unocss-ui/preset:根据组件库自身需求抽取出来的 UnoCSS 的预设
  • unocss-ui:项目的入口文件,在这里引用 @unocss-ui/components@unocss-ui/preset

这里解释一下 @unocss-ui/components@unocss-ui/presetunocss-ui 三个模块的关系

  • @unocss-ui/components 是组件库的源码,包含 Button.vueTag.vue 等文件,可以直接从该模块中引入组件:
// App.vue
import { UButton } from '@unocss-ui/components'
  • @unocss-ui/preset 是封装的 UnoCSS 预设文件,需要搭配其实现组件库的某些功能,引用方式:
// uno.config.ts
import { presetUnocssUI } from '@unocss-ui/preset' 
  • unocss-ui 这个模块相当于是上面两个模块的汇总,使得用户只需要安装 unocss-ui 模块即可使用其中的子模块:
// App.vue
import { UButton } from 'unocss-ui'

// uno.config.ts
import { presetUnocssUI } from 'unocss-ui'

如果你愿意,也可以分别安装 @unocss-ui/components@unocss-ui/preset 模块。

顺带一提,子模块的命名往往都是 @组织名/模块名,UnoCSS UI 也采用这种设计。


PNPM Monorepo 常用操作: --filter, -w

PNPM 多模块下常用的命令:

  • --filter-F 后跟模块名,表示后面的操作是在该模块进行
  • -w 表示在根模块下进行操作

根模块下安装的依赖,子模块是可以直接使用的,而子模块之间互相不共享依赖。

请熟悉以下几个例子:若不清楚 -Dadd 等指令含义,先查询资料补一些 NPM / PNPM 基础

# 给 example 模块添加 Vue 依赖
pnpm --filter example add vue

# 给根模块添加 eslint 开发依赖
pnpm add -wD eslint

# 在 @unocss-ui/components 模块下执行 pnpm build 操作
# 需要在 @unocss-ui/components 模块下的 scripts 中配置 build 脚本
pnpm --filter @unocss-ui/components build

# 在 example 模块下执行 pnpm dev 操作
# 需要在 example 模块下的 scripts 中配置 dev 脚本
pnpm --filter example dev

在根模块的 package.json 中,配置了一些执行脚本:根据上面的介绍能理解,就是对子模块的操作在根目录下进行了汇总。

"scripts": {
	// 在 @unocss-ui/components 下执行 pnpm build
    "build:components": "pnpm --filter @unocss-ui/components build",
    "build:preset": "pnpm --filter @unocss-ui/preset build",
    "build:unocss-ui": "pnpm --filter unocss-ui build",
    // 同时执行上面 3 个构建操作
    "build:all": "pnpm build:preset && pnpm build:components && pnpm build:unocss-ui",

	// 在 example 下执行 pnpm dev
    "dev:example": "pnpm --filter example dev",
    "build:example": "pnpm --filter example build",
    "preview:example": "pnpm --filter example preview",
    "dev:demo": "pnpm --filter demo dev",
    "build:demo": "pnpm --filter demo build",
    "preview:demo": "pnpm --filter demo preview",
    "lint": "eslint .",
 	"lint:fix": "eslint --fix ."
}

这样的好处是每次要操作子模块,只需要在根目录下进行操作,而无需不停的 cd 切换到子目录去执行操作。(当然进入子模块后再执
行操作也是可以的)

Monorepo 中的依赖管理

最偷懒的做法是将所有需要的依赖安装到根模块中,子模块中都可以直接使用。

但是我认为还是需要做一些区分的:

  • 在根模块中安装一些所有子项目通用的开发时依赖,如:eslint,typescript,lint-staged 等。
  • 在各个子模块安装其需要的依赖,例如 demo 和 example 都是 Vue 项目,可以分别安装 vue、vite 等依赖,而 @unocss-ui/preset 只是个标准的 TypeScript 项目,无需安装 vue 等依赖。

这样的好处是你把子模块视作单独的项目时也可以清楚的知道它必须有哪些依赖。

当然这些并不是强制性的,如果嫌麻烦,全部使用 pnpm -w add xxx 安装在根模块就可以了。

项目整体结构

经过上面的介绍,其实项目整体结构很简单,再梳理一下核心内容如下:

.
├── demo 			// 子项目 demo: 用于测试组件库打包的 Vue 项目
├── example 		// 子模块 example: 用于开发组件时进行实时预览,以及作为一个示例项目展示的 Vue 项目
├── LICENSE
├── package.json 	// 根模块 unocss-ui-monorepo
├── packages
│   ├── components 	// 子模块 @unocss-ui/components: 组件库源码
│   ├── preset 		// 子模块 @unocss-ui/preset: 组件库的 UnoCSS 预设
│   └── unocss-ui	// 子模块 unocss-ui: 组件库的汇总
├── pnpm-workspace.yaml // 设置 pnpm monorepo 的子模块
├── README.md 
├── tsconfig.json
└── // 省略一些配置文件如 .npmrc .eslintrc .gitignore 等

以上是这个项目的整体架构,知道了这些可以让你熟悉项目的结构,从而减少对其的恐惧。但是不可能项目每个文件都由我来介绍的清清楚楚,下面聊聊我认为比较合理的源码学习与查看方式。

对该项目的学习应该基于以下的原则:

1、从整体到局部,从根模块到子模块。首先应当看项目根目录下有哪些文件,例如本项目根目录下有一些我没有介绍到的文件:.eslintrc.npmrctsconfig.json 等,因为这些并不影响你对项目的整体理解。但是我建议遇到没见过的后缀名就百度查询一下相关资料,至少需要对其有简单的概念(是怎么产生的,是否是某个开发依赖的配置文件,用来做什么的),久而久之的积累下来会发现:前端其实就那么些个配置文件!

对于每个子模块中的内容,可以不用一开始全部看完,但是需要知道这个模块是用来干嘛的(这个我已经在上面介绍过了)。

2、先从项目的依赖开始看起。package.json 中有非常多的配置项,其中大部分与打包与发布有关,初次学习应该将重点放在 dependencisdevDependencies 这两个配置上,看看是否所有的依赖项都认识,如果遇到不认识的依赖还是需要自行百度。

3、熟悉了整体结构,可以开始看细节

基于上面的介绍,项目的整体结构应当是非常清晰的。

基于原子化 CSS 的组件封装方式

原子化 CSS 基础

如果你对原子化 CSS 没有任何概念,建议先从 TailwindCSS 开始了解并查询相关资料,理解它是什么,如何使用的。但是很多人哪怕接触过原子化 CSS,可能也无法理解它的好处。

在我看来,原子化 CSS 最大的好处其实是 减少人的编码心智负担

或许你会感到奇怪,一大堆的类似内联样式的书写方式,把代码写在 HTML 标签里,怎么会减少人的心智负担呢,应该是加大了心智负担才对呀!如果这样能减少心智负担,那远古时期就应该流行内联样式才对!

原子化 VS 内联样式

首先原子化 CSS 和内联样式是不一样的,主要体现在它非常的简短,例如实现这么一个简单圆圈效果:
在这里插入图片描述

<!-- 使用内联样式 -->
<div style="width: 1.25rem; height: 1.25rem; background-color: white; border: 2px solid red; border-radius: 100%;" />

<!-- 使用原子化 CSS -->
<div class="m-15 h-15 w-15 border-5 border-red-500 rounded-full bg-white" />

从这个角度来看原子化 CSS 可以认为是内联样式的简写,毫无疑问比它短很多,样式越多越明显。

如果要再给这个圆圈添加一个鼠标悬浮效果呢?常规的内联样式无法实现,需要借助选择器。而在原子化 CSS 中只需要这样添加以下属性:hover:bg-gray-100

<div class="m-15 h-15 w-15 border-5 border-red-500 rounded-full bg-white hover:bg-gray-100" />

再比如要给所有子标签添加边距这么一个简单的功能:
在这里插入图片描述

 <div>
   <span> A </span>
   <span style="margin-left: 16px;"> B </span>
   <span style="margin-left: 16px;"> C </span>
 </div>

使用原子化 CSS 非常简单:

<div class="space-x-4">
  <span> A </span>
  <span> B </span>
  <span> C </span>
</div>

原子化 CSS 包含了很多功能性极强的 class,因此它其实是内联样式的全方面升级。

原子化 VS class

这点我认为没有太大比较的必要,class 的本质是将相同属性的标签抽象出一份来维护。原子化也可以通过 @apply 实现类似的效果,而且更加灵活:

在这里插入图片描述

<div class="flex gap-2">
	<div class="circle border-red-500 ">
	<div class="circle border-blue-500">
	<div class="circle border-green-500">
</div>
.circle {
	@apply m-15 h-15 w-15 border-5 rounded-full bg-white hover:bg-gray-100;
}

毫无疑问相比原生 css 它依旧突出一个简洁。


在原子化中,@apply 这种用法只是用来辅助,大部分情况下都我都更愿意直接用原子化写,如果实在是重复的太多了,就用它。

因为使用 class 很大程度上会有一个困扰,也就是起名问题,原子化可以避免这个问题。

原子化对组件封装的影响

使用原子化 CSS 可以减少心智负担主要体现在以下几个方面:

  • 不用非常频繁的起类名,只会偶尔需要用到 class
  • 虽然类似内联样式,但是从写法上来说比它简洁太多,视觉效果很好
  • 写某个模块时不需要额外考虑对其他模块的影响,只需要注重当前内容

传统组件封装中由于 style 中的内容过多,我们一般会抽取出一个单独的 .css 文件,并且还要尽量想办法去进行各种抽取有共同点的 class 等操作,这些都是对 “心智负担” 的压力的体现。

使用了原子化的思路减少了巨量的 css,完全可以不考虑以上的操作。并且可以实现一个组件文件尽量减少其外部依赖,即我认为基于原子化 CSS 的组件文件完全可以只由一个 .vue 文件实现其全部内容,而不是在设计层面抽象出各种依赖再引入,这一点也实在是令人有巨大的心智负担。

尤其是在看别人的项目的时候,我经常会想着看看它的组件中的某一个很小的功能是如何实现的,奈何有些项目实在是将一个模块拆分的七零八碎,各种引入,令人眼花缭乱,更有甚者会滥用 “自动引入依赖” 这种功能,导致有时候在网页上看看代码根本无法理解一些逻辑的源自哪里。

UnoCSS UI 从开发之初的设计理念就是:简单就是最好的,因此:

  • 项目中没有使用那些看起来甜甜的插件(自动导入等)
  • 每个组件不过多的依赖于其他东西,所有组件只依靠一个 .vue 便实现其所有功能,如果你只想看某个组件的具体实现,只需要没有任何压力的看这个组件的 .vue 就可以了。

例如你可以查看这个 Button.vue 查看一下封装一个 Button 代码量其实非常的少 。

因此我认为在理解了整个项目的设计结构后,剩下的事情就非常简单了:挑选你感兴趣并想学习的组件源码去查看学习。

如果是萌新,尽量从比较简单的组件开始学习:Button,Tag,Alert 等。

@unocss-ui/components 项目结构

基于以上思想来看,其实 @unocss-ui/components 这个子项目的源码结构非常简单:

.
├── package.json
├── README.md
├── src
│   ├── components // 组件源码尽量简单独立、无依赖,一个 .vue 实现所有功能
│   │   ├── Alert.vue
│   │   ├── Badge.vue
│   │   ├── Button.vue
│   │   ├── Checkbox.vue
│   │   ├── ...
│   ├── composables // 一些可复用的函数
│   └── index.ts // 组件库入口文件,用于导出所有组件
├── tsconfig.json
├── tsconfig.node.json
├── uno.config.ts
└── vite.config.ts

@unocss-ui/preset

该 preset 没有做太复杂的事情,核心就是定义了 safelist 和 theme 两个属性。

safelist

就像之前所说的,该组件库中的组件都是不依赖于外部文件的,其实 preset 的主要意义是设置一些 safelist。

简单来说 safelist 解决的问题就是动态拼接 CSS 失效的问题,例如现在需要封装一个可以传入颜色的圆圈组件:

<script setup>
defineProps({
  color: { type: String, default: 'red' },
})
</script>

<template>
  <div
    class="h-15 w-15 border-5 rounded-full bg-white hover:bg-gray-100"
    :class="`border-${color}-500 `"
  />
</template>
<div class="m-15 flex gap-2">
	<Circle color="red" />
	<Circle color="blue" />
	<Circle color="green" />
</div>

以上代码非常合理,但却不一定会生效,因为 其中包含字符串拼接的 class,如果想要确保它一定会生效,可以配置 safelist:

// uno.config.ts
safelist: ['bg-red-500', 'bg-blue-500', 'bg-green-500']

因此 @unocss-ui/preset 大部分的配置其实就是针对 safelist,来保证我在代码中使用动态拼接 class 是正常的。

theme

参考:https://unocss.dev/config/theme#theme

在项目中,往往都是有 “主题色” 的概念的,UnoCSS UI 预设中约定了主题色为以下:

  • primary - indigo
  • secondary - teal
  • accent - pink
  • success - green
  • info - blue
  • warning - yellow
  • error - red
import { colors } from 'unocss/preset-mini'

// ...
theme: {
  colors: {
    primary: colors.indigo, // 简单的使用调色板颜色,否则需要自行书写 50, 100, 200, 300 这些数字对应的具体颜色
    secondary: colors.teal,
    accent: colors.pink,
    success: colors.green,
    info: colors.blue,
    warning: colors.yellow,
    error: colors.red,
  },
},
// ...

使用 bg-primary-500 等价于 bg-indigo-500,这样的好处是当你想一键切换主题只需要改一行配置即可。

同时,为了让代码中使用的更随心所欲,我们将其与 safelist 结合,来实现代码中可以使用动态拼接成主题色的 class

const types = ['primary', 'secondary', 'accent', 'success', 'info', 'warning', 'error']

// ...
safelist: [
  ...types.map(t => nums.map(n => `bg-${t}-${n}`)).flat(),
  ...types.map(t => nums.map(n => `text-${t}-${n}`)).flat(),
  // ...
],

对于大部分组件来说,完全可以接受一个类型固定的 type,然后动态的拼接到 bgtext 等 class 中

defineProps<{
  type?: 'success' | 'info' | 'warning' | 'error' | 'primary' | 'secondary' | 'accent'
}()

// ...
<div
	// ....
	:class="text-${type}-700 bg-${type}-500"
>
// ...
</div>

目前的 preset 源码 也比较简单,只是遇到了需要动态拼接的 class 情况才放到这里,后面会按需增加:

import type { Preset } from 'unocss'
import { colors } from 'unocss/preset-mini'

const types = ['primary', 'secondary', 'accent', 'success', 'info', 'warning', 'error']
const nums = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950']
const sizes = ['sm', 'md', 'lg', 'full']

export function presetUnocssUI(): Preset {
  return {
    name: '@unocss-ui/preset',
    safelist: [
      ...types.map(t => nums.map(n => `bg-${t}-${n}`)).flat(),
      ...types.map(t => nums.map(n => `border-${t}-${n}`)).flat(),
      ...types.map(t => nums.map(n => `text-${t}-${n}`)).flat(),
      ...types.map(t => nums.map(n => `focus:ring-${t}-${n}`)).flat(),
      ...types.map(t => nums.map(n => `focus:border-${t}-${n}`)).flat(),
      ...types.map(t => `border-r-${t}-500`),
      ...sizes.map(s => `rounded-${s}`),
    ],
    theme: {
      colors: {
        primary: colors.indigo,
        secondary: colors.teal,
        accent: colors.pink,
        success: colors.green,
        info: colors.blue,
        warning: colors.yellow,
        error: colors.red,
      },
    },
  }
}

顺带一提,@unocss-ui/preset 不仅用于该组件库,也可以单独使用。

只要在你的项目中引用了该 preset,即可以使用 bg-primary-500 这种带有主题风格的颜色 class。

当你想覆盖 UnoCSS UI 默认的主题配置时,也需要引入其并重新覆盖 theme 即可:

import { defineConfig, presetUno } from 'unocss'
import { colors } from 'unocss/preset-mini'
import { presetUnocssUI } from 'unocss-ui'

export default defineConfig({
  theme: {
    colors: {
      primary: colors.red, // 覆盖 primary
      secondary: colors.blue, // 覆盖 secondary
      accent: colors.green, // 覆盖 accent
    },
  },
  presets: [
    presetUno(),
    presetUnocssUI(), // 引入该 preset
  ],
})

example

example 预览地址:https://cherryful.github.io/unocss-ui/

example 这个子项目目前的意义主要在于开发时的调试,以及本身作为一个示例项目来展示组件。

只需要通过以下指令运行起来,然后就可以直接修改 @unocss-ui/components 中的源码,就能进行实时的开发调试。

git clone https://github.com/cherryful/unocss-ui
cd unocss-ui
pnpm install

pnpm dev:example

demo

demo 这个子项目是用来测试组件库打包效果的,当你开发完 @unocss-ui/components 或 @unocss-ui/preset 后可以看看打包后的效果是否正常:

pnpm build:all

pnpm dev:demo

TODO

这篇文章想讲的东西还有很多(后面还会更新),并且组件库本身也在快速开发与迭代中,非常欢迎各位同学参与建设,学习源码,对我提出意见。

如果觉得本文能帮上你,或者认为这个项目还不错,欢迎给个 Star。

Github 地址:https://github.com/cherryful/unocss-ui

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

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

相关文章

HashTable 在蚂蚁转化归因中的极致运用

作者&#xff1a;开七 蚂蚁集团数据技术专家 本文围绕 hash cluster 表运用及 Shuffle 过程原理进行讨论&#xff0c;欢迎各位开发者加入大数据计算 MaxCompute 社区&#xff1a;https://developer.aliyun.com/group/maxcompute 概述 蚂蚁的转化归因在初期运行两个多小时的情况…

Facebook拆分的深度思考:社交媒体真的是必需品吗?

在当今数字化时代&#xff0c;社交媒体已经成为我们日常生活中不可或缺的一部分。而Facebook作为其中的巨头之一&#xff0c;不可否认地对人们的社交行为和信息传播产生了巨大的影响。 然而&#xff0c;随着越来越多的争议和讨论浮出水面&#xff0c;我们有必要进行深入思考&a…

文档处理新探究成果——前沿技术CCIG文档图像智能分析论坛分享

目录 前言 一、文档分析与识别最新研究 二、视觉-语言预训练模型及迁移学习 三、篡改文本图像的生成与检测技术 四、智能文档处理技术在工业界的应用与挑战 总结 前言 图文智能处理前沿技术一直是我所关注的技术&#xff0c;尤其在现在集成多态大模型的基础之上&#xff0…

关于PCBA元器件布局的重要性

SMT贴片加工逐步往高密度、细间距的设计发展&#xff0c;元器件的最小间距设计&#xff0c;需考虑SMT厂家的经验和工艺完善程度。元器件最小间距的设计&#xff0c;除了保证SMT焊盘间安全距离外&#xff0c;还应考虑元器件的可维护性。 器件布局时保证安全间距 1、安全距离跟…

设计模式-简单例子理解适配器模式、装饰器模式

文章目录 一、适配器模式1. 要点2. Demo 二、装饰器模式1. 要点2. Demo 三、区别 本文参考&#xff1a; 基本原理&#xff1a;装饰器模式 | 菜鸟教程 (runoob.com) 基本原理&#xff1a;适配器模式 | 菜鸟教程 (runoob.com) 优缺点和区别&#xff0c;装饰模式&#xff1a;适配器…

微服务流量控制组件Sentinel

1 简介 Sentinel是阿里开源的项目&#xff0c;是一款面向分布式服务架构的轻量级流量控制组件&#xff0c;主要以流量为切入点&#xff0c;从流量控制、熔断降级、系统自适应保护等多个维度来保障服务的稳定性。 核心思想是&#xff1a;根据对应资源配置的规则来为资源执行相…

西米支付:“中止”支付牌照,汇卡支付机构“失联”

近日&#xff0c;又一家支付公司因“失联”被列入了经营异常名录。 工商信息显示&#xff0c;目前被“中止”中的持牌支付机构广东汇卡商务服务有限公司&#xff08;简称“汇卡支付”&#xff09;因“通过登记的住所或者经营场所无法联系” 被广州市市场监督管理局列入经营异常…

网络进阶学习:单臂路由(灵魂五问)

单臂路由&#xff08;灵魂五问&#xff09; 一问&#xff1a;什么是单臂路由&#xff1f;二问&#xff1a;单臂路由这一概念怎么出现的&#xff1f;三问&#xff1a;单臂路由解决什么问题&#xff1f;能不能用其他方式取代单臂路由?四问&#xff1a;单臂路由最合适的应用场景&…

电脑E盘被不小心格式化了?别急,介绍三种数据恢复方法

电脑E盘格式化后如何恢复数据&#xff1f;意外的电脑E盘格式化或许是每个人都遇到过的问题。然而&#xff0c;当您发现您的重要数据已经丢失时&#xff0c;您可能会感到沮丧甚至绝望。但请不要担心。在本文中&#xff0c;我们将介绍一些有助于您找回数据的方法&#xff0c;希望…

2023年5月DAMA-CDGA/CDGP数据治理认证咋样

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

uvc驱动ioctl分析下

uvc驱动ioctl分析下 文章目录 uvc驱动ioctl分析下uvc_ioctl_enum_input枚举输入uvc_query_ctrl__uvc_query_ctrluvc_ioctl_g_input 获取输入uvc_ioctl_s_input 设置输入uvc_query_v4l2_ctrluvc_ioctl_queryctrl查询控制器uvc_ioctl_query_ext_ctrl查询扩展控制器 uvc_ioctl_g_c…

系统分析师经典易错题,解题思路二

企业应用集成(Enterprise Application Integration EAI)技术企业应用集成技术可以消除信息孤岛,它将多个企业信息系统连接起来,实现无缝集成,使他们就像一个整体一样。EAI是伴随着企业信息系统的发展而产生和演变的,企业的价值取向是推动EAI技术发展的原动力,而EAI的实现…

煤矿电子封条系统 yolov7网络模型

煤矿电子封条系统通过yolov7网络模型算法&#xff0c;煤矿电子封条系统可以实现对煤矿井下人员的出入管理&#xff0c;提高对煤矿井下人员的监管效果。YOLOv7 的策略是使用组卷积来扩展计算块的通道和基数。研究者将对计算层的所有计算块应用相同的组参数和通道乘数。然后&…

从热爱到深耕,在开发路上的他们勇敢逐梦

2022年的程序员节&#xff0c; #大龄程序员去哪儿了#成为了社交媒体上最火的话题之一&#xff0c;程序员的职场成长问题在社会上引起了广泛关注。 有2位在技术领域摸爬滚打很多年的开发者&#xff0c;35岁后的他们&#xff0c;有70后&#xff0c;有80后&#xff0c;依然在编程…

【Java编程系列】Springcloud-gateway自带限流方案实践篇

1、前言 作为一个后端开发&#xff0c;对于后端服务的安全性方面&#xff0c;一定要有足够的考虑。近期的开发工作中&#xff0c;有一个实现分享外部链接的需求点&#xff0c;个人认为这一块会有安全隐患。比如&#xff0c;因为这个分享的外链会被用户无限制点开查看&#xff0…

常见分布函数。

一维常见分布函数 1.离散型 ① 0 - 1分布 记 X~B(1,p) 如果X的概率分布为 ( 1 0 p 1 − p ) \begin{pmatrix} 1 & 0 \\ p & 1-p \end{pmatrix} (1p​01−p​),则称X服从参数为P的0-1分布&#xff08;0<p<1&#xff09;。 注&#xff1a;0-1分布又称一次伯努利试…

iOS-Telegraph异步响应实现

背景 Telegraph该库只支持管理本地同步请求&#xff0c;为了长远打算&#xff0c;需要研究是否能使response异步回调的方法 参考gitHub-Telegraph文档 现象&#xff1a;根据文档说明和示例&#xff0c;以及查看源码实现确认该第三方库确实只支持管理本地同步的请求响应 它的…

【程序员日记】——从业务编排到低代码 | 京东云技术团队

之前总聊微服务&#xff0c;今天换一个话题—低代码。 低代码这个词也是最近这几年很火的概念&#xff0c;尤其是遇到大环境下行&#xff0c;很多大厂和互联网那个公司也在慢慢在低代码方向发力&#xff0c;当然&#xff0c;对于传统项目交付型的软件公司&#xff0c;低代码也…

LabVIEWCompactRIO 开发指南28 可重入和非重入子VI之间的权衡

LabVIEWCompactRIO 开发指南28 了解可重入和非重入子VI之间的权衡 重入是子VI执行属性中的设置。在LabVIEW FPGA中&#xff0c;子VI执行默认设置为可重入。重入在FPGA逻辑中创建子VI的多个副本。这能够并行执行子VI的多个副本&#xff0c;同时存储不同且独立的数据存储。 在…

计算GMAC和GFLOPS

GMAC 代表“Giga Multiply-Add Operations per Second”&#xff08;每秒千兆乘法累加运算&#xff09;&#xff0c;是用于衡量深度学习模型计算效率的指标。它表示每秒在模型中执行的乘法累加运算的数量&#xff0c;以每秒十亿 (giga) 表示。 乘法累加 (MAC) 运算是许多数学计…