JS组件系列之JS组件封装过程详解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

JS组件系列之JS组件封装过程详解
前⾔:
之前分享了那么多bootstrap组件的使⽤经验,这篇⽂章打算研究下JS组件的扩展和封装,我们来感受下JQuery为我们提供$.Extend的神奇,看看我们怎么⾃定义⾃⼰的组件,⽐如我们想扩展⼀个$("#id").MyJsControl({})做我们⾃⼰的组件,我们该如何去做呢,别急,我们慢慢来看看过程。

⼀、扩展已经存在的组件
1、需求背景
很多时候,我们使⽤jquery.ajax的⽅式向后台发送请求,型如
$.ajax({
type: "post",
url: "/User/Edit",
data: { data: JSON.stringify(postdata) },
success: function (data, status) {
if (status == "success") {
toastr.success('提交数据成功');
$("#tb_aaa").bootstrapTable('refresh');
}
},
error: function (e) {
},
complete: function () {
}
});
这种代码太常见了,这个时候我们有这样⼀个需求:在⾃⼰调⽤ajax请求的时候,我们不想每次都写error:function(e){}这种代码,但是我们⼜想让它每次都将ajax的错误信息输出到浏览器让⽤户能够看到。

怎么办呢?
2、实现原理
要想实现以上效果其实并不难,我们可以将$.ajax({})封装⼀层,在封装的公共⽅法⾥⾯定义error对应的事件即可。

确实,这样能达到我们的要求,但是并不完美,原因很简单:1)在jquery的基础上⾯再封装⼀层,效率不够⾼;2)需要改变调⽤者的习惯,每次调⽤ajax的时候需要按照我们定义的⽅法的规则来写,⽽不能直接⽤原⽣的$.ajax({})这种写法,这是我们不太想看到。

既然如此,那我们如何做到既不封装控件,⼜能达到以上要求呢?答案就是通过我们的$.extend去扩展原⽣的jquery.ajax。

其实实现起来也并不难,通过以下⼀段代码就能达到我们的要求。

(function ($) {
//1.得到$.ajax的对象
var _ajax = $.ajax;
$.ajax = function (options) {
//2.每次调⽤发送ajax请求的时候定义默认的error处理⽅法
var fn = {
error: function (XMLHttpRequest, textStatus, errorThrown) {
toastr.error(XMLHttpRequest.responseText, '错误消息', { closeButton: true, timeOut: 0, positionClass: 'toast-top-full-width' });
},
success: function (data, textStatus) { },
beforeSend: function (XHR) { },
complete: function (XHR, TS) { }
}
//3.如果在调⽤的时候写了error的处理⽅法,就不⽤默认的
if (options.error) {
fn.error = options.error;
}
if (options.success) {
fn.success = options.success;
}
if (options.beforeSend) {
fn.beforeSend = options.beforeSend;
}
if (plete) {
plete = plete;
}
//4.扩展原⽣的$.ajax⽅法,返回最新的参数
var _options = $.extend(options, {
error: function (XMLHttpRequest, textStatus, errorThrown) {
fn.error(XMLHttpRequest, textStatus, errorThrown);
},
success: function (data, textStatus) {
fn.success(data, textStatus);
},
beforeSend: function (XHR) {
fn.beforeSend(XHR);
},
complete: function (XHR, TS) {
plete(XHR, TS);
}
});
//5.将最新的参数传回ajax对象
_ajax(_options);
};
})(jQuery);
如果没接触过jquery⾥⾯$.extend这个⽅法的童鞋可能看不懂以上是什么意思。

好,我们⾸先来看看jquery API对$.extend()⽅法是作何解释的。

什么意思呢?我们来看官⽅的两个例⼦就知道了
栗⼦⼀:
var settings = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };
$.extend(settings, options);
结果:
settings == { validate: true, limit: 5, name: "bar" }
栗⼦⼆:
var empty = {};
var defaults = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };
var settings = $.extend(empty, defaults, options);
结果:
settings == { validate: true, limit: 5, name: "bar" }
empty == { validate: true, limit: 5, name: "bar" }
以上的两个简单例⼦就说明extend()⽅法作⽤就是合并另个对象,有相同的则覆盖,没有相同的则添加。

