0%

样式文件的动态引用

样式文件的动态引用

背景

要实现一个主题切换功能,通常的解决方案是替换css文件,由此就引出了样式文件的动态引用。样式文件的动态引用普遍有两种方式。

动态创建Link标签

1
2
3
4
5
6
7
8
9
/** 获取css */
export const includeLinkStyle = async (sourceThemeName) => {
let cssPath = ``;
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = cssPath;
document.getElementsByTagName('head')[0].appendChild(link);
};

动态创建Style标签

1
2
3
4
5
6
7
8
/** 获取css */
export const includeLinkStyle = async (sourceThemeName) => {
let cssPath = ``;
const cssText = await axios.get(cssPath);
var style = document.createElement('style');
style.innerHTML = cssText.data;
document.getElementsByTagName('head')[0].appendChild(style);
};

两种方式并无本质区别,都是动态创建了一个元素,写入元素属性,将元素压入文档流。不过由于浏览器的资源请求机制,在实际应用上加载远程样式时仍有一些区别。

资源请求机制

假设在example.com域下有资源style.css

1
2
3
4
body{
background: red;
background-image: url('./2.png');
}

以动态创建Link标签为例。浏览器中可以查看到2.png的请求,请求头为:

1
2
3
4
5
6
7
8
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: connect.sid=s%3AxFoVr0cFWtheWipka_J25nHMCikvPAJp.Irxj4n60P43ve%2BR1OL6VethJP5FDe3QNt5GZk0QplTM; thinkjs=a3139926-434d-4dbc-a9a9-8a5f279727bf; thinkjs.sig=5dzO8-ZdaKKGRWImhC1DTl4GemI
Host: example.com // host为css文件所在域
Proxy-Connection: keep-alive
Referer: http://example.com/style.css
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.0.478.37

以动态创建Style标签的方式。浏览器中可以查看到2.png的请求,请求头为:

1
2
3
4
5
6
7
8
9
10
11
12
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Connection: keep-alive
Cookie: thinkjs=3cc3a7a5-5435-413d-86b0-86fd9c807403; thinkjs.sig=9k3bn5ttg8Z5iGHIqiP2jpBOn5E
Host: localhost:8080 // host为html文件所在域
If-None-Match: W/"910-osEmo5hhdX1FHE/d8oogcny8bhI"
Referer: http://localhost:8080/
Sec-Fetch-Dest: image
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.0.478.37

可以这么理解,以link方式请求了css文件,css内部的相对路径,都是相对于css文件的。如果拿到了css文件的text值并写入htmlstyle标签,请求是相对于html的。

如此,其实以动态创建Style标签的方式是拿不到背景图片的。

总结

资源的相对路径引用,多多少少会存在一些问题。如果可以的话,主题样式文件,应该尽量以文件名作为区分例如theme1.style.min.css,theme1-1.png而不是以路径作为区分\theme1\style.min.css\theme1\1.png

参考 & 引用

https://segmentfault.com/a/1190000007491687