JS动态引入CSS如何适配任意目录层级的HTML文件
项目目录结构
|--js |-- main.js |--css |--main.css |--Folder1 |-- c.html |--Folder2 |-- d.html |--a.html |--b.html
问题说明
所有HTML文件均引入main.js,原有动态加载main.css的逻辑仅对根目录下的a.html、b.html生效;Folder1、Folder2目录下的c.html、d.html加载样式时,会从HTML当前所在目录查找css文件夹,导致样式加载失败。
原有实现代码:
var theorigin = window.location.origin; var thefile = window.location.pathname.split("/").pop(); var folder = window.location.pathname.replace(thefile, ""); var newdest = theorigin + folder; var link = document.createElement("link"); link.href = newdest + "../css/main.css"; link.type = "text/css"; link.rel = "stylesheet"; document.head.appendChild(link);
备注:已知可直接在子目录HTML中编写
<link href="../css/main.css" rel="stylesheet" />引入样式,但因特定原因不采用该方案。
需求:实现无论HTML文件位于哪个目录层级,都可以通过公共的main.js正确动态引入根目录下的main.css。
解决方案
方案1:根绝对路径(最简单,适配根目录部署场景)
不需要拼接相对路径,路径以/开头时,浏览器会自动从站点根目录开始寻址资源,完全不受当前HTML所在目录层级影响:
const link = document.createElement("link"); link.rel = "stylesheet"; link.type = "text/css"; link.href = "/css/main.css"; document.head.appendChild(link);
如果项目部署在域名根目录(比如访问地址为https://yourdomain.com/a.html),直接用这个方案即可,代码量最少,不存在路径计算出错的可能。如果项目部署在域名下的子路径(比如访问地址为https://yourdomain.com/project/a.html),该方案会寻址到域名根下的css路径导致加载失败,使用方案2即可。
方案2:基于main.js自身路径计算(全场景兼容,最稳妥)
原有逻辑的核心问题是依赖当前HTML的路径拼接相对地址,只要HTML目录层级变化,相对路径就会失效。实际上main.js的存储位置是固定的,永远在根目录的js文件夹下,我们可以直接获取main.js自身的加载地址,反推出css的正确路径,完全和HTML所在位置解耦:
// 获取当前正在执行的main.js对应的script标签 const currentScript = document.currentScript; // 拿到main.js的完整访问地址,兼容带查询参数的场景,比如 https://xxx.com/project/js/main.js?v=1.0 const jsFullPath = currentScript.src; // 替换路径末尾的js/main.js段,得到css文件的正确地址 const cssPath = jsFullPath.replace(/js\/main\.js(\?.*)?$/, 'css/main.css'); const link = document.createElement("link"); link.rel = "stylesheet"; link.type = "text/css"; link.href = cssPath; document.head.appendChild(link);
该方案不受部署路径、HTML目录层级影响,只要不改动js、css文件夹的相对位置,后续新增任意层级的子目录存放HTML,加载逻辑都不需要调整。
内容的提问来源于stack exchange,提问作者Xion

