我有一个关于用户卡的小项目。
我有一个JSON文件,其中包含生成卡片的用户数据。
我的任务是在卡片中显示用户拥有的那些社交网络的图标。如果用户没有任何社交网络-不要在他的个人资料中显示此社交网络的图标。
坦率地说,我不明白该怎么做。
JSON中的数据以这种形式出现(以一个用户为例):
{
"id": 7,
"firstName": "Daniel",
"lastName": "Day-Lewis",
"profilePicture": "https://i2.wp.com/comicbookdebate.com/wp-content/uploads/2019/07/There20will20be20blood202-750x460.jpg?resize=750%2C460&ssl=1",
"contacts": [
"https://www.facebook.com/JasonStatham/",
"https://twitter.com/realjstatham",
"https://www.instagram.com/jasonstatham/?hl=ru"
]
}
JS索引文件(添加,以便清楚我如何在这个项目中使用布局):
'use strict';
const cardsContainer = document.querySelector('#root');
async function loadCards(url) {
try {
const response = await fetch(url);
const data = await response.json();
const cards = data.map((data) => generateUserCard(data));
cardsContainer.append(...cards);
} catch(e) {
throw new Error(e);
}
}
loadCards('./assets/js/data.json');
function generateUserCard(userObj) {
const fullName =
`${userObj.firstName} ${userObj.lastName}`.trim() ||
CARD_CONSTANTS.userName;
const imgWrapper = createUserCardImageWrapper(userObj, fullName);
const cardName = createElement('h2', {classNames: ['cardName']}, fullName);
const cardDescription = createElement('p', {classNames: ['cardDescription']}, userObj.description || CARD_CONSTANTS.cardDescription);
const cardArticle = createElement('article', {classNames: ['cardContainer']}, imgWrapper, cardName, cardDescription);
const card = createElement('li', {classNames: ['userCardWrapper']}, cardArticle);
return card;
}
function createUserCardImageWrapper(userObj, fullName) {
const userImgElem = createElement('img', {
classNames: ['cardImg'],
attributes: {
src: userObj.profilePicture,
alt: fullName,
'data-id': userObj.id,
},
listeners: {
error: errorHandler,
load: loadHandler,
},
});
const initialsElem = createElement(
'div',
{ classNames: ['initials'] },
getInitials(fullName)
);
const imgWrapperElem = createElement(
'div',
{
classNames: ['cardImgWrapper'],
attributes: { id: `imgWrapper${userObj.id}` },
},
initialsElem
);
return imgWrapperElem;
}
function errorHandler({ target }) {
target.remove();
}
function loadHandler({
target,
target: {
dataset: { id },
},
}) {
document.getElementById(`imgWrapper${id}`).append(target);
}
我是这样把社交网络和图标联系起来的(以Twitter为例):
const SUPPORTED_SOCIAL_NETWORKS = new Map([
[
"twitter.com",
{
src: "https://w7.pngwing.com/pngs/872/50/png-transparent-computer-icons-social-media-logo-twitter-social-media-blue-logo-social-media-thumbnail.png",
alt: "twitter link for",
},
],
["www.facebook.com"],
]);
这实际上非常简单,参见代码
中的注释
// Get the network hosts for of a user and optionally filter them
let getNetworkHosts = (userId, filter) => {
if (match = users.filter( user => userId === user.id )) {
contacts = match[0].contacts.map( url => (new URL(url)).hostname)
if (filter) contacts = contacts.filter(filter)
return contacts
}
}
// A filter that can be applied to a list
let supportedNetworkFilter = elem => SUPPORTED_SOCIAL_NETWORKS[elem]
// Create an image tag
let createImage = (url) => {
let img = document.createElement("img")
img.src = url
return img
}
users =
[ { "id": 7
, "firstName": "Daniel"
, "lastName": "Day-Lewis"
, "profilePicture": "https://i2.wp.com/comicbookdebate.com/wp-content/uploads/2019/07/There20will20be20blood202-750x460.jpg?resize=750%2C460&ssl=1"
, "contacts":
[ "https://www.facebook.com/JasonStatham/"
, "https://twitter.com/realjstatham"
, "https://www.instagram.com/jasonstatham/?hl=ru"
]
}
]
const SUPPORTED_SOCIAL_NETWORKS =
{ "twitter.com":
{ src: "https://w7.pngwing.com/pngs/872/50/png-transparent-computer-icons-social-media-logo-twitter-social-media-blue-logo-social-media-thumbnail.png"
, alt: "twitter link for"
}
, "www.facebook.com": {} // Oops, facebook has no face
}
// Add some images to a div
let div = document.getElementById('images')
for (network of getNetworkHosts(7, supportedNetworkFilter)) {
div.appendChild(createImage(SUPPORTED_SOCIAL_NETWORKS[network].src))
}
<div id="images"></div>