【99.9%解决】vue3+vite+typescript+vscode使用@alias路径别名配置不正确导致红色波浪线的解决办法

相信很多人设置了别名“@”后在编辑器内产生了大量的红色波浪线,警告无法读取相关模块。网上针对这个问题都没有好好分析原因,并且提供真正理解之下的解决方案。我在历经各种失败后,总结出这篇文章,希望对大家有所帮助。
当然我因为是匆忙上手vue项目,没有系统去学习nodejsvite等,所以很可能这个问题产生的根本原因只是你我都没仔细看说明书~~~

各种出错情况

在这里罗列一下我曾出现的问题,大家如果有别的现象,但后来通过本文所提方法解决了,请写在留言里,我会补充进来。

  • vscode编辑器中出现大量红色波浪线警告,这就是路径没配置好的最明显证据;
  • 使用typescript就出错,使用javascript就正常,把<script lang="ts"></script>中的lang="ts"删除后正常;
  • .vue组件页面中用import引入时不出现警告,但在独立的.js.ts文件中引用文件时出现波浪警告;
  • npm run dev时出现错误提示;
  • 编辑器有大量红色警告,但执行npm run dev命令正常启动服务;
  • 无论开发状态下有没有出现红色警告,但执行命令npm run devvite build正常,执行npm run build时却失败,出现类似提示Cannot find module '@/test/types' or its corresponding type declarations (我就一直卡在这里);
  • 编译时提示模块找不到,出现类似src/index.ts:4:31 - error TS7016: Could not find a declaration file for module '@/components/system/Register.vue'. 'E:/Projects/test/src/components/system/Register.vue' implicitly has an 'any' type.的提示

在这里插入图片描述

vite和typescript调用分析

Vite 配置中设置路径别名时,.vue 文件和 .ts 文件的处理方式有所不同。

  • .vue 文件中的路径解析会被 Vite 的插件自动处理。
    比如 .vue非typerscript代码中找不到 @ 别名,很可能是因为vite.config.ts 文件中没有正确配置路径别名。
  • .ts 文件的别名解析可能依赖于 tsconfig.json 的配置。
    比如 .ts 文件中找不到 @ 别名,很可能是因为tsconfig.json 文件中没有正确配置路径别名。

如果这两个没有配置正确,那自然就会出现之前提及的各种错误。
比如单独的ts或ts代码片段里出现错误,那就说明vite配置好了,但typescript没有配置好。

解决方案

不要跳,一步步看,看懂了以后遇到任何类似问题都能解决了。

- 主要配置

这是网上出现的最主要方案,但很可能配完以后还是失败。

  1. 确认 Vite 配置中的路径别名生效:
    vite.config.ts 中,确保别名配置正确,主要写法如下:
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';export default defineConfig({plugins: [vue()],resolve: {alias: {'@': '/src'}}
});
  1. tsconfig.json 中设置路径别名:
    确保在 tsconfig.json 文件中加入类似下面的配置,以便 TypeScript 在编译时能正确解析 @,主要写法如下:
// tsconfig.json
{"compilerOptions": {"baseUrl": ".","paths": {"@/*": ["src/*"]}}
}

如果配置完成后还是失败,但情况与之前不同了,那么恭喜你,我们将进入下个必要手段:

  1. 开发时虽然路径有波浪线警告,但执行npm run dev命令正常,前端可运行【说明vite.config.ts配置正确】;
  2. 运行vite build正常【说明vite.config.ts配置正确】;
  3. 运行npm run build失败【说明tsconfig.json配置错误】。

- 次要及必要配置(往往是这一步导致的错)

你再仔细看看你的ts.config.json真是写得一摸一样么?反正我不是。。。

用vite首次创建项目时,tsconfig.json往往内容是这样的:

// tsconfig.json
{"files": [],"references": [{ "path": "./tsconfig.app.json" },{ "path": "./tsconfig.node.json" }]
}

你改完以后的代码往往是这样的:

