前言 这个文章我将会简单实现 jQuery 的 Dom 操作方法。其中并不会做兼容性处理只是技术实现。而且是直接 操作DOM对象而非 jQuery 对象。而且我也没有实现事件委托 delegate
事件绑定方法 on
,等等。
to-do-list
全局变量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 (function (window ) { function _query (selector ) { this .selector = selector; this .node = document .querySelectorAll(selector); this .nodes = Array .prototype.slice.call(this .node); } _query.prototype = { constructor : _query //这里写dom方法 } function init(selector) { return new _query(selector); } window ._ = init; })(window );
html方法 1 2 3 4 5 6 7 8 html: function (htmlString ) { if (!!htmlString) { this .nodes.forEach(function (e ) { e.innerHTML = htmlString.toString(); }); } return this .nodes[0 ].innerHTML; }
text方法 1 2 3 4 5 6 7 8 9 text: function (txtString ) { if (!!txtString) { this .nodes.forEach(function (e ) { e.textContent = txtString.toString(); }); } else { return this .nodes[0 ].textContent; } }
操作class方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 hasClass: function (c ) { return this .nodes.some(function (e ) { if (e.className.split(" " ).indexOf(c) >= 0 ) { return true ; } }); }, addClass: function (c ) { this .nodes.forEach(function (e ) { e.className = e.className + " " + c; }); return this ; }, removeClass: function (c ) { this .nodes.forEach(function (e ) { var classList = e.className.split(" " ); e.className = classList.filter(function (item ) { if (item != c) { return true ; } }).join(" " ); }); return this ; }
遍历 包括 parent
parents
prev
prevAll
next
nextAll
children
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 parent: function ( ) { var parent = this .nodes[0 ].parentNode; this .nodes = [parent]; return this ; }, validElement: function (query, ele ) { var first = query.charAt(0 ); var name = query.slice(1 ); switch (first) { case "#" : if (ele.id == name) { return true ; } break ; case "." : if (ele.className.split(" " ).indexOf(name) > -1 ) { return true ; } default : if (ele.tagName.toLowerCase() === query.toLowerCase()) { return true ; } else { return false ; } } }, parents: function (select ) { var node = this .nodes[0 ], list = [], i = 1 ; while (node.parentNode.tagName.toLowerCase() !== "html" ) { if (i !== 1 ) { list.push(node); } i++; node = node.parentNode; }; if (!!select) { var _this = this ; this .nodes = list.filter(function (e ) { return _this.validElement(select, e); }); } else { this .nodes = list; } return this ; }, children: function (select ) { var node = this .nodes[0 ]; var list = Array .prototype.slice.call(node.children); if (!!select) { var _this = this ; this .nodes = list.filter(function (e ) { return _this.validElement(select, e); }); } else { this .nodes = list } return this ; }, next: function ( ) { this .nodes = [this .nodes[0 ].nextElementSibling]; return this ; }, nextAll: function (select ) { var node = this .nodes[0 ], list = [], next = node.nextElementSibling; while (!!next) { list.push(next); next = next.nextElementSibling; } if (!!select) { var _this = this ; this .nodes = list.filter(function (e ) { return _this.validElement(select, e); }); } else { this .nodes = list } return this ; }, prev: function ( ) { this .nodes = [this .nodes[0 ].previousElementSibling]; return this ; }, prevAll: function (select ) { var node = this .nodes[0 ], list = [], prev = node.previousElementSibling; while (!!prev) { list.push(prev); prev = prev.previousElementSibling; } if (!!select) { var _this = this ; this .nodes = list.filter(function (e ) { return _this.validElement(select, e); }); } else { this .nodes = list } return this ; }
操作css方法 css 方法传入的参数分别士两个参数,或者一个对象,传入对象时候意味着可以一次修改多个style样式, 若不存在第二个参数时候则使用 getComputedStyle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 css: function (a, b ) { if (typeof a == "string" && !b) { return window .getComputedStyle(this .nodes[0 ], null )[a]; } else if (typeof a == "object" ) { this .nodes.forEach(function (e ) { for (var k in a) { e.style[k] = a[k]; } }); return this ; } else if (typeof a == "string" && typeof b == "string" ) { this .nodes.forEach(function (e ) { e.style[a] = b; }); return this ; } }
源码及使用 下载
1 2 3 4 5 6 7 <script src ="_query.js" > </script > <script > _("p" ).text("hello gary" ); </script >
小结 一直想动手实现 jQuery 但是迟迟没有动手,事实证明有时候还是不要眼高手低为好,我只是写了几个操作DOM和 CSS 样式的方法,并且也没有考虑兼容性的问题就已经写了很多行,可见jquery还是很值得前端学习的,无论是 它自带的基础函数还是DOM\CSS的兼容性处理都非常好,而且代码简洁多了。之后我会尝试使用 getter setter
简单模仿 vue 实现 MVVM 框架。