基于Jquery WeUI的微信开发H5页面控件的经验总结(2)
在微信开发H5页面的时候,往往借助于WeUI或者Jquery WeUI等基础上进行界面效果的开发,由于本人喜欢在Asp.net的Web界面上使用JQuery,因此比较倾向于使用 jQuery WeUI,本篇随笔结合官方案例和自己的项目实际开发过程的经验总结,对在H5页面开发过程中设计到的界面控件进行逐一的分析和总结,以期能够给大家在H5页面开发过程中提供有用的参考。
本篇随笔继续上篇随笔《基于Jquery WeUI的微信开发H5页面控件的经验总结(1)》进行介绍其他部分的内容。
7)条码、二维码生成
在我们做一些扫码操作的时候,我们可能需要根据一些参数生成一些URL,然后生成一个二维码的方式,方便手机扫码直接查看,或者给一些条码设备进行条码的读取,那么这两种情况结合起来就是二维码和条码的处理场景。
例如下面的处方信息展示里面,就需要这样的场景。
二维码QRCode使用的地址是:https://github.com/davidshimjs/qrcodejs
条码JsBarcode使用的地址是:https://github.com/lindell/JsBarcode
使用前,我们引入所需要的qrcodejs和JsBarcode的JS库文件。
<script src="~/Content/JQueryTools/qrcodejs/qrcode.min.js"></script>
<script src="~/Content/JQueryTools/JsBarcode/dist/JsBarcode.all.min.js"></script>
二维码和条码的处理脚本很简单,如下JS代码所示。
//条码
JsBarcode("#barcode", "@ViewBag.Info.PrescriptionNo", {
format: "CODE128",
lineColor: "#0aa",
height: 50,
displayValue: false
}); //二维码
var url = '@ViewBag.WebsiteDomain/h5/PrescriptionDetail?id=@ViewBag.Info.ID';
var qrcode = new QRCode(document.getElementById("qrcode"), {
text: url, //"@ViewBag.Info.PrescriptionNo",
width: 128,
height: 128,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRCode.CorrectLevel.H
});
使用脚本处理的方式非常不错。
8)JQuery的Ajax/Post/Get等相关处理
在我们前面很多案例代码里面,都采用了JQuery的Ajax/Post/Get/getJSON等函数,它们之间很多时候可以相互替代,差异只是很少的部分。
$.get()方法使用GET方式来进行异步请求,它的语法结构为:$.get( url [, data] [, callback] )。如下代码所示。
$.getJSON()是专门为ajax获取json数据而设置的,并且支持跨域调用,其语法的格式为:getJSON(url,[data],[callback])。
var flowUsers = [];
var url = '/qyh5flow/GetCorpUser';
$.getJSON(url, function (data) {
$.each(data, function (i, item) {
flowUsers.push({
title: item.name, value: item.userid
});
});
$("#txtSelectSignUser").select({
title: "选择会签人员",
items: flowUsers,
multi: true,
//min: 2,
//max: 3,
});
});
$.get()和$.getJSON()两种方法,后者比前者多了一个对返回数据进行JSON转换对象的处理,$.get()方法需要使用下面代码进行JSON的转换。
var data = $.parseJSON(json);
$.post()方法使用POST方式来进行异步请求,它的语法结构为:$.post(url,[data],[callback],[type]),这个相对于$.get()的操作,使用POST方式提交。
其中的type:type为请求的数据类型,可以是html,xml,json等类型,如果我们设置这个参数为:json,那么返回的格式则是json格式的,如果没有设置,就和$.get()返回的格式一样,都是字符串的。
如下代码是我们使用$.post()的函数进行数据的提交,注意我们也需要使用$.parseJSON进行返回值JSON转换对象的处理。
$.post(url, postData, function (json) {
//转义JSON为对象
var data = $.parseJSON(json);
if (data.Success) {
$.toptip("删除成功!", 'success'); //在界面上找到对应控件ID,移除控件
RemoveImg();
}
else {
$.toast("操作失败:" + data.ErrorMessage, "forbidden");
}
});
$.ajax()是jquery中通用的一个ajax封装,其语法的格式为:$.ajax(options),其中options是一个object类型,它指明了本次ajax调用的具体参数。
一般在使用FormData对象的时候,我倾向于使用$.ajax进行处理,以便更多的弹性化设置。
//提交表单数据和文件
var url = "/qyH5Flow/PaymentSave?userid=@ViewBag.userid";
$.ajax({
url: url,
type: 'post',
processData: false,
contentType: false,
data: formData,
success: function (json) {
//转义JSON为对象
var data = $.parseJSON(json);
if (data.Success) {
$.toast("保存成功,稍后请到列表界面查看。");
}
else {
$.toast("保存失败:" + data.ErrorMessage, "forbidden");
}
}
});
以上就我进行在案例里面使用的各种操作,有时候可以相互替换,根据需要选择不同的操作方式即可。
9)JS脚本的数组对象处理
上面我们使用了各种异步的操作,如JQuery的Ajax/Post/Get/getJSON等函数操作,经常会涉及对数组的遍历处理或者插入处理。
JS数组是一个很的强大的数组对象,支持很多复杂的操作,对数组的操作也是我们经常处理的方式之一。
例如对于返回的数据,我们一般需要进行数组的遍历,然后逐一追加到界面显示,这里就需要使用$.each()函数。
//动态处理图片绑定
$.getJSON("/Qyh5Flow/GetImageList2?attachGuid=" + info.AttachGUID, function (data) {
$.each(data, function (i, item) {
$("#imgAttach").append(`<img class='weui-uploader__file' src='${item.Text}' id='img_${item.Value}'/>`);
});
});
$.each()函数另一个经常使用的场景就是根据JQuery选择器进行元素集合的遍历处理。
var itemCount = 0;
//计算单选框的选中数量
$("input[type='radio']:checked").each(function(){
itemCount += 1;
});
//复选框选中算一个
var chkName = []
$("input[type='checkbox']:checked").each(function () {
var name = $(this).attr('name');
if (chkName.indexOf(name) < 0) {
itemCount += 1;
chkName.push(name);
}
});
我们在需要加入对象的时候,就需要使用push()函数操作了,有时候往往和$.each()函数配合使用。
var items = [];
$.each(data, function (i, item) {
items.push({
title: item.Text, value: item.Value
});
});
或者进行元素遍历查询的时候,如下代码所示。
//构建选中的列表内容
var list = [];
//计算单选框
$("input[type='radio']:checked").each(function () {
list.push($(this).val());
});
//计算复选框
$("input[type='checkbox']:checked").each(function () {
list.push($(this).val());
});
如果我们需要判断某个对象是否在集合里面,我们就会用到$.inArray() 函数进行判断,如下代码所示。
if ($.inArray(key, addKeyList) == -1) {
addKeyList.push(key);
addValueList.push(value);
sendList.push({ key: key, value: value}); $('#tagsToSend').addTag(value);
}
另外,我们对数组还需要了解,如何移除单个或者所有的集合,这个就用到了splice()函数,如下代码所示。
addKeyList.splice(i, 1);//移除某个对象
addValueList.splice(i, 1);//移除某个对象
sendList.splice(i, 1);//移除某个对象
如果需要清空数组,常用的做法如下所示,也是使用splice()函数。
//清空用户选择
function ClearChoice() {
$('#tagsToSend').importTags(''); sendList.splice(0, sendList.length);//待发送的部门、标签、用户列表
addKeyList.splice(0, addKeyList.length);//键的集合
addValueList.splice(0, addValueList.length);//值的集合
}
以上就是我们操作数据的时候,经常使用的一些方法。
10)查询即时列表展示
有时候,我们需要根据查询的条件,对数据库的信息进行检索,然后即时的显示在列表中,供选择使用,如下界面所示。
上图是我项目中,根据拼音码或者名称对药品进行检索,返回的数据进行显示的处理。
为了使用搜索栏,我们使用了微信WeUI定义的搜索栏样式,以下是界面定义的搜索栏DIV层,如下代码。
<!--搜索栏,类似于微信原生的搜索栏,应用于常见的搜索场景。-->
<div class="weui-search-bar" id="searchBar">
<form class="weui-search-bar__form" onkeydown="if(event.keyCode==13) return false;">
<div class="weui-search-bar__box">
<i class="weui-icon-search"></i>
<input type="search" class="weui-search-bar__input" id="searchInput" placeholder="搜索" required="">
<a href="javascript:clear()" class="weui-icon-clear" id="searchClear"></a>
</div>
<label class="weui-search-bar__label" id="searchText" style="transform-origin: 0px 0px 0px; opacity: 1; transform: scale(1, 1);">
<i class="weui-icon-search"></i>
<span>请输入你想要查看的关键字</span>
</label>
</form>
<a href="javascript:clear()" class="weui-search-bar__cancel-btn" id="searchCancel">取消</a>
</div>
我们在JS代码上执行对应事件的处理,如下所示。
主要就是监控Input控件的内容变化,进行及时的查询和内容展示。
//查询框输入内容触发事件
$('#searchInput').bind('input propertychange', function () {
var name = $("#searchInput").val(); //获取Json对象集合,并生成数据显示内容
var url = "/h5/FindDrugWithPager?page=1&rows=5&Name=" + encodeURI(name);
$.getJSON(url, function (data) {
$("#searchContent").html("");
var html = "";
$.each(data.rows, function (i, item) {
var background = (i % 2 == 0) ? "background-color:Highlight" : "";
html += `<li>
<div class='pic'><img src='@ViewBag.WebsiteDomain/Content/images/drug.png' /></div>
<div class='text'>
<h2><i></i><span>` + item.CommonName + `</span><em>`+ item.Specification +`</em></h2>
<p>商品名:` + item.ProductName + `</p>
<p>厂 家:`+item.Manufacturer +`</p>
</div>
<a class='ture' href=\"javascript:;\" onclick=\"AddDrug('` + item.ID + `','`+ item.ProductName +`')\" ><img src='@ViewBag.WebsiteDomain/Content/images/add1-24.png'></a>
</li>`;
});
$("#searchContent").html(html);
});
}); function cancel() {
$("#searchContent").empty();
} function clear() { $('#searchInput').val('')
$("#searchContent").empty();
}
这里的HTML模板,我们有时候也使用代码块的方式,在模板代码里面插入变量,如下所示。
$.getJSON("/Qyh5Flow/GetImageList2?attachGuid=" + info.AttachGUID, function (data) {
$.each(data, function (i, item) {
$("#previewImage").append(`<img class="weui-preview-box" src='${item.Text}' id='img_${item.Value}'/>`);
});
});
这里的代码块,开始和结束符使用了 ` ` 符号块,其中插入了变量${item.Text} 、${item.Value}等变量字符串,并没有打断模板的内容,如果多行,我们一样的处理,非常方便。
$.getJSON(url, function (data) {
var html = "";
$.each(data.rows, function (i, item) {
html += `<div class="weui-panel weui-panel_access">
<div class="weui-panel__hd">
<span>${item.FormName}</span>:<span>${item.EditorName}</span>,<span>${item.Edittime}</span>
<span class="ord-status-txt-ts fr"><b>${GetStatus(item.Status)}</b></span>
</div>
<div class="weui-media-box__bd pd-10">
<div class="weui-media-box_appmsg ord-pro-list">
<div class="weui-media-box__bd">
<p class="weui-media-box__desc">标题:<span>${item.Title}</span></p>
<div class="clear mg-t-10">
<div class="pro-amount fl"><span class="font-13">当前处理类型:<em class="num font-15">${item.Proc_TypeName}</em></span></div>
<div class="pro-amount fr"><span class="font-13">当前处理人:<em class="name">${item.Proc_UserName}</em></span></div>
</div>
</div>
</div>
</div>
<div class="weui-panel__ft">
<div class="weui-cell weui-cell_access weui-cell_link oder-opt-btnbox">
<a href="${item.ViewUrl}?id=${item.ID}" class="ords-btn-dele">查看详情</a>
</div>
</div>
</div>`; }); $("#" +divname).html(html);
});
这是我们推荐使用的JS代码块,整块代码都不影响阅读,而且可以换行排版,非常直观。
11)界面弹窗处理
在微信Weui里面定义了几种常规的弹窗处理。
对话框只能通过 JavaScript 进行调用,微信WeUI提供了三种常用的对话框 Alert, Confirm, Prompt 和 Login。我们也可以通过 $.modal
来自定义对话框
实际上, Alert, Confirm, Prompt 和 Login 都是 Modal 的一种定制而已。
一般的JS调用代码如下所示。
//常规提示窗口
$.alert("自定义的消息内容", "自定义的标题"); //确认提示窗口
$.confirm("自定义的消息内容", "自定义的标题", function() {
//点击确认后的回调函数
}, function() {
//点击取消后的回调函数
});
例如我们在流程表单处理里面,会在操作前进行提示用户是否确认处理。
//退回拟稿人重新处理
function ApplyCancel(opinion) {
var tipMessage2 = "数据检查完毕,如确认无误将【退回拟稿人重新处理】,您确实要提交吗?";
$.confirm(tipMessage2, "退回拟稿人重新处理?", function () {
var userid = "@ViewBag.userid";
var applyid = "@Request["id"]";
var url = "/QyH5Flow/SkipFirstApply";
//构造参数发送给后台
var postData = {
userid: userid,
applyId: applyid,
opinion: opinion
};
$.post(url, postData, function (json) {
var data = $.parseJSON(json);
if (data.Success) {
//console.log(data);
//提示处理结果
$.toast("您已经退回经办人进行修改。"); $.closePopup();
initControls();//重新加载
}
else {
$.toast("操作失败:" + data.ErrorMessage);
}
}); }, function () {
//取消操作
});
}
登陆窗口界面效果如下所示。
$.login("自定义的消息内容", function(username, password) {
// 这里进行登录操作
}, function() {
}); //如果参数过多,建议通过 object 方式传入
$.login({
title: '标题',
text: '内容文案',
username: 'tom', // 默认用户名
password: 'tom', // 默认密码
onOK: function (username, password) {
//点击确认
},
onCancel: function () {
//点击取消
}
});
我们可以利用登录框进行一个系统账号的绑定,如下是实际项目的处理代码。
$(document).on('click', '#btnBind', function() {
$.login({
title: '登录',
text: '请输入用户名和密码',
onOK: function (username, password) {
var url = "/H5/VerifyUser?openid=@ViewBag.openid";
var postData = {
username: username,
password: password
}; $.post(url, postData, function (json) {
//转义JSON为对象
var data = $.parseJSON(json);
if (data.Success) {
$.toptip('登录成功!');
location.reload();//刷新页面
//WeixinJSBridge.call('closeWindow');//关闭窗口
}
else {
$.toptip("登录失败:" + data.ErrorMessage, "forbidden");
}
});
},
onCancel: function () {
$.toptip('取消登录!', 'cancel');
}
});
});
上述的几种对话框都是 $.modal
的一种特殊形式。你可以通过 $.modal
来定制对话框
$.modal({
title: "Hello",
text: "我是自定义的modal",
buttons: [
{ text: "支付宝", onClick: function(){ console.log(1)} },
{ text: "微信支付", onClick: function(){ console.log(2)} },
{ text: "取消", className: "default", onClick: function(){ console.log(3)} },
]
});
默认情况下,点击对话框的按钮都会先关闭对话框再触发回调函数。可以通过JS来关闭任何正在显示的对话框:
$.closeModal();
除了上面的几种情况的模态对话框,还有一种是Popup弹出遮盖下面页面的场景,如常规的购物车的情况。
Popup 是一个覆盖式的弹出层,可以完全盖住当前页面或者遮盖一半。
例如我在流程处理页面中,往往需要进行审核、会签处理的时候,弹出对应的处理内容,这个就是Popup的使用场景。
我们通过JS进行调用显示窗口。
$("#SignAction").popup();//主动弹出窗口
其中SignAction层就是一个popup的窗口层,视图HTML代码如下所示。
我们只需要注意到 class='weui-popup__container popup-bottom' 的说明,就知道它的样式了,从底部弹出的Popup窗口。
如果没有加上Popup-bottom的样式,那么就是全屏覆盖的模式。
关闭 Popup
给任何链接加上 class='close-popup'
则点击之后可以关闭当前打开的 popup. 你也可以通过 $.closePopup()
来关闭。
12)微信JSSDK的整合等处理
微信JSSDK提供了很多丰富的功能,我们可以利用JSSDK实现图片的上传、预览、扫码等操作,图片上传由于我使用了附件上传的方式,因此不在介绍较为繁琐的JSSDK图片上传模式,有兴趣可以参考我之前随笔《微信开发中使用微信JSSDK和使用URL.createObjectURL上传预览图片的不同处理对比》了解下不同。
a) 图片预览
一般我们在一些查看内容的视图界面里面,往往对图片进行预览操作,这时候可以利用JSSDK的图片预览接口,在使用JSSDK接口前,需要进行接口的初始化,然后才能调用,下面是初始化和调用的案例代码。
<!--微信API初始化-->
<script language="javascript">
var appid = '@ViewBag.appid';
var noncestr = '@ViewBag.noncestr';
var signature = '@ViewBag.signature';
var timestamp = '@ViewBag.timestamp'; wx.config({
debug: false,
appId: appid, // 必填,公众号的唯一标识
timestamp: timestamp, // 必填,生成签名的时间戳
nonceStr: noncestr, // 必填,生成签名的随机串
signature: signature, // 必填,签名,见附录1
jsApiList: [
'checkJsApi',
'chooseImage',
'previewImage',
'uploadImage',
'downloadImage'
]
}); //所有准备好后,通过样式查找的方式,加入对应集合,然后绑定click事件
wx.ready(function () {
var $images = $(".preview").find("img");
var imgPaths = [];
$images.each(function(){
imgPaths.push(this.src);
}); $images.on("click",function(){
wx.previewImage({
current: this.src,
urls: imgPaths
});
});
});
</script>
而图片的初始化,我们可以在HTML代码进行处理即可。
<div id="previewImage" class="preview">
@if (ViewBag.PresImages != null)
{
for (var i = 0; i < ViewBag.PresImages.Count; i++)
{
<img class="weui-preview-box" src='@ViewBag.PresImages[i]' alt="处方图片">
}
}
</div>
b) 调用扫码处理
我们可以利用JSSDK调用手机的扫码操作,让其进行相应的扫码处理,如下是使用JSSDK进行扫码的JS代码。
<script language="javascript">
var appid = '@ViewBag.appid';
var noncestr = '@ViewBag.noncestr';
var signature = '@ViewBag.signature';
var timestamp = '@ViewBag.timestamp'; wx.config({
debug: false,
appId: appid, // 必填,公众号的唯一标识
timestamp: timestamp, // 必填,生成签名的时间戳
nonceStr: noncestr, // 必填,生成签名的随机串
signature: signature, // 必填,签名,见附录1
jsApiList: [
'checkJsApi',
'chooseImage',
'previewImage',
'uploadImage',
'downloadImage',
'scanQRCode'
]
}); //所有准备好后
wx.ready(function () {
document.querySelector('#scancode').onclick = function () {//调用扫码事件返回扫码值
wx.scanQRCode({
needResult: 1,
desc: 'scanQRCode desc',
success: function (res) {
//console.log(res.resultStr);
var isUrl = CheckUrl(res.resultStr);
if (isUrl) {
location.href = res.resultStr;//跳转页面
}
}
});
};
});
//验证URL字符串
function CheckUrl(str) {
var RegUrl = new RegExp();
RegUrl.compile("^[A-Za-z]+://[A-Za-z0-9-_]+\\.[A-Za-z0-9-_%&\?\/.=]+$");//jihua.cnblogs.com
if (!RegUrl.test(str)) {
return false;
}
return true;
}
</script>
上面扫码后,识别判断URL,如果是URL,那么页面地址自动调整到相应的界面上去。
以上就是一些实际项目中运用到的各种界面处理和JS处理代码,抛砖引玉,希望大家多多支持和鼓励。
基于Jquery WeUI的微信开发H5页面控件的经验总结(2)的更多相关文章
- 基于Jquery WeUI的微信开发H5页面控件的经验总结(1)
在微信开发H5页面的时候,往往借助于WeUI或者Jquery WeUI等基础上进行界面效果的开发,由于本人喜欢在Asp.net的Web界面上使用JQuery,因此比较倾向于使用 jQuery WeUI ...
- 基于 jQuery 的专业 ASP.NET WebForms/MVC 控件库!
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- 工作小记:企业微信 嵌H5页面 用户权限获取匹配
一.背景 领导让研究一个活儿:企业微信开发H5应用,微信端客户进入H5页面跟现有的Web系统打通用户权限.通俗的讲:嵌入企业微信H5页面,客户点进去按原权限加载内容.开发者中心有文档,附上两个关键链接 ...
- 基于SpringBoot的开源微信开发平台,Jeewx-Boot 1.0 版本发布
项目介绍 JeewxBoot 是一款基于SpringBoot的免费微信开发平台.支持微信公众号.小程序官网.微信抽奖活动. Jeewx-Boot实现了微信公众号管理.小程序CMS.微信抽奖活动等基础功 ...
- offline页面开发常用方法及页面控件验证
offline页面开发常用方法及页面控件验证,对一些CheckBoxList操作进行封装,新人可以直接使用该代码. 1.返回上一页网址 /// <summary> /// Descript ...
- Android微信九宫格图片展示控件
版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/214 Android微信九宫格图片展示控件 半年前,公司产 ...
- aspx页面控件id上自动加前缀
公司的一个.net项目,使用的传统aspx页面开发,每个控件上自动加了前缀,最初以为是extjs.net自带的功能,后来研究发现,主要是因为内部使用了母版页.<asp:Content ID=&q ...
- Xamarin iOS教程之页面控件
Xamarin iOS教程之页面控件 Xamarin iOS 页面控件 在iPhone手机的主界面中,经常会看到一排小白点,那就是页面控件,如图2.44所示.它是由小白点和滚动视图组成,可以用来控制翻 ...
- RS开发日期提示控件默认为昨天之进阶篇
时隔<RS开发日期提示控件默认为昨天>这篇博文已经很久了,请原谅我隔了这么久才继续来写这篇笔记.也希望读到这篇笔记的朋友可以从这篇笔记中学习到一些关于RS日期控件和JS的一些应用知识,当然 ...
随机推荐
- 吴裕雄--天生自然 R语言开发学习:基本图形(续三)
#---------------------------------------------------------------# # R in Action (2nd ed): Chapter 6 ...
- (五)mybatis-spring的集成
mybatis-spring的集成 源码下载(数据库使用derby,具体数据库结构参考这里) 在src下新建applicationContext.xml 配置内容:数据源.SqlSessionFact ...
- GYOJ_1812_股票(stock)
题目描述 2130年,股神巴菲特投胎了!他投胎到你身上! 你作为股神转世,能力比原股神还要强,你可以预测到今后n天的股价.假设刚开始你的手上有1元钱,你想知道n天后你最多可以赚到多少钱.作为股神转世, ...
- JMeter之BeanShell断言---equals使用
判断变量是否为root if(!"${User}".equals("root")){ Failure=true; FailureMessage="ER ...
- 模型压缩之Channel Pruning
论文地址 channel pruning是指给定一个CNN模型,去掉卷积层的某几个输入channel以及相应的卷积核, 并最小化裁剪channel后与原始输出的误差. 可以分两步来解决: channe ...
- 直播问答App乃虚火,调侃知识终不能长久盈利
随着王思聪在微博宣布"我.我乐意",一款叫"冲顶大会"的App冲到了大众面前,紧接着"芝士超人"携10亿元奖金从天而降,瞬间之内,在线答 ...
- 读书笔记——《在线》
* 2017年10月24日 星期二 晴* ## "在线"是未来世界发展的关键.一个事物是不是符合未来发展的趋势,就是要看它是否在线. 插图 **在线** 正文 作者是王坚,阿里巴巴 ...
- 玩转iOS开发:iOS中的GCD开发(三)
上一章, 我们了解到了GCD里的一些队列和任务的知识, 也实践了一下, 同时我们也对主队列的一些小情况了解了一下, 比如上一章讲到的卡线程的问题, 如果没有看的朋友可以去看看玩转iOS开发:iOS中的 ...
- python语法生成器、迭代器、闭包、装饰器总结
1.生成器 生成器的创建方法: (1)通过列表生成式创建 可以通过将列表生成式的[]改成() eg: # 列表生成式 L = [ x*2 for x in range(5)] # L = [0, 2, ...
- 每日一译系列-模块化css怎么玩(译文)
原文链接:How Css Modules Work 原文作者是Preact的作者 这是一篇关于如何使用Css Modules的快速介绍,使用到的工具是Webpack吊炸的css-loader 首先,我 ...