首页 前端知识 携程前端面试题及答案,jQuery UI widget源码解析,熟练web开发

携程前端面试题及答案,jQuery UI widget源码解析,熟练web开发

2024-09-21 21:09:55 前端知识 前端哥 947 168 我要收藏
  1. }

  2. };

  3. // extend with the existing constructor to carry over any static properties

  4. //合并对象,将旧插件实例,及版本号、prototype合并到constructor

  5. $.extend(constructor, existingConstructor, {

  6. version: prototype.version,

  7. // copy the object used to create the prototype in case we need to

  8. // redefine the widget later

  9. //创建一个新的插件对象

  10. //将插件实例暴露给外部,可用户修改及覆盖

  11. _proto: $.extend({}, prototype),

  12. // track widgets that inherit from this widget in case this widget is

  13. // redefined after a widget inherits from it

  14. _childConstructors: []

  15. });

  16. //实例化父类 获取父类的  prototype

  17. basePrototype = new base();

  18. // we need to make the options hash a property directly on the new instance

  19. // otherwise we’ll modify the options hash on the prototype that we’re

  20. // inheriting from

  21. //这里深复制一份options

  22. basePrototype.options = $.widget.extend({}, basePrototype.options);

  23. //在传入的ui原型中有方法调用this._super 和this.__superApply会调用到base上(最基类上)的方法

  24. $.each(prototype, function(prop, value) {

  25. //如果val不是function 则直接给对象赋值字符串

  26. if (!$.isFunction(value)) {

  27. proxiedPrototype[prop] = value;

  28. return;

  29. }

  30. //如果val是function

  31. proxiedPrototype[prop] = (function() {

  32. //两种调用父类函数的方法

  33. var _super = function() {

  34. //将当期实例调用父类的方法

  35. return base.prototype[prop].apply(this, arguments);

  36. },

  37. _superApply = function(args) {

  38. return base.prototype[prop].apply(this, args);

  39. };

  40. return function() {

  41. var __super = this._super,

  42. __superApply = this._superApply,

  43. returnValue;

  44. //                console.log(prop, value,this,this._super,‘===’)

  45. //                debugger;

  46. //在这里调用父类的函数

  47. this._super = _super;

  48. this._superApply = _superApply;

  49. returnValue = value.apply(this, arguments);

  50. this._super = __super;

  51. this._superApply = __superApply;

  52. //                console.log(this,value,returnValue,prop,‘===’)

  53. return returnValue;

  54. };

  55. })();

  56. });

  57. //    console.info(proxiedPrototype)

  58. //    debugger;

  59. //这里是实例化获取的内容

  60. constructor.prototype = $.widget.extend(basePrototype, {

  61. // TODO: remove support for widgetEventPrefix

  62. // always use the name + a colon as the prefix, e.g., draggable:start

  63. // don’t prefix for widgets that aren’t DOM-based

  64. widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name

  65. }, proxiedPrototype, {

  66. //重新把constructor指向 constructor 变量

  67. constructor: constructor,

  68. namespace: namespace,

  69. widgetName: name,

  70. widgetFullName: fullName

  71. });

  72. // If this widget is being redefined then we need to find all widgets that

  73. // are inheriting from it and redefine all of them so that they inherit from

  74. // the new version of this widget. We’re essentially trying to replace one

  75. // level in the prototype chain.

  76. //这里判定插件是否被使用了。一般来说,都不会被使用的。

  77. //因为插件的开发者都是我们自己,呵呵

  78. if (existingConstructor) {

  79. $.each(existingConstructor._childConstructors, function(i, child) {

  80. var childPrototype = child.prototype;

  81. // redefine the child widget using the same prototype that was

  82. // originally used, but inherit from the new version of the base

  83. $.widget(childPrototype.namespace + “.” + childPrototype.widgetName, constructor, child._proto);

  84. });

  85. // remove the list of existing child constructors from the old constructor

  86. // so the old child constructors can be garbage collected

  87. delete existingConstructor._childConstructors;

  88. } else {

  89. //父类添加当前插件的实例 主要用于作用域链查找 不至于断层

  90. base._childConstructors.push(constructor);

  91. }

  92. //将此方法挂在jQuery对象上

  93. $.widget.bridge(name, constructor);

  94. return constructor;

  95. };

  96. //扩展jq的extend方法,实际上类似$.extend(true,…) 深复制

  97. $.widget.extend = function(target) {

  98. var input = widget_slice.call(arguments, 1),

  99. inputIndex = 0,

  100. inputLength = input.length,

  101. key, value;

  102. for (; inputIndex < inputLength; inputIndex++) {

  103. for (key in input[inputIndex]) {

  104. value = input[inputIndex][key];

  105. if (input[inputIndex].hasOwnProperty(key) && value !== undefined) {

  106. // Clone objects

  107. if ($.isPlainObject(value)) {

  108. target[key] = KaTeX parse error: Undefined control sequence: \[ at position 22: …inObject(target\̲[̲key\]) ? .widget.extend({}, target[key], value) :

  109. // Don’t extend strings, arrays, etc. with objects

  110. $.widget.extend({}, value);

  111. // Copy everything else by reference

  112. } else {

  113. target[key] = value;

  114. }

  115. }

  116. }

  117. }

  118. return target;

  119. };

  120. //bridge 是设计模式的一种,这里将对象转为插件调用

  121. $.widget.bridge = function(name, object) {

  122. var fullName = object.prototype.widgetFullName || name;

  123. //这里就是插件了

  124. //这部分的实现主要做了几个工作,也是制作一个优雅的插件的主要代码

  125. //1、初次实例化时将插件对象缓存在dom上,后续则可直接调用,避免在相同元素下widget的多实例化。简单的说,就是一个单例方法。

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

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

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

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

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

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

  132. returnValue = this;

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

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

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

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

  137. if (isMethodCall) {

  138. this.each(function() {

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

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

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

  142. returnValue = instance;

  143. return false;

  144. }

  145. if (!instance) {

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

  147. }

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

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

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

  151. }

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

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

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

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

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

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

  158. return false;

  159. }

  160. });

  161. } else {

  162. this.each(function() {

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

  164. if (instance) {

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

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

  167. if (instance._init) {

  168. instance._init();

  169. }

  170. } else {

  171. //缓存插件实例

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

  173. }

  174. });

  175. }

  176. return returnValue;

  177. };

  178. };

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

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

  181. $.Widget._childConstructors = [];

  182. $.Widget.prototype = {

  183. widgetName: “widget”,

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

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

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

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

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

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

  190. widgetEventPrefix: “”,

  191. defaultElement: “

    ”,

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

  193. options: {

  194. disabled: false,

  195. // callbacks

  196. create: null

  197. },

  198. _createWidget: function(options, element) {

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

  200. this.element = $(element);

  201. this.uuid = widget_uuid++;

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

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

  204. this.bindings = $();

  205. this.hoverable = $();

  206. this.focusable = $();

  207. if (element !== this) {

  208. //            debugger

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

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

  211. remove: function(event) {

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

  213. this.destroy();

  214. }

  215. }

  216. });

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

  218. // element within the document

  219. element.ownerDocument :

  220. // element is window or document

  221. element.document || element);

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

  223. }

  224. this._create();

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

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

  227. this._init();

  228. },

  229. _getCreateOptions: $.noop,

  230. _getCreateEventData: $.noop,

  231. _create: $.noop,

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

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

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

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

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

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

最后

大厂面试问深度,小厂面试问广度,如果有同学想进大厂深造一定要有一个方向精通的惊艳到面试官,还要平时遇到问题后思考一下问题的本质,找方法解决是一个方面,看到问题本质是另一个方面。还有大家一定要有目标,我在很久之前就想着以后一定要去大厂,然后默默努力,每天看一些大佬们的文章,总是觉得只有再学深入一点才有机会,所以才有恒心一直学下去。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

[外链图片转存中…(img-HG4GNKw8-1712542046396)]

最后

大厂面试问深度,小厂面试问广度,如果有同学想进大厂深造一定要有一个方向精通的惊艳到面试官,还要平时遇到问题后思考一下问题的本质,找方法解决是一个方面,看到问题本质是另一个方面。还有大家一定要有目标,我在很久之前就想着以后一定要去大厂,然后默默努力,每天看一些大佬们的文章,总是觉得只有再学深入一点才有机会,所以才有恒心一直学下去。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-TrsDOHtc-1712542046396)]

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

javascript jQuery

2024-09-21 22:09:33

【若依】表格固定列宽

2024-09-21 22:09:30

Knockout-jQueryUI 使用指南

2024-09-21 22:09:29

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