前端js动态加载css
用户是有这么一个需求,图标库要自己管理,分析如下:
用户从阿里icon上自行下载图标,将css文件传到服务器上,后台需获取用户上传的所有css文件,解析出文件中的选择器名返回给前台做展示,同时前台需自行加载这些css文件。
后台代码:
定义一个CssParserUtil类来获取css文件及选择器。
package com.fh.util;
import java.io.*;
import java.util.List;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.log4j.Logger;
import org.w3c.css.sac.InputSource;
import org.w3c.dom.css.*;
import com.steadystate.css.parser.CSSOMParser;
public class CssParserUtil {
private final static Logger logger = Logger.getLogger(CssParserUtil.class);
//icon命名规范
private static String ICON_EXTRACT_REGULAR_EXPRESSION = "icon-([\\S]+):[\\S]+";
//获取所有的类选择器
public static List<String> getSelectors(InputStream inStream) {
List<String> selectorArr = new ArrayList<String>();
try {
InputSource source = new InputSource();
source.setByteStream(inStream);
source.setEncoding("UTF-8");
final CSSOMParser parser = new CSSOMParser();
CSSStyleSheet sheet = parser.parseStyleSheet(source, null, null);
CSSRuleList rules = sheet.getCssRules();
if (rules.getLength() == 0) {
return null;
}
for (int i = 0; i < rules.getLength(); i++) {
final CSSRule rule = rules.item(i);
//获取样式名称
if (rule instanceof CSSStyleRule) {
String selectorText = ((CSSStyleRule) rule).getSelectorText();
Pattern pattern = Pattern.compile(ICON_EXTRACT_REGULAR_EXPRESSION);
Matcher matcher = pattern.matcher(selectorText);
if (matcher.find()) {
String icon = matcher.group(1);
selectorArr.add(icon);
}
}
//获取样式内容
// String cssText = ((CSSStyleRule)rule).getCssText();
// System.out.println(cssText);
}
} catch (IOException e) {
e.printStackTrace();
logger.error(e.getMessage());
}
return selectorArr;
}
//获取 static/css/mycss/modularIcon/路径下所有的css文件 和css文件内的icon名字
public static PageData getFiles(String path) {
PageData pd = new PageData();
path = PathUtil.getClasspath() + path;
File file = new File(path);
//判断当前路径是否存在
if(file.exists()){
File[] fileList = file.listFiles();//该目录下的所有文件放置在一个File类型的数组中
List<File> cssList = new ArrayList<>();//css文件集合
List<String> cssPathList = new ArrayList<String>();//css文件路径
List<String> selectorArr = new ArrayList<String>();
List<String> selectorArrTemp = new ArrayList<String>();//icon名字
if(fileList != null){
for (int i = 0; i < fileList.length; i++) {
if (fileList[i].isFile()) {
//是否为文件
cssList.add(fileList[i]);
//将路径中的'\'变为'/'避免传到前台后由于转义导致的路径失效
cssPathList.add(fileList[i].getPath().replace('\\','/'));
InputStream inStream = null;
try {
inStream = new FileInputStream(fileList[i]);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
selectorArrTemp = getSelectors(inStream);
selectorArr.addAll(selectorArrTemp);
}
}
}
pd.put("cssList",cssList);
pd.put("cssPathList",cssPathList);
pd.put("cssfont",selectorArr);
}
return pd;
}
public static void main(String[] args) throws IOException {
String local = PathUtil.getClasspath() + Const.ICON_CSS_PATH;
getFiles(local);
// InputStream inStream = new FileInputStream(new File("D://trtc_web//trtc_web//src//main//webapp//static//css//mycss//iconfont.css"));
//
//
// List<String> selectorArr = getSelectors(inStream);
//// pd.put("cssfont",selectorArr);
//
// System.out.println(selectorArr);
}
}
Controller中调用该工具类
PageData iconPd = CssParserUtil.getFiles(Const.ICON_CSS_PATH);
pd.putAll(iconPd);
mv.addObject("pd", pd);
前台页面图标展示:
<tr>
<td style="width:70px;text-align: right;padding-top: 13px;">图标:</td>
<td>
<ul class="icon-lists">
<c:forEach var="icon" items="${pd.cssfont}">
<li><i class="iconfont icon-${icon}"></i></li>
</c:forEach>
</ul>
<input type="hidden" name="modular_icon" id="modular_icon" value="${pd.modular_icon}">
</td>
</tr>
js加载css文件
function loadFontCss() {
<%--var link = document.createElement('link');--%>
var head = document.getElementsByTagName('head')[0];
<%--<c:forEach var="cssItem" items="${pd.cssPathList}">--%>
<%--link.rel = 'stylesheet';--%>
<%--link.type = 'text/css';--%>
<%--var linkUrl = ('${cssItem}').split('../../')[1];--%>
<%--link.href = linkUrl;--%>
<%--head.appendChild(link);--%>
<%--console.log(link);--%>
<%--</c:forEach>--%>
<c:forEach var="cssItem" items="${pd.cssPathList}">
var style = document.createElement('style');
style.textContent = '@import "' + ('${cssItem}').split('../../')[1] + '"';
var fi = setInterval(function() {
try {
style.sheet.cssRules; // <--- MAGIC: only populated when file is loaded
CSSDone('listening to @import-ed cssRules');
clearInterval(fi);
} catch (e){}
}, 10);
head.appendChild(style)
</c:forEach>
}
转载自:https://blog.csdn.net/Duoooooo/article/details/86690637