Javascript 创建子元素并附加到父节点的通用函数
我想创建并使用通用javascript函数,通过该函数可以轻松、快速、灵活地为父节点创建新的子节点 看看我的代码:Javascript 创建子元素并附加到父节点的通用函数,javascript,html,function,dom,Javascript,Html,Function,Dom,我想创建并使用通用javascript函数,通过该函数可以轻松、快速、灵活地为父节点创建新的子节点 看看我的代码: <!DOCTYPE html> <html> <body> <style> div { border: 2px solid #eeeeee; background-color: #dff0d8; } ol { background-color: #dff0d8; } li { background-c
<!DOCTYPE html>
<html>
<body>
<style>
div {
border: 2px solid #eeeeee;
background-color: #dff0d8;
}
ol {
background-color: #dff0d8;
}
li {
background-color: #eff0c8;
}
</style>
<script>
function addNewElement(newElementType,parentId) {
var newElement = document.createElement(newElementType);
newElement.innerHTML = 'new element';
parentId.appendChild(newElement);
// actually I want to use just this simple code, what makes this function universal, but it doesn't work..
// while next commented lines work as it should
/**
if (parentId == "someThing"){
someThing.appendChild(newElement);
}
if (parentId == "list"){
list.appendChild(newElement);
}
**/
}
</script>
<p>In next example we can add new child element to this list:</p>
<ol id="list">
<li>1</li>
<li>2</li>
<li>3</li>
</ol>
<button onclick="addNewElement('li','list')">Add new li-element to this list</button>
<p>In next example we can add new child element to this div:</p>
<div id="someThing">Something here</div>
<button onclick="addNewElement('div','someThing')">Add new div-element to this div</button>
</body>
</html>
我是JS的新手,所以我不完全理解为什么不能使用它parentId.appendChild(newElement)
来获得相同的结果
我想即使没有任何jQuery或其他库,也应该很容易让它工作
因此,我问您如何实现这一点?首先,您不应该多次使用同一个元素ID 根据: id属性为HTML元素指定一个唯一的id(该值在HTML文档中必须是唯一的) 因此,我更改了您的HTML,即从按钮中删除ID,并将所需ID传递到
addNewElement
函数:
<p>In next example we can add new child element to this list:</p>
<ol id="list">
<li>1</li>
<li>2</li>
<li>3</li>
</ol>
<button onclick="addNewElement('li', 'list')">Add new li-element to this list</button>
<p>In next example we can add new child element to this div:</p>
<div id="someThing">Something here</div>
<button onclick="addNewElement('div', 'someThing')">Add new div-element to this div</button>
function addNewElement(elementType, parentId) {
let parentElement = document.getElementById(parentId);
let newElement = document.createElement(elementType);
newElement.innerHTML = 'new element';
parentElement.appendChild(newElement);
}
它是有效的
请查看以了解更多详细信息。好吧,我找到了修复它的简单方法,但我正在寻找更基本的方法:
document.getElementById(parentId).appendChild(newElement);
编辑:
另一种方法是:
<!DOCTYPE html>
<html>
<body>
<style>
div {
border: 2px solid #eeeeee;
background-color: #dff0d8;
}
ol {
background-color: #dff0d8;
}
li {
background-color: #eff0c8;
}
</style>
<script>
function addNewElement(newElementType,parentId,parentElementType) {
//document.getElementById(clickedId).appendChild(newElement);
var el = parentElementType + "[id=" + parentId + "]";
el = document.querySelector(el);
var newElement = document.createElement(newElementType);
newElement.innerHTML = 'new element';
el.appendChild(newElement);
}
</script>
<p>In next example we can add new child element to this list:</p>
<ol id="list">
<li>1</li>
<li>2</li>
<li>3</li>
</ol>
<button onclick="addNewElement('li','list','ol')">Add new li-element to this list</button>
<p>In next example we can add new child element to this div:</p>
<div id="someThing">Something here</div>
<button onclick="addNewElement('div','someThing','div')">Add new div-element to this div</button>
</body>
</html>
div{
边框:2个实心#eeeeee;
背景色:#dff0d8;
}
ol{
背景色:#dff0d8;
}
李{
背景色:#eff0c8;
}
函数addNewElement(newElementType、parentId、parentElementType){
//document.getElementById(单击EDID).appendChild(新元素);
var el=parentElementType+“[id=“+parentId+”]”;
el=文档查询选择器(el);
var newElement=document.createElement(newElementType);
newElement.innerHTML='newElement';
el.appendChild(新元素);
}
在下一个示例中,我们可以将新的子元素添加到此列表中:
一,
二,
三,
将新的li元素添加到此列表中
在下一个示例中,我们可以向该div添加新的子元素:
这里有东西
将新div元素添加到此div
但现在我们需要在这个新示例中传递addNewElement函数中的父节点类型。或者我们也可以为ul和div元素定义类,并使用它们代替id。
这是一种更先进的方法,但在某些情况下可能更有用。这是关于和的纪录片
如果您想获得更多信息,也请阅读此文。我知道您已经有了一个适合您的答案,但我只想添加一个,它显示了一种更灵活的方法,即使用配置对象而不是只传递标记名。为了使它更灵活,您可以传递对父对象的引用,而不是id。此外,如果您想在将新创建的元素添加到DOM后对其进行处理,它会返回对该元素的引用
'use strict';
var addNewElement = function (configItems, elParent) {
var newElements = [];
if (!Array.isArray(configItems)) {
// if configItems is not an array, and therefore a
// single config object or string, turn it into
// a single element array
configItems = [configItems];
}
// If elParent is a string assume it is
// the id of an element in the page and select it
if (typeof elParent === 'string') {
elParent = document.getElementById(elParent);
}
configItems.forEach(function (config) {
var option,
elChild;
// if a string is passed in, assume it is
// the tagName and create a default config object
if (typeof config === 'string') {
config = {tag: config};
}
elChild = document.createElement(config.tag);
for (option in config) {
if (config.hasOwnProperty(option)) {
switch (option) {
case 'tag':
// do nothing, already used tag to create new element
break;
case 'html':
// just a shortcut so we don't have to use
// innerHTML in our config object
elChild.innerHTML = config.html;
break;
case 'text':
// another shortcut
elChild.textContent = config.text;
break;
case 'class':
// if we are passed an array convert it to a space delimited string
elChild.className = Array.isArray(config.class) ?
config.class.join(' ') : config.class;
break;
default:
// if we haven't already handled it, assume it is
// an attribute to add to the element
elChild.setAttribute(option, config[option]);
}
}
}
// default text if none was specified
if (elChild.innerHTML === '') {
elChild.innerHTML = 'new element';
}
newElements.push(elChild);
elParent.appendChild(elChild);
});
// return a reference to the new element(s)
// in case you want to do something else with it
// after it was inserted into the document
// returns a single item or an array depending on how many
// items you passed it in configItems
return newElements.length === 1 ? newElements[0] : newElements;
};
用法如下所示:
// just add a new element with the default text by id
addNewElement('li', 'list');
var list = document.getElementById('list');
// a little fancier, this time using an element reference
addNewElement({
tag: 'li',
html: 'Custom List Item!',
class: 'fancy'
}, list);
addNewElement({
tag: 'input',
placeholder: 'Type here',
value: 'Delete me'
}, document.body); // attach to the body
// do something with the element
// after we create it
var houdini = addNewElement({
tag: 'li',
text: 'Now you see me.',
class: ['houdini', 'show'],
}, list);
setTimeout(function () {
houdini.textContent = "Now you don't";
houdini.classList.remove('show');
}, 2000);
var checkElements = addNewElement([
{
tag: 'input',
id: 'check',
type: 'checkbox',
checked: 'checked',
},
{
tag: 'label',
for: 'check',
html: 'Uncheck me!'
}
], document.body);
在行动中展示它
使用
之所以出现
'class'
这种情况,是因为在ES3中不能使用保留字作为带有点符号的属性名,因此在设计DOM API时,它们使用className
来表示类属性。从ES5开始我们就可以了。这允许我们添加一个'class'
快捷方式属性。虽然您已经接受了答案,但我觉得提供一种更具扩展性的方法可能是值得的,它允许您使用不引人注目的JavaScript(而不是依赖于诸如onclick
之类的在线事件处理程序)来简化维护
它的可扩展性和可定制性也更高:
// a simple function to help derive the correct element
// from the supplied argument, 'needle':
function derive(needle) {
// if the needle has a nodeType and if that nodeType is
// exactly equal to 1:
if (needle.nodeType && needle.nodeType === 1) {
// the needle is then an element-node, and here
// we convert that node into an Array of one:
needle = [needle];
// otherwise, if the needle is a string, and
// document.getElementById() finds an element
// with that id:
} else if ('string' === typeof needle && document.getElementById(needle)) {
// we find that element-node again, using the string
// and again convert it to an Array of one:
needle = [document.getElementById(needle)];
// otherwise, if the needle is - again - a string, and
// document.querySelectorAll() can find a collection
// (of one or more) elements matching the selector that
// the needle is implied to be then we retrieve those
// elements and, using Array.from(), we convert the
// collection into an Array:
} else if ('string' === typeof needle && document.querySelectorAll(needle)) {
needle = Array.from(document.querySelectorAll(needle));
}
// here we return the results to the calling context:
return needle;
}
function addNewElement(opts) {
// the default settings for the function:
// append: Boolean, true: the content will be
// inserted after the found sibling-
// node; false: the content will be
// inserted before the found sibling-
// node.
// classes: String, a string of white-space
// separated class-names to add to
// the new contents,
// Array, an array of class-names to
// add to the new contents.
// content: String, a string of HTML you wish
// to appear in the newly-added content.
// count: Number, the number of elements you
// wish to insert at once.
// create: String, the element-type to create
// null, if you want the function to
// 'decide' for itself.
// parent: Node, the element to which you want
// to add new elements,
// String, the id of the element to
// which you want to add new elements,
// or a CSS selector by which you want
// find the element(s) in the document
// to add new elements to.
// sibling: Node, the node beside which the new
// element(s) should be added.
// Null, the function will try to determine
// the desired element beside which the
// content should be added, based on
// the 'append' setting (above).
var settings = {
'append': true,
'classes' : null,
'content': 'Newly-added element.',
'count': 1,
'create': null,
'parent': document.body,
'sibling': null
},
// uninitialised variables for use later, primarily
// to declare/instantiate variables in one place:
parents,
childType,
created,
sibling,
clone,
classes,
count,
// a documentFragment to enable the addition of multiple
// elements at the same time without triggering (quite so)
// many redraws of the document/page:
fragment = document.createDocumentFragment();
// using Object.keys to iterate over the opts Object, if
// one is supplied or an empty object to avoid errors,
// using the Array.prototype.forEach() method:
Object.keys(opts || {}).forEach(function(key) {
// here we update/overwrite the keys of the
// settings object to the values held in those
// properties of the opts Object:
settings[key] = opts[key];
});
// we call the derive function to retrieve an array
// of element(s):
parents = derive(settings.parent);
// checking, and then storing, the value of
// settings.append; it it's equal to true the
// assessment returns true, if it's equal to
// false the assessment returns false (this
// is a naive check, because it requires that
// a Boolean is stored in that property):
appendCheck = settings.append === true;
// ensuring that the settings.count number
// is a number by parsing the potential
// String, other-based number, into base-10:
count = parseInt(settings.count, 10);
// iterating over each of the parents:
parents.forEach(function(pater) {
// 'pater' the first argument is a reference
// to the current array-element of the array
// over which we're iterating.
// retrieving the element-type to be created,
// if a value was supplied in settings.create
// then we use that (we don't check it's a
// valid element, or that it can be validly
// contained in the nominated parent), otherwise
// if the current element node has children
// then we retrieve the localName of its
// lastElementChild, if it has no children
// the ternary returns null and we move to
// the string of 'div':
childType = settings.create || (pater.children.length > 0 ? pater.lastElementChild.localName : null) || 'div';
// here we create the element:
created = document.createElement(childType);
// if the earlier assessment of settings.append
// resulted in true:
if (appendCheck === true) {
// we find the sibling beside which to insert the
// new content; if a node was supplied we use that,
// otherwise we use the lastElementChild or lastChild:
sibling = settings.sibling || pater.lastElementChild || pater.lastChild;
} else if (appendCheck === false) {
// otherwise, we use either the supplied value or
// we use the firstElementChild or firstChild:
sibling = settings.sibling || pater.firstElementChild || pater.firstChild
}
// assign the supplied - or default - content to the
// created element:
created.innerHTML = settings.content;
// if any class-names have been supplied:
if (settings.classes) {
// we first check whether the settings.classes
// variable is an Array (using Array.isArray),
// which returns a Boolean (true or false); if
// it returns true we simply use the Array otherwise
// we assume it's a String and split that String
// on its white-space characters (/\s+/):
classes = Array.isArray(settings.classes) ? settings.classes : settings.classes.split(/\s+/);
// iterating over the array of class-names:
classes.forEach(function(cN) {
// the first argument (cN) is a reference
// to the current array-element of the
// Array over which we're iterating.
// here we use the Element.classList API to
// add each of the class-names:
created.classList.add(cN);
});
}
// a simple for loop to add the desired
// number of new elements (as supplied in
// the settings.count, or opts.count
// setting):
for (var i = 0; i < count; i++) {
// clone the created-element (and its
// child elements):
clone = created.cloneNode(true);
// append the cloned node to the
// documentFragment we created
// earlier:
fragment.appendChild(clone);
}
// here we use parentNode.insertBefore() to insert
// the new contents (held in fragment) either the
// sibling.nextSibling (if appendCheck is true) or
// before the sibling (if appendCheck is false):
pater.insertBefore(fragment, (appendCheck ? sibling.nextSibling : sibling));
});
}
// retrieving the <button> elements on the page, and converting
// to an Array, using Array.from():
var buttons = Array.from(document.querySelectorAll('button'));
// iterating over those <button> elements in the Array:
buttons.forEach(function(button) {
// using the anonymous function of the addEventListener()
// to call the addNewElement function, in which
// we set the opts.parent setting to the
// previousElementSibling of the button
// firing the event:
button.addEventListener('click', function() {
addNewElement({
'parent': button.previousElementSibling
});
});
});
在下一个示例中,我们可以将新的子元素添加到此列表中:
一,
二,
三,
将新的li元素添加到此列表中
在下一个示例中,我们可以向该div添加新的子元素:
这里有东西
在这个div中添加新的div元素
哈哈,你更快了:)谢谢你的回答!起初,我调用addNewElement函数时没有“this.id”参数,我只是在尝试它,当我第一次发布问题时,我忘了删除它。我同意,在这种情况下不应该使用相同的元素ID来避免问题。那么,你认为除了“getElementById”没有其他方法了吗?我在寻找更简单的东西,所以我忘了这个…)@WebSurfer是的:)我相信在这种情况下没有其他方法,因为你应该明确知道一个元素应该附加一个孩子。我发现了!至少还有一种方法可以做到这一点,尽管这是一种更高级的方法——document.querySelector或document.queryselectoral。不过,在某些情况下,它们可能更有用^_^@是的,我知道这些函数。无论如何,谢谢!但是在您的案例中使用它们需要对HTML进行一些额外的更改。而且,它们的性能不如getElementById
。。由于它们相对较新,人们说它们可能是有车的,而且资源更密集。是的,我现在会坚持使用getElementById,或者在某些情况下会使用getElementsByClass,但是如果适合的话,我也会尝试在其他复杂的情况下使用这个新特性。谢谢你的帮助!我不明白这个问题。已经有了一个花孩子的函数,您还需要有一个元素来附加它。再简单不过了。如何获取父元素实际上并不相关,可以封装在函数中。我不明白你想达到什么目的。@DaveNewton也许是某个编辑了我的文章并替换了几个字的版主让你更难理解,请检查其他编辑。我希望您能理解,我提供的代码除了我想要改进的注释部分外,其他部分都不起作用,并且没有很多“if-else”检查,它更通用。。我希望通过ButtonOnClick和addNewElement函数读取传递的参数就可以访问它。主要原因是简化添加新孩子的过程,并获得更智能、更短的代码。现在可以了吗?您所需要添加的只是通过ID获取元素(或者任何您想要用来获取实际元素的机制)。我不明白怎么会更简单
// a simple function to help derive the correct element
// from the supplied argument, 'needle':
function derive(needle) {
// if the needle has a nodeType and if that nodeType is
// exactly equal to 1:
if (needle.nodeType && needle.nodeType === 1) {
// the needle is then an element-node, and here
// we convert that node into an Array of one:
needle = [needle];
// otherwise, if the needle is a string, and
// document.getElementById() finds an element
// with that id:
} else if ('string' === typeof needle && document.getElementById(needle)) {
// we find that element-node again, using the string
// and again convert it to an Array of one:
needle = [document.getElementById(needle)];
// otherwise, if the needle is - again - a string, and
// document.querySelectorAll() can find a collection
// (of one or more) elements matching the selector that
// the needle is implied to be then we retrieve those
// elements and, using Array.from(), we convert the
// collection into an Array:
} else if ('string' === typeof needle && document.querySelectorAll(needle)) {
needle = Array.from(document.querySelectorAll(needle));
}
// here we return the results to the calling context:
return needle;
}
function addNewElement(opts) {
// the default settings for the function:
// append: Boolean, true: the content will be
// inserted after the found sibling-
// node; false: the content will be
// inserted before the found sibling-
// node.
// classes: String, a string of white-space
// separated class-names to add to
// the new contents,
// Array, an array of class-names to
// add to the new contents.
// content: String, a string of HTML you wish
// to appear in the newly-added content.
// count: Number, the number of elements you
// wish to insert at once.
// create: String, the element-type to create
// null, if you want the function to
// 'decide' for itself.
// parent: Node, the element to which you want
// to add new elements,
// String, the id of the element to
// which you want to add new elements,
// or a CSS selector by which you want
// find the element(s) in the document
// to add new elements to.
// sibling: Node, the node beside which the new
// element(s) should be added.
// Null, the function will try to determine
// the desired element beside which the
// content should be added, based on
// the 'append' setting (above).
var settings = {
'append': true,
'classes' : null,
'content': 'Newly-added element.',
'count': 1,
'create': null,
'parent': document.body,
'sibling': null
},
// uninitialised variables for use later, primarily
// to declare/instantiate variables in one place:
parents,
childType,
created,
sibling,
clone,
classes,
count,
// a documentFragment to enable the addition of multiple
// elements at the same time without triggering (quite so)
// many redraws of the document/page:
fragment = document.createDocumentFragment();
// using Object.keys to iterate over the opts Object, if
// one is supplied or an empty object to avoid errors,
// using the Array.prototype.forEach() method:
Object.keys(opts || {}).forEach(function(key) {
// here we update/overwrite the keys of the
// settings object to the values held in those
// properties of the opts Object:
settings[key] = opts[key];
});
// we call the derive function to retrieve an array
// of element(s):
parents = derive(settings.parent);
// checking, and then storing, the value of
// settings.append; it it's equal to true the
// assessment returns true, if it's equal to
// false the assessment returns false (this
// is a naive check, because it requires that
// a Boolean is stored in that property):
appendCheck = settings.append === true;
// ensuring that the settings.count number
// is a number by parsing the potential
// String, other-based number, into base-10:
count = parseInt(settings.count, 10);
// iterating over each of the parents:
parents.forEach(function(pater) {
// 'pater' the first argument is a reference
// to the current array-element of the array
// over which we're iterating.
// retrieving the element-type to be created,
// if a value was supplied in settings.create
// then we use that (we don't check it's a
// valid element, or that it can be validly
// contained in the nominated parent), otherwise
// if the current element node has children
// then we retrieve the localName of its
// lastElementChild, if it has no children
// the ternary returns null and we move to
// the string of 'div':
childType = settings.create || (pater.children.length > 0 ? pater.lastElementChild.localName : null) || 'div';
// here we create the element:
created = document.createElement(childType);
// if the earlier assessment of settings.append
// resulted in true:
if (appendCheck === true) {
// we find the sibling beside which to insert the
// new content; if a node was supplied we use that,
// otherwise we use the lastElementChild or lastChild:
sibling = settings.sibling || pater.lastElementChild || pater.lastChild;
} else if (appendCheck === false) {
// otherwise, we use either the supplied value or
// we use the firstElementChild or firstChild:
sibling = settings.sibling || pater.firstElementChild || pater.firstChild
}
// assign the supplied - or default - content to the
// created element:
created.innerHTML = settings.content;
// if any class-names have been supplied:
if (settings.classes) {
// we first check whether the settings.classes
// variable is an Array (using Array.isArray),
// which returns a Boolean (true or false); if
// it returns true we simply use the Array otherwise
// we assume it's a String and split that String
// on its white-space characters (/\s+/):
classes = Array.isArray(settings.classes) ? settings.classes : settings.classes.split(/\s+/);
// iterating over the array of class-names:
classes.forEach(function(cN) {
// the first argument (cN) is a reference
// to the current array-element of the
// Array over which we're iterating.
// here we use the Element.classList API to
// add each of the class-names:
created.classList.add(cN);
});
}
// a simple for loop to add the desired
// number of new elements (as supplied in
// the settings.count, or opts.count
// setting):
for (var i = 0; i < count; i++) {
// clone the created-element (and its
// child elements):
clone = created.cloneNode(true);
// append the cloned node to the
// documentFragment we created
// earlier:
fragment.appendChild(clone);
}
// here we use parentNode.insertBefore() to insert
// the new contents (held in fragment) either the
// sibling.nextSibling (if appendCheck is true) or
// before the sibling (if appendCheck is false):
pater.insertBefore(fragment, (appendCheck ? sibling.nextSibling : sibling));
});
}
// retrieving the <button> elements on the page, and converting
// to an Array, using Array.from():
var buttons = Array.from(document.querySelectorAll('button'));
// iterating over those <button> elements in the Array:
buttons.forEach(function(button) {
// using the anonymous function of the addEventListener()
// to call the addNewElement function, in which
// we set the opts.parent setting to the
// previousElementSibling of the button
// firing the event:
button.addEventListener('click', function() {
addNewElement({
'parent': button.previousElementSibling
});
});
});