是否可以在jQuery或vanilla js中具有类似的 ngFor
或 ng-repeat
概念?
想做类似但不以角度的方式做的事情。
<div *ngFor="let inputSearch of searchBoxCount" class="col-sm-12">
<textarea name="{{inputSearch.name}}" id="{{inputSearch.name}}" rows="2" class="search-area-txt" attr.placeholder="{{placeholder}} {{inputSearch.name}}">
</textarea>
</div>
也许与data=""
属性一起使用,无论是有意义的。
如果在javascript
中想要它,则必须在循环中动态创建元素。*Angular中的NGFO和NGREPEAT是包含模板绑定的指令,我们在JavaScript或jQuery中都无法使用。一旦指令遇到角度,请尝试渲染各自的模板,直到循环结束。无论如何,通过JavaScript,我们可以这样做。如果要使用各自的id
将6个 divs
附加到 body
元素,则必须像以下那样做。
var array = ['first', 'second', 'third', .......so on];
for(var i=0; i<array.length; i++){
var elem = document.createElement("div");
elem.setAttribute('id', array[i]);
document.body.appendChild(elem);
}
我们不能像与Ngfor Angular那样做。
const anArray = [
{ tittle: "One", body: "Example 1" },
{ tittle: "Two", body: "Example 2" }
]
function ngForFunctionality() {
let value = '';
anArray.forEach((post) => {
value += `<li>${post.tittle} - ${post.body}</li>`;
});
document.body.innerHTML = value;
};
ngForFunctionality();
<body></body>
在jQuery中,我会做这样的事情:
html:
<div class="searchbox-container col-sm-12">
</div>
javaScript:
var textAreas = $.map(searchBoxCount, function(inputSearch) {
return $("<textarea></textarea")
.attr({
name: inputSearch.name,
id: inputSearch.name
rows: "2",
placeholder: placeholder + " " + inputSearch.name
})
.addClass("search-area-txt");
});
$('.searchbox-container').append(textAreas);
没有简单的方法可以通过Vanilla获得类似的NGFOR。但这可能!
我的实现(您可以使用更多的正则表达式):
html代码:
<ul id="my-list">
<li *for="let contact of contactsList">
<span class="material-icons">{{ contact.icon }}</span>
<span>{{ contact.value }}</span>
</li>
</ul>
JS代码用于实施*for
,例如Angular的*ngFor
:
/**
* (*for) cicle implementation
* @param element the root element from HTML part where you want to apply (*for) cicle. This root element cannot to use (*for). Just children are allowed to use it.
* @returns void
*/
function htmlFor(element) {
return replace(element, element);
}
/**
* Recursive function for map all descendants and replace (*for) cicles with repetitions where items from array will be applied on HTML.
* @param rootElement The root element
* @param el The mapped root and its children
*/
function replace(rootElement, el) {
el.childNodes.forEach((childNode) => {
if (childNode instanceof HTMLElement) {
const child = childNode;
if (child.hasAttribute('*for')) {
const operation = child.getAttribute('*for');
const itemsCommand = /let (.*) of (.*)/.exec(operation);
if (itemsCommand?.length === 3) {
const listName = itemsCommand[2];
const itemName = itemsCommand[1];
if (rootElement[listName] && Array.isArray(rootElement[listName])) {
for (let item of rootElement[listName]) {
const clone = child.cloneNode(true);
clone.removeAttribute('*for');
const htmlParts = clone.innerHTML.split('}}');
htmlParts.forEach((part, i, parts) => {
const position = part.indexOf('{{');
if (position >= 0) {
const pathTovalue = part
.substring(position + 2)
.replace(/ /g, '');
const prefix = part.substring(0, position);
let finalValue = '';
let replaced = false;
if (pathTovalue.indexOf('.') >= 0) {
const byPatternSplitted = pathTovalue.split('.');
if (byPatternSplitted[0] === itemName) {
replaced = true;
for (const subpath of byPatternSplitted) {
finalValue = item[subpath];
}
}
} else {
if (pathTovalue === itemName) {
replaced = true;
finalValue = item;
}
}
parts[i] = prefix + finalValue;
}
return part;
});
clone.innerHTML = htmlParts.join('');
el.append(clone);
}
}
}
el.removeChild(child);
}
replace(rootElement, child);
}
});
}
最后,在您的组件代码中:
document.addEventListener('DOMContentLoaded', () => {
const rootElement = document.getElementById('my-list');
rootElement.contactsList = [
{
icon: 'icon-name',
value: 'item value here',
},
...
];
htmlFor(rootElement);
});
完成。您的香草代码上有一个*for
。
如果有人想试验此*for
与Angular的*ngFor
的性能比较,请与我分享,因为我很好奇。
stackblitz上的代码