// tsconfig.json
{"files": [],"references": [{ "path": "./tsconfig.app.json" },{ "path": "./tsconfig.node.json" }],"compilerOptions": {"baseUrl": ".","paths": {"@/*": ["src/*"],}}
}

问题就出在这里了。

typescript在解析时,他根据配置引入了 ./tsconfig.app.json 这个配置文件,而这个配置文件可能是这样的;

// tsconfig.app.json
{"compilerOptions": {"target": "ES2020","useDefineForClassFields": true,"module": "ESNext","lib": ["ES2020", "DOM", "DOM.Iterable"],"skipLibCheck": true,/* Bundler mode */"moduleResolution": "Bundler","allowImportingTsExtensions": true,"isolatedModules": true,"moduleDetection": "force","noEmit": true,"jsx": "preserve",/* Linting */"strict": true,"noUnusedLocals": true,"noUnusedParameters": true,"noFallthroughCasesInSwitch": true,"noUncheckedSideEffectImports": true,},"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
}

发现没,这里也有一个compilerOptions项,现在你有那种茅塞顿开的感觉了么?
反正当我看到这个的时候恍然大悟了,原来是tm被覆盖了啊!

路径别名配置的生效文件: 由于 tsconfig.json 文件引用了 tsconfig.app.json 和 tsconfig.node.json,要确保这两个文件中没有覆盖 baseUrl 和 paths 配置。一般来说,主要的路径别名配置应位于 tsconfig.app.json 文件中,以便应用编译时可以正确使用别名。

事情到这里都应该知道怎么处理了吧?其实有很多种方式,这里列二种区别明显的:

方法一:覆盖

我让你覆盖,我让你覆盖。
你是不是要覆盖,行,我让你也有,你爱覆盖谁覆盖谁!

