使用 append child 时更短的方法
Shorter method when using append child
我正在从通过获取请求返回的对象创建一些元素,想知道是否有更好的方法来简化它?
就目前而言,它按预期工作,但对于看似简单的任务来说,它似乎太长了?
async function getJobs() {
const response = await fetch('https://app.beapplied.com/public/all-jobs');
const data = await response.json();
console.log(data.jobs);
for (const job of data.jobs) {
const jobContainer = document.getElementById("jobData");
const jobListing = document.createElement('li');
jobContainer.appendChild(jobListing);
jobListing.setAttribute('class', 'whr-item')
const jobLink = document.createElement('a');
jobListing.appendChild(jobLink);
jobLink.setAttribute('href', job.applyLink)
let jobTitle = document.createElement("h3");
jobTitle.innerHTML = job.title;
jobTitle.setAttribute('class', 'whr-title')
jobLink.appendChild(jobTitle);
const jobInfo = document.createElement('ul');
jobListing.appendChild(jobInfo);
jobInfo.setAttribute('class', 'whr-info')
let jobTeam = document.createElement("li");
jobTeam.innerHTML = job.team;
jobTeam.setAttribute('class', 'whr-dept')
jobInfo.appendChild(jobTeam);
let jobLocation = document.createElement("li");
jobLocation.innerHTML = job.location
jobLocation.setAttribute('class', 'whr-location')
jobInfo.appendChild(jobLocation);
}
}
getJobs()
<ul id="jobData" class="whr-items"></ul>
由于您要分配给嵌套子项的 .innerHTML
,写出 HTML 字符串和插值将是等效的,并且一目了然更容易理解:
const jobContainer = document.getElementById("jobData");
for (const job of data.jobs) {
jobContainer.insertAdjacentHTML(
'beforeend',
`<li class="whr-item">
<a href="${job.applyLink}">
<h3>${job.title}</h3>
</a>
<ul>
<li class="whr-dept">${job.team}</li>
<li class="whr-location">${job.location}</li>
</ul>
</li>
`
);
}
也就是说,直接插入外部值 HTML(或将 .innerHTML
与外部值一起使用)存在安全风险,因为它允许任意代码执行。我建议写出 HTML 而没有 插入的值,然后在创建结构后安全地插入它们。例如,您可以将 createElement
用于 .whr-item
,这样您就可以引用它,插入它的 HTML 而没有动态值,然后执行
item.querySelector('a').href = job.applyLink;
item.querySelector('h3').href = job.title;
item.querySelector('.whr-dept').href = job.team;
item.querySelector('.whr-location').href = job.location;
这将是一种更安全的方法。
我创建了自己的 class 来制作包含标签、class 和文本的简单元素。您可以对其进行扩展和修改以满足您的所有需求。
更新:
我为您的问题添加了一个如何使用 class 的示例。
由于 CORS 错误,我复制了请求数据并创建了一个对象,而不是执行获取请求。这也意味着您必须向下滚动一点,因为 json 数据很长。
我还制作了一个名为 insert
的辅助函数,用于更轻松地附加节点。
class Elm {
constructor(tag) {
this.tag = tag;
this.classList = [];
this.attributes = [];
this.txt = ""
return this;
}
class(cls) {
this.classList.push(cls);
return this;
}
text(txt) {
this.txt = txt;
return this;
}
attr(attr, val) {
this.attributes.push({
attr,
val
});
return this;
}
create() {
const e = document.createElement(this.tag);
if (this.classList.length)
e.classList.add(...this.classList);
if (this.txt.length) e.textContent = this.txt;
if (this.attributes.length) this.attributes.forEach(atr => e.setAttribute(atr.attr, atr.val));
return e;
}
}
function insert(targetNode, childrenArray) {
targetNode.append(...childrenArray);
return targetNode;
}
async function getJobs() {
const data = {
jobs: [{
id: 12878,
title: "Facilities Coordinator",
location: "Avon Tyrrell Outdoor Centre",
closes: "2021-09-27T07:59:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 1415,
createdAt: "2021-09-15T10:30:13.312Z",
package: "£18,525",
hash: "dbppfgddee",
Org: {
customLogoURL: "https://beapplied.global.ssl.fastly.net/org/1415/logo.png",
apiUrl: "https://app.beapplied.com/B1o/public-jobs",
retentionMonths: 48,
id: 1415,
name: "UK Youth",
customLogo: true,
domain: "ukyouth.org",
OrgTiers: [{
id: "1382",
OrgId: "1415",
TierId: "4",
createdAt: "2021-02-19T18:34:45.692Z",
updatedAt: "2021-02-19T18:34:45.692Z",
}, ],
},
orgLogo: "https://beapplied.global.ssl.fastly.net/org/1415/logo.png",
},
{
id: 12875,
title: "Digital Recruitment Officer",
location: "Home based with some travel",
closes: "2021-10-15T11:00:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 1085,
createdAt: "2021-09-15T09:30:44.770Z",
package: "£30,000 per annum plus benefits",
hash: "lalasq2s0f",
Org: {
customLogoURL: "https://beapplied.global.ssl.fastly.net/org/1085/logo.png",
apiUrl: "https://app.beapplied.com/NDV/public-jobs",
retentionMonths: 48,
id: 1085,
name: "The Trussell Trust",
customLogo: true,
domain: "trusselltrust.org",
OrgTiers: [{
id: "1052",
OrgId: "1085",
TierId: "4",
createdAt: "2020-08-19T15:36:57.700Z",
updatedAt: "2020-08-19T15:36:57.700Z",
}, ],
},
orgLogo: "https://beapplied.global.ssl.fastly.net/org/1085/logo.png",
},
{
id: 12873,
title: "Editorial Manager",
location: "Central London, Blackfriars - we offer flexibility to work remotely",
closes: "2021-09-28T07:00:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 2,
createdAt: "2021-09-15T07:30:43.858Z",
package: "circa £45k plus excellent benefits",
hash: "yefkapfn7d",
Org: {
customLogoURL: "https://logo.clearbit.com/nesta.org.uk",
apiUrl: "https://app.beapplied.com/0M/public-jobs",
retentionMonths: 48,
id: 2,
name: "Nesta",
customLogo: false,
domain: "nesta.org.uk",
OrgTiers: [{
id: "93",
OrgId: "2",
TierId: "4",
createdAt: "2017-02-13T12:56:56.014Z",
updatedAt: "2018-02-21T10:42:01.318Z",
}, ],
},
orgLogo: "https://logo.clearbit.com/nesta.org.uk",
},
{
id: 12867,
title: "Partnerships Senior Account Executive - Motorsport & Football",
location: "London",
closes: "2021-09-21T22:59:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 878,
createdAt: "2021-09-14T18:24:32.381Z",
package: "£27,000 ",
hash: "ozd7o9yxmy",
Org: {
customLogoURL: "https://beapplied.global.ssl.fastly.net/org/878/logo.png",
apiUrl: "https://app.beapplied.com/gDo/public-jobs",
retentionMonths: 48,
id: 878,
name: "OMG UK",
customLogo: true,
domain: "omnicommediagroup.com",
OrgTiers: [{
id: "845",
OrgId: "878",
TierId: "4",
createdAt: "2020-02-17T15:45:22.547Z",
updatedAt: "2020-02-17T15:45:22.547Z",
}, ],
},
orgLogo: "https://beapplied.global.ssl.fastly.net/org/878/logo.png",
},
{
id: 12862,
title: "Researcher",
location: "London or Birmingham ",
closes: "2021-10-17T19:00:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 1490,
createdAt: "2021-09-14T14:01:43.555Z",
package: "£24,000-30,000 PA depending on experience",
hash: "pjqnt94d3x",
Org: {
customLogoURL: "https://beapplied.global.ssl.fastly.net/org/1490/logo.png",
apiUrl: "https://app.beapplied.com/0vJ/public-jobs",
retentionMonths: 48,
id: 1490,
name: "BOP Consulting",
customLogo: true,
domain: "bop.co.uk",
OrgTiers: [{
id: "1457",
OrgId: "1490",
TierId: "4",
createdAt: "2021-04-27T20:02:37.063Z",
updatedAt: "2021-04-27T20:02:37.063Z",
}, ],
},
orgLogo: "https://beapplied.global.ssl.fastly.net/org/1490/logo.png",
},
{
id: 12861,
title: "Talent Manager: FTC Nov 2021 -April 2022",
location: "London and Remote - we are a hybrid organisation",
closes: "2021-09-29T11:00:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 706,
createdAt: "2021-09-14T13:57:57.425Z",
package: "£37,600 - £41,000",
hash: "9fcnvbhovr",
Org: {
customLogoURL: "https://beapplied.global.ssl.fastly.net/org/706/logo.png",
apiUrl: "https://app.beapplied.com/X4M/public-jobs",
retentionMonths: 48,
id: 706,
name: "Comic Relief",
customLogo: true,
domain: "comicrelief.com",
OrgTiers: [{
id: "673",
OrgId: "706",
TierId: "4",
createdAt: "2018-05-10T07:28:08.566Z",
updatedAt: "2019-01-08T08:07:28.542Z",
}, ],
},
orgLogo: "https://beapplied.global.ssl.fastly.net/org/706/logo.png",
},
{
id: 12860,
title: "Analyst (A Sustainable Future)",
location: "Central London, Blackfriars - we offer flexibility to work remotely",
closes: "2021-10-05T07:00:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 2,
createdAt: "2021-09-14T12:42:54.213Z",
package: "£34k, plus excellent benefits",
hash: "1yut7jhl6h",
Org: {
customLogoURL: "https://logo.clearbit.com/nesta.org.uk",
apiUrl: "https://app.beapplied.com/0M/public-jobs",
retentionMonths: 48,
id: 2,
name: "Nesta",
customLogo: false,
domain: "nesta.org.uk",
OrgTiers: [{
id: "93",
OrgId: "2",
TierId: "4",
createdAt: "2017-02-13T12:56:56.014Z",
updatedAt: "2018-02-21T10:42:01.318Z",
}, ],
},
orgLogo: "https://logo.clearbit.com/nesta.org.uk",
},
],
};
const container = document.querySelector("#jobData");
data.jobs.forEach(job => {
const jobItem = new Elm("li")
.class("whr-item")
.create();
const jobTitle = new Elm("a")
.attr("href", job.Org.apiUrl)
.text(job.title)
.create();
const jobInfo = new Elm("ul")
.class("whr-info")
.create();
const jobTeam = new Elm("li")
.class("whr-dept")
.text(`Group: ${job.Org.name}`)
.create();
const jobLocation = new Elm("li")
.class("whr-location")
.text(`Location: ${job.location}`)
.create();
// <JobItem class="whr-item">
// <JobTitle href="">Title of the Job </JobTitle>
// <JobInfo class="whr-info">
// <JobTeam class="whr-dept">Team Name</JobTeam>
// <JobLocation class="whr-location">Location of the Job</JobLocation>
// </JobInfo>
// </JobItem>
const final = insert(jobItem, [
jobTitle,
insert(jobInfo, [
jobTeam,
jobLocation,
]),
]);
container.appendChild(final);
});
}
window.onload = () => getJobs();
html,
body {
padding: 0;
margin: 0;
height: 100%;
}
.whr-items {
padding: 0;
}
.whr-item {
display: flex;
flex-direction: column;
padding: 0.75rem 1rem;
list-style-type: none;
}
.whr-item:nth-child(2n) {
background-color: lightgrey;
}
.whr-item a {
text-decoration: none;
color: black;
font-size: 1.2rem;
margin-bottom: 0.5rem;
}
.whr-item li,
.whr-item ul {
padding: 0;
list-style-type: none;
}
<ul id="jobData" class="whr-items"></ul>
function getJobs() {
fetch('https://app.beapplied.com/public/all-jobs')
.then(response => response.json())
.then(data => data.jobs.map(job => createJobHTML(job))) // create HTML for each job
.then(htmlArr => document.getElementById("jobData").innerHTML = htmlArr.join(''));
}
function createJobHTML(job){
return `<li class="whr-item">
<a href="${job.applyLink}">
<h3 class="whr-title">${job.title}</h3>
</a>
<ul class="whr-info">
<li class="whr-dept">${job?.team ?? '-'}</li>
<li class="whr-location">${job?.location ?? '-'}</li>
</ul>
</li>`;
}
getJobs();
<ul id="jobData" class="whr-items"></ul>
我正在从通过获取请求返回的对象创建一些元素,想知道是否有更好的方法来简化它?
就目前而言,它按预期工作,但对于看似简单的任务来说,它似乎太长了?
async function getJobs() {
const response = await fetch('https://app.beapplied.com/public/all-jobs');
const data = await response.json();
console.log(data.jobs);
for (const job of data.jobs) {
const jobContainer = document.getElementById("jobData");
const jobListing = document.createElement('li');
jobContainer.appendChild(jobListing);
jobListing.setAttribute('class', 'whr-item')
const jobLink = document.createElement('a');
jobListing.appendChild(jobLink);
jobLink.setAttribute('href', job.applyLink)
let jobTitle = document.createElement("h3");
jobTitle.innerHTML = job.title;
jobTitle.setAttribute('class', 'whr-title')
jobLink.appendChild(jobTitle);
const jobInfo = document.createElement('ul');
jobListing.appendChild(jobInfo);
jobInfo.setAttribute('class', 'whr-info')
let jobTeam = document.createElement("li");
jobTeam.innerHTML = job.team;
jobTeam.setAttribute('class', 'whr-dept')
jobInfo.appendChild(jobTeam);
let jobLocation = document.createElement("li");
jobLocation.innerHTML = job.location
jobLocation.setAttribute('class', 'whr-location')
jobInfo.appendChild(jobLocation);
}
}
getJobs()
<ul id="jobData" class="whr-items"></ul>
由于您要分配给嵌套子项的 .innerHTML
,写出 HTML 字符串和插值将是等效的,并且一目了然更容易理解:
const jobContainer = document.getElementById("jobData");
for (const job of data.jobs) {
jobContainer.insertAdjacentHTML(
'beforeend',
`<li class="whr-item">
<a href="${job.applyLink}">
<h3>${job.title}</h3>
</a>
<ul>
<li class="whr-dept">${job.team}</li>
<li class="whr-location">${job.location}</li>
</ul>
</li>
`
);
}
也就是说,直接插入外部值 HTML(或将 .innerHTML
与外部值一起使用)存在安全风险,因为它允许任意代码执行。我建议写出 HTML 而没有 插入的值,然后在创建结构后安全地插入它们。例如,您可以将 createElement
用于 .whr-item
,这样您就可以引用它,插入它的 HTML 而没有动态值,然后执行
item.querySelector('a').href = job.applyLink;
item.querySelector('h3').href = job.title;
item.querySelector('.whr-dept').href = job.team;
item.querySelector('.whr-location').href = job.location;
这将是一种更安全的方法。
我创建了自己的 class 来制作包含标签、class 和文本的简单元素。您可以对其进行扩展和修改以满足您的所有需求。
更新:
我为您的问题添加了一个如何使用 class 的示例。
由于 CORS 错误,我复制了请求数据并创建了一个对象,而不是执行获取请求。这也意味着您必须向下滚动一点,因为 json 数据很长。
我还制作了一个名为 insert
的辅助函数,用于更轻松地附加节点。
class Elm {
constructor(tag) {
this.tag = tag;
this.classList = [];
this.attributes = [];
this.txt = ""
return this;
}
class(cls) {
this.classList.push(cls);
return this;
}
text(txt) {
this.txt = txt;
return this;
}
attr(attr, val) {
this.attributes.push({
attr,
val
});
return this;
}
create() {
const e = document.createElement(this.tag);
if (this.classList.length)
e.classList.add(...this.classList);
if (this.txt.length) e.textContent = this.txt;
if (this.attributes.length) this.attributes.forEach(atr => e.setAttribute(atr.attr, atr.val));
return e;
}
}
function insert(targetNode, childrenArray) {
targetNode.append(...childrenArray);
return targetNode;
}
async function getJobs() {
const data = {
jobs: [{
id: 12878,
title: "Facilities Coordinator",
location: "Avon Tyrrell Outdoor Centre",
closes: "2021-09-27T07:59:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 1415,
createdAt: "2021-09-15T10:30:13.312Z",
package: "£18,525",
hash: "dbppfgddee",
Org: {
customLogoURL: "https://beapplied.global.ssl.fastly.net/org/1415/logo.png",
apiUrl: "https://app.beapplied.com/B1o/public-jobs",
retentionMonths: 48,
id: 1415,
name: "UK Youth",
customLogo: true,
domain: "ukyouth.org",
OrgTiers: [{
id: "1382",
OrgId: "1415",
TierId: "4",
createdAt: "2021-02-19T18:34:45.692Z",
updatedAt: "2021-02-19T18:34:45.692Z",
}, ],
},
orgLogo: "https://beapplied.global.ssl.fastly.net/org/1415/logo.png",
},
{
id: 12875,
title: "Digital Recruitment Officer",
location: "Home based with some travel",
closes: "2021-10-15T11:00:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 1085,
createdAt: "2021-09-15T09:30:44.770Z",
package: "£30,000 per annum plus benefits",
hash: "lalasq2s0f",
Org: {
customLogoURL: "https://beapplied.global.ssl.fastly.net/org/1085/logo.png",
apiUrl: "https://app.beapplied.com/NDV/public-jobs",
retentionMonths: 48,
id: 1085,
name: "The Trussell Trust",
customLogo: true,
domain: "trusselltrust.org",
OrgTiers: [{
id: "1052",
OrgId: "1085",
TierId: "4",
createdAt: "2020-08-19T15:36:57.700Z",
updatedAt: "2020-08-19T15:36:57.700Z",
}, ],
},
orgLogo: "https://beapplied.global.ssl.fastly.net/org/1085/logo.png",
},
{
id: 12873,
title: "Editorial Manager",
location: "Central London, Blackfriars - we offer flexibility to work remotely",
closes: "2021-09-28T07:00:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 2,
createdAt: "2021-09-15T07:30:43.858Z",
package: "circa £45k plus excellent benefits",
hash: "yefkapfn7d",
Org: {
customLogoURL: "https://logo.clearbit.com/nesta.org.uk",
apiUrl: "https://app.beapplied.com/0M/public-jobs",
retentionMonths: 48,
id: 2,
name: "Nesta",
customLogo: false,
domain: "nesta.org.uk",
OrgTiers: [{
id: "93",
OrgId: "2",
TierId: "4",
createdAt: "2017-02-13T12:56:56.014Z",
updatedAt: "2018-02-21T10:42:01.318Z",
}, ],
},
orgLogo: "https://logo.clearbit.com/nesta.org.uk",
},
{
id: 12867,
title: "Partnerships Senior Account Executive - Motorsport & Football",
location: "London",
closes: "2021-09-21T22:59:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 878,
createdAt: "2021-09-14T18:24:32.381Z",
package: "£27,000 ",
hash: "ozd7o9yxmy",
Org: {
customLogoURL: "https://beapplied.global.ssl.fastly.net/org/878/logo.png",
apiUrl: "https://app.beapplied.com/gDo/public-jobs",
retentionMonths: 48,
id: 878,
name: "OMG UK",
customLogo: true,
domain: "omnicommediagroup.com",
OrgTiers: [{
id: "845",
OrgId: "878",
TierId: "4",
createdAt: "2020-02-17T15:45:22.547Z",
updatedAt: "2020-02-17T15:45:22.547Z",
}, ],
},
orgLogo: "https://beapplied.global.ssl.fastly.net/org/878/logo.png",
},
{
id: 12862,
title: "Researcher",
location: "London or Birmingham ",
closes: "2021-10-17T19:00:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 1490,
createdAt: "2021-09-14T14:01:43.555Z",
package: "£24,000-30,000 PA depending on experience",
hash: "pjqnt94d3x",
Org: {
customLogoURL: "https://beapplied.global.ssl.fastly.net/org/1490/logo.png",
apiUrl: "https://app.beapplied.com/0vJ/public-jobs",
retentionMonths: 48,
id: 1490,
name: "BOP Consulting",
customLogo: true,
domain: "bop.co.uk",
OrgTiers: [{
id: "1457",
OrgId: "1490",
TierId: "4",
createdAt: "2021-04-27T20:02:37.063Z",
updatedAt: "2021-04-27T20:02:37.063Z",
}, ],
},
orgLogo: "https://beapplied.global.ssl.fastly.net/org/1490/logo.png",
},
{
id: 12861,
title: "Talent Manager: FTC Nov 2021 -April 2022",
location: "London and Remote - we are a hybrid organisation",
closes: "2021-09-29T11:00:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 706,
createdAt: "2021-09-14T13:57:57.425Z",
package: "£37,600 - £41,000",
hash: "9fcnvbhovr",
Org: {
customLogoURL: "https://beapplied.global.ssl.fastly.net/org/706/logo.png",
apiUrl: "https://app.beapplied.com/X4M/public-jobs",
retentionMonths: 48,
id: 706,
name: "Comic Relief",
customLogo: true,
domain: "comicrelief.com",
OrgTiers: [{
id: "673",
OrgId: "706",
TierId: "4",
createdAt: "2018-05-10T07:28:08.566Z",
updatedAt: "2019-01-08T08:07:28.542Z",
}, ],
},
orgLogo: "https://beapplied.global.ssl.fastly.net/org/706/logo.png",
},
{
id: 12860,
title: "Analyst (A Sustainable Future)",
location: "Central London, Blackfriars - we offer flexibility to work remotely",
closes: "2021-10-05T07:00:00.000Z",
public: true,
archived: false,
phase: "ACTIVE_APPLYING",
OrgId: 2,
createdAt: "2021-09-14T12:42:54.213Z",
package: "£34k, plus excellent benefits",
hash: "1yut7jhl6h",
Org: {
customLogoURL: "https://logo.clearbit.com/nesta.org.uk",
apiUrl: "https://app.beapplied.com/0M/public-jobs",
retentionMonths: 48,
id: 2,
name: "Nesta",
customLogo: false,
domain: "nesta.org.uk",
OrgTiers: [{
id: "93",
OrgId: "2",
TierId: "4",
createdAt: "2017-02-13T12:56:56.014Z",
updatedAt: "2018-02-21T10:42:01.318Z",
}, ],
},
orgLogo: "https://logo.clearbit.com/nesta.org.uk",
},
],
};
const container = document.querySelector("#jobData");
data.jobs.forEach(job => {
const jobItem = new Elm("li")
.class("whr-item")
.create();
const jobTitle = new Elm("a")
.attr("href", job.Org.apiUrl)
.text(job.title)
.create();
const jobInfo = new Elm("ul")
.class("whr-info")
.create();
const jobTeam = new Elm("li")
.class("whr-dept")
.text(`Group: ${job.Org.name}`)
.create();
const jobLocation = new Elm("li")
.class("whr-location")
.text(`Location: ${job.location}`)
.create();
// <JobItem class="whr-item">
// <JobTitle href="">Title of the Job </JobTitle>
// <JobInfo class="whr-info">
// <JobTeam class="whr-dept">Team Name</JobTeam>
// <JobLocation class="whr-location">Location of the Job</JobLocation>
// </JobInfo>
// </JobItem>
const final = insert(jobItem, [
jobTitle,
insert(jobInfo, [
jobTeam,
jobLocation,
]),
]);
container.appendChild(final);
});
}
window.onload = () => getJobs();
html,
body {
padding: 0;
margin: 0;
height: 100%;
}
.whr-items {
padding: 0;
}
.whr-item {
display: flex;
flex-direction: column;
padding: 0.75rem 1rem;
list-style-type: none;
}
.whr-item:nth-child(2n) {
background-color: lightgrey;
}
.whr-item a {
text-decoration: none;
color: black;
font-size: 1.2rem;
margin-bottom: 0.5rem;
}
.whr-item li,
.whr-item ul {
padding: 0;
list-style-type: none;
}
<ul id="jobData" class="whr-items"></ul>
function getJobs() {
fetch('https://app.beapplied.com/public/all-jobs')
.then(response => response.json())
.then(data => data.jobs.map(job => createJobHTML(job))) // create HTML for each job
.then(htmlArr => document.getElementById("jobData").innerHTML = htmlArr.join(''));
}
function createJobHTML(job){
return `<li class="whr-item">
<a href="${job.applyLink}">
<h3 class="whr-title">${job.title}</h3>
</a>
<ul class="whr-info">
<li class="whr-dept">${job?.team ?? '-'}</li>
<li class="whr-location">${job?.location ?? '-'}</li>
</ul>
</li>`;
}
getJobs();
<ul id="jobData" class="whr-items"></ul>