使用vanilla JS,使用模板文字循环使用数组作为prop的对象数组

时间:2018-05-02 00:12:09

标签: javascript mapping template-literals

我自学了自己的香草JS,并希望能够很好地使用它。

我已经在脑子里绞了好几天。我正在尝试使用模板文字来显示数组中对象的属性。

这些对象是投资组合项目。在每个对象中,我有一个属性是图标图像的数组。除了所有图标图像之外,我能够在页面上呈现所有内容。

我只能在我的div中显示1个图标图像,其中class =“技能使用”。

有人可以帮我弄清楚如何映射该图标数组中的所有图像吗?

或者,是否有更好的(或推荐的)方式来做这件事?

const projects = [
      { 
        image: "http://via.placeholder.com/360x180",
        title: "Project 1",
        skillIconImages: ["http://via.placeholder.com/50x50", "http://via.placeholder.com/55x50", "http://via.placeholder.com/50x55", "http://via.placeholder.com/60x50"],
        description: "Ex rationibus deterruisset eos, ius tale nullam officiis an. Duo propriae mentitum salutandi id, nulla nobis persequeris ut eam, ex dicta libris laboramus duo. Amet errem voluptatibus an vix, eum ut nulla scriptorem. Ea etiam noluisse perfecto eum. Nec ad consul ubique, his id reque nonumy percipit." 
      },
      {
        image: "http://via.placeholder.com/360x180",
        title: "Project 2",
        skillIconImages: ["http://via.placeholder.com/50x50", "http://via.placeholder.com/55x50", "http://via.placeholder.com/50x55", "http://via.placeholder.com/60x50"],
        description: "Ex rationibus deterruisset eos, ius tale nullam officiis an. Duo propriae mentitum salutandi id, nulla nobis persequeris ut eam, ex dicta libris laboramus duo. Amet errem voluptatibus an vix, eum ut nulla scriptorem. Ea etiam noluisse perfecto eum. Nec ad consul ubique, his id reque nonumy percipit."
      },
      {
        image: "http://via.placeholder.com/360x180",
        title: "Project 3",
        skillIconImages: ["http://via.placeholder.com/50x50", "http://via.placeholder.com/55x50", "http://via.placeholder.com/50x55", "http://via.placeholder.com/60x50"],
        description: "Ex rationibus deterruisset eos, ius tale nullam officiis an. Duo propriae mentitum salutandi id, nulla nobis persequeris ut eam, ex dicta libris laboramus duo. Amet errem voluptatibus an vix, eum ut nulla scriptorem. Ea etiam noluisse perfecto eum. Nec ad consul ubique, his id reque nonumy percipit."
      }
    ];

以下是我尝试将其呈现到页面的方式:

let portfolioItemsDiv = document.getElementById('portfolio-items');
    
    projects.forEach((project) => {
      
      portfolioItemsDiv.innerHTML += `
      <div class="portfolio-item">
        <img src="${project.image}" alt="${project.title}" />
        <h3 class="project-title">${project.title}</h3>
        <div class="skills-used">
          ${project.skillIconImages.map((x) => '<img src="' + x +'"')}
        </div>
        <div class="project-description">
          <p>${project.description}</p>
        </div>
      </div>
    `;
    });

如果需要整个(非重构)函数,那么它是:

(() => {
    const projects = [
      { 
        image: "http://via.placeholder.com/360x180",
        title: "Project 1",
        skillIconImages: ["http://via.placeholder.com/50x50", "http://via.placeholder.com/55x50", "http://via.placeholder.com/50x55", "http://via.placeholder.com/60x50"],
        description: "Ex rationibus deterruisset eos, ius tale nullam officiis an. Duo propriae mentitum salutandi id, nulla nobis persequeris ut eam, ex dicta libris laboramus duo. Amet errem voluptatibus an vix, eum ut nulla scriptorem. Ea etiam noluisse perfecto eum. Nec ad consul ubique, his id reque nonumy percipit." 
      },
      {
        image: "http://via.placeholder.com/360x180",
        title: "Project 2",
        skillIconImages: ["http://via.placeholder.com/50x50", "http://via.placeholder.com/55x50", "http://via.placeholder.com/50x55", "http://via.placeholder.com/60x50"],
        description: "Ex rationibus deterruisset eos, ius tale nullam officiis an. Duo propriae mentitum salutandi id, nulla nobis persequeris ut eam, ex dicta libris laboramus duo. Amet errem voluptatibus an vix, eum ut nulla scriptorem. Ea etiam noluisse perfecto eum. Nec ad consul ubique, his id reque nonumy percipit."
      },
      {
        image: "http://via.placeholder.com/360x180",
        title: "Project 3",
        skillIconImages: ["http://via.placeholder.com/50x50", "http://via.placeholder.com/55x50", "http://via.placeholder.com/50x55", "http://via.placeholder.com/60x50"],
        description: "Ex rationibus deterruisset eos, ius tale nullam officiis an. Duo propriae mentitum salutandi id, nulla nobis persequeris ut eam, ex dicta libris laboramus duo. Amet errem voluptatibus an vix, eum ut nulla scriptorem. Ea etiam noluisse perfecto eum. Nec ad consul ubique, his id reque nonumy percipit."
      }
    ];
    
    // get the DOM element to where all the portfolio items will go into
    let portfolioItemsDiv = document.getElementById('portfolio-items');
    
    // render each project to the DOM 
    projects.forEach((project) => {
      portfolioItemsDiv.innerHTML += `
      <div class="portfolio-item">
        <img src="${project.image}" alt="${project.title}" />
        <h3 class="project-title">${project.title}</h3>
        <div class="skills-used">
          ${project.skillIconImages.map((x) => '<img src="' + x +'"')}
        </div>
        <div class="project-description">
          <p>${project.description}</p>
        </div>
      </div>
    `;
    });
  })();

