使用 Javascript 循环创建多个 HTML 元素

Using Javascript loop to create multiple HTML elements

我想使用 javascript 循环来创建多个 HTML 包装元素并将 JSON 响应 API 数据插入到某些元素(图片、标题, url, 等等...).

这是我需要line-by-line的东西吗?

<a class="scoreboard-video-outer-link" href="">
  <div class="scoreboard-video--wrapper">
    <div class="scoreboard-video--thumbnail">
      <img src="http://via.placeholder.com/350x150">
    </div>
    <div class="scoreboard-video--info">
      <div class="scoreboard-video--title">Pelicans @ Bulls Postgame: E'Twaun Moore 10-8-17</div>
    </div>
  </div>
</a>

我在尝试什么:

var link = document.createElement('a');
document.getElementsByTagName("a")[0].setAttribute("class", "scoreboard-video-outer-link");
document.getElementsByTagName("a")[0].setAttribute("url", "google.com"); 
mainWrapper.appendChild(link);

var videoWrapper= document.createElement('div');
document.getElementsByTagName("div")[0].setAttribute("class", "scoreboard-video-outer-link");
link.appendChild(videoWrapper);

var videoThumbnailWrapper = document.createElement('div');
document.getElementsByTagName("div")[0].setAttribute("class", "scoreboard-video--thumbnail");
 videoWrapper.appendChild(videoThumbnailWrapper);

var videoImage = document.createElement('img');
document.getElementsByTagName("img")[0].setAttribute("src", "url-of-image-from-api");
videoThumbnailWrapper.appendChild(videoImage);

然后我基本上对所有嵌套的 HTML 元素重复该过程。

如果您能告诉我最好的方法来完成我在这里要解释的内容,我将不胜感激?好像会变得很乱。

