vant 4 正式发布,支持暗黑主题,那么是如何实现的呢

news2024/11/23 15:41:44

2022年10月25日首发于掘金,现在同步到公众号。

11. 前言

大家好,我是若川。我倾力持续组织了一年多源码共读,感兴趣的可以加我微信 lxchuan12 参与。另外,想学源码,极力推荐关注我写的专栏《学习源码整体架构系列》,目前是掘金关注人数(4.6k+人)第一的专栏,写有20余篇源码文章。


我们开发业务时经常会使用到组件库,一般来说,很多时候我们不需要关心内部实现。但是如果希望学习和深究里面的原理,这时我们可以分析自己使用的组件库实现。有哪些优雅实现、最佳实践、前沿技术等都可以值得我们借鉴。

相比于原生 JS 等源码。我们或许更应该学习,正在使用的组件库的源码,因为有助于帮助我们写业务和写自己的组件。

如果是 Vue 技术栈,开发移动端的项目,大多会选用 vant 组件库,目前(2022-10-24) star 多达 20.3k。我们可以挑选 vant 组件库学习,我会写一个组件库源码系列专栏[1],欢迎大家关注。

这次我们来分析 vant4 新增的暗黑主题是如何实现的。文章中的 vant4 的版本是 4.0.0-rc.6vant 的核心开发者是@chenjiahan[2],一直在更新vant 。预计不久后就会发布 vant4 正式版。

暗黑主题如图所示:

f94a88ddbe1b98116c770b85ab6a27db.png
暗黑主题

也可以打开官方文档链接[3],自行体验。

学完本文,你将学到:

1. 学会暗黑主题的原理和实现
2. 学会使用 vue-devtools 打开组件文件,并可以学会其原理
3. 学会 iframe postMessage 和 addEventListener 通信
4. 学会 ConfigProvider 组件 CSS 变量实现对主题的深度定制原理
5. 学会使用 @vue/babel-plugin-jsx 编写 jsx 组件
6. 等等

22. 准备工作

看一个开源项目,第一步应该是先看 README.md[4] 再看贡献文档 github/CONTRIBUTING.md[5]

不知道大家有没有发现,很多开源项目都是英文的 README.md,即使刚开始明显是为面向中国开发者。再给定一个中文的 README.md。主要原因是因为英文是世界通用的语言。想要非中文用户参与进来,英文是必备。也就是说你开源的项目能提供英文版就提供。

2.1 克隆源码

贡献文档中有要求:You will need Node.js >= 14[6] and pnpm[7].

# 推荐克隆我的项目
git clone https://github.com/lxchuan12/vant-analysis
cd vant-analysis/vant

# 或者克隆官方仓库
git clone git@github.com:vant-ui/vant.git
cd vant

# Install dependencies
pnpm i

# Start development
pnpm dev

我们先来看 pnpm dev 最终执行的什么命令。

vant 项目使用的是 monorepo 结构。查看根路径下的 package.json

2.2 pnpm dev

// vant/package.json
{
    "private": true,
    "scripts": {
        "prepare": "husky install",
        "dev": "pnpm --dir ./packages/vant dev",
  },
}

再看 packages/vant/package.json

// vant/packages/vant/package.json
{
  "name": "vant",
  "version": "4.0.0-rc.6",
  "scripts": {
    "dev": "vant-cli dev",
  },
}

pnpm dev 最终执行的是:vant-cli dev 启动了一个服务。本文主要是讲主题切换的实现,所以我们就不深入 vant-cli dev 命令了。

执行 pnpm dev 后,命令终端输入如图所示,可以发现是使用的是目前最新版本的 vite 3.1.8

aa2508e8350eb8a51c54e54a80e6258d.png
pnpm-dev-vite

这时我们打开 http://localhost:5173/#/zh-CN/config-provider

33. 文档网站

打开后,我们可以按 F12vue-devtools 来查看vant 官方文档的结构。如果没有安装,我们可以访问vue-devtools 官网[8]通过谷歌应用商店去安装。如果无法打开谷歌应用商店,可以通过这个极简插件链接[9] 下载安装。

a496e2c0a0a8c6d9630753a607dcb535.png
VanDocHeader 组件

mobile 端

4fe3a83ceebb12f3fdf4726e6b21a8be.png
VanDocSimulator 组件

3.1 通过 vue-devtools 打开组件文件

8dc7e745d559d1a15da8289473c616e6.png
打开 VanDocSimulator 组件文件