// tsconfig.json 原内容不变
{"files": [],"references": [{ "path": "./tsconfig.app.json" },{ "path": "./tsconfig.node.json" }],// 写不写都可以/*"compilerOptions": {"baseUrl": ".","paths": {"@/*": ["src/*"],}}*/
}// tsconfig.app.json
{"compilerOptions": {// 原配置"noUncheckedSideEffectImports": true,... // 不管tsconfig.json写不写,我都给他写一下"baseUrl": ".","paths": {"@/*": ["src/*"]}},"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
}

方法二:继承

references配置的模块就是子模块,那我让子模块继承extends父模块的衣钵不就行了?

// tsconfig.json
{"files": [],"references": [{ "path": "./tsconfig.app.json" },{ "path": "./tsconfig.node.json" }],// 新增配置"compilerOptions": {"baseUrl": ".","paths": {"@/*": ["src/*"],}}
}// tsconfig.app.json
{// 加一句:继承,从你爸爸这里继承配置,看谁覆盖谁"extends": "./tsconfig.json",// 原生配置"compilerOptions": {"noUncheckedSideEffectImports": true,...},"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
}

通过继承,可以在 tsconfig.json 中定义一些通用的配置项,然后在 tsconfig.app.json 中只定义特定的或覆盖的配置项。这样可以减少重复配置,提高维护性。
了解了继承的概念后,以后你可以根据项目需要写不同的配置,然后把他们按需引进来就行了~~
哇哦,有用却用不上的概念又多了一点点。

其它情况

上面的操作基本上能解决99%的问题,现在我再提几个可能存在的情况。

- 安装依赖

在vue里使用typescript,请看一下node_modules/里是不是已经安装了vuevue-tsc,这个问题一般是不存在的,除非你中途从js转到了ts。。。

npm install vue vue-tsc --save-dev

- path在vite.config.ts的应用

有些人喜欢使用 path 模块的 resolve 方法,将 __dirnamesrc 组合成一个绝对路径,更保险一点。

  • 跨平台兼容性:path 模块确保路径在不同操作系统上都能正确解析,避免了路径分隔符不一致的问题。
  • 动态路径生成:path.resolve 可以根据当前文件的位置动态生成路径,适用于项目结构复杂或路径需要动态变化的场景。
  • 可读性和维护性:使用 path 模块的代码更具可读性和维护性,尤其是在大型项目中,路径管理变得更加清晰。
  1. 先安装path模块
cnpm i path
  1. vite.config.ts里设置
...
import path from 'path'export default defineConfig({...resolve: {alias: {'@': path.resolve(__dirname, 'src')}...}...
})
  1. 示例
// 1. path
const path = require('path');const srcPath = path.resolve(__dirname, 'src');
console.log(srcPath); // 输出: C:\Users\user\project\src//2. 原始
const srcPath = '/src';
console.log(srcPath); // 输出: /src
  • __dirname 是当前文件 config.js 所在的目录路径,即 C:\Users\user\project。
  • path.resolve(__dirname, ‘src’) 会将 C:\Users\user\project 和 src 组合成一个绝对路径 C:\Users\user\project\src。
    这个路径是正确的,无论你在哪个操作系统上运行,都会生成正确的路径。

- 版本不同、模块冲突、完整安装等问题

这个情况就很复杂了,每个人当前系统都有差异,不太好分析。

比如你在vite.config.ts中配置如下:

export default defineConfig({plugins: [vue()],resolve: {alias: {'@': path.resolve(__dirname, 'src')},extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']},// 编译时的配置build: {outDir: 'dist',assetsDir: 'static',rollupOptions: {input: 'src/main.ts',},},// 配置生产环境的目录,注意process必须配置了 npm i @types/nodebase: process.env.NODE_ENV === 'production' ? '/abc/' : '/',
})

此刻
如果你没有安装path,那path.resolve(__dirname, 'src')path就无法识别
如果你没有安装@types/node,那base: process.env.NODE_ENV === 'production' ? '/abc/' : '/',process就无法识别

只能先安装了

npm i path
npm i @types/node

其它情况你只能根据错误提示来安装了,如果实在不行我建议就删了重新部署一个干净的,再把项目代码放进去就行了。

- 书写错误

昨天为了写这篇文章,为了测试,在我现有代码上做了很多次改动,结果整个系统崩掉了,所以诸位兄弟姐妹一定要仔细看代码啊。

我的错误也是挺特殊的,正好与本文契合:

我的vite.config.ts写成这样了,@多了一个斜杠/

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'// https://vite.dev/config/
export default defineConfig({...resolve: {alias: {'@/': path.resolve(__dirname, 'src')}},...
})

然后死活整不出了。。。
这个问题解决也简单:

// 1. 方案一,删掉斜杠
...
export default defineConfig({...resolve: {alias: {'@': path.resolve(__dirname, 'src')}},...
})// 2. 方案二,为了斜杠而斜杠
...
export default defineConfig({...resolve: {alias: {'@/': `${path.resolve(__dirname, 'src')}/`}},...
})// 3. 方案三,之前已经写过了,这里重申一下:注意斜杠是在前面的
...
export default defineConfig({...resolve: {alias: {'@': '/src'}},...
})

通过这里的知识点,其实你已经可以写很多自己的别名了,比如你常用目录是在a/b/c,那就搞个别名叫abc呗~~

- vue声明

vscode开发typescript在引用vue时会提示找不到模块,错误提示大概如下:

`src/index.ts:4:31 - error TS7016: Could not find a declaration file for module '@/components/system/Register.vue'. 'E:/Projects/test/src/components/system/Register.vue' implicitly has an 'any' type.`

这时需要在环境配置中加入声明,一般用方法一就够了。

// src/vite-env.d.ts
/// <reference types="vite/client" />// 定义 .vue 文件的模块声明,使 TypeScript 能够正确识别和处理 Vue 组件
// 1. 方法1:更适合项目中有复杂的组件配置需求,或者需要更精确的类型检查
declare module "*.vue" { import { ComponentOptions } from 'vue'const componentOptions: ComponentOptionsexport default componentOptions
}// 2. 方法2
declare module "*.vue" {import Vue from 'vue';export default Vue;  
}// 注意,当自定义目录下有一些常规内容读不了,试试把这个目录也加进去,如下
// 定义路径别名的类型声明
declare module '@/xxxx/*' {import type { ComponentOptions } from 'vue'const componentOptions: ComponentOptionsexport default componentOptions
}

- 清空缓存重启服务

有时 TypeScript 缓存可能会导致配置更改没有生效。尝试清理缓存(删除 node_modulesdist_vite 等文件夹),然后重新构建。

cnpm install 

也可以重启vite服务

vite --force 

也可以重启vscode

- 文件后缀或目录完整度

这条不是本文的主题,本文主题是@别名,但会有同学因为这个问题导致出错,所以这里提一下。

还记得原生代码中有这句么?

// tsconfig.app.json
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]

目的很明确了,include 就相当于一个白名单,名单里有的文件类型才编译,那为什么有些人必须要写了这句才能解决@的问题呢?
不是tsconfig.app.json里配置了include么?

我猜,我猜啊,他们这一类在tsconfig.json的配置中没有里这个references

  // tsconfig.json"references": [{ "path": "./tsconfig.app.json" },{ "path": "./tsconfig.node.json" }],

因为他们的tsconfig.json里既没有include,又没有references引入tsconfig.app.json,所以出错了。

好了,现在知道为什么要加了不?参考下方代码。

"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]

我目前强迫症,喜欢把 src/**/*.d.ts 给加进去

- baseUrl基目录

compilerOptions中一般要把baseUrl加进去,"baseUrl": "." 的意思就是将项目的基目录为当前目录。

如果你的文件在D:/project/test/tsconfig.ts,那么.就意味着D:/project/test/是基目录,一切从此出发。

// tsconfig.ts
"compilerOptions": {"baseUrl": ".","paths": {"@/*": ["src/*"],}}

你可以注意一下这个位置有没有配置错误。

- 小经验

编译的时候两个命令都用一下最好

vite build
npm run build

这两者产生的错误警告有所不同,编译有时候npm没通过,vite却通过了。

总结

- 文字

  1. 因为是 vitetypescript两条线走路,所以有两处需要配置。
  2. 不管你怎么改,万变不离其宗:主旨就是让typescript调用的时候能看到你的完整路径!
  3. 完整路径由 根目录+目录名+文件名+文件后缀 组成,从这几点上去考虑,相信很快就能找到你自己代码的病症,开出准确的方子来解决。

- 代码

这里贴一下较为完整又精简够用的配置代码

// 1. vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'// https://vite.dev/config/
export default defineConfig({plugins: [vue()],resolve: {alias: {'@': path.resolve(__dirname, 'src')},extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']},// 编译时的配置build: {outDir: 'dist',assetsDir: 'static',rollupOptions: {input: 'src/main.ts',},},// 配置生产环境的目录,注意process必须配置了 npm i @types/nodebase: process.env.NODE_ENV === 'production' ? '/abc/' : '/',
})// 2.tsconfig.json
{"files": [],"references": [{ "path": "./tsconfig.app.json" },{ "path": "./tsconfig.node.json" }],"compilerOptions": {"baseUrl": ".","paths": {"@/*": ["src/*"]}}
}// 3. tsconfig.app.json
{"extends": "./tsconfig.json", // 继承自tsconfig.json"compilerOptions": {"target": "ES2020","useDefineForClassFields": true,"module": "ESNext","lib": ["ES2020", "DOM", "DOM.Iterable"],"skipLibCheck": true,/* Bundler mode */"moduleResolution": "Bundler","allowImportingTsExtensions": true,"isolatedModules": true,"moduleDetection": "force","noEmit": true,"jsx": "preserve",/* Linting */"strict": true,"noUnusedLocals": true,"noUnusedParameters": true,"noFallthroughCasesInSwitch": true,"noUncheckedSideEffectImports": true},"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
}

如果对你有帮助,一键三连!
如果对你有帮助,一键三连!
如果对你有帮助,一键三连!

参考:
vue3+vite+typescript+setup组合式代码风格的模式开发的项目所需的一些必备内容,该安装安装,该创建创建
vue3+vite+ts 配置别名@报错找不到模块
【typescript - tsc 编译后路径问题/路径别名问题】
【解决90%】vue3+vite3+ts使用@alias路径别名爆红解决办法
Vue3解决“找不到模块“@/components/xxx.vue”或其相应的类型声明”

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

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

相关文章

「Mac畅玩鸿蒙与硬件18」鸿蒙UI组件篇8 - 高级动画效果与缓动控制

高级动画可以显著提升用户体验&#xff0c;为应用界面带来更流畅的视觉效果。本篇将深入介绍鸿蒙框架的高级动画&#xff0c;包括弹性动画、透明度渐变和旋转缩放组合动画等示例。 关键词 高级动画弹性缓动自动动画缓动曲线 一、Animation 组件的高级缓动曲线 缓动曲线&#…

BFS解决拓扑排序(3)_火星词典

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 BFS解决拓扑排序(3)_火星词典 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录…

QT中使用图表之QChart绘制X轴为日期时间轴的折线图

显然X轴是日期时间轴的话&#xff0c;那么我们使用的轴类就得是QDateTimeAxis QChart中日期时间轴的精度是毫秒 因此图表里面的数据的x值需要是一个毫秒数&#xff0c;才能显示出来 --------------------------------------------------------------------------------------…

C++现代教程七之模块

优点 编译时间减少&#xff1a;模块消除了重复解析和编译头文件的需要&#xff0c;从而显著减少了编译时间。特别是在大型项目中&#xff0c;这一点尤为重要。更好的封装性&#xff1a;模块允许更严格的封装&#xff0c;可以明确地控制哪些符号对外可见。这有助于减少命名冲突和…

ML 系列:第 18 部 - 高级概率论:条件概率、随机变量和概率分布

文章目录 一、说明二、关于条件概率2.1 为什么我们说条件概率&#xff1f;2.2 为什么条件概率在统计学中很重要 三、 随机变量的定义3.1 定义3.2 条件概率中的随机变量 四、概率分布的定义五、结论 一、说明 条件概率是极其重要的概率概念&#xff0c;它是因果关系的数学表述&…

Spring @RequestMapping 注解

文章目录 Spring RequestMapping 注解一、引言二、RequestMapping注解基础1、基本用法2、处理多个URI 三、高级用法1、处理HTTP方法2、参数和消息头处理 四、总结 Spring RequestMapping 注解 一、引言 在Spring框架中&#xff0c;RequestMapping 注解是构建Web应用程序时不可…

Nginx简单安装

nginx&#xff08;“engine x”&#xff09;是一个具有高性能的 http 和反向代理 的 web服务器&#xff0c;同时也是个 POP3/SMTP/IMAP代理服务器。 web服务器&#xff1a;也叫网页服务器&#xff0c;WebServer &#xff0c;主要功能是为用户提供网上信息浏览服务。 http&am…

硅谷甄选(七)属性管理模块

属性管理模块 6.1 属性管理模块的静态组件 属性管理分为上面部分的三级分类模块以及下面的添加属性部分。我们将三级分类模块单独提取出来做成全局组件 6.1.1 三级分类全局组件&#xff08;静态&#xff09; 注意&#xff1a;要在src\components\index.ts下引入。 <temp…

完美日记营销模式对开源 AI 智能名片 2 + 1 链动模式 S2B2C 商城小程序的启示

摘要&#xff1a;本文通过分析完美日记在营销中利用社会基础设施升级红利、网红与新流量平台、KOL 和私域流量等策略取得成功的案例&#xff0c;探讨其对开源 AI 智能名片 2 1 链动模式 S2B2C 商城小程序在营销推广、用户获取与留存、提升复购率等方面的启示&#xff0c;为商城…

【Hive sql 面试题】统计Top3歌单以及每个Top3歌单下的Top3歌曲(难)

表数据如下&#xff1a; 1 1 经典老歌 1 月亮代表我的心 2 1 经典老歌 1 月亮代表我的心 3 1 经典老歌 3 夜来香 4 1 经典老歌 4 我只在乎你 5 1 经典老歌 5 千言万语 6 1 经典老歌 5 千言万语 7 2 流行金曲 7 突然好想你 8 2 流行金曲 8 后来 9 2 流行金曲 9 童话 10 2 流行金…

深入剖析卷积神经网络中的卷积核

深入剖析卷积神经网络中的卷积核 前言一、卷积核的数学基础代码示例&#xff1a;简单的2D卷积操作 二、卷积核的类型与作用1. 边缘检测卷积核代码示例&#xff1a;Sobel算子 2. 模糊与平滑卷积核代码示例&#xff1a;高斯滤波器 三、卷积核的实际应用四、卷积核的初始化与学习五…

【GIT】-git常见指令

概念 远程仓库和本地仓库 常用指令&#xff1a; ls/ll查看当前目录cat查看文件内容touch创建文件vivi编辑器 备注&#xff1a; git GUI&#xff1a;是git提供的图形化工具 GIT Bash&#xff1a;Git提供的命令行工具 在安装GIT后要配置用户和账号&#xff01; 配置用户信息 …

高效实现聚水潭·奇门售后数据集成MySQL案例详解

聚水潭奇门数据集成到MySQL的技术案例分享 在现代企业的数据管理中&#xff0c;如何高效、准确地实现不同系统之间的数据对接和集成是一个关键问题。本文将聚焦于一个具体的系统对接集成案例&#xff1a;将聚水潭奇门平台的售后单数据集成到MySQL数据库中&#xff0c;方案名称…

软件测试八股文个人总结

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 前面看到了一些面试题&#xff0c;总感觉会用得到&#xff0c;但是看一遍又记不住&#xff0c;所以我把面试题都整合在一起&#xff0c;都是来自各路大佬的分享&am…

python读取视频并转换成gif图片

1. 安装三方库 moviepy 将视频转换成gif&#xff0c;需要使用 moviepy库 确保已经安装了moviepy库 pip install moviepy2. 代码实现&#xff1a; from moviepy.editor import VideoFileClipmyclip VideoFileClip("video.mp4") myclip2 myclip.subclip(0, 10).re…

k8s部署redis远程连接示例

一、环境 节点 IP 服务 master 192.168.126.46 docker、kubeadm、kubelet、kubectl、flannel、telnet node1 192.168.126.47 docker、kubeadm、kubelet、kubectl、flannel、telnet node2 192.168.126.48 docker、kubeadm、kubelet、kubectl、flannel、telnet ubunt…

UI自动化测试 —— CSS元素定位实践!

前言 自动化测试元素定位是指在自动化测试过程中&#xff0c;通过特定的方法或策略来准确识别和定位页面上的元素&#xff0c;以便对这些元素进行进一步的操作或断言。这些元素可以是文本框、按钮、链接、图片等HTML页面上的任何可见或不可见的组件。 在自动化测试中&#xf…

【含开通报告+文档+源码】基于SpringBoot的新能源充电桩管理系统的设计与实现

开题报告 近年来&#xff0c;随着全球对环境问题的关注和新能源汽车的普及&#xff0c;新能源充电桩的需求显著增加[1]。为了满足大量新能源车辆的充电需求&#xff0c;各地纷纷建设新能源充电桩站点。然而&#xff0c;随着充电桩数量的增加&#xff0c;管理和运营充电桩也面临…

Unity引擎材质球残留贴图引用的处理

大家好&#xff0c;我是阿赵。   这次来分享一下Unity引擎材质球残留贴图引用的处理 一、 问题 在使用Unity调整美术效果的时候&#xff0c;我们很经常会有这样的操作&#xff0c;比如&#xff1a; 1、 同一个材质球切换不同的Shader、 比如我现在有2个Shader&#xff0c;…

一行代码实现垂直居中

实现元素垂直居中的方案有很多&#xff0c;比如定位、伸缩盒子、行高等等。 但在 2024 年的Chrome 123 版本中&#xff0c; CSS 原生可以使用 1 个 CSS 属性 align-content: center进行垂直居中。 如何使用 <!DOCTYPE html> <html lang"en"> <head&…