2 个答案:

答案 0 :(得分:1)

您必须关闭img标记(这是主要问题),并join映射数组以获取字符串:

${project.skillIconImages.map((x) => '<img src="' + x +'">').join("")}
//                                                       ^   ^^^^^^^^

此外,您应该尽量减少innerHTML的分配数量,而不是使用+=并不断更改它(这对性能不利),您应该将HTML累积到字符串中然后使用{ {1}}只有一次:

innerHTML = thatAccumulatedString

或者使用var htmlString = ""; htmlString += "... generated HTML for a portfolio ..."; .innerHTML = htmlString; 在内部进行累积(也为什么不继续使用reduce内的模板文字),如:

map

CSSless演示:

&#13;
&#13;
let portfolioItemsDiv = document.getElementById('portfolio-items');

portfolioItemsDiv.innerHTML = projects.reduce((htmlString, project) => {
    return htmlString + `
        <div class="portfolio-item">
            <img src="${project.image}" alt="${project.title}" />
            <h3 class="project-title">${project.title}</h3>
            <div class="skills-used">
            ${
                project.skillIconImages.map(x => `<img src="${x}">`).join("")
            }
            </div>
            <div class="project-description">
                <p>${project.description}</p>
            </div>
        </div>
    `;
}, "");
&#13;
const projects = [{"image":"http://via.placeholder.com/360x180","title":"Project 1","skillIconImages":["http://via.placeholder.com/50x50","http://via.placeholder.com/55x50","http://via.placeholder.com/50x55","http://via.placeholder.com/60x50"],"description":"Ex rationibus deterruisset eos, ius tale nullam officiis an. Duo propriae mentitum salutandi id, nulla nobis persequeris ut eam, ex dicta libris laboramus duo. Amet errem voluptatibus an vix, eum ut nulla scriptorem. Ea etiam noluisse perfecto eum. Nec ad consul ubique, his id reque nonumy percipit."},{"image":"http://via.placeholder.com/360x180","title":"Project 2","skillIconImages":["http://via.placeholder.com/50x50","http://via.placeholder.com/55x50","http://via.placeholder.com/50x55","http://via.placeholder.com/60x50"],"description":"Ex rationibus deterruisset eos, ius tale nullam officiis an. Duo propriae mentitum salutandi id, nulla nobis persequeris ut eam, ex dicta libris laboramus duo. Amet errem voluptatibus an vix, eum ut nulla scriptorem. Ea etiam noluisse perfecto eum. Nec ad consul ubique, his id reque nonumy percipit."},{"image":"http://via.placeholder.com/360x180","title":"Project 3","skillIconImages":["http://via.placeholder.com/50x50","http://via.placeholder.com/55x50","http://via.placeholder.com/50x55","http://via.placeholder.com/60x50"],"description":"Ex rationibus deterruisset eos, ius tale nullam officiis an. Duo propriae mentitum salutandi id, nulla nobis persequeris ut eam, ex dicta libris laboramus duo. Amet errem voluptatibus an vix, eum ut nulla scriptorem. Ea etiam noluisse perfecto eum. Nec ad consul ubique, his id reque nonumy percipit."}];

let portfolioItemsDiv = document.getElementById('portfolio-items');

portfolioItemsDiv.innerHTML = projects.reduce((htmlString, project) => {
    return htmlString + `
        <div class="portfolio-item">
            <img src="${project.image}" alt="${project.title}" />
            <h3 class="project-title">${project.title}</h3>
            <div class="skills-used">
            ${
                project.skillIconImages.map(x => `<img src="${x}">`).join("")
            }
            </div>
            <div class="project-description">
                <p>${project.description}</p>
            </div>
        </div>
    `;
}, "");
&#13;
&#13;
&#13;