如图所示,我们通过 vue-devtools 打开 VanDocSimulator 组件文件。

曾经在我的公众号@若川视野 发起投票[10]分析这个功能的原理。感兴趣的小伙伴可以查看。

我们可以看到 vant/packages/vant-cli/site/desktop/components/Simulator.vue 文件,主要是 iframe 实现的,渲染的链接是 /mobile.html#/zh-CN。我们也可以直接打开 mobile 官网[11] 验证下。

// vant/packages/vant-cli/site/desktop/components/Simulator.vue
<template>
  <div :class="['van-doc-simulator', { 'van-doc-simulator-fixed': isFixed }]">
    <iframe ref="iframe" :src="src" :style="simulatorStyle" frameborder="0" />
  </div>
</template>

<script>
export default {
  name: 'VanDocSimulator',

  props: {
    src: String,
  },
  // 省略若干代码
}

3.2 desktop 端

和打开 VanDocSimulator 类似,我们通过 vue-devtools 打开 VanDocHeader 组件文件。

打开了文件后,我们也可以使用 `Gitlens`[12] 插件。根据 git 提交记录 feat(@vant/cli): desktop site support dark mode[13],查看添加暗黑模式做了哪些改动。

接着我们来看 vant/packages/vant-cli/site/desktop/components/Header.vue 文件。找到切换主题的代码位置如下:

模板部分

// vant/packages/vant-cli/site/desktop/components/Header.vue

<template>
    <li v-if="darkModeClass" class="van-doc-header__top-nav-item">
    <a
        class="van-doc-header__link"
        target="_blank"
        @click="toggleTheme"
    >
        <img :src="themeImg" />
    </a>
    </li>
</template>

JS部分

// vant/packages/vant-cli/site/desktop/components/Header.vue

<script>

import { getDefaultTheme, syncThemeToChild } from '../../common/iframe-sync';

export default {
  name: 'VanDocHeader',
  data() {
    return {
      currentTheme: getDefaultTheme(),
    };
  },
    watch: {
        // 监听主题变化,移除和添加样式 class
        currentTheme: {
            handler(newVal, oldVal) {
                window.localStorage.setItem('vantTheme', newVal);
                document.documentElement.classList.remove(`van-doc-theme-${oldVal}`);
                document.documentElement.classList.add(`van-doc-theme-${newVal}`);
                // 我们也可以在这里加上debugger自行调试。
                debugger;
                // 同步到 mobile 的组件中
                syncThemeToChild(newVal);
            },
            immediate: true,
        },
    },

    methods: {
        // 切换主题
        toggleTheme() {
          this.currentTheme = this.currentTheme === 'light' ? 'dark' : 'light';
        },
    }
}

</script>

3.3 iframe 通信 iframe-sync

上文JS代码中,有 getDefaultTheme, syncThemeToChild 函数引自文件 vant/packages/vant-cli/site/common/iframe-sync.js

文件开头主要判断 iframe 渲染完成。

// vant/packages/vant-cli/site/common/iframe-sync.js

import { ref } from 'vue';
import { config } from 'site-desktop-shared';

let queue = [];
let isIframeReady = false;

function iframeReady(callback) {
  if (isIframeReady) {
    callback();
  } else {
    queue.push(callback);
  }
}

if (window.top === window) {
  window.addEventListener('message', (event) => {
    if (event.data.type === 'iframeReady') {
      isIframeReady = true;
      queue.forEach((callback) => callback());
      queue = [];
    }
  });
} else {
  window.top.postMessage({ type: 'iframeReady' }, '*');
}

后半部分主要是三个函数 getDefaultThemesyncThemeToChilduseCurrentTheme

// 获取默认的主题
export function getDefaultTheme() {
  const cache = window.localStorage.getItem('vantTheme');

  if (cache) {
    return cache;
  }

  const useDark =
    window.matchMedia &&
    window.matchMedia('(prefers-color-scheme: dark)').matches;
  return useDark ? 'dark' : 'light';
}

// 同步主题到 iframe 用 postMessage 通信
export function syncThemeToChild(theme) {
  const iframe = document.querySelector('iframe');
  if (iframe) {
    iframeReady(() => {
      iframe.contentWindow.postMessage(
        {
          type: 'updateTheme',
          value: theme,
        },
        '*'
      );
    });
  }
}

