我的课程当然是一个单页面的应用程序。我在脚本中有两个功能。其中一个负责页面的结构(部分html),另一个负责页面内容的过滤。 m在控制台中出现错误“无法读取null的'firstChild'属性”。我假设由于第一个函数是异步的,因此第二个在第一个函数之前完成,并且我得到了一个错误。但这不能正常工作。如何解决?
//navigation for the single page app.
// It loads html code from external html files.
// External HTML pages after visited once are then stored.
// Keys correspond to piece identifiers.
// Values are the text content of each loaded external HTML file.
var partialHtmlCache = {};
// HTTP GET request using XMLHttpRequest.
// Fetches the file at the given path, then
// calls the callback with the text content of the file.
function fetchFile(path, callback) {
// Create a new AJAX request for fetching the partial HTML file.
var request = new XMLHttpRequest();
request.onload = function () {
callback(request.responseText);
};
request.open("GET", path);
request.send(null);
}
// This function implements a simple cache.
function getContent(pieceId, callback) {
// If the page has been fetched before,
if (partialHtmlCache[pieceId]) {
// Pass the previously fetched content to the callback.
callback(partialHtmlCache[pieceId]);
} else {
// If the page has not been fetched before.
fetchFile(pieceId + ".html", function (content) {
// Store the fetched content in the cache.
partialHtmlCache[pieceId] = content;
// Pass the newly fetched content to the callback.
callback(content);
});
}
}
// Updates the content based on the piece identifier.
function navigate() {
// Get a reference to the "contentcont" div.
var contentDiv = document.getElementById("contentcont"),
// Remove "#" character.
pieceId = location.hash.substr(1);
// Change the "contentcont" div innerHTML based on the piece identifier.
getContent(pieceId, function (content) {
contentDiv.innerHTML = content;
});
}
// If no fragment identifier is provided,
if (!location.hash) {
// default to #home.
location.hash = "#home";
}
// Navigate once to the initial fragment identifier.
navigate();
// Navigate whenever the fragment identifier value changes.
window.addEventListener("hashchange", navigate);
//Card filter on Tutorials Page
//Array with Cards
const cards = [
//Fundamentals
{
title: "Auzre basics",
description: "Azure Fundamentals",
category: "Fundamentals",
src: "https://www.youtube.com/embed/KXkBZCe699A",
},
];
function showCards() {
// Div containing cards with video Tutorials.
var cards_container = document.getElementById("cards");
// Remove all current card divs so we can replace with new ones below.
// If we don't do this the divs we add below will just be added after whatever
// is already on the page.
while (cards_container.firstChild) {
cards_container.removeChild(cards_container.firstChild);
}
var selected_category = document.getElementById("category-selector").value;
for (i = 0; i < cards.length; i++) {
var current_card = cards[i];
// The following two variables are boolean values
// category_correct is equal to true either if the selected option is all
// or the current Cards category value is the same as that selected.
var category_correct =
selected_category == "all" || current_card.category == selected_category;
// Only show Cards with the correct category
if (category_correct) {
var bootcolumn = generate_card_html(current_card);
cards_container.appendChild(bootcolumn);
}
}
}
function generate_card_html(card) {
var bootcolumn = document.createElement("div");
bootcolumn.setAttribute("class", "col-12 col-md-6 col-xl-3"); //
var card_div = document.createElement("div");
card_div.setAttribute("class", "card"); // Give div class="card"
var embed_div = document.createElement("div");
embed_div.setAttribute("class", "embed-responsive embed-responsive-16by9"); // add responsive embed.
var iframe = document.createElement("iframe"); // add iframe parameters
iframe.width = "320";
iframe.height = "220";
iframe.src = card.src;
iframe.frameborder = "0";
iframe.allow =
"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture";
iframe.allowfullscreen;
var card_body = document.createElement("div");
card_body.setAttribute("class", "card-body");
var header = document.createElement("h5");
header.setAttribute("class", "card-title");
header.innerHTML = card.title;
var description = document.createElement("p");
description.setAttribute("class", "card-text");
description.innerHTML = card.description;
bootcolumn.appendChild(card_div);
card_div.appendChild(embed_div);
embed_div.appendChild(iframe);
card_div.appendChild(card_body);
card_body.appendChild(header);
card_body.appendChild(description);
return bootcolumn;
}
showCards();
//Partial Html thats being injected into #contentcont
<label for="category-selector">Category: </label>
<select name="category" id="category-selector" onchange="showCards()">
<option value="all">All</option>
<option value="Fundamentals">Fundamentals</option>
<option value="Infrastructure">Infrastructure</option>
<option value="ai">AI & Data</option>
<option value="iot">Internet of things</option>
<option value="Security">Security</option>
<option value="devops">DevOps</option>
<option value="WebMobile">Web & Mobile</option>
</select>
<div class="row cards" id="cards"></div>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous"
/>
<link rel="stylesheet" href="assets/style.css" />
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.11.2/css/all.css"
/>
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.11.2/css/v4-shims.css"
/>
</head>
<body>
<div class="container-fluid">
<div class="main">
<nav class="navbar navbar-expand-lg fixed-top">
<a class="navbar-brand" href=""></a>
<button
class="navbar-toggler custom-toggler"
type="button"
data-toggle="collapse"
data-target="#navbar-content"
aria-controls="navbar-content"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar-content">
<ul class="navbar-nav ml-auto mt-2 mt-lg-0">
<li class="nav-item active">
<a class="nav-link" href="#home"
>Home<span class="sr-only">(current)</span></a
>
</li>
<li class="nav-item">
<a class="nav-link" href="#categories"
>Categories</a
>
</li>
<li class="nav-item">
<a class="nav-link" href="#tutorials">Tutorials</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#news">News</a>
</li>
<li class="nav-item">
<a
class="nav-link"
href="https://www.facebook.com/"
target="_blank"
rel="noopener"
><i class="fa fa-facebook-f"></i
><span class="sr-only">facebook</span></a
>
</li>
</ul>
</div>
</nav>
<div id="contentcont"></div>
</div>
</div>
<script
src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"
></script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"
></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/typed.js@2.0.11"></script>
<script src="/assets/script.js"></script>
</body>
</html>
答案 0 :(得分:0)
我可以从提供的代码中学到什么:
您的JavaScript代码正在调用navigate()
,随后几乎是showCards()
。
问题在于showCards()
依赖于navigate()
异步加载的内容。
与其直接调用showCards()
,不如尝试修改navigate()
:
function navigate() {
var contentDiv = document.getElementById("contentcont"),
pieceId = location.hash.substr(1);
getContent(pieceId, function (content) {
contentDiv.innerHTML = content;
// EDIT: now that content has been added to DOM, you can safely show cards:
showCards();
});
}