就是这么简单。

了解了$.extend()的作⽤,我们就能⼤概看懂上⾯那个扩展jquery.ajax的实现了吧。

主要的步骤分为:
1)定义默认的error处理⽅法。

var fn = {
error: function (XMLHttpRequest, textStatus, errorThrown) {
toastr.error(XMLHttpRequest.responseText, '错误消息', { closeButton: true, timeOut: 0, positionClass: 'toast-top-full-width' });
},
success: function (data, textStatus) { },
beforeSend: function (XHR) { },
complete: function (XHR, TS) { }
}
2)判断⽤户在调⽤$.ajax({})的时候是否⾃定了error:function(){},如果定义过,则使⽤⽤户定义的,反之则⽤默认的error处理⽅法。

3)使⽤$.extend()将error默认处理⽅法传⼊$.ajax()的参数中。

我们看options参数时包含$.ajax()⽅法⾥⾯所有的参数的,然后⽤默认的fn去扩展它即可。

通过以上三步就能够实现对$.ajax()⽅法⾥⾯error默认处理⽅法。

这样扩展,对于我们使⽤者来说完全感觉不到变化,我们仍然可以$.ajax({});这样去发送ajax请求,如果没有特殊情况,不⽤写error处理⽅法。

3、组件扩展的意义
使⽤组件扩展,能够帮助我们在原有组件上⾯增加⼀些和我们系统业务相关的处理需求,⽽在使⽤时,还是和使⽤原⽣组件⼀样去调⽤,免去了在组件上⾯再封装⼀层的臃肿。

⼆、扩展⾃⼰组件
上⾯通过$.extend()⽅法扩展了$.ajax()的error事件处理⽅法。

下⾯我们来封装⼀个⾃⼰的组件试试,功能很简单,但⽐较有说明性。

我们就以select这个组件为例,很多情况下,我们的select⾥⾯的option都是需要从数据库⾥⾯取数据的,所以⼀般的做法就是发送⼀个ajax请求,然后在success⽅法⾥⾯拼html。

现在我们就封装⼀个select远程取数据的⽅法。

1、代码实现以及使⽤⽰例
先上⼲货吧,将写好的整出来:
(function ($) {
//1.定义jquery的扩展⽅法combobox
$bobox = function (options, param) {
if (typeof options == 'string') {
return $bobox.methods[options](this, param);
}
//2.将调⽤时候传过来的参数和default参数合并
options = $.extend({}, $bobox.defaults, options || {});
//3.添加默认值
var target = $(this);
target.attr('valuefield', options.valueField);
target.attr('textfield', options.textField);
target.empty();
var option = $('<option></option>');
option.attr('value', '');
option.text(options.placeholder);
target.append(option);
//4.判断⽤户传过来的参数列表⾥⾯是否包含数据data数据集,如果包含,不⽤发ajax从后台取,否则否送ajax从后台取数据 if (options.data) {
init(target, options.data);
}
else {
//var param = {};
options.onBeforeLoad.call(target, options.param);
if (!options.url) return;
$.getJSON(options.url, options.param, function (data) {
init(target, data);
});
}
function init(target, data) {
$.each(data, function (i, item) {
var option = $('<option></option>');
option.attr('value', item[options.valueField]);
option.text(item[options.textField]);
target.append(option);
});
options.onLoadSuccess.call(target);
}
target.unbind("change");
target.on("change", function (e) {
if (options.onChange)
return options.onChange(target.val());
});
}
//5.如果传过来的是字符串,代表调⽤⽅法。

$bobox.methods = {
getValue: function (jq) {
return jq.val();
},
setValue: function (jq, param) {
jq.val(param);
},
load: function (jq, url) {
$.getJSON(url, function (data) {
jq.empty();
var option = $('<option></option>');
option.attr('value', '');
option.text('请选择');
jq.append(option);
$.each(data, function (i, item) {
var option = $('<option></option>');
option.attr('value', item[jq.attr('valuefield')]);
option.text(item[jq.attr('textfield')]);
jq.append(option);
});
});
}
};
//6.默认参数列表
$bobox.defaults = {
url: null,
param: null,
data: null,
valueField: 'value',
textField: 'text',
placeholder: '请选择',
onBeforeLoad: function (param) { },
onLoadSuccess: function () { },
onChange: function (value) { }
};
})(jQuery);
先来看看我们⾃定义组件如何使⽤:
⽤法⼀:通过URL远程取数据并初始化
⾸先定义⼀个空的select
<select id="sel_search_plant" class="form-control"></select>
然后初始化它
$(function(){
$('#sel_search_plant').combobox({
url: '/apiaction/Plant/Find',
valueField: 'TM_PLANT_ID',
textField: 'NAME_C'
});
})
参数很简单,就不⼀⼀介绍了。

很简单有⽊有~~
⽤法⼆:取值和设置
var strSelectedValue = $('#sel_search_plant').combobox("getValue");
$('#sel_search_plant').combobox("setValue", "aaa");
其实对于简单的select标签,博主觉得这⾥的getValu和SetValue意义不⼤,因为直接通过$('#sel_search_plant').val()就能解决的事,何必要再封⼀层。

这⾥仅仅是做演⽰,试想,如果是封装成类似select2或者multiselect这种组件,getValue和setValue的意义就有了,你觉得呢?
2、代码详细讲解
上⾯的实现代码,如果您⼀眼就能看懂,证明您是经常封组件的⼤虾了,下⾯的就不⽤看了。

如果看不懂,也没关系,我们将代码拆开详细看看⾥⾯是什么⿁。

(1)⾸先看看我们最常看到的如下写法:
(function ($) {
//....封装组件逻辑
})(jQuery);
初初看到这种⽤法,博主也是狂抓,这是什么⿁嘛,四不像啊。

使⽤多了之后才知道原来这就是⼀个匿名函数的形式。

将它拆开来看如下:
var fn = function($){
//.....组件封装逻辑
};
fn(jQuery);
也就是说这种写法就表⽰先定义⼀个⽅法,然后⽴即调⽤这个⽅法,jQuery相当于实参。

打开jquery.js的原⽂件可以看到,jQuery是这个⽂件⾥⾯的⼀个全局变量。

(2)定义⾃⼰的组件的代码:
$bobox = function (options, param) {
};
习惯这种写法的应该知道,这个就表⽰向jquery对象添加⾃定义⽅法,⽐如你想使⽤⽂章开始的 $("#id").MyJsControl({}) 这种⽤法,你就可以这样定义$.fn.MyJsControl=function(options){} 。

(3)options = $.extend({}, $bobox.defaults, options || {}); 这⼀句,看过上⽂的朋友应该还记得extend这么⼀个⽅法吧,怎么样,⼜来了你。

这句话其实就没什么好说的了,合并默认参数和⽤户传进来的参数。

(4)默认参数列表
$bobox.defaults = {
url: null,
param: null,
data: null,
valueField: 'value',
textField: 'text',
placeholder: '请选择',
onBeforeLoad: function (param) { },
onLoadSuccess: function () { },
onChange: function (value) { }
};
如果⽤户没有传参,就⽤默认的参数列表。

如果你够细⼼,你会发现博主之前分享的其他bootstrap组件的js⽂件⾥⾯都有这么⼀个default参数列表。

我们随便找两个:
bootstrap上传组件
bootstrap table组件
基本都是这么些⽤法。

这样来看,是否也可以⾃⼰封⼀个js组件~~
三、总结
以上就是博主对js组件扩展以及封装⽤法的认识和总结。

当然,都是些⽐较简单基础的封装,如果想要实现类似bootstrap table的组件,那还差得很远。

不过万丈⾼楼平地起,只要打好基础,封⼀个⾃⼰的table组件也不是什么⼤问题。

如果⼤家有任何疑问请给我留⾔,⼩编会及时回复⼤家的。

在此也⾮常感谢⼤
家对⽹站的⽀持!。

相关文档
最新文档