编写函数来循环jquery样式库中的元素
Write function to loop over elements in jquery style library
我正在编写一个非常简单的jquery模仿库,以便进行一些简单的DOM操作。
我正在编写允许我更改文本颜色等的方法。当我想更改类元素的颜色时,我必须在每个方法中使用一个循环。理想情况下,我希望有一个函数为我做那个循环,然后我可以在每个方法中使用。不幸的是,我的尝试没有奏效。
请参阅下面的代码:
function _(elem) {
this.classOrId(elem);
}
_.prototype = {
add: function(text) {
if (this.e.length >= 1) {
for (var i = 0; i < this.e.length; i++) {
this.e[i].innerHTML = this.e[i].innerHTML + text;
}
} else {
this.e.innerHTML = this.e.innerHTML + text;
}
return this;
},
replace: function(text) {
if (this.e.length >= 1) {
for (var i = 0; i < this.e.length; i++) {
this.e[i].textContent = text;
}
} else {
this.e.textContent = text;
document.body.appendChild(elem);
}
return this;
}
}
_.prototype.classOrId = function(elem) {
var classOrId = elem.charAt(0);
if (classOrId === "#") {
elem = this.sliceElement(elem);
this.e = document.getElementById(elem);
return this;
} else if (classOrId === ".") {
elem = this.sliceElement(elem)
this.e = document.getElementsByClassName(elem);
return this;
}
};
_.prototype.sliceElement = function(elem) {
var elem = elem.slice(1);
return elem;
};
正如您所看到的,在这个代码中有大量的重复。我试着写以下内容来减少重复,但没有奏效。如有任何建议,我们将不胜感激。
_.prototype.loopOverElements = function(effect) {
for (var i = 0; i < this.e.length; i++) {
return this.e[i][effect];
}
}
在下面的代码中,当将javascript DOM方法(如innerHTML
、style
)传递到函数中时,它不会识别它们。
对于上面的代码,如果我将效果传递到loopOverElements函数中,则表明console.log(this.e[i][effect])
在传递到方法中时是未定义的。
你可能应该在代码评审上发布这篇文章,但我会试一试。首先困扰我的是所有的if (this.e.length >= 1) { } else { }
。使e
成为一个数组,即使只有一个元素,也只有变量的值应该"variate"而不是其类型。
关于classOrId()
,由于document.querySelectorAll(返回所需的数组),它可以减少到一行。因此代码变为:
function _(elem) {
var about = {
Name: "pQuery",
Version: 0.1,
Author: "Paul Fitzgerald"
}
if (elem) {
if (window === this) {
return new _(elem);
}
this.e = document.querySelectorAll(elem); // no need for classOrId() anymore
} else {
return about;
}
}
_.prototype = {
add: function (text) {
// no if else anymore
for (var i = 0; i < this.e.length; i++) {
this.e[i].innerHTML = this.e[i].innerHTML + text;
}
return this;
}
}
关于重复,将函数分成类似的用法,例如,您可以为所有与样式相关的操作编写一个函数:
_.prototype = {
_eachStyle: function (prop, value) {
for (var i = 0; i < this.e.length; i++) {
this.e[i].style[prop] = value;
}
return this;
},
hide: function () {
return _eachStyle('display', 'none');
},
color: function (color) {
return _eachStyle('color', color);
}
}
对于基本属性:
_.prototype = {
_each: function (prop, value, append) {
append = append || false; // by default, replace the value
for (var i = 0; i < this.e.length; i++) {
this.e[i][prop] = append ? element[prop] + value : value;
}
return this;
},
add: function (text) {
return _each('innerHTML', text, true);
},
replace: function (text) {
return _each('textContent', text);
}
}
类似地,对于在所有元素上调用的函数:
_.prototype = {
_eachFn: function (fn, args) {
for (var i = 0; i < this.e.length; i++) {
this.e[i][fn](args);
}
return this;
},
remove: function () {
return _eachFn('remove');
},
}
正如我之前在聊天会话中提到的,您基本上希望对数组中的每个DOM元素应用转换。使用一个定义需要做什么的函数并通过该函数映射每个元素是理想的方法。
_.prototype.loopOverElements = function(effect) {
for (var i = 0; i < this.e.length; i++) {
effect(this.e[i]);
}
};
And I can use it as
var test = new _('.test');
test.loopOverElements(function(elem) {
elem.innerHTML += " Modified";
});
以下是此实现的工作演示
但是您的要求是您想要一个有两个参数的循环方法——propertyName
和value
。与此相关的问题很多,比如假设属性为style.color
。无法使用this.e[i]['style.color']
访问该属性。它不是有效的js。应该是this.e[i]['style']['color']
。所以基本上this.e[i][effect]
在这种情况下不会起作用。类似于lodash的库有一个_.set
方法,您可以在其中指定属性路径,并且将正确设置值您可以在此处查看实现。
我创建了set方法的一个简单实现。
_.prototype.set = function set(obj, path, value) {
var codeString = 'obj';
codeString += path.split('.').reduce(function(prev, curr) {
return prev += '.' + curr;
}, '');
codeString += ' = value';
eval(codeString);
};
Now your loop code looks like
_.prototype.loopOverElements = function(property, value){
for(var i = 0; i < this.e.length; i++){
this.set(this.e[i], property, value);
}
};
And it can be used like
document.addEventListener("DOMContentLoaded", function(event) {
var test = new _('.testClass');
test.loopOverElements('style.color', 'red');
});
以下是此实现的工作演示
使用括号表示法,即[effect]
而不是.effect
:
_.prototype.loopOverElements = function(effect){
for(var i = 0; i < this.e.length; i++){
return this.e[i][effect];
}
}
另请参阅JavaScript属性访问:点符号与括号?。
另一种解决问题的方法是使用回调函数:
_.prototype.applyOnElements = function(callback) {
for(var i = 0; i < this.e.length; i++){
callback(this.e[i]);
}
}
你这样使用它:
this.applyOnElements(function(element) {
element.style.color = myColor;
});
然后,通过用Array.forEach替换循环并在该函数中包含if (this.e is array) then ... else ... endif
来避免更多的代码重复,还有改进的地方。
- 如何提供在javascript中编写对对象的重复访问以设置元素样式的简写
- .clone().appendTo-替换不起作用的元素样式
- 使用JavaScript更改带有窗口高度的元素样式
- Javascript重置元素样式
- 取消:活动元素样式
- 什么是最好的表单元素样式库/插件(jQuery)
- 更改页面滚动上的元素样式
- 动态更新数百万个 DOM 元素样式的最快方法
- 覆盖元素.样式表.css文本
- 在禁用 JavaScript 时添加元素样式
- 确定所有屏幕尺寸的元素样式
- 设置 HEAD 元素样式以将其用作数据存储
- 如何使用带有 % 符号值的 ERB 和 JQuery 修改元素样式属性
- asp.net 高度属性的元素样式问题
- 如何覆盖元素样式,使其无法更改
- 如何使用ng样式单击时更新元素样式
- 使用 jQuery 更新 HTML 元素样式参数值
- 将鼠标悬停在另一个元素上时更改元素样式
- 如何将加载到<对象>中的元素样式设置为数据
- 在jQuery UI对话框中设置元素样式