// 接收、使用主题色
export function useCurrentTheme() {
  const theme = ref(getDefaultTheme());

  // 接收到 updateTheme 值
  window.addEventListener('message', (event) => {
    if (event.data?.type !== 'updateTheme') {
      return;
    }

    const newTheme = event.data?.value || '';
    theme.value = newTheme;
  });

  return theme;
}

在项目中,我们可以可以搜索 useCurrentTheme 看在哪里使用的。很容易我们可以发现 vant/packages/vant-cli/site/mobile/App.vue 文件中有使用。

3.4 mobile 端

// 模板部分
// vant/packages/vant-cli/site/mobile/App.vue

<template>
  <demo-nav />
  <router-view v-slot="{ Component }">
    <keep-alive>
      <demo-section>
        <component :is="Component" />
      </demo-section>
    </keep-alive>
  </router-view>
</template>
// js 部分
// vant/packages/vant-cli/site/mobile/App.vue
<script>
import { watch } from 'vue';
import DemoNav from './components/DemoNav.vue';
import { useCurrentTheme } from '../common/iframe-sync';
import { config } from 'site-mobile-shared';

export default {
  components: { DemoNav },

  setup() {
    const theme = useCurrentTheme();

    watch(
      theme,
      (newVal, oldVal) => {
        document.documentElement.classList.remove(`van-doc-theme-${oldVal}`);
        document.documentElement.classList.add(`van-doc-theme-${newVal}`);

        const { darkModeClass, lightModeClass } = config.site;
        if (darkModeClass) {
          document.documentElement.classList.toggle(
            darkModeClass,
            newVal === 'dark'
          );
        }
        if (lightModeClass) {
          document.documentElement.classList.toggle(
            lightModeClass,
            newVal === 'light'
          );
        }
      },
      { immediate: true }
    );
  },
};
</script>

<style lang="less">
@import '../common/style/base';

body {
  min-width: 100vw;
  background-color: inherit;
}

.van-doc-theme-light {
  background-color: var(--van-doc-gray-1);
}

.van-doc-theme-dark {
  background-color: var(--van-doc-black);
}

::-webkit-scrollbar {
  width: 0;
  background: transparent;
}
</style>

上文阐述了浅色主题和暗黑主题的实现原理,我们接着来看如何通过 `ConfigProvider` 组件[14]实现主题的深度定制。

44. ConfigProvider 组件,深度定制主题

这个组件的文档有说明,主要就是利用 CSS 变量[15]来实现的,具体可以查看这个链接学习。这里举个简单的例子。

// html
<div id="app" style="--van-color: black;--van-background-color: pink;">hello world</div>
// css
#app {
  color: var(--van-color);
  background-color: var(--van-background-color);
}

可以预设写好若干变量,然后在 style 中修改相关变量,就能得到相应的样式,从而达到深度定制修改主题的能力。

比如:如果把 --van-color: black;,改成 --van-color: red; 则字体颜色是红色。如果把 --van-background-color: pink; 改成 --van-background-color: white; 则背景色是白色。

vant 中有一次提交把之前所有的 less 变量,改成了原生 cssvar 变量。breaking change: no longer support less vars[16]

vantConfigProvider 组件其实就是利用了这个原理。

知晓了上面的原理,我们再来简单看下 ConfigProvider 具体实现。

// vant/packages/vant/src/config-provider/ConfigProvider.tsx
// 代码有省略
function mapThemeVarsToCSSVars(themeVars: Record<string, Numeric>) {
  const cssVars: Record<string, Numeric> = {};
  Object.keys(themeVars).forEach((key) => {
    cssVars[`--van-${kebabCase(key)}`] = themeVars[key];
  });
  // 把 backgroundColor 最终生成类似这样的属性
  // {--van-background-color: xxx}
  return cssVars;
}

export default defineComponent({
  name,

  props: configProviderProps,

  setup(props, { slots }) {
    // 完全可以在你需要的地方打上 debugger 断点
    debugger;
    const style = computed<CSSProperties | undefined>(() =>
      mapThemeVarsToCSSVars(
        extend(
          {},
          props.themeVars,
          props.theme === 'dark' ? props.themeVarsDark : props.themeVarsLight
        )
      )
    );

    // 主题变化添加和移除相应的样式类
    if (inBrowser) {
      const addTheme = () => {
        document.documentElement.classList.add(`van-theme-${props.theme}`);
      };
      const removeTheme = (theme = props.theme) => {
        document.documentElement.classList.remove(`van-theme-${theme}`);
      };

      watch(
        () => props.theme,
        (newVal, oldVal) => {
          if (oldVal) {
            removeTheme(oldVal);
          }
          addTheme();
        },
        { immediate: true }
      );

      onActivated(addTheme);
      onDeactivated(removeTheme);
      onBeforeUnmount(removeTheme);
    }

    // 插槽
    // 用于 style
    // 把 backgroundColor 最终生成类似这样的属性
    // {--van-background-color: xxx}

    return () => (
      <props.tag class={bem()} style={style.value}>
        {slots.default?.()}
      </props.tag>
    );
  },
});

