我正在为 js 中的 html 设置动态配置文件卡并使用外部 json 文件,但我一直遇到一个问题,即 js json 脚本的社交部分将值显示为未定义
<script>var profiles = {}
window.onload = function () {
GetProfiles()
}
function GetProfiles(){
$.getJSON('https://gameremporium.us/image/Profile/profile.json', function(data) {
var projson = data;
for(var q in projson){
jsonpro = projson[q];
for(var i in jsonpro){
profile = jsonpro[i];
if (typeof profile["name"] != "" || typeof profile["name"] != undefined){
profiles["name"] += profile.name;
}
if (typeof profile["Nick_name"] != "" || typeof profile["Nick_name"] != undefined){
profiles["Nick"] += profile.Nick_name;
}
if (typeof profile["role"] != "" || typeof profile["role"] != undefined){
profiles["role"] += profile.role;
}
if (typeof profile["description"] != "" || typeof profile["description"] != undefined){
profiles["description"] += profile.description;
}
if (typeof profile["image"] != "" || typeof profile["image"] != undefined){
profiles["image"] += profile.image_name;
}
if (typeof profile["imageBG"] != "" || typeof profile["imageBG"] != undefined){
profiles["imageBG"] += profile.imageBG_name;
}
if (typeof profile["contact"] != "" || typeof profile["contact"] != undefined){
profiles["contact"] += profile.contact_link;
}
for(var a in profile){
social = profile[a].social_links;
for(var a in social){
media = social[a]
if(media["link_one"].name && media["link_one"].link != ""){
profiles.social["link_one"]["name"] += media.name;
profiles.social["link_one"]["link"] += media.link;
}
if(media.name && media.link != ""){
profiles.social["link_two"]["name"] += media.name
profiles.social["link_two"]["link"] += media.link
}
if(media.name && media.link != ""){
profiles.social["link_three"]["name"] += media.name
profiles.social["link_three"]["link"] += media.link
}
if(media.name && media.link_four.link != ""){
profiles.social["link_four"]["name"] += media.name
profiles.social["link_four"]["link"] += media.link
}
if(media.name && media.link != ""){
profiles.social["link_five"]["name"] += media.name
profiles.social["link_five"]["link"] += media.link
}
if(media.name && media.link != ""){
profiles.social["link_six"]["name"] += media.name
profiles.social["link_six"]["link"] += media.link
}
}
}
SetProfiles(profiles);
}
};
})
};
function SetProfiles(profiles){
for(var i in profiles){
profile = profiles[i];
document.getElementById("profiles").innerHTML = '<div class="card"><img src="'+profile["imageBG"]+'" alt="background-image" class="bg-img"><img src='+profile["image"]+'" alt="avatar" class="profile-img"><h1>"'+profile["name"]+'"</h1><p class="about-info">"'+profile["description"]+'"</p><a href="'+profile["contact"]+'" class="btn">Contact</a><ul class="social-list" id="social"><li><a href="@" class="social-link"><i class="fa fa-facebook-square"></i></a></li></ul></div>';
}
}</script>
THe problem
代码在下面并且没有从 json 文件的配置文件部分的社会嵌套值中获取名称值
for(var a in profile){
social += profile[a].social_links;
if(typeof social.link_one.name && social.social_links.link_one.link != ""){
编辑:更新代码现在只显示一切回到未定义状态
你的示例代码中有太多需要修复的地方,所以我不会逐行检查它,而是提供这个替代代码建议。
// kicks off the profile fetching/rendering
makeCards();
// gets the data and invokes addCard for each profile
async function makeCards () {
const json = await getProfiles();
const container = document.getElementById('profiles');
Object.values(json.Profiles).forEach(profile => addCard(profile, container));
}
// makes an individual profile card and adds to parent
function addCard(profile, parent) {
// bail if we don't have a profile or a parent node
if (!profile || !parent) {
return;
}
// use a template literal instead of string concatenation for the html
parent.innerHTML += `
<div class="card">
${imgHtml(profile)}
<h1>${profile.name}</h1>
<p class="about-info">
${contactLinkHtml(profile)}
<ul class="social-list" id="social">
<li>
<a href="@" class="social-link><i class="fa facebook-square"></i></a>
</li>
</ul>
</p>
</div>
`
}
// use fallback image when image_name isn't present
function imgHtml ({image_name}) {
return `<img src="${image_name || '//placekitten.com/200'}" alt="avatar" class="profile-img" />`
}
// return html only when contact_link is present
function contactLinkHtml ({contact_link}) {
return !contact_link ? '' : `<a href="${contact_link}" class="btn">Contact</a>`
}
// ------ the rest is just hand-waving data stuff --------- //
// simulate the fetch request
async function getProfiles() {
return new Promise((resolve) => {
setTimeout(resolve(json(), 500));
})
}
// sample data
function json() {
return {
"Profiles": {
"profile 1": {
"name": "LoneOxi",
"Nick_name": "",
"image_name": "",
"imageBG_name": "",
"contact_link": "",
"description": "",
"role": "",
"social_links": {
"link_one": {
"name": "",
"link": ""
},
"link_two": {
"name": "",
"link": ""
},
"link_three": {
"name": "",
"link": ""
},
"link_four": {
"name": "",
"link": ""
},
"link_five": {
"name": "",
"link": ""
},
"link_six": {
"name": "",
"link": ""
},
"link_seven": {
"name": "",
"link": ""
}
}
},
"profile 2": {
"name": "Lonnie Gibson",
"Nick_name": "Quentin",
"image_name": "//placekitten.com/201",
"imageBG_name": "LonnieGBG.jpg",
"contact_link": "",
"description": "",
"role": "",
"social_links": {
"link_one": {
"name": "",
"link": ""
},
"link_two": {
"name": "",
"link": ""
},
"link_three": {
"name": "",
"link": ""
},
"link_four": {
"name": "",
"link": ""
},
"link_five": {
"name": "",
"link": ""
},
"link_six": {
"name": "",
"link": ""
},
"link_seven": {
"name": "",
"link": ""
}
}
}
}
}
}
:root {
font-family: sans-serif;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
#profiles {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.card {
border-radius: 8px;
box-shadow: 4px 4px 8px #00000033;
width: 200px;
padding: .5rem;
}
.profile-img {
width: 100px;
aspect-ratio: 1;
border-radius: 4px;
}
<div id="profiles"></div>
更新:
我强烈建议您将数组用于项目列表而不是命名每个项目,例如
profile 1
, profile 2
.
例如,您的个人资料列表可能如下所示。 (为了简洁和可读性,我省略了一些配置文件属性。)
{
"profiles": [
{
"name": "LoneOxi",
"nickname": "",
"imageUrl": "",
},
{
"name": "Lonnie Gibson",
"nickname": "Quentin",
"imageUrl": "//placekitten.com/201"
}
]
}
除了消除json中的杂音和复杂度,还可以直接使用map、forEach、for...of等数组迭代方式
obj.Profiles.forEach(profile => console.log(profile.name))
与
link_one
,link_two
相同。以这种方式命名它们毫无意义。我建议您使用名称作为密钥:
{
"social_links": {
"facebook": "https://...",
"twitter": "https://...",
"instagram": "https://...."
}
}
您可以使用 for...in 循环 或通过 Object.entries:
迭代这些for(const name in social_links) {
const url = social_links[name];
// do stuff with name and url
}
Object.entries(social_links).forEach(([name, url]) => {
// do stuff with name and url
});
或者只使用您已经在使用的对象的数组:
{
"social_links": [
{
"name": "facebook",
"link": "https://..."
},
{
"name": "twitter",
"link": "https://..."
},
{
"name": "instagram",
"link": "https://..."
},
]
}
social_links.forEach(item => {
// do stuff with item.name, item.link
})
我认为将 json 响应的根保留为一个对象以允许额外的元数据或其他内容是个好主意,但将您的 API 响应放在一起可能看起来更像这样。
{
metadata: {
lastUpdated: '2023-04-04'
},
profiles: [
{
name: "Lonnie Gibson",
image: "/path/to/avatar.jpg",
bgImage: "/path/to/bgImage.jpg",
social: [
{
name: 'facebook',
url: 'https://facebook.com/...'
},
{
name: 'twitter',
url: 'https://twitter.com/...'
}
]
},
{
name: "Someone Else",
image: "/path/to/avatar.jpg",
bgImage: "/path/to/bgImage.jpg",
social: [
{
name: 'facebook',
url: 'https://facebook.com/...'
},
{
name: 'twitter',
url: 'https://twitter.com/...'
}
]
}
]
}