前言
这个文章我将会简单实现 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 框架。