有小伙伴可能注意到了,这感觉就是和 react 类似啊。其实 vue 也是支持 jsx。不过需要配置插件 `@vue/babel-plugin-jsx`[17]。全局搜索这个插件,可以搜索到在 vant-cli 中配置了这个插件。

55. 总结

我们通过查看 README.md 和贡献文档等,知道了项目使用的 monorepovite 等,pnpm i 安装依赖,pnpm dev 跑项目。

我们学会了利用 vue-devtools 快速找到我们不那么熟悉的项目中的文件,并打开相应的文件。

通过文档桌面端和移动端的主题切换,我们学到了原来是 iframe 渲染的移动(mobile)端,通过 iframe postMessageaddEventListener 通信切换主题。

学会了 ConfigProvider 组件是利用CSS 变量[18] 预设变量样式,来实现的定制主题。

也学会使用 `@vue/babel-plugin-jsx`[19] 编写 jsx 组件,和写 react 类似。

相比于原生 JS 等源码。我们或许更应该学习,正在使用的组件库的源码,因为有助于帮助我们写业务和写自己的组件。开源项目通常有很多优雅实现、最佳实践、前沿技术等都可以值得我们借鉴。

如果是自己开源写项目相对耗时耗力,而且短时间很难有很大收益,很容易放弃。而刚开始可能也无法参与到开源项目中,这时我们可以先从看懂开源项目的源码做起。对于写源码来说,看懂源码相对容易。看懂源码后可以写文章分享回馈给社区,也算是对开源做出一种贡献。重要的是行动起来,学着学着就会发现很多都已经学会,锻炼了自己看源码的能力。

如果看完有收获,欢迎点赞、评论、分享支持。你的支持和肯定,是我写作的动力

参考资料

[1]

组件库源码系列专栏: https://juejin.cn/column/7140264842954276871

[2]

@chenjiahan: https://github.com/chenjiahan/

[3]

官方文档链接: https://vant-contrib.gitee.io/vant/v4/#/zh-CN/config-provider

[4]

README.md: https://github.com/youzan/vant

[5]

github/CONTRIBUTING.md: https://github.com/youzan/vant/blob/main/.github/CONTRIBUTING.md

[6]

Node.js >= 14: https://nodejs.org

[7]

pnpm: https://pnpm.io

[8]

vue-devtools 官网: https://devtools.vuejs.org/guide/installation.html

[9]

极简插件链接: https://chrome.zzzmh.cn/info/nhdogjmejiglipccpnnnanhbledajbpd

[10]

发起投票: https://mp.weixin.qq.com/s/9gYmrJLdKwJ1TCVm-MUzrA

[11]

mobile 官网: https://vant-contrib.gitee.io/vant/mobile.html#/zh-CN

[12]

Gitlens: https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens

[13]

feat(@vant/cli): desktop site support dark mode: https://github.com/youzan/vant/commit/35a990ed65500311cbcafae506780dc6d3fb49fa

[14]

ConfigProvider 组件: https://vant-contrib.gitee.io/vant/#/zh-CN/config-provider

[15]

CSS 变量: https://developer.mozilla.org/zh-CN/docs/Web/CSS/Using_CSS_custom_properties

[16]

breaking change: no longer support less vars: https://github.com/youzan/vant/commit/ada5db011c676893a2917b9424be1aeafe54134b#diff-9a3dd1c100237e3a5d11553bb08a5f74144c9aecc67a995b8e608bfe2ebcf7f2

[17]

@vue/babel-plugin-jsx: https://www.npmjs.com/package/@vue/babel-plugin-jsx

[18]

CSS 变量: https://developer.mozilla.org/zh-CN/docs/Web/CSS/Using_CSS_custom_properties

[19]

@vue/babel-plugin-jsx: https://www.npmjs.com/package/@vue/babel-plugin-jsx

