当数组没有重复时如何防止 .createElement 视图重复
how to prevent .createElement view duplication when array doesn't have duplication
let recipes = [];
let favouriteRecipes;
let ul = document.querySelector(".list-group");
const fetchRecipes = async function() {
try {
const res = await axios.get('https://api.spoonacular.com/recipes/complexSearch?apiKey=e7221d9e49e04040afd50e7b626e2f88&number=2');
recipes.push(...res.data.results);
createNewRecipe(recipes);
} catch (error) {
console.log(error);
}
}
const createNewRecipe = function(recipes) {
for (let recipe of recipes) {
let li = document.createElement('li');
li.textContent = recipe.title;
li.id = recipe.id;
li.className = "list-group-item";
let img = document.createElement('img');
img.src = recipe.image;
img.className = "card-img-top";
li.append(img);
ul.append(li);
let recipeId = document.getElementById(recipe.id).id;
fetchIndividualRecipe(recipeId, li);
addToFavourites(recipeId);
}
}
const fetchIndividualRecipe = async function(recipeId, li) {
try {
let id = recipeId;
const res = await axios.get(`https://api.spoonacular.com/recipes/${id}/information?apiKey=e7221d9e49e04040afd50e7b626e2f88&includeNutrition=true`)
createRecipeDetails(res, li);
} catch (error) {
console.log(error);
}
}
const createRecipeDetails = function(individualRecipeData, li) {
let cookingTime = individualRecipeData.data.readyInMinutes;
let calories;
for (let nutrient of individualRecipeData.data.nutrition.nutrients) {
if (nutrient.name === "Calories") {
calories = nutrient.amount;
}
}
let spanMinutes = document.createElement("span");
let spanCalories = document.createElement("span");
spanMinutes.className = "badge bg-secondary";
spanCalories.className = "badge bg-secondary"
spanMinutes.textContent = cookingTime + " minutes";
spanCalories.textContent = calories + " calories";
li.append(spanMinutes);
li.append(spanCalories);
}
// Add to favourites
const addToFavourites = function(id) {
document.getElementById(id).addEventListener('click', function() {
let clickedId = parseInt(id);
for (let recipe of recipes) {
if (recipe.id === clickedId) {
newFavRecipe = recipe;
displayFavouriteRecipes(newFavRecipe)
}
}
})
}
// Display favourites
const displayFavouriteRecipes = function(recipeReceived) {
let newRecipe = recipeReceived;
favouriteRecipes = JSON.parse(localStorage.getItem("favRecipes") || "[]");
let foundRecipe = false;
if (newRecipe) {
for (let rec of favouriteRecipes) {
if (rec.id.toString() === newRecipe.id.toString()) {
foundRecipe = true;
}
}
if (!foundRecipe) {
favouriteRecipes.push(newRecipe);
}
}
for (let favRec of favouriteRecipes) {
if (foundRecipe !== true) {
let h4 = document.createElement('h4');
h4.innerHTML = favRec.title;
document.body.append(h4);
}
}
localStorage.setItem("favRecipes", JSON.stringify(favouriteRecipes));
}
fetchRecipes();
displayFavouriteRecipes();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Recipes Project V1</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css" />
<link rel="stylesheet" href="recipes-coding-project-v1.css" />
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark">
<div class="container container-fluid">
<a class="navbar-brand" href="#">
<i class="bi bi-egg-fried"></i> Recipes
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="#">Recipe List</a>
</li>
</ul>
<span class="navbar-text">
Favourite Recipes
<i class="bi bi-heart-fill empty-heart"></i>
</span>
</div>
</div>
</nav>
<main class="container">
<h1>Recipes</h1>
<ul class="list-group list-group-flush"></ul>
<h2>Favourite Recipes</h2>
<ul class="list-group list-group-flush favourite-recipes-ul"></ul>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script src="recipes-coding-project-v1.js"></script>
</body>
</html>
目标:我只想在单击图片时添加一次 obj(食谱),将其保存到 localStorage 中的一个数组,并在视图中为我的 localStorage 数组中的每个食谱创建一个 h4。
问题:我的问题是,当我第一次创建新食谱并将其显示在视图中时,它仅在视图中复制,但在我的本地存储阵列中没有复制(按预期工作)。
但是,当我刷新时,视图会准确反映我的数组,而不是副本。没有错误或任何错误,我更改了我的代码几次,但我造成的伤害更大,它重复了每个食谱。
我的Html:
<main class="container">
<h1>Recipes</h1>
<ul class="list-group list-group-flush"></ul>
<h2>Favourite Recipes</h2>
<ul class="list-group list-group-flush favourite-recipes-ul"></ul>
</main>
这是我的代码:
// Add to favourites
const addToFavourites = function (id) {
document.getElementById(id).addEventListener('click', function() {
let clickedId = parseInt(id);
for (let recipe of recipes) {
if(recipe.id === clickedId) {
newFavRecipe = recipe;
displayFavouriteRecipes(newFavRecipe)
}
}
})
}
// Display favourites
const displayFavouriteRecipes = function (recipeReceived) {
let newRecipe = recipeReceived;
favouriteRecipes = JSON.parse(localStorage.getItem("favRecipes") || "[]");
let foundRecipe = false;
if (newRecipe) {
for (let rec of favouriteRecipes) {
if (rec.id.toString() === newRecipe.id.toString()) {
foundRecipe = true;
}
}
if (!foundRecipe) {
favouriteRecipes.push(newRecipe);
}
}
for (let favRec of favouriteRecipes) {
if (foundRecipe !== true) {
let h4 = document.createElement('h4');
h4.innerHTML = favRec.title;
document.body.append(h4);
}
}
localStorage.setItem("favRecipes", JSON.stringify(favouriteRecipes));
}
fetchRecipes();
displayFavouriteRecipes();
我重写了很多代码。我分离了从 API 获取数据并创建 Element.
的逻辑
现在应该可以了。
const createNewRecipe = (recipes, indivRecipes) => {
let ul = document.querySelector(".list-group");
for (let i = 0; i < recipes.length; i++) {
let li = document.createElement("li");
li.textContent = recipes[i].title;
li.id = recipes[i].id;
li.setAttribute("title", recipes[i].title);
li.className = "list-group-item";
let img = document.createElement("img");
img.src = recipes[i].image;
img.className = "card-img-top";
li.append(img);
ul.append(li);
createRecipeDetails(indivRecipes[i], li);
}
};
const createRecipeDetails = function (individualRecipeData, li) {
let cookingTime = individualRecipeData.data.readyInMinutes;
let calories;
for (let nutrient of individualRecipeData.data.nutrition.nutrients) {
if (nutrient.name === "Calories") {
calories = nutrient.amount;
}
}
let spanMinutes = document.createElement("span");
let spanCalories = document.createElement("span");
spanMinutes.className = "badge bg-secondary";
spanCalories.className = "badge bg-secondary";
spanMinutes.textContent = cookingTime + " minutes";
spanCalories.textContent = calories + " calories";
li.append(spanMinutes);
li.append(spanCalories);
};
//Click Event
document
.querySelector("ul.list-group.list-group-flush")
.addEventListener("click", addFavoriteRecipes);
function addFavoriteRecipes(event) {
const li = event.target.closest("li");
if (li) {
const recipeId = li.id;
const favoriteRecipes = JSON.parse(
localStorage.getItem("favRecipes") || "[]"
);
const checkIndex = favoriteRecipes.findIndex(el => el.id === recipeId);
if (checkIndex === -1) {
const ul = document.querySelector("ul.favourite-recipes-ul");
const h4 = document.createElement("h4");
const title = li.getAttribute("title");
h4.innerHTML = title;
ul.append(h4);
favoriteRecipes.push({ id: li.id, title: title });
localStorage.setItem("favRecipes", JSON.stringify(favoriteRecipes));
}
}
}
const fetchIndivRecipe = async function (recipeId) {
try {
const res = await axios.get(
`https://api.spoonacular.com/recipes/${recipeId}/information?apiKey=e7221d9e49e04040afd50e7b626e2f88&includeNutrition=true`
);
return res;
} catch (error) {
console.log(error);
throw new Error(error);
}
};
const fetchRecipes = async function () {
try {
const res = await axios.get(
"https://api.spoonacular.com/recipes/complexSearch?apiKey=e7221d9e49e04040afd50e7b626e2f88&number=2"
);
// recipes.push(...res.data.results);
// console.log({ recipes });
return res.data.results;
} catch (error) {
console.log(error);
}
};
const fetchAllIndivRecipes = async recipes => {
const res = recipes.map(recipe => fetchIndivRecipe(recipe.id));
return Promise.all(res);
};
const loadFavorite = () => {
const favoriteRecipes = JSON.parse(
localStorage.getItem("favRecipes") || "[]"
);
const ul = document.querySelector("ul.favourite-recipes-ul");
for (let favRec of favoriteRecipes) {
const h4 = document.createElement("h4");
h4.innerHTML = favRec.title;
ul.append(h4);
}
};
const main = async () => {
try {
const recipes = await fetchRecipes();
const indivRecipes = await fetchAllIndivRecipes(recipes);
createNewRecipe(recipes, indivRecipes);
loadFavorite();
} catch (err) {
console.log(err);
}
};
main();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Recipes Project V1</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css"
/>
<link rel="stylesheet" href="recipes-coding-project-v1.css" />
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark">
<div class="container container-fluid">
<a class="navbar-brand" href="#">
<i class="bi bi-egg-fried"></i> Recipes
</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarText"
aria-controls="navbarText"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="#">Recipe List</a>
</li>
</ul>
<span class="navbar-text">
Favourite Recipes
<i class="bi bi-heart-fill empty-heart"></i>
</span>
</div>
</div>
</nav>
<main class="container">
<h1>Recipes</h1>
<ul class="list-group list-group-flush"></ul>
<h2>Favourite Recipes</h2>
<ul class="list-group list-group-flush favourite-recipes-ul"></ul>
</main>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"
></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script src="recipes-coding-project-v1.js"></script>
</body>
</html>
let recipes = [];
let favouriteRecipes;
let ul = document.querySelector(".list-group");
const fetchRecipes = async function() {
try {
const res = await axios.get('https://api.spoonacular.com/recipes/complexSearch?apiKey=e7221d9e49e04040afd50e7b626e2f88&number=2');
recipes.push(...res.data.results);
createNewRecipe(recipes);
} catch (error) {
console.log(error);
}
}
const createNewRecipe = function(recipes) {
for (let recipe of recipes) {
let li = document.createElement('li');
li.textContent = recipe.title;
li.id = recipe.id;
li.className = "list-group-item";
let img = document.createElement('img');
img.src = recipe.image;
img.className = "card-img-top";
li.append(img);
ul.append(li);
let recipeId = document.getElementById(recipe.id).id;
fetchIndividualRecipe(recipeId, li);
addToFavourites(recipeId);
}
}
const fetchIndividualRecipe = async function(recipeId, li) {
try {
let id = recipeId;
const res = await axios.get(`https://api.spoonacular.com/recipes/${id}/information?apiKey=e7221d9e49e04040afd50e7b626e2f88&includeNutrition=true`)
createRecipeDetails(res, li);
} catch (error) {
console.log(error);
}
}
const createRecipeDetails = function(individualRecipeData, li) {
let cookingTime = individualRecipeData.data.readyInMinutes;
let calories;
for (let nutrient of individualRecipeData.data.nutrition.nutrients) {
if (nutrient.name === "Calories") {
calories = nutrient.amount;
}
}
let spanMinutes = document.createElement("span");
let spanCalories = document.createElement("span");
spanMinutes.className = "badge bg-secondary";
spanCalories.className = "badge bg-secondary"
spanMinutes.textContent = cookingTime + " minutes";
spanCalories.textContent = calories + " calories";
li.append(spanMinutes);
li.append(spanCalories);
}
// Add to favourites
const addToFavourites = function(id) {
document.getElementById(id).addEventListener('click', function() {
let clickedId = parseInt(id);
for (let recipe of recipes) {
if (recipe.id === clickedId) {
newFavRecipe = recipe;
displayFavouriteRecipes(newFavRecipe)
}
}
})
}
// Display favourites
const displayFavouriteRecipes = function(recipeReceived) {
let newRecipe = recipeReceived;
favouriteRecipes = JSON.parse(localStorage.getItem("favRecipes") || "[]");
let foundRecipe = false;
if (newRecipe) {
for (let rec of favouriteRecipes) {
if (rec.id.toString() === newRecipe.id.toString()) {
foundRecipe = true;
}
}
if (!foundRecipe) {
favouriteRecipes.push(newRecipe);
}
}
for (let favRec of favouriteRecipes) {
if (foundRecipe !== true) {
let h4 = document.createElement('h4');
h4.innerHTML = favRec.title;
document.body.append(h4);
}
}
localStorage.setItem("favRecipes", JSON.stringify(favouriteRecipes));
}
fetchRecipes();
displayFavouriteRecipes();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Recipes Project V1</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css" />
<link rel="stylesheet" href="recipes-coding-project-v1.css" />
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark">
<div class="container container-fluid">
<a class="navbar-brand" href="#">
<i class="bi bi-egg-fried"></i> Recipes
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="#">Recipe List</a>
</li>
</ul>
<span class="navbar-text">
Favourite Recipes
<i class="bi bi-heart-fill empty-heart"></i>
</span>
</div>
</div>
</nav>
<main class="container">
<h1>Recipes</h1>
<ul class="list-group list-group-flush"></ul>
<h2>Favourite Recipes</h2>
<ul class="list-group list-group-flush favourite-recipes-ul"></ul>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script src="recipes-coding-project-v1.js"></script>
</body>
</html>
目标:我只想在单击图片时添加一次 obj(食谱),将其保存到 localStorage 中的一个数组,并在视图中为我的 localStorage 数组中的每个食谱创建一个 h4。
问题:我的问题是,当我第一次创建新食谱并将其显示在视图中时,它仅在视图中复制,但在我的本地存储阵列中没有复制(按预期工作)。 但是,当我刷新时,视图会准确反映我的数组,而不是副本。没有错误或任何错误,我更改了我的代码几次,但我造成的伤害更大,它重复了每个食谱。
我的Html:
<main class="container">
<h1>Recipes</h1>
<ul class="list-group list-group-flush"></ul>
<h2>Favourite Recipes</h2>
<ul class="list-group list-group-flush favourite-recipes-ul"></ul>
</main>
这是我的代码:
// Add to favourites
const addToFavourites = function (id) {
document.getElementById(id).addEventListener('click', function() {
let clickedId = parseInt(id);
for (let recipe of recipes) {
if(recipe.id === clickedId) {
newFavRecipe = recipe;
displayFavouriteRecipes(newFavRecipe)
}
}
})
}
// Display favourites
const displayFavouriteRecipes = function (recipeReceived) {
let newRecipe = recipeReceived;
favouriteRecipes = JSON.parse(localStorage.getItem("favRecipes") || "[]");
let foundRecipe = false;
if (newRecipe) {
for (let rec of favouriteRecipes) {
if (rec.id.toString() === newRecipe.id.toString()) {
foundRecipe = true;
}
}
if (!foundRecipe) {
favouriteRecipes.push(newRecipe);
}
}
for (let favRec of favouriteRecipes) {
if (foundRecipe !== true) {
let h4 = document.createElement('h4');
h4.innerHTML = favRec.title;
document.body.append(h4);
}
}
localStorage.setItem("favRecipes", JSON.stringify(favouriteRecipes));
}
fetchRecipes();
displayFavouriteRecipes();
我重写了很多代码。我分离了从 API 获取数据并创建 Element.
的逻辑现在应该可以了。
const createNewRecipe = (recipes, indivRecipes) => {
let ul = document.querySelector(".list-group");
for (let i = 0; i < recipes.length; i++) {
let li = document.createElement("li");
li.textContent = recipes[i].title;
li.id = recipes[i].id;
li.setAttribute("title", recipes[i].title);
li.className = "list-group-item";
let img = document.createElement("img");
img.src = recipes[i].image;
img.className = "card-img-top";
li.append(img);
ul.append(li);
createRecipeDetails(indivRecipes[i], li);
}
};
const createRecipeDetails = function (individualRecipeData, li) {
let cookingTime = individualRecipeData.data.readyInMinutes;
let calories;
for (let nutrient of individualRecipeData.data.nutrition.nutrients) {
if (nutrient.name === "Calories") {
calories = nutrient.amount;
}
}
let spanMinutes = document.createElement("span");
let spanCalories = document.createElement("span");
spanMinutes.className = "badge bg-secondary";
spanCalories.className = "badge bg-secondary";
spanMinutes.textContent = cookingTime + " minutes";
spanCalories.textContent = calories + " calories";
li.append(spanMinutes);
li.append(spanCalories);
};
//Click Event
document
.querySelector("ul.list-group.list-group-flush")
.addEventListener("click", addFavoriteRecipes);
function addFavoriteRecipes(event) {
const li = event.target.closest("li");
if (li) {
const recipeId = li.id;
const favoriteRecipes = JSON.parse(
localStorage.getItem("favRecipes") || "[]"
);
const checkIndex = favoriteRecipes.findIndex(el => el.id === recipeId);
if (checkIndex === -1) {
const ul = document.querySelector("ul.favourite-recipes-ul");
const h4 = document.createElement("h4");
const title = li.getAttribute("title");
h4.innerHTML = title;
ul.append(h4);
favoriteRecipes.push({ id: li.id, title: title });
localStorage.setItem("favRecipes", JSON.stringify(favoriteRecipes));
}
}
}
const fetchIndivRecipe = async function (recipeId) {
try {
const res = await axios.get(
`https://api.spoonacular.com/recipes/${recipeId}/information?apiKey=e7221d9e49e04040afd50e7b626e2f88&includeNutrition=true`
);
return res;
} catch (error) {
console.log(error);
throw new Error(error);
}
};
const fetchRecipes = async function () {
try {
const res = await axios.get(
"https://api.spoonacular.com/recipes/complexSearch?apiKey=e7221d9e49e04040afd50e7b626e2f88&number=2"
);
// recipes.push(...res.data.results);
// console.log({ recipes });
return res.data.results;
} catch (error) {
console.log(error);
}
};
const fetchAllIndivRecipes = async recipes => {
const res = recipes.map(recipe => fetchIndivRecipe(recipe.id));
return Promise.all(res);
};
const loadFavorite = () => {
const favoriteRecipes = JSON.parse(
localStorage.getItem("favRecipes") || "[]"
);
const ul = document.querySelector("ul.favourite-recipes-ul");
for (let favRec of favoriteRecipes) {
const h4 = document.createElement("h4");
h4.innerHTML = favRec.title;
ul.append(h4);
}
};
const main = async () => {
try {
const recipes = await fetchRecipes();
const indivRecipes = await fetchAllIndivRecipes(recipes);
createNewRecipe(recipes, indivRecipes);
loadFavorite();
} catch (err) {
console.log(err);
}
};
main();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Recipes Project V1</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css"
/>
<link rel="stylesheet" href="recipes-coding-project-v1.css" />
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark">
<div class="container container-fluid">
<a class="navbar-brand" href="#">
<i class="bi bi-egg-fried"></i> Recipes
</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarText"
aria-controls="navbarText"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="#">Recipe List</a>
</li>
</ul>
<span class="navbar-text">
Favourite Recipes
<i class="bi bi-heart-fill empty-heart"></i>
</span>
</div>
</div>
</nav>
<main class="container">
<h1>Recipes</h1>
<ul class="list-group list-group-flush"></ul>
<h2>Favourite Recipes</h2>
<ul class="list-group list-group-flush favourite-recipes-ul"></ul>
</main>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"
></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script src="recipes-coding-project-v1.js"></script>
</body>
</html>