如何去思考一个JQ的组件封装?想请教一个比较详细的思路,我自身在思考的时候对于这个学习没有一个太理想的思路。主要是在JS的代码结构规划上面。
比如:我有一个表格,里面放进了数量,名字,高度,宽度,等等一系列的数据,数据格式object,array,number,fn()等等各种都有。在外面调用这个组件时根据传入的数据将对应的信息显示出来。
这是一个别人封装的插件样例:
(function($ , undefined) {
var Table = function (element, options) {
this.$this = $(element);
this.options = $.extend({}, $.fn.table.defaults, options);
this.init();
};
// 使用proptotype给Table添加属性,
Table.prototype = {
constructor: Table,
dataToObj: function(str){
if(typeof str == "string" && str[0] == "&"){
str = str.substring(1, str.length);
}
if(typeof str == "string"){
str = str.replace(/&/g,"','");
str = str.replace(/=/g,"':'");
str = "({'"+str +"'})";
return eval(str);
}
},
init: function () {
var options = this.options;
if(!options.columns) return false;
this.$this.html("");
this.initTableHead();
this.initTableBody(options.currentPage);
},
initTableHead: function(){
var options = this.options,
tableWrap = this.$this,
attributesArr = [],
theadStr = '<thead><tr class="'+options.hdBg+'">';
for(var i=0, len=options.columns.length; i< len; i++){
theadStr += '<th data-attribute="'+options.columns[i].dataIndex+'" width="'+(options.columns[i].width || "")+'">'+options.columns[i].title+'</th>';
attributesArr.push(options.columns[i].dataIndex);
}
this.options.attributes = attributesArr;
theadStr += '</tr></thead><tbody></tbody>';
this.$this.append(theadStr);
},
initTableBody: function(currentPage){
var that = this, options = this.options, data = null;
data = this.dataToObj(options.data);
$.ajax({
type: "POST",
dataType: "json",
url: options.url,
data: options.data,
beforeSend: function(){
Common.showLoading();
},
timeout: options.timeout,
complete: function(XMLHttpRequest, textStatus){
if(textStatus == "timeout"){ Common.dialogTip({info: "请求超时,请重试!!!"}); }
Common.hideLoading();
},
success : function(result){
if(result.errorCode == "106"){
location.href= result.info + "?goto=" + location.href;
}else if(result.success) {
var totalCount = result.total,
attributes = options.attributes,
tbodyWrap = that.$this.find("tbody"),
rowStr = "",
tbodyStr = "";
if(result.data.length > 0){
$.each(result.data,function(index, row){
var rowStr="<tr>";
for(var key in attributes){
var tddata=(row[attributes[key]] || "");
if(row[attributes[key]] === 0){
tddata = "0";
}
//去除html标签,如果有的话
var reg =new RegExp("<\/?[^>]*>");
if(reg.test(tddata)){
tddata =tddata.replace(/<[^>]+>/g,"");
}
rowStr +="<td>"+tddata+"</td>";
}
rowStr+="</tr>";
tbodyStr += rowStr;
});
tbodyWrap.html(tbodyStr);
that.rendererTd(result.data);
//加载分页
if(options.pagingBar && result.data.length > 0){
pageNo = data ? data.pageNo : 0;
that.loadPagingBar(result.total, parseInt(currentPage || pageNo));
}
}else{
tbodyWrap.html('<tr><td colspan="'+options.columns.length+'" class="text-center">没有找到任何数据!!!</td></tr>');
$('#'+options.pagingBarId).html("");
}
if(typeof(options.callback) == 'function'){
options.callback(result, data)
}
}else {
that.dialogTip(result.info);
}
}
});
},
rendererTd: function(rowsData){
var columns = this.options.columns,
rowElem = null,
rendererTd = null;
this.$this.children("tbody").children("tr").each(function(index, elem){
rowElem = $(elem);
$.each(columns, function(i, item){
if(columns[i].renderer && typeof columns[i].renderer == "function"){
rendererTd = rowElem.children("td:eq("+i+")");
columns[i].renderer.call(rendererTd, rendererTd.text(), rowsData[index]);
}
});
});
var onRendered = this.options.onRendered;
if (onRendered && typeof(onRendered) == "function") {
onRendered.call(this);
}
},
loadPagingBar: function(total, currentPage){
total = total || 0;
currentPage = currentPage || 1;
var that = this,
options = this.options,
totalPages = Math.ceil(total/options.pageSize),
pageWrap = $('#'+options.pagingBarId);
//console.log(total + "......" +totalPages);
pageWrap.html('');
pageWrap.html('<ul class="pagination pagination-sm" id="pager-ext" style="margin:7px 0 2px 0;"></ul>');
pageWrap.find('#pager-ext').twbsPagination({
totalPages:totalPages,
visiblePages:options.visiblePages,
startPage: currentPage,
first: '第一页',
prev: '上一页',
next: '下一页',
last: '最后页',
onPageClick: function (event, page) {
if(typeof options.onPageClick == "function"){
var obj = options.onPageClick(event, page);
$.extend(that.options, obj);
that.initTableBody(page);
}
}
});
pageWrap.data("currPage", currentPage);
pageWrap.find('#pager-ext').append('<li class="last active disabled"><a href="#">共'+totalPages+' 页</a></li>');
pageWrap.find('#pager-ext').append('<li class="last active disabled"><a href="#">总计 '+total+' 条</a></li>');
},
dialogTip: function(info){
var dialogStr = '<div class="modal fade">'+
'<div class="modal-dialog">'+
'<div class="modal-content">'+
'<div class="modal-header">'+
'<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>'+
'<h4 class="modal-title">友情提示</h4>'+
'</div>'+
'<div class="modal-body text-overflow">'+info+
'</div>'+
'</div>'+
'</div>'+
'</div>';
var wrap = $(dialogStr);
$("body").append(wrap);
wrap.modal('show');
wrap.find(".close").on("click", function(){
wrap.modal('hide');
$("body").removeClass("modal-open");
wrap.remove();
});
}
};
// option 可以是对象或者是方法名
// value option为方法名时的参数
$.fn.table = function (option, value) {
var methodReturn;
var $set = this.each(function () {
var $this = $(this),
options = typeof option === 'object' && option,
data = new Table(this, options);
if (typeof option === 'string') {
methodReturn = data[option](value);
};
});
return methodReturn ? $set : methodReturn;
};
/*
* columns = [{ title: '供货商来源', width: 150, dataIndex: 'c', renderer:function(value,obj){
* return value+':'+obj.d;
* }}]
*
* */
$.fn.table.defaults = {
url : "",
data:"",
pageSize:10,
timeout: 10000,
currentPage: 1,
autoLoad:true,
columns : null,
pagingBar:true,
hdBg:"success",
pagingBarId: "paginationholder",
visiblePages:7,
onPageClick: null,
onRendered: null,
callback: null
};
// 将插件类暴露给外界:
$.fn.table.Constructor = Table;
})(jQuery);Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
jquery 求教:如何去思考一个JQ的组件封装?-PHP中文网问答-jquery 求教:如何去思考一个JQ的组件封装?-PHP中文网问答
围观一下哦,学习一下。
(一)思考该组件在项目中的文件结构
通俗讲就是,你的组件代码及资源文件(可能包括模板html、css、js、img甚至依赖其他的子组件等等..)放在项目中的哪里?根据实际项目大小及业务场景的区分,一般都会将组件文件独立并解耦。
(二)你的组件主要实现什么功能,如何渲染页面?
题主描述的组件主要有2个功能:
根据调用时传入的数据进行数据过滤
将过滤后的数据通过表格的方式渲染在视图上
(三)应用层如何调用你的组件?
比如将你的组件挂载在 window 对象上? 或是模块化调用?
(四)组件中涉及的数据结构是怎样的?
如何存储 数量,名字,高度,宽度,等等一系列的数据 对应于 不同的数据格式?怎样的结构方便遍历查询?
(五)思考实现组件的具体编码逻辑
正如题主所说的通过 jQuery 操作DOM,暴露应用层的接口,创建组件实例并渲染页面,并且在编码过程中可以通过模拟接口来模拟组件实例的生成。
ps:当然,一般的组件也会涉及 网络请求的处理,项目本身的一些静态配置及公有方法的调用,同其他组件间的调用联系 等等问题。如果你的组件层拥有很多组件的话,同时也可以为他们定义一个统一的执行生命周期(比如,组件属性设置-渲染-事件绑定-销毁),这样方便其他组件层开发人员的编码及后期维护。
总之围绕着 Don't repeat yourself. 的编码原则的话,你会发现你的组件们会越来越健壮并且越来越可维护、可拓展。