6b8f2b844c53ee37fe491e383efd08ec.gif

················· 若川简介 ·················

你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》20余篇,在知乎、掘金收获超百万阅读。
从2014年起,每年都会写一篇年度总结,已经坚持写了8年,点击查看年度总结。
同时,持续组织了一年多源码共读活动,帮助5000+前端人学会看源码。公众号愿景:帮助5年内前端人走向前列。

e5d5d50834afc6a95c95d8f7b60d0111.jpeg

扫码加我微信 lxchuan12、拉你进源码共读

今日话题

目前建有江西|湖南|湖北 籍 前端群,想进群的可以加我微信 lxchuan12 进群。分享、收藏、点赞、在看我的文章就是对我最大的支持~

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

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

相关文章

八股文总是忘?一张图牢记JVM内存结构|金三银四系列

金三银四又来啦&#xff01;八股文还是得复习起来&#xff0c;最近准备把一些常见的八股文知识点聊聊。本文详解了JVM内存结构和各个部分详细内容&#xff0c;应付面试绰绰有余&#xff01;点击上方“后端开发技术”&#xff0c;选择“设为星标” &#xff0c;优质资源及时送达…

visual studio2022配置opencv

标题&#xff1a;在vs下配置使用opencv 流程&#xff1a; 1、下载安装opencv 2、添加环境变量 3、vs中配置属性 4、使用 5、可能遇到的报错和解决 1、 下载安装opencv 官网下载地址&#xff1a; https://opencv.org/releases/ 我这里是windows环境&#xff0c;所以选择点击w…

Java数据结构之优先级队列

前言总是忘了优先队列的一些应用&#xff0c;其实这都是很基础的了。为了再加强印象&#xff0c;抄一遍吧。PriorityQueue简介PriorityQueue&#xff0c;即优先级队列。优先级队列可以保证每次取出来的元素都是队列中的最小或最大的元素&#xff08;Java优先级队列默认每次取出…

微信小程序 if语法、for循环 条件渲染、列表渲染等讲解

这篇文章我想给大家学习的就是如何使用 if 去判断 组件的是显示和隐藏&#xff0c;如何使用for循环来渲染列表等重复的内容。 1.if语法的使用 在小程序中&#xff0c;我们可以使用wx:if"{{条件}}"来判断是否需要渲染该代码块 也可以用 wx:elif 和wx:else 来添加 el…

【java】Spring Boot -- Spring的IOC实现原理

文章目录IOC定义理解IOC不使用IOC&#xff1a;使用IOC&#xff1a;使用IOC的好处IOC提供被依赖对象的方式构造器注入setter 方法注入接口方式注入简单模拟IOC总结IOC定义 IoC 全称为 Inversion of Control&#xff0c;翻译为 “控制反转”&#xff0c;它还有一个别名为 DI&…

【Selenium】十分钟手把手带你学会WebDriver API

目录 1、定位元素【8种】 2、操作测试对象 3、添加等待 4、弹窗类型 5、浏览器的操作 6、键盘事件 7、选择框 8、上传文件 1、定位元素【8种】 元素定位是自动化测试的核心&#xff0c;想要去操作一个对象&#xff0c;第一步就是需要我们先去识别这个对象。每个对象就会…

全民ChatGPT热:快来解锁你的“全能网友”

前 言 2021年11月30日&#xff0c;OpenAI推出人工智能聊天原型ChatGPT&#xff0c;赚足了眼球&#xff0c;在AI界引发了类似AIGC让艺术家失业的大讨论。 据报道&#xff0c;ChatGPT在开放试用的短短几天&#xff0c;就吸引了超过 100 万互联网注册用户。并且社交网络流传出各种…

html5标签

图片&#xff1a;image 主要属性&#xff1a; src&#xff1a;源属性的值是图像的 URL 地址。 alt&#xff1a;用来为图像定义一串预备的可替换的文本。 注意事项&#xff1a; 注意: 假如某个 HTML 文件包含十个图像&#xff0c;那么为了正确显示这个页面&#xff0c;需要加…

速通Spring

尚硅谷2023最新版Spring6课程_bilibili 1 Spring 【强制】Spring是什么&#xff1f; 1) Spring是一款主流的Java EE轻量级开源框架。 轻量级&#xff1a;体积很小&#xff0c;且不需要依赖于其他组件。 2) 狭义的Spring。 Spring Framework。 3) 广义的Spring。 以Spring F…

python对多个csv文件进行合并(表头需一致)