看看这个 - [underscore._template] 它非常小,在这种情况下很有用。 (https://www.npmjs.com/package/underscore.template).

const targetElement = document.querySelector('#target')

// Define your template
const template = UnderscoreTemplate(
'<a class="<%- link.className %>" href="<%- link.url %>">\
  <div class="<%- wrapper.className %>">\
    <div class="<%- thumbnail.className %>">\
      <img src="<%- thumbnail.image %>">\
    </div>\
    <div class="<%- info.className %>">\
      <div class="<%- info.title.className %>"><%- info.title.text %></div>\
    </div>\
  </div>\
</a>');
 
// Define values for template
const obj = {
  link: {
    className: 'scoreboard-video-outer-link',
    url: '#someurl'
  },
  wrapper: {
    className: 'scoreboard-video--wrapper'
  },
  thumbnail: {
    className: 'scoreboard-video--thumbnail',
    image: 'http://via.placeholder.com/350x150'
  },
  info: {
    className: 'scoreboard-video--info',
    title: {
      className: 'scoreboard-video--title',
      text: 'Pelicans @ Bulls Postgame: E`Twaun Moore 10-8-17'
    }
  }
};

// Build template, and set innerHTML to output element.
targetElement.innerHTML = template(obj)

// And of course you can go into forEach loop here like

const arr = [obj, obj, obj]; // Create array from our object
arr.forEach(item => targetElement.innerHTML += template(item))
<script src="https://unpkg.com/underscore.template@0.1.7/dist/underscore.template.js"></script>
<div id="target">qq</div>

简短版

Markup.js's loops.

长版

您会发现许多有效解决此问题的解决方案。但这可能不是重点。关键是:这样做对吗?您可能使用了错误的工具来解决问题。

我使用过执行类似操作的代码。我没有写它,但我不得不使用它。您会发现这样的代码很快就会变得非常难以管理。你可能会想:“哦,但我知道它应该做什么。一旦完成,我不会改变它。”

代码分为两类:

  • 您停止使用的代码因此不需要更改。
  • 您一直在使用的代码,因此需要更改。

所以,“它有效吗?”这不是正确的问题。有很多问题,但其中一些是:“我能维护这个吗?它容易阅读吗?如果我改变一个部分,它只会改变我需要改变的部分,还是它也会改变我需要改变的其他部分?不打算改变吗?

我的意思是您应该使用模板库。 JavaScript.

有很多

一般来说,您应该使用整个JavaScript 应用程序框架。现在主要有3个:

  • ReactJS
  • Vue.js
  • Angular 2

老实说,请注意,我没有听从自己的建议,仍然使用 Angular。 (原来的,不是Angular2.)但这是一个陡峭的学习曲线。有很多库也包含模板功能。

但是您显然已经设置了整个项目,您只想将模板插入到 现有 JavaScript 代码中。您可能需要一种模板语言来完成它的工作并且不妨碍。当我开始的时候,我也想要那个。我用过 Markup.js 。它很小,很简单,并且在 post.

中可以满足您的需求

https://github.com/adammark/Markup.js/

这是第一步。我认为它的 loops feature 正是您所需要的。以此为起点,及时构建完整的框架。

这是我的答案。它被记录下来。为了查看代码片段中的效果,您必须进入开发人员控制台以检查包装器元素或查看您的开发人员控制台日志。

我们基本上创建了一些辅助方法来轻松创建元素并将它们附加到 DOM - 它真的没有看起来那么难。这也应该让您可以轻松地将 JSON 检索到的对象作为属性附加到您的元素!

这是一个基本版本,可以让您大致了解正在发生的事情以及如何使用它

//create element function

function create(tagName, props) {
  return Object.assign(document.createElement(tagName), (props || {}));
}

//append child function

function ac(p, c) {
  if (c) p.appendChild(c);
  return p;
}

//example: 
//get wrapper div
let mainWrapper = document.getElementById("mainWrapper");

//create link and div
let link = create("a", { href:"google.com" });
let div = create("div", { id: "myDiv" });

//add link as a child to div, add the result to mainWrapper
ac(mainWrapper, ac(div, link));

//create element function

function create(tagName, props) {
  return Object.assign(document.createElement(tagName), (props || {}));
}

//append child function

function ac(p, c) {
  if (c) p.appendChild(c);
  return p;
}

//example: 
//get wrapper div
let mainWrapper = document.getElementById("mainWrapper");

//create link and div
let link = create("a", { href:"google.com", textContent: "this text is a Link in the div" });
let div = create("div", { id: "myDiv", textContent: "this text is in the div! " });

//add link as a child to div, add the result to mainWrapper
ac(mainWrapper, ac(div, link));
div {
border: 3px solid black;
padding: 5px;

}
<div id="mainWrapper"></div>

下面是如何使用更详尽的注释代码具体执行您的要求。

//get main wrapper
let mainWrapper = document.getElementById("mainWrapper");

//make a function to easily create elements
//function takes a tagName and an optional object for property values
//using Object.assign we can make tailored elements quickly.

function create(tagName, props) {
  return Object.assign(document.createElement(tagName), (props || {}));
}


//document.appendChild is great except 
//it doesn't offer easy stackability
//The reason for this is that it always returns the appended child element
//we create a function that appends from Parent to Child 
//and returns the compiled element(The Parent).
//Since we are ALWAYS returning the parent(regardles of if the child is specified) 
//we can recursively call this function to great effect
//(you'll see this further down)
function ac(p, c) {
  if (c) p.appendChild(c);
  return p;
}

//these are the elements you wanted to append
//notice how easy it is to make them!

//FYI when adding classes directly to an HTMLElement
//the property to assign a value to is className  -- NOT class
//this is a common mistake, so no big deal!

var link = create("a", {
  className: "scoreboard-video-outer-link",
  url: "google.com"
});

var videoWrapper = create("div", {
  className: "scoreboard-video-outer-link"
});

var videoThumbnailWrapper = create("div", {
  className: "scoreboard-video--thumbnail"
});

var videoImage = create("img", {
  src: "url-of-image-from-api"
});

//here's where the recursion comes in:
ac(mainWrapper, ac(link, ac(videoWrapper, ac(videoThumbnailWrapper, videoImage))));

//keep in mind that it might be easiest to read the ac functions backwards
//the logic is this:

//Append videoImage to videoThumbnailWrapper
//Append (videoImage+videoThumbnailWrapper) to videoWrapper 
//Append (videoWrapper+videoImage+videoThumbnailWrapper) to link
//Append (link+videoWrapper+videoImage+videoThumbnailWrapper) to mainWrapper

let mainWrapper = document.getElementById('mainWrapper');

function create(tagName, props) {
  return Object.assign(document.createElement(tagName), (props || {}));
}

function ac(p, c) {
  if (c) p.appendChild(c);
  return p;
}

var link = create("a", {
  className: "scoreboard-video-outer-link",
  url: "google.com"
});

var videoWrapper = create("div", {
  className: "scoreboard-video-outer-link"
});

var videoThumbnailWrapper = create("div", {
  className: "scoreboard-video--thumbnail"
});



var videoImage = create("img", {
  src: "url-of-image-from-api"
});

ac(mainWrapper, ac(link, ac(videoWrapper, ac(videoThumbnailWrapper, videoImage))));
//pretty fancy.
//This is just to show the output in the log,
//feel free to just open up the developer console and look at the mainWrapper element.

console.dir(mainWrapper);
<div id="mainWrapper"></div>