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

时间:2017-10-13 21:34:21

标签: javascript json api-design

我想使用javascript循环来创建多个HTML包装器元素,并将JSON响应API数据插入到一些元素(图像,标题,网址等)中。

这是我需要逐行进行的吗?

<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元素重复该过程。

  • 创建A-tag
  • 为A-tag
  • 创建class和href属性
  • 将类名和网址附加到属性
  • 将A-tag附加到主包装

  • 创建DIV

  • 为DIV创建类属性
  • 将DIV附加到新添加的A-tag

如果你能告诉我最好的方法去做我想在这里解释的事情,我会非常感激吗?好像它会变得非常混乱。

3 个答案:

答案 0 :(得分:2)

短版

Markup.js's loops

长版

您会找到许多解决此问题的工作的解决方案。但这可能不是重点。关键是:是不是?你可能会使用错误的工具解决问题。

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

代码分为两类:

  • 您停止使用的代码,因此您无需更改。
  • 您继续使用的代码,因此您需要更改。

所以,“它有效吗?”这不是正确的问题。有很多问题,但其中一些问题是:“我能保持这个吗?它是否易于阅读?如果我改变一个部分,它是否只改变了我需要改变的部分,还是改变了别的东西我不是故意改变?“

我在这里得到的是你应该使用模板库。有许多JavaScript。

通常,您应该使用整个JavaScript应用程序框架。现在有三个主要的:

  • ReactJS
  • Vue.js
  • Angular 2

为了诚实,请注意我不遵循自己的建议,仍然使用Angular。 (原来的,不是Angular 2.)但这是一个陡峭的学习曲线。有很多库也包含模板能力。

但是您显然已经设置了整个项目,并且您只想将模板插入现有的 JavaScript代码中。您可能想要一种模板语言,它可以完成它的工作并且不会受到影响。当我开始时,我也想要那样。我用了Markup.js。它很小,很简单,它可以在这篇文章中做到你想要的。

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

这是第一步。我认为它loops feature正是你所需要的。从那开始,及时完成一个完整的框架。

答案 1 :(得分:2)

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

我们基本上创建了一些辅助方法来轻松创建元素并将它们附加到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));

&#13;
&#13;
//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));
&#13;
div {
border: 3px solid black;
padding: 5px;

}
&#13;
<div id="mainWrapper"></div>
&#13;
&#13;
&#13;

以下是如何使用更详尽的注释代码专门执行您所要求的内容。

//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

&#13;
&#13;
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);
&#13;
<div id="mainWrapper"></div>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

看看这个 - [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>