之前写过python对【多个Excel文件】中的【单个sheet】进行合并&#xff0c;参考&#xff1a;点我 之前也写过python对【多个Excel文件】中的【多个sheet】进行合并&#xff0c;参考&#xff1a;点我 今天再写一个python对多个csv格式的文件进行合并的小工具 但是大家切记&am…

GIS开源框架:ArcGIS文件地理数据库(GDB)解析与入库

对于GIS专业毕业的同学&#xff0c;想必对于ArcGIS软件不会太陌生&#xff0c;对于地理数据库也有一定的了解和使用经验。但是&#xff0c;撇开软件操作层面不谈&#xff0c;作为一个WebGIS/GIS开发人员&#xff0c;我们如何通过GIS开源框架去完成地理数据库的自动化解析和入库…

解决不同影像裁剪后栅格数据行列不一致问题

前言在处理栅格数据时&#xff0c;尽管用同一个矢量文件裁剪栅格数据&#xff0c;不同数据来源的栅格行列数也会出现不一致的情况。如果忽略或解决不好&#xff0c;会导致后续数据处理出现意想不到的误差或错误&#xff0c;尤其是利用编程实现数据处理时。因此&#xff0c;应当…

VisualGDB 5.6R9 FOR WINDOWS

Go cross-platform with comfort VisualGDB 是 Visual Studio 的一个非常强大的扩展&#xff0c;它允许您调试或调试嵌入式系统。这个程序有一个非常有吸引力的用户界面&#xff0c;它有许多调试或调试代码的功能。VisualGDB 还有一个向导可以帮助您调试程序&#xff0c;为您提…

【C++】关键字、命名空间、输入和输出、缺省参数、函数重载

C关键字(C98)命名空间产生背景命名空间定义命名空间使用输入&输出缺省参数什么叫缺省参数缺省参数分类函数重载函数重载概念C支持函数重载的原理--名字修饰C关键字(C98) C总计63个关键字&#xff0c;C语言32个关键字。 下面我们先看一下C有多少关键字&#xff0c;不对关键…

Linux 解压JAR包 查看class内容

快速解决方案 查询class相对路径&#xff1a;jar tf test.jar | grep "test.class"单独解压class文件&#xff1a;jar xvf test.jar com/test/test.class查看class文件内容&#xff1a;javap -c com/test/test.class 背景 服务运行后&#xff0c;日志打印出来发现…

【taichi】利用 taichi 编写深度学习算子 —— 以提取右上三角阵为例

本文以取 (bs, n, n) 张量的右上三角阵并展平为向量 (bs, n*(n1)//2)) 为例&#xff0c;展示如何用 taichi 编写深度学习算子。 如图&#xff0c;要把形状为 (bs,n,n)(bs,n,n)(bs,n,n) 的张量&#xff0c;转化为 (bs,n(n1)2)(bs,\frac{n(n1)}{2})(bs,2n(n1)​) 的向量。我们先写…

各种素材网站大全【全部倾倒,福利倒计时-JS,HTML,游戏素材,UI,图片素材等

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏&#xff1a;解忧杂货铺 ⭐各种素材网站大全⭐ 文章目录⭐各种素材网站大全⭐&#x1f3b6;大家必逛的四大天王…

STM32F769BIT6微控制器STM32F769IGT6详细规格

说明STM32F7 32 位 MCUFPU 基于高性能的 ARMCortex-M7 32 位 RISC 内核&#xff0c;工作频率高达 216MHz。Cortex-M7 内核具有单浮点单元(SFPU)精度&#xff0c;支持所有 ARM 单精度数据处理指令与数据类型。同时执行全套 DSP 指令和存储保护单元&#xff08;MPU&#xff09;&a…

JVM02类加载子系统

1. 加载阶段 通过一个类的全限定名获取定义此类的二进制字节流 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构 在内存中生成一个代表这个类的java.lang.Class对象&#xff0c;作为方法区这个类的各种数据的访问入口 加载class文件的方式 从本地系统中直接…

六、HTTP 首部字段

HTTP 首部字段 一、HTTP 报文首部 HTTP 请求报文由方法、URI、HTTP 版本、HTTP 首部字段等部分构成。 HTTP 响应报文由HTTP版本、状态码&#xff08;数字和原因短语&#xff09;、HTTP首部字段3部分构成。 HTTP 协议的请求和响应报文中必定包含 HTTP 首部。首部内容为客户端…