Bootstrap嵌入jqGrid,使你的table牛逼起來
Bootstrap原生的table組件只能滿足簡單的數(shù)據(jù)展示,滿足不了更富有操作性的要求。當(dāng)然了,你可以找到一款叫做“DataTables-1.10.11”的基于bootstrap的table組件,但如果你對API看得不甚了解的話,用起來可就痛苦了,但是如果你選擇使用jqGrid,那么本篇教程就給你帶來了解決這種富操作性table的解決方案。
一、效果展示
OK,就展示這一張圖片,相信你已經(jīng)愛上了bootstrap版的jqGrid,和bootstrap很兼容,簡直完美,當(dāng)然了,這需要我們在緣由的jqGrid上進行一些改動,同時對組件進行一定的封裝。
二、資源下載
我反正挺熱愛分享的,關(guān)于jqGrid的組件代碼,你可以從jqGrid的官網(wǎng)上下載,但是下載下來需要一些改動,那么我直接將改動后的jqGrid上傳到了git,你只需要把提供的文件導(dǎo)入到你對應(yīng)的項目即可。
另外,你還需要下載一個jquery-ui-1.10.0.custom.css,我就不提供下載地址了,不過我相信,你肯定會找得到,就算是用頻出事故的度娘,你也可以找得到。
三、本篇都講一些什么
自從建了QQ群后,“絡(luò)繹不絕”的有同學(xué)加入到群中,但我也發(fā)現(xiàn),進群的一步人直接來找我要demo,或者項目代碼,這個我可不喜歡,自己動手做一做,去實現(xiàn)以下,改造一下,才會是你自己的東西,完全照搬我的代碼顯然你得不到更多的幫助,希望以上同學(xué)學(xué)習(xí)的時候再主動一些。
說完上面這點小廢話后,我們言歸正傳,來說說我們本篇博客主要來講些什么,什么才是在bootstrap中嵌入jqGrid的關(guān)鍵所在,我總結(jié)有如下:
jqGrid在bootstrap中的布局方案jqGrid自身的構(gòu)造化參數(shù)jqGrid在bootstrap中的模塊化jqGrid的數(shù)據(jù)操作
暫定分為以上部分來說明,但必須注意,限于篇幅,博客中只提供思路和部分代碼。
①、 jqGrid在bootstrap中的布局方案
<!DOCTYPE html> <html lang="zh-CN"> <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ include file="/components/common/taglib.jsp"%> <%@ include file="/components/common/csslib.jsp"%> <head> <link type="text/css" rel="stylesheet" href="${ctx}/css/deal/my_pay_list.css" /> </head> <body> <div class="container"> <form class="form-horizontal" id="jqgridForm" role="form" action="${ctx}/deal/datablePayDealOrdersList" method="post"> <div class="form-group"> <div class="col-sm-12"> <label for="name" class="control-label pull-left">項目名稱:</label> <div class="col-sm-3"> <input type="text" name="name" class="form-control" id="name" placeholder="請輸入項目名稱" value="" /> </div> </div> </div> <div class="form-group"> <div class="col-sm-12"> <button type="button" class="btn btn-primary pull-right" id="searchBtn">檢索</button> </div> </div> <div class="form-group"> <div class="col-sm-12"> <table id="pageGrid" rel="jqgridForm" class="jqgrid"></table> <div id="pageGridPager"></div> </div> </div> </form> </div> <%@ include file="/components/common/jslib.jsp"%> <script type="text/javascript" src="${ctx}/js/deal/my_pay_list.js"></script> </body> </html>
介于每個人的項目千差萬別,列出的代碼中我們只關(guān)注jqGrid部分:
id="jqgridForm"
,此處我們?yōu)閖qGrid包含一層檢索條件的form表單,也就是效果圖上列出的search部分,當(dāng)點擊檢索按鈕時,就把form表單域的查詢條件提交到controller,進而獲取的數(shù)據(jù)。id="searchBtn"
,定義檢索按鈕,后面講模塊化會用得到。<table id="pageGrid" rel="jqgridForm" class="jqgrid"></table> <div id="pageGridPager"></div>
定義jqGrid的table元素和jqGrid的footer元素,使用的規(guī)則我的項目暫時約定這種規(guī)則,你也可以有你自己的規(guī)則。通過rel指定form的id,可以更便捷的使用table的檢索form。②、 jqGrid自身的構(gòu)造化參數(shù)
構(gòu)造化參數(shù),我把他提取到了①中的my_pay_list.js中。
$(function() { var jqOption = { datatype : "xml", mtype : "POST", shrinkToFit : true, viewrecords : false, rownumbers : false, autowidth : true, height : "100%", colNames : [ 'id', 'status', '項目信息', '項目狀態(tài)', '訂單號', '項目名稱', '下單時間', '支付金額', '支持?jǐn)?shù)量', '訂單狀態(tài)', '操作' ], colModel : [ { name : 'id', index : 'id', hidden : true }, { name : 'status', index : 'status', hidden : true }, { name : 'image_str', index : 'image_str', width : 140, resizable : false, sortable : false, formatter : function(cellvalue, options, rowObject) { if (cellvalue == '支付總花費:') { return cellvalue; } }, align : 'left' }, { name : 'oper', index : 'oper', width : 90, resizable : false, sortable : false, align : 'center', formatter : function(cellvalue, options, rowObject) { var status = parseInt($(rowObject).find("status").text()); var id = $(rowObject).find("id").text(); if (status == 0) { return '<a class="color0088cc" width="700" target="dialog" href="' + common.ctx + '/deal/initPayg/' + id + '">去支付</a>'; } if (status == 1 || status == 3) { return '<a class="color0088cc" target="_blank" href="' + common.ctx + '/deal/showDealOr/' + id + '">查看詳情</a>'; } if (status == 2) { return '<a class="color0088cc" target="ajaxTodo" href="' + common.ctx + '/deal/receivder/' + id + '">確認(rèn)收貨</a>'; } }, } ], xmlReader : { repeatitems : false, root : "PageGrid", row : "map", page : 'page', total : 'total', records : 'records', id : 'ID' }, rowNum : 50, rowList : [ 50, 100, 200, 300 ], pager : "#pageGridPager", footerrow : true, loadError : YUNM.ajaxError, gridComplete : function() { var $form = $("#" + $("#pageGrid").attr("rel")); $.ajax({ type : $form.method || 'POST', url : common.ctx + "/deal/getAllOrded", data : $form.serializeArray(), dataType : "json", cache : false, success : function(json) { $("#pageGrid").footerData("set", { image_str : "支付總花費:", order_price : json.message }); }, error : YUNM.ajaxError }); if ($.fn.ajaxTodo) { $("a[target=ajaxTodo]", $("#pageGrid")).ajaxTodo(); } // dialog if ($.fn.ajaxTodialog) { $("a[target=dialog]", $("#pageGrid")).ajaxTodialog(); } }, }; initEnv(jqOption); });
一點都不熟悉jqGrid的同學(xué),建議先看jqGrid的demo,以及jqGrid的官方文檔,當(dāng)然了,對于已經(jīng)熟悉jqGrid的同學(xué),doc和demo肯定是必看的。
以上文件列出的屬性非常多,對于jqGrid,我不做過多的介紹,本篇的主旨主要來介紹如何將jqGrid嵌入到bootstrap,那么重點就不在于介紹jqGrid上,我只介紹幾個關(guān)鍵點:
formatter: function(cellvalue, options, rowObject) {
,formatter還是很經(jīng)常要使用的,那么對于如何獲得對應(yīng)單元格的值就很重要,我的jqGrid使用的是xml(datatype : “xml”)數(shù)據(jù)格式,那么可通過$(rowObject).find("deal_id").text()
找到對應(yīng)deal_id列的值。xmlReader : { repeatitems : false, root : "PageGrid",
,注意xmlReader中的參數(shù)值,在接下來介紹④jqGrid的數(shù)據(jù)操作會細(xì)節(jié)介紹,和后臺的xml數(shù)據(jù)封裝有關(guān)系。$("#pageGrid").footerData("set", {image_str : "支付總花費:", order_price : json.message});
,關(guān)于footerData方法,使用起來也很方便,效果可參照效果圖。initEnv(jqOption);
方法,在頁面onload后,我們將jqGrid的初始化參數(shù)傳遞給initEnv方法,后續(xù)③jqGrid在bootstrap中的模塊化會介紹initEnv方法。③、jqGrid在bootstrap中的模塊化
②中我們注意到initEnv方法,那么這個方法內(nèi)部就是專門針對jqGrid做的模塊化封裝工作。
initEnv方法
function initEnv(jqOption) { $(window).resize(function() { initLayout(); }); initUI(null, jqOption); }
該方法中,我們將會看到initLayout方法和initUI方法,具體內(nèi)容稍候介紹。
initLayout
function initLayout() { $("table[rel=jqgridForm]").each(function() { var rel = $(this).attr("rel"); if (rel) { var $form = $("#" + rel); var tableWidth = $form.width(); $(this).setGridWidth(tableWidth, true); } }); }
也就是說,在窗口縮放的時候,我們?yōu)閖qGrid重新繪制寬度,使其自適應(yīng)于bootstrap的響應(yīng)式布局。使用的方法就是jqGrid的setGridWidth方法。
initUI
function initUI(_box, jqOption) { var $p = $(_box || document); if (jqOption) { YUNM.debug("初始化jqgrid"); var $form = $("#" + $("#pageGrid").attr("rel")); YUNM.debug(YUNM.array2obj($form.serializeArray())); // 初始化 var op = $.extend({ url : $form.attr("action"), postData : YUNM.array2obj($form.serializeArray()), }, jqOption); $("#pageGrid").jqGrid(op); // 檢索按鈕 $("#searchBtn", $form).click(function() { $("#pageGrid").jqGrid('setGridParam', { url : $form.attr("action"), page : 1, postData : YUNM.array2obj($form.serializeArray()), }); $("#pageGrid").trigger("reloadGrid"); }); // toolbar,將button的圓角去掉 $(".btn", $form).each(function() { var $this = $(this); $this.css({ "border-radius" : "0px", "border-bottom" : "0", }); }); } } array2obj : function(array) { var params = $({}); $.each(array, function(i) { var $param = $(this)[0]; params.attr($param.name, $param.value); }); return params[0]; },
如果你曾看過我之前的系列文章,對于initUi方法就不會太陌生,熟悉dwz的朋友,自然也不會陌生,我項目中的大部分模板還是依賴于dwz,謝謝這些前輩們。
var $form = $("#" + $("#pageGrid").attr("rel"));
由于我們在jqGrid上關(guān)聯(lián)了form檢索條件的form表單,此處就可以將form表單對象取到,取到form表單對象,自然也就去得到了檢索域的值($form.serializeArray()
)。拿到form表單的檢索域值后,此時就需要做一番處理了。我們知道,jqGrid在向controller傳遞參數(shù)時,必然需要上送分頁、排序的相關(guān)字段(page、rows、sord、sidx),使用的方法是$("#pageGrid").jqGrid({postData:xxx});
,通常情況下,我們上送form表單時,只需要使用$form.serializeArray()
就可以,但如果此時,只是將xxx替換為$form.serializeArray()
,那么controller中將不會獲得分頁、排序的相關(guān)字段(page、rows、sord、sidx),這是一個沖突,此時怎么處理呢?解決辦法就是將form表單數(shù)據(jù)對象化(array2obj 方法),然后我們再通過var op =$.extend({url:$form.attr("action"),postData:YUNM.array2obj($form.serializeArray()),},jqOption);$("#pageGrid").jqGrid(op);
將檢索域的值和分頁、排序的相關(guān)字段一起上送到controller。$("#searchBtn", $form).click
通過封裝click事件,將jqGrid的數(shù)據(jù)重新加載。$(".btn", $form).each(function() {
此處的方法將檢索button去圓角,使其更貼合jqGrid,見效果圖。④ 、jqGrid的數(shù)據(jù)操作
數(shù)據(jù)操作部分,我認(rèn)為包含有 檢索參數(shù)傳遞、分頁排序參數(shù)傳遞、sql語句的編寫。
關(guān)于參數(shù)傳遞,前端的參數(shù)封裝在③中已有介紹,我們來看一看controller中如何處理數(shù)據(jù)的。
首先,我們來定義PageGrid,也就是jqGrid中xmlReader的數(shù)據(jù)源。
package com.honzh.common.page; import java.util.List; import com.thoughtworks.xstream.annotations.XStreamAlias; @XStreamAlias("pageGrid") @SuppressWarnings("rawtypes") public class PageGrid { private int page; private int total; private int records; private List data; public int getPage() { return this.page; } public void setPage(int page) { this.page = page; } public int getTotal() { return this.total; } public void setTotal(int total) { this.total = total; } public int getRecords() { return this.records; } public void setRecords(int records) { this.records = records; } public List getData() { return this.data; } public void setData(List data) { this.data = data; } }
項目中需要xstream.jar,自行下載。
XStreamComponent.java
package com.honzh.common.page; import org.apache.commons.lang.StringUtils; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.io.xml.DomDriver; import com.thoughtworks.xstream.mapper.DefaultMapper; import com.thoughtworks.xstream.mapper.XStream11XmlFriendlyMapper; public class XStreamComponent { private XStream xstream; public static XStreamComponent newInstance() { XStreamComponent xmlComponent = new XStreamComponent(); xmlComponent.alias(new Class[] { PageGrid.class }); return xmlComponent; } public XStreamComponent() { this.xstream = new XStream(new DomDriver()); } public String toXML(Object obj) { return this.xstream.toXML(obj); } public String toPageXML(Object obj) { registerConverter(new MapCustomConverter(new DefaultMapper(XStream11XmlFriendlyMapper.class.getClassLoader()))); return toXML(obj); } public Object fromPageXML(String xml) { registerConverter(new MapCustomConverter(new DefaultMapper(XStream11XmlFriendlyMapper.class.getClassLoader()))); return fromXML(xml); } public Object fromXML(String xml) { return this.xstream.fromXML(xml); } @SuppressWarnings("rawtypes") public void processAnnotations(Class type) { this.xstream.processAnnotations(type); } @SuppressWarnings("rawtypes") public void processAnnotations(Class[] types) { this.xstream.processAnnotations(types); } @SuppressWarnings("rawtypes") public void alias(String name, Class type) { this.xstream.alias(name, type); } @SuppressWarnings("rawtypes") public void alias(Class[] types) { for (Class type : types) { String className = type.getName(); try { String[] classNames = StringUtils.split(className, "."); this.xstream.alias(classNames[(classNames.length - 1)], type); } catch (Exception ex) { this.xstream.alias(className, type); } } } public void registerConverter(Converter converter) { this.xstream.registerConverter(converter); } @SuppressWarnings("rawtypes") public void useAttributeFor(Class definedIn, String fieldName) { this.xstream.useAttributeFor(definedIn, fieldName); } }
主要將pageGrid封裝為xml對象,進而傳遞會前端。
MapCustomConverter.java
package com.honzh.common.page; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.mapper.Mapper; public class MapCustomConverter extends AbstractCollectionConverter { public MapCustomConverter(Mapper mapper) { super(mapper); } @SuppressWarnings("rawtypes") public boolean canConvert(Class type) { return (type.equals(HashMap.class)) || (type.equals(Hashtable.class)) || (type.getName().equals("java.util.LinkedHashMap")) || (type.getName().equals("sun.font.AttributeMap")); } @SuppressWarnings({ "rawtypes" }) public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { Map map = (Map) source; for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = (Map.Entry) iterator.next(); writer.startNode(entry.getKey() == null ? "null" : entry.getKey().toString()); writer.setValue(entry.getValue() == null ? "" : entry.getValue().toString()); writer.endNode(); } } @SuppressWarnings("rawtypes") public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { Map map = (Map) createCollection(context.getRequiredType()); populateMap(reader, context, map); return map; } @SuppressWarnings({ "rawtypes", "unchecked" }) protected void populateMap(HierarchicalStreamReader reader, UnmarshallingContext context, Map map) { while (reader.hasMoreChildren()) { reader.moveDown(); Object key = reader.getNodeName(); Object value = reader.getValue(); map.put(key, value); reader.moveUp(); } } }
主要將數(shù)據(jù)庫中獲取的hashmap轉(zhuǎn)換為標(biāo)準(zhǔn)的xml格式數(shù)據(jù)。
BaseConditionVO.java
package com.honzh.common.persistence; import java.util.HashMap; import java.util.Map; import org.apache.ibatis.session.RowBounds; /** * 分頁查詢時的參數(shù)設(shè)置類.<br> * * <P> * 1.PAGE_SHOW_COUNT──當(dāng)然默認(rèn)一頁顯示10。<br> * 2.pageNum──第幾頁。<br> * 3.numPerPage──一頁顯示多少,為空時,顯示PAGE_SHOW_COUNT。<br> * 4.totalCount──總共數(shù)目。totalCount/numPerPage=多少頁<br> * 5.orderField──排序的列。<br> * 6.orderDirection──排序的方向。 * </P> */ public class BaseConditionVO { public final static int PAGE_SHOW_COUNT = 50; private int pageNum = 1; private int numPerPage = 0; private long totalCount = 0; private String orderField = ""; private String orderDirection = ""; /** * @Fields ps : 對參數(shù)類型進行封裝. */ private Map<String, Object> mo = new HashMap<String, Object>(); public int getPageNum() { return pageNum; } public void setPageNum(int pageNum) { this.pageNum = pageNum; } public int getNumPerPage() { return numPerPage > 0 ? numPerPage : PAGE_SHOW_COUNT; } public void setNumPerPage(int numPerPage) { this.numPerPage = numPerPage; } public String getOrderField() { return orderField; } public void setOrderField(String orderField) { this.orderField = orderField; } public String getOrderDirection() { return "desc".equals(orderDirection) ? "desc" : "asc"; } public void setOrderDirection(String orderDirection) { this.orderDirection = orderDirection; } public long getTotalCount() { return totalCount; } public void setTotalCount(long totalCount) { this.totalCount = totalCount; } public int getStartIndex() { int pageNum = this.getPageNum() > 0 ? this.getPageNum() - 1 : 0; return pageNum * this.getNumPerPage(); } public RowBounds createRowBounds() { RowBounds ro = new RowBounds(this.getStartIndex(), this.getNumPerPage()); return ro; } /** * @Title: addParams * @Description: 添加查詢條件 * @param key * @param value */ public void addParams(String key, Object value) { this.getMo().put(key, value); } /** * @Title: getParams * @Description: 獲取查詢條件 * @param key * @return */ public Object getParams(String key) { return this.getMo().get(key); } /** * @return the mo */ public Map<String, Object> getMo() { return mo; } /** * @param mo * the mo to set */ public void setMo(Map<String, Object> mo) { this.mo = mo; } @Override public String toString() { return "條件:" + pageNum + "," + numPerPage + "," + totalCount + "," + orderField + "," + orderDirection + "," + mo; } }
分頁的查詢數(shù)據(jù)對象,包括分頁、排序、檢索域。
protected BaseConditionVO getBaseConditionVOForTable() { BaseConditionVO vo = new BaseConditionVO(); // 分頁的參數(shù) int currentPage = getParaToInt("page"); int sizes = getParaToInt("rows"); String sortOrder = getPara("sord"); String sortCol = getPara("sidx"); vo.setNumPerPage(sizes); vo.setPageNum(currentPage); vo.setOrderField(sortCol); vo.setOrderDirection(sortOrder); return vo; } 將jqGrid傳遞的參數(shù)轉(zhuǎn)換為BaseConditionVO分頁查詢對象。 protected void renderXml(HttpServletResponse res, String xmlResponse) { try { res.setCharacterEncoding("UTF-8"); res.setHeader("Content-type", "text/xml"); PrintWriter out = res.getWriter(); out.print(xmlResponse); if (out != null) { out.close(); } } catch (IOException e) { logger.error(e.getMessage()); logger.error(e.getMessage(), e); } }
將xml寫入到輸出流中。
定義完了這些基礎(chǔ)的對象,接下來,我們就要著手獲取數(shù)據(jù)和傳遞數(shù)據(jù)了。
@SuppressWarnings("rawtypes") @RequestMapping(value = "datablePayDealOrdersList") public void datablePayDealOrdersList(HttpServletResponse response) { try { logger.debug("獲取我支付的訂單"); XStreamComponent xstreamComponent = XStreamComponent.newInstance(); // 獲取列表參數(shù) BaseConditionVO vo = getBaseConditionVOForTable(); vo.addParams("name", getPara("name")); logger.debug("我支付的訂單查詢" + vo); // 我創(chuàng)建的項目 List myDealOrders = dealOrderService.getByIssueUid(vo, vo.createRowBounds()); Long count = dealOrderService.searchIssueTotalCount(vo); String xmlResponse = xstreamComponent.toPageXML(createPageGrid(myDealOrders, vo, count.intValue())); renderXml(response, xmlResponse.replaceAll("__", "_")); } catch (UncategorizedSQLException e) { logger.error(e.getMessage()); logger.error(e.getMessage(), e); renderXml(response, Constants.QUERY_ERROR); } catch (Exception e) { logger.error(e.getMessage()); logger.error(e.getMessage(), e); renderXml(response, Constants.SERVER_ERROR); } }
我們來詳細(xì)說明一下:
1. XStreamComponent.newInstance()
創(chuàng)建xml流對象。
2. BaseConditionVO vo = getBaseConditionVOForTable();
創(chuàng)建分頁查詢參數(shù)對象。
3. vo.addParams("name", getPara("name"));
將檢索域的值放入到查詢對象中。
4. dealOrderService.getByIssueUid(vo, vo.createRowBounds());
mybatis的分頁查詢方式,超簡單,之前一個群里的朋友專門做了一種mybatis的分頁組件,我覺得用原始的mybatis查詢方法更有效率,之后,我們會寫出對應(yīng)的mybatis中xml的sql寫法。
5. renderXml(response, xmlResponse.replaceAll("__", "_"));
將數(shù)據(jù)寫入到j(luò)sp的out輸出流中。
最后,我們來介紹,通過mybatis如何獲取分頁數(shù)據(jù)。
mapper.java
package com.honzh.biz.database.mapper; import java.math.BigDecimal; import java.util.HashMap; import java.util.List; import org.apache.ibatis.session.RowBounds; import com.honzh.common.persistence.BaseConditionVO; public interface DealOrderMapper { @SuppressWarnings("rawtypes") List<HashMap> getByIssueUid(BaseConditionVO vo, RowBounds createRowBounds); }
想mapper.xml傳遞的兩個對象,分別是BaseConditionVO 還有分頁的RowBounds ,xml中sql就會自動分頁。
mapper.xml
<select id="getByIssueUid" resultType="hashmap" parameterType="map"> select * from daa WHERE is_delete=0 <if test="mo.name != null and mo.name != ''"> and y.name like CONCAT('%','${mo.name}','%') </if> <choose> <when test="orderField !=null and orderField !=''"> ORDER BY ${orderField} <if test="orderDirection != null and orderDirection != ''">${orderDirection}</if> </when> <otherwise> order by d.order_time DESC </otherwise> </choose> </select>
你完全可以不關(guān)注RowBounds ,mybatis內(nèi)部會自動為你封裝好limit的。檢索域的name可以直接通過mo.name或得到。orderField、orderDirection也傳遞過來了。
到此為止,整篇的Bootstrap嵌入jqGrid就圓滿結(jié)束了,ok,使你的table牛逼起來吧!
相關(guān)文章
基于jquery實現(xiàn)狀態(tài)限定編輯的代碼
基于jquery實現(xiàn)狀態(tài)限定編輯的代碼,需要的朋友可以參考下2012-02-02jQuery實現(xiàn)的小圖列表,大圖展示效果幻燈片示例
這篇文章主要介紹了jQuery實現(xiàn)的小圖列表,大圖展示效果幻燈片,結(jié)合完整實例形式分析了jQuery圖片滑動切換功能的相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2016-10-10jQuery News Ticker 基于jQuery的即時新聞行情展示插件
今天分享一個新聞行情的jQUery插件,可以幫助大家使用比較小的頁面區(qū)域來展示最新最重要的信息。2011-11-11解決qrcode.js生成二維碼時必須定義一個空div的問題
這篇文章主要介紹了解決qrcode.js生成二維碼時必須定義一個空div的問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07