【问题标题】:Using vanilla JS, Loop through an array of objects with an array as a prop using template literals使用 vanilla JS,使用模板文字循环遍历对象数组,并将数组作为道具
【发布时间】:2018-05-02 09:08:52
【问题描述】:

我正在自学 vanilla JS,希望能真正精通它。

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

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

我只能使用 class="skills-used" 在我的 div 中显示 1 个图标图像。

谁能帮我弄清楚如何映射该图标数组中的所有图像?

或者,是否有更好的(或推荐的)方法来代替?

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>
    `;
    });
  })();

【问题讨论】:

    标签: javascript mapping template-literals


    【解决方案1】:

    你必须关闭 img 标记(这是主要问题)和 join 映射数组以获得字符串:

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

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

    var htmlString = "";
    
    htmlString += "... generated HTML for a portfolio ...";
    
    .innerHTML = htmlString;
    

    或者使用 reduce 在内部进行累积(为什么不继续在 map 中使用模板文字),例如:

    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>
        `;
    }, "");
    

    无 CSS 演示:

    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>
        `;
    }, "");
    &lt;div id="portfolio-items"&gt;&lt;/div&gt;

    【讨论】:

    • 天哪!你解决了!太感谢了!也感谢您的额外反馈。我将不得不在我的代码中研究与性能相关的问题......但我专注于让事物首先出现在 DOM 上。说真的,谢谢!
    • @whoDoDaWhatWhat 不客气!我很高兴能帮上忙。
    【解决方案2】:

    除了缺少上面答案中指定的img 的结束/&gt; 标记外,如果您担心性能,那么如果您经常直接从文档中更改 HTML,这将是一个问题,您可以使用DocumentFragment 来满足此类要求。

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

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

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

    您可以通过将template 包装到object literals 中来分隔template,这样您也可以对它们进行分类。

    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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-08
      • 2021-02-11
      • 1970-01-01
      • 2019-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多