首页 前端知识 jQuery UI widget源码解析,中高级前端开发应该要了解

jQuery UI widget源码解析,中高级前端开发应该要了解

2024-04-03 12:04:07 前端知识 前端哥 211 387 我要收藏
  1. //1、初次实例化时将插件对象缓存在dom上,后续则可直接调用,避免在相同元素下widget的多实例化。简单的说,就是一个单例方法。

  2. //2、合并用户提供的默认设置选项options

  3. //3、可以通过调用插件时传递字符串来调用插件内的方法。如:$(‘#id’).menu(‘hide’) 实际就是实例插件并调用hide()方法。

  4. //4、同时限制外部调用“_”下划线的私有方法

  5. $.fn[name] = function(options) {

  6. var isMethodCall = typeof options === “string”,

  7. args = widget_slice.call(arguments, 1),

  8. returnValue = this;

  9. // allow multiple hashes to be passed on init.

  10. //可以简单认为是$.extend(true,options,args[0],…),args可以是一个参数或是数组

  11. options = !isMethodCall && args.length ? $.widget.extend.apply(null, [options].concat(args)) : options;

  12. //这里对字符串和对象分别作处理

  13. if (isMethodCall) {

  14. this.each(function() {

  15. var methodValue, instance = $.data(this, fullName);

  16. //如果传递的是instance则将this返回。

  17. if (options === “instance”) {

  18. returnValue = instance;

  19. return false;

  20. }

  21. if (!instance) {

  22. return $.error("cannot call methods on " + name + " prior to initialization; " + “attempted to call method '” + options + “'”);

  23. }

  24. //这里对私有方法的调用做了限制,直接调用会抛出异常事件

  25. if (!$.isFunction(instance[options]) || options.charAt(0) === “_”) {

  26. return $.error(“no such method '” + options + “’ for " + name + " widget instance”);

  27. }

  28. //这里是如果传递的是字符串,则调用字符串方法,并传递对应的参数.

  29. //比如插件有个方法hide(a,b); 有2个参数:a,b

  30. //则调用时$(‘#id’).menu(‘hide’,1,2);//1和2 分别就是参数a和b了。

  31. methodValue = instance[options].apply(instance, args);

  32. if (methodValue !== instance && methodValue !== undefined) {

  33. returnValue = methodValue && methodValue.jquery ? returnValue.pushStack(methodValue.get()) : methodValue;

  34. return false;

  35. }

  36. });

  37. } else {

  38. this.each(function() {

  39. var instance = $.data(this, fullName);

  40. if (instance) {

  41. instance.option(options || {});

  42. //这里每次都调用init方法

  43. if (instance._init) {

  44. instance._init();

  45. }

  46. } else {

  47. //缓存插件实例

  48. $.data(this, fullName, new object(options, this));

  49. }

  50. });

  51. }

  52. return returnValue;

  53. };

  54. };

  55. //这里是真正的widget基类

  56. $.Widget = function( /* options, element */ ) {};

  57. $.Widget._childConstructors = [];

  58. $.Widget.prototype = {

  59. widgetName: “widget”,

  60. //用来决定事件的名称和插件提供的callbacks的关联。

  61. // 比如dialog有一个close的callback,当close的callback被执行的时候,一个dialogclose的事件被触发。

  62. // 事件的名称和事件的prefix+callback的名称。widgetEventPrefix 默认就是控件的名称,但是如果事件需要不同的名称也可以被重写。

  63. // 比如一个用户开始拖拽一个元素,我们不想使用draggablestart作为事件的名称,我们想使用dragstart,所以我们可以重写事件的prefix。

  64. // 如果callback的名称和事件的prefix相同,事件的名称将不会是prefix。

  65. // 它阻止像dragdrag一样的事件名称。

  66. widgetEventPrefix: “”,

  67. defaultElement: “

    ”,

  68. //属性会在创建模块时被覆盖

  69. options: {

  70. disabled: false,

  71. // callbacks

  72. create: null

  73. },

  74. _createWidget: function(options, element) {

  75. element = $(element || this.defaultElement || this)[0];

  76. this.element = $(element);

  77. this.uuid = widget_uuid++;

  78. this.eventNamespace = “.” + this.widgetName + this.uuid;

  79. this.options = $.widget.extend({}, this.options, this._getCreateOptions(), options);

  80. this.bindings = $();

  81. this.hoverable = $();

  82. this.focusable = $();

  83. if (element !== this) {

  84. //            debugger

  85. $.data(element, this.widgetFullName, this);

  86. this._on(true, this.element, {

  87. remove: function(event) {

  88. if (event.target === element) {

  89. this.destroy();

  90. }

  91. }

  92. });

  93. this.document = $(element.style ?

  94. // element within the document

  95. element.ownerDocument :

  96. // element is window or document

  97. element.document || element);

  98. this.window = $(this.document[0].defaultView || this.document[0].parentWindow);

  99. }

  100. this._create();

  101. //创建插件时,有个create的回调

  102. this._trigger(“create”, null, this._getCreateEventData());

  103. this._init();

  104. },

  105. _getCreateOptions: $.noop,

  106. _getCreateEventData: $.noop,

  107. _create: $.noop,

  108. _init: $.noop,

  109. //销毁模块:去除绑定事件、去除数据、去除样式、属性

  110. destroy: function() {

  111. this._destroy();

  112. // we can probably remove the unbind calls in 2.0

  113. // all event bindings should go through this._on()

  114. this.element.unbind(this.eventNamespace).removeData(this.widgetFullName)

  115. // support: jquery <1.6.3

  116. // http://bugs.jquery.com/ticket/9413

  117. .removeData($.camelCase(this.widgetFullName));

  118. this.widget().unbind(this.eventNamespace).removeAttr(“aria-disabled”).removeClass(

  119. this.widgetFullName + "-disabled " + “ui-state-disabled”);

  120. // clean up events and states

  121. this.bindings.unbind(this.eventNamespace);

  122. this.hoverable.removeClass(“ui-state-hover”);

  123. this.focusable.removeClass(“ui-state-focus”);

  124. },

  125. _destroy: $.noop,

  126. widget: function() {

  127. return this.element;

  128. },

  129. //设置选项函数

  130. option: function(key, value) {

  131. var options = key,

  132. parts, curOption, i;

  133. if (arguments.length === 0) {

  134. // don’t return a reference to the internal hash

  135. //返回一个新的对象,不是内部数据的引用

  136. return $.widget.extend({}, this.options);

  137. }

  138. if (typeof key === “string”) {

  139. // handle nested keys, e.g., “foo.bar” => { foo: { bar: ___ } }

  140. options = {};

  141. parts = key.split(“.”);

  142. key = parts.shift();

  143. if (parts.length) {

  144. curOption = options[key] = $.widget.extend({}, this.options[key]);

  145. for (i = 0; i < parts.length - 1; i++) {

  146. curOption[parts[i]] = curOption[parts[i]] || {};

  147. curOption = curOption[parts[i]];

  148. }

  149. key = parts.pop();

  150. if (arguments.length === 1) {

  151. return curOption[key] === undefined ? null : curOption[key];

  152. }

  153. curOption[key] = value;

  154. } else {

  155. if (arguments.length === 1) {

  156. return this.options[key] === undefined ? null : this.options[key];

  157. }

  158. options[key] = value;

  159. }

  160. }

  161. this._setOptions(options);

  162. return this;

  163. },

  164. _setOptions: function(options) {

  165. var key;

  166. for (key in options) {

  167. this._setOption(key, options[key]);

  168. }

  169. return this;

  170. },

  171. _setOption: function(key, value) {

  172. this.options[key] = value;

  173. if (key === “disabled”) {

  174. this.widget().toggleClass(this.widgetFullName + “-disabled”, !! value);

  175. // If the widget is becoming disabled, then nothing is interactive

  176. if (value) {

  177. this.hoverable.removeClass(“ui-state-hover”);

  178. this.focusable.removeClass(“ui-state-focus”);

  179. }

  180. }

  181. return this;

  182. },

  183. enable: function() {

  184. return this._setOptions({

  185. disabled: false

  186. });

  187. },

  188. disable: function() {

  189. return this._setOptions({

  190. disabled: true

  191. });

  192. },

  193. _on: function(suppressDisabledCheck, element, handlers) {

  194. var delegateElement, instance = this;

  195. // no suppressDisabledCheck flag, shuffle arguments

  196. if (typeof suppressDisabledCheck !== “boolean”) {

  197. handlers = element;

  198. element = suppressDisabledCheck;

  199. suppressDisabledCheck = false;

  200. }

  201. // no element argument, shuffle and use this.element

  202. if (!handlers) {

  203. handlers = element;

  204. element = this.element;

  205. delegateElement = this.widget();

  206. } else {

  207. // accept selectors, DOM elements

  208. element = delegateElement = $(element);

  209. this.bindings = this.bindings.add(element);

  210. }

  211. $.each(handlers, function(event, handler) {

  212. function handlerProxy() {

  213. // allow widgets to customize the disabled handling

  214. // - disabled as an array instead of boolean

  215. // - disabled class as method for disabling individual parts

  216. if (!suppressDisabledCheck && (instance.options.disabled === true || $(this).hasClass(“ui-state-disabled”))) {

  217. return;

  218. }

  219. return (typeof handler === “string” ? instance[handler] : handler).apply(instance, arguments);

  220. }

  221. // copy the guid so direct unbinding works

  222. if (typeof handler !== “string”) {

  223. handlerProxy.guid = handler.guid = handler.guid || handlerProxy.guid || $.guid++;

  224. }

  225. var match = event.match(/^([\w:-]*)\s*(.*)$/),

  226. eventName = match[1] + instance.eventNamespace,

  227. selector = match[2];

  228. if (selector) {

  229. delegateElement.delegate(selector, eventName, handlerProxy);

  230. } else {

  231. element.bind(eventName, handlerProxy);

  232. }

  233. });

  234. },

  235. _off: function(element, eventName) {

  236. eventName = (eventName || “”).split(" ").join(this.eventNamespace + " ") + this.eventNamespace;

  237. element.unbind(eventName).undelegate(eventName);

  238. },

  239. _delay: function(handler, delay) {

  240. function handlerProxy() {

  241. return (typeof handler === “string” ? instance[handler] : handler).apply(instance, arguments);

  242. }

  243. var instance = this;

  244. return setTimeout(handlerProxy, delay || 0);

  245. },

  246. _hoverable: function(element) {

  247. this.hoverable = this.hoverable.add(element);

  248. this._on(element, {

  249. mouseenter: function(event) {

  250. $(event.currentTarget).addClass(“ui-state-hover”);

  251. },

  252. mouseleave: function(event) {

  253. $(event.currentTarget).removeClass(“ui-state-hover”);

  254. }

  255. });

  256. },

  257. _focusable: function(element) {

  258. this.focusable = this.focusable.add(element);

  259. this._on(element, {

  260. focusin: function(event) {

  261. $(event.currentTarget).addClass(“ui-state-focus”);

  262. },

  263. focusout: function(event) {

  264. $(event.currentTarget).removeClass(“ui-state-focus”);

  265. }

  266. });

  267. },

  268. _trigger: function(type, event, data) {

  269. var prop, orig, callback = this.options[type];

  270. data = data || {};

  271. event = $.Event(event);

  272. event.type = (type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type).toLowerCase();

  273. // the original event may come from any element

  274. // so we need to reset the target on the new event

  275. event.target = this.element[0];

  276. // copy original event properties over to the new event

  277. orig = event.originalEvent;

  278. if (orig) {

  279. for (prop in orig) {

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
img

最后

推荐一些系统学习的途径和方法。

路线图

每个Web开发人员必备,很权威很齐全的Web开发文档。作为学习辞典使用,可以查询到每个概念、方法、属性的详细解释,注意使用英文关键字搜索。里面的一些 HTML,CSS,HTTP 技术教程也相当不错。

CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

HTML 和 CSS:

html5知识

css基础知识

识点,真正体系化!**

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-O2GEVXKW-1711756375226)]

最后

推荐一些系统学习的途径和方法。

路线图

每个Web开发人员必备,很权威很齐全的Web开发文档。作为学习辞典使用,可以查询到每个概念、方法、属性的详细解释,注意使用英文关键字搜索。里面的一些 HTML,CSS,HTTP 技术教程也相当不错。

CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

HTML 和 CSS:

html5知识

css基础知识

转载请注明出处或者链接地址:https://www.qianduange.cn//article/4446.html
标签
element-ui
评论
发布的文章

java解析超大json文件数据

2024-04-19 21:04:10

头歌-JavaScript基础

2024-04-19 21:04:54

C#Json序列化及反序列化

2024-04-19 21:04:40

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!