答案 1 :(得分:0)

除了错过上面答案中指定的/>的结束img标记之外,如果您担心性能,那么如果您经常更改HTML,则会出现问题从文档中,您可以使用DocumentFragment来满足此类要求。

  

DocumentFragment接口表示最小的文档对象   没有父母。它用作Document的轻量级版本   存储由节点组成的文档结构的一部分   像标准文件。关键的区别在于因为   文档片段不是活动文档树结构的一部分,   对片段所做的更改不会影响文档,导致重排,   或者在进行更改时可能会产生任何性能影响。

您可以使用document.createDocumentFragment创建文档片段,然后将所有HTML添加到片段中。

您甚至可以在将元素添加到fragment之后修改元素,就像使用document document.querySelector('div')一样,选择文档中的所有div,类似fragment.querySelector('div')将会选择片段中的div元素。  做任何你喜欢的事情,然后,最后,将它附加到应该是有效文档节点的元素。

您可以将template包装成object literals,将其分类为{{3}}。

let portfolioItemsDiv = document.querySelector('#portfolio-items');
let fragment = document.createDocumentFragment();
let template = {
  portfolio: (project) => {
    return `<div class="portfolio-item">
        <img src="${project.image}" alt="${project.title}" />
        <h3 class="project-title">${project.title}</h3>
        <div class="skills-used">
          ${project.skillIconImages.map((x) => '<img src="' + x +'"/>')}
        </div>
        <div class="project-description">
          <p>${project.description}</p>
        </div>
      </div>
    `
  }
};


// render each project to the DOM 
projects.forEach((project) => {
  let temp = document.createElement('div');
  temp.innerHTML = template['portfolio'].call(this, project);
  fragment.appendChild(temp.firstChild);
});

portfolioItemsDiv.appendChild(fragment);

请参阅下面的演示

const projects = [{
    "image": "https://via.placeholder.com/360x180",
    "title": "Project 1",
    "skillIconImages": ["https://via.placeholder.com/50x50", "https://via.placeholder.com/55x50", "https://via.placeholder.com/50x55", "https://via.placeholder.com/60x50"],
    "description": "Ex rationibus deterruisset eos, ius tale nullam officiis an. Duo propriae mentitum salutandi id, nulla nobis persequeris ut eam, ex dicta libris laboramus duo. Amet errem voluptatibus an vix, eum ut nulla scriptorem. Ea etiam noluisse perfecto eum. Nec ad consul ubique, his id reque nonumy percipit."
  },
  {
    "image": "https://via.placeholder.com/360x180",
    "title": "Project 2",
    "skillIconImages": ["https://via.placeholder.com/50x50", "https://via.placeholder.com/55x50", "https://via.placeholder.com/50x55", "https://via.placeholder.com/60x50"],
    "description": "Ex rationibus deterruisset eos, ius tale nullam officiis an. Duo propriae mentitum salutandi id, nulla nobis persequeris ut eam, ex dicta libris laboramus duo. Amet errem voluptatibus an vix, eum ut nulla scriptorem. Ea etiam noluisse perfecto eum. Nec ad consul ubique, his id reque nonumy percipit."
  },
  {
    "image": "https://via.placeholder.com/360x180",
    "title": "Project 3",
    "skillIconImages": ["https://via.placeholder.com/50x50", "https://via.placeholder.com/55x50", "https://via.placeholder.com/50x55", "https://via.placeholder.com/60x50"],
    "description": "Ex rationibus deterruisset eos, ius tale nullam officiis an. Duo propriae mentitum salutandi id, nulla nobis persequeris ut eam, ex dicta libris laboramus duo. Amet errem voluptatibus an vix, eum ut nulla scriptorem. Ea etiam noluisse perfecto eum. Nec ad consul ubique, his id reque nonumy percipit."
  }
];

// get the DOM element to where all the portfolio items will go into
let portfolioItemsDiv = document.querySelector('#portfolio-items');
let fragment = document.createDocumentFragment();
let template = {
  portfolio: (project) => {
    return `<div class="portfolio-item">
        <img src="${project.image}" alt="${project.title}" />
        <h3 class="project-title">${project.title}</h3>
        <div class="skills-used">
          ${project.skillIconImages.map((x) => '<img src="' + x +'"/>')}
        </div>
        <div class="project-description">
          <p>${project.description}</p>
        </div>
      </div>
    `
  }
};

// render each project to the DOM 
projects.forEach((project) => {
  let temp = document.createElement('div');
  temp.innerHTML = template['portfolio'].call(this, project);
  fragment.appendChild(temp.firstChild);
});

//append the fragment to the document element
portfolioItemsDiv.appendChild(fragment);
<div id="portfolio-items">
</div>