<ul>
<li id="item1">选项1</li>
<li id="item2">选项2</li>
<li id="item3">选项3</li>
<li id="item4">选项4</li>
<li id="item5">选项5</li>
</ul>
let allChildren = item3.parentNode.children
let array = {
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if (allChildren[i] !== item3) {
array[array.length] = allChildren[i] //给伪数组添加子元素
array.length += 1
}
}
console.log(array) // 获得items3的兄弟元素的伪数组
复制代码
function getSiblings(node) { // 这个这就是API
let allChildren = node.parentNode.children
let array = {
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if (allChildren[i] !== node) {
array[array.length] = allChildren[i]
array.length += 1
}
}
return array
}
console.log(getSiblings(item3)) // 获得items3的兄弟元素
复制代码
let classes = {'a':true,'b':false,'c':true}
for (let key in classes) { // 遍历这个哈希表
let value = classes[key]
if (value) { // value值为真则添加,假则删除
node.classList.add(key)
} else {
node.classList.remove(key)
}
}
复制代码
function addClass(node, classes) {
for (let key in classes) {
let value = classes[key]
if (value) {
node.classList.add(key)
} else {
node.classList.remove(key)
}
}
}
addClass(item3, {a:true,b:false,c:true})
复制代码
只要有类似的代码,就有优化的空间 。css
function addClass(node, classes) {
for (let key in classes) {
let value = classes[key]
let methodName = value ? 'add':'remove' //若是value值为真,methodName为add,假则为remove
node.classList.['methodName'](key)
}
}
ffdom.addClass(item3, {a:true,b:false,c:true})
复制代码
function addClass(node, classes) {
classes.forEach((value)=> node.classList.add(value))
}
addClass(item3, ['a','b','c'])
复制代码
利用命名空间的设计模式,关联两个独立的函数,这样还能够防止代码覆盖的问题。node
window.xxxxdom = {} /*yui使用的就是命名空间的模式*/
xxxxdom.getSiblings = function(node) {
let allChildren = node.parentNode.children
let array = { // 伪数组
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if (allChildren[i] !== node) {
array[array.length] = allChildren[i] // 伪数组没有push()方法,利用length来添加元素
array.length += 1
}
}
return array
}
xxxxdom.addClass = function(node, classes) {
classes.forEach((value)=> node.classList.add(value))
}
xxxxdom .getSiblings(items)
xxxxdom .addClass(item3, ['a','b','c'])
复制代码
去掉xxxxdom,改写成如下模式,咱们有两种方法。设计模式
item3.getSiblings()
item3.addClass(['a','b','c'])
复制代码
这样作的缺点:会产生代码覆盖的问题。api
Node.prototype.getSiblings = function() {
let allChildren = this.parentNode.children // this 隐式指向 Node
let array = {
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if (allChildren[i] !== this) {
array[array.length] = allChildren[i]
array.length += 1
}
}
return array
}
Node.prototype.addClass = function(classes) {
classes.forEach((value)=> this.classList.add(value))
}
console.log(item3.getSiblings()) // 获得一个item3的兄弟元素的伪数组
item3.addClass(['a','b','c'])
复制代码
用call就是显示指定this,this是第一个参数 不用是显示隐式指定this数组
item3.getSiblings.call(item3)
item3.addClass.call(item3,['a','b','c'])
复制代码
本身创造一个构造函数,就是能够解决代码覆盖的问题。bash
创造一个Node2的构造函数,它接收一个node参数,返回一个哈希表,它的key就是咱们的想要的api。使用时,传入node参数,就可使用了。dom
window.Node2 = function(node) {
return {
getSiblings: function() {
let allChildren = node.parentNode.children // node 是传进来的节点参数
let array = {
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if (allChildren[i] !== node) {
array[array.length] = allChildren[i]
array.length += 1
}
}
return array
}
addClass: function(classes) {
classes.forEach((value)=> node.classList.add(value))
}
}
}
var node2 = Node2(item3)
node2.getSiblings()
node2.addClass(['a','b','c']))
复制代码
将Node2改成jQuery,jQuery接收一个旧的dom,返回一个新的对象,这个新的对象有新的api,内部实现仍是调用旧的api,只不过好用了一些。jQuery实质上是一个构造函数,接收一个参数,这个参数可使节点或选择器,而后返回一个方法对象去操做节点。函数
window.jQuery = function(node) {
return {
getSiblings: function() {
let allChildren = node.parentNode.children
let array = {
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if (allChildren[i] !== node) {
array[array.length] = allChildren[i]
array.length += 1
}
}
return array
}
addClass: function(classes) {
classes.forEach((value)=> node.classList.add(value))
}
}
}
var node2 = jQuery(item3)
node2.getSiblings()
node2.addClass(['a','b','c']))
复制代码
传参node能够不仅是node还能够是选择器selector,只须要进行类型检测便可。优化
window.jQuery = function(nodeOrSelector) {
let node
if(typeof nodeOrSelector === 'string') { // 类型检测
node = document.querySelector(nodeOrSelector)
} else {
node = nodeOrSelector
}
return {
getSiblings: function() {
let allChildren = node.parentNode.children
let array = {
length: 0
}
for (let i = 0; i < allChildren.length; i++) {
if (allChildren[i] !== node) {
array[array.length] = allChildren[i]
array.length += 1
}
}
return array
}
addClass: function(classes) {
classes.forEach((value)=> node.classList.add(value))
}
}
}
var node2 = jQuery('#item3') // 能够经过选择器来找到node了
node2.getSiblings()
node2.addClass(['red','b','c']))
相关css
css
.red {color: red;}
复制代码
window.jQuery = function(nodeOrSelector) {
let nodes
if(typeof nodeOrSelector === 'string') {
let temp = document.querySelectorAll(nodeOrSelector) // 伪数组
for(let i=0;i<temp.length;i++) {
node[i] = temp[i]
}
nodes.length = temp.length // 利用temp去掉多余的原型,直接指向object.prototype
} else if(nodeOrSelector instanceof Node) {
nodes = {0:nodeOrSelector, length:1}
}
nodes.getSiblings = function() {}
nodes.addClass = function() {}
return nodes
}
var node2 = jQuery('ul > li')
console.log(node2)
复制代码
window.jQuery = function(nodeOrSelector) {
let nodes
if(typeof nodeOrSelector === 'string') {
let temp = document.querySelectorAll(nodeOrSelector) // 伪数组
for(let i=0;i<temp.length;i++) {
node[i] = temp[i]
}
nodes.length = temp.length object.prototype
} else if(nodeOrSelector instanceof Node) {
nodes = {0:nodeOrSelector, length:1}
}
nodes.addClass = function() { //添加addClass()方法
classes.forEach((value)=> {
for(let i = 0; i < nodes.length; i++) {
node[i].classList.add(value)
}
}
}
return nodes
}
var node2 = jQuery('ul > li')
node2.addClass(['blue'])
复制代码
添加getText()和setText()动画
window.jQuery = function(nodeOrSelector) {
let nodes
if(typeof nodeOrSelector === 'string') {
let temp = document.querySelectorAll(nodeOrSelector) // 伪数组
for(let i=0;i<temp.length;i++) {
node[i] = temp[i]
}
nodes.length = temp.length // 利用temp去掉多余的原型,直接指向object.prototype
} else if(nodeOrSelector instanceof Node) {
nodes = {0:nodeOrSelector, length:1}
}
nodes.addClass = function() {
classes.forEach((value)=> {
for(let i = 0; i < nodes.length; i++) {
node[i].classList.add(value)
}
}
}
nodes.getText = function() { // 添加getText()
var texts = []
for(let i = 0; i < nodes.length; i++) {
text.push(nodes[i].textContent)
}
return texts
}
nodes.setText = function() { // 添加setText()
for(let i = 0; i < nodes.length: i++) {
nodes[i].textContent = texgt
}
}
return nodes
}
var node2 = jQuery('ul > li')
node2.addClass(['blue'])
node2.getText()
node2.setText('hi')
复制代码
window.jQuery = function(nodeOrSelector) {
let nodes = {}
if(typeof nodeOrSelector === 'string') {
let temp = document.querySelectorAll(nodeOrSelector) // 伪数组
for(let i=0;i<temp.length;i++) {
node[i] = temp[i]
}
nodes.length = temp.length // 利用temp去掉多余的原型,直接指向object.prototype
} else if(nodeOrSelector instanceof Node) {
nodes = {0:nodeOrSelector, length:1}
}
nodes.addClass = function() {
classes.forEach((value)=> {
for(let i = 0; i < nodes.length; i++) {
node[i].classList.add(value)
}
}
}
node2.text = function(text) { // 将getText()和setText()合并
if(text === undefined) {
var texts = []
for(let i = 0; i < nodes.length; i++) {
text.push(nodes[i].textContent)
}
return texts
}
} else {
for(let i = 0; i < nodes.length: i++) {
nodes[i].textContent = text
}
}
return nodes
}
var node2 = jQuery('ul > li')
node2.addClass(['blue'])
console.log(node2.text())
node2.text('hi')
复制代码
jQuery的实现思路:建立一个jQuery构造函数,接收一个node或selector,并把它封装成一个伪数组,而后在这个伪数组上增长几个api,返回这个伪数组。
window.jQuery = function(nodeOrSelector) {
let nodes = {
0: nodeOrSelector,
length: 1
}
nodes.addClass = function(classes) {}
nodes.text = function(text) {}
return nodes
}
var node2 = jQuery('ul > li')
{0: li, 1: li, length: 5, addClass: f, text: f}
node2.addClass(['blue'])
node2.text()
node2[0].classList.add('blue')
复制代码
jQuery的优势:
饥人谷jQeury相关课程https://xiedaimala.com/