重构MVC
上一篇文章简单的介绍了一下关于MVC架构的信息,本篇我们将实际的在我们的项目中实际的应用一下;
- 第一步就是创建文件;
- 接着就按照上篇文章最后的图片来完成就可以了
export const state = {recipe: {},
};export const loadRecipe = async function (id) {const res = await fetch(`https://forkify-api.herokuapp.com/api/v2/recipes/${id}`);const data = await res.json();if (!res.ok) throw new Error(`${data.message} (${res.status})`);let { recipe } = data.data;recipe = {id: recipe.id,title: recipe.title,publisher: recipe.publisher,sourceUrl: recipe.source_url,image: recipe.image_url,servings: recipe.servings,cookingTime: recipe.cooking_time,ingredients: recipe.ingredients,};console.log(recipe);
};
- 然后我们在控制器中导入model
import * as model from './model.js';
- 之后我们就可以调用了,然后我们把加载食谱的给加上
await model.loadRecipe(id);
- model中缺少了错误处理的代码,我们加上
export const loadRecipe = async function (id) {try {const res = await fetch(`https://forkify-api.herokuapp.com/api/v2/recipes/${id}`);const data = await res.json();if (!res.ok) throw new Error(`${data.message} (${res.status})`);const { recipe } = data.data;state.recipe = {id: recipe.id,title: recipe.title,publisher: recipe.publisher,sourceUrl: recipe.source_url,image: recipe.image_url,servings: recipe.servings,cookingTime: recipe.cooking_time,ingredients: recipe.ingredients,};console.log(state.recipe);} catch (err) {alert(err);}
};
const { recipe } = model.state;先暂时加上运行看看效果
- 接下来我们处理视图,之后导出并导入
class RecipeView {#parentElement = document.querySelector('.recipe');
}export default new RecipeView();
import recipeView from './view/recipeView.js';
- 我们首先在控制器将视图渲染出来
//(2)渲染菜谱recipeView.render(model.state.recipe);
- 然后我们在视图中将渲染的代码写出来
import icons from 'url:../../img/icons.svg';class RecipeView {#parentElement = document.querySelector('.recipe');#data;render(data) {this.#data = data;const markup = this.#generateMarkup();this.#clear();this.#parentElement.insertAdjacentHTML('afterbegin', markup);}#clear() {this.#parentElement.innerHTML = '';}renderSpinner = function () {const markup = `<div class="spinner"><svg><use href="${icons}#icon-loader"></use></svg></div>`;this.#parentElement.innerHTML = '';this.#parentElement.insertAdjacentHTML('afterbegin', markup);};#generateMarkup() {return `<figure class="recipe__fig"><img src="${this.#data.image}" alt="Tomato" class="recipe__img" /><h1 class="recipe__title"><span>${this.#data.title}</span></h1></figure><div class="recipe__details"><div class="recipe__info"><svg class="recipe__info-icon"><use href="${icons}#icon-clock"></use></svg><span class="recipe__info-data recipe__info-data--minutes">${this.#data.cookingTime}</span><span class="recipe__info-text">minutes</span></div><div class="recipe__info"><svg class="recipe__info-icon"><use href="${icons}#icon-users"></use></svg><span class="recipe__info-data recipe__info-data--people">${this.#data.servings}</span><span class="recipe__info-text">servings</span><div class="recipe__info-buttons"><button class="btn--tiny btn--increase-servings"><svg><use href="${icons}#icon-minus-circle"></use></svg></button><button class="btn--tiny btn--increase-servings"><svg><use href="${icons}#icon-plus-circle"></use></svg></button></div></div><div class="recipe__user-generated"><svg><use href="${icons}#icon-user"></use></svg></div><button class="btn--round"><svg class=""><use href="${icons}#icon-bookmark-fill"></use></svg></button></div><div class="recipe__ingredients"><h2 class="heading--2">Recipe ingredients</h2><ul class="recipe__ingredient-list">${this.#data.ingredients.map(ing => {return `<li class="recipe__ingredient"><svg class="recipe__icon"><use href="${icons}#icon-check"></use></svg><div class="recipe__quantity">${ing.quantity}</div><div class="recipe__description"><span class="recipe__unit">${ing.unit}</span>${ing.description}}</div></li>`;}).join('')}</ul></div><div class="recipe__directions"><h2 class="heading--2">How to cook it</h2><p class="recipe__directions-text">This recipe was carefully designed and tested by<span class="recipe__publisher">${this.#data.publisher}</span>. Please check outdirections at their website.</p><aclass="btn--small recipe__btn"href="${this.#data.sourceUrl}"target="_blank"><span>Directions</span><svg class="search__icon"><use href="${icons}#icon-arrow-right"></use></svg></a></div>`;}
}export default new RecipeView();
- 之后我们在处理一下图标的视图
import icons from 'url:../img/icons.svg';
........
renderSpinner = function () {const markup = `<div class="spinner"><svg><use href="${icons}#icon-loader"></use></svg></div>`;this.#parentElement.innerHTML = '';this.#parentElement.insertAdjacentHTML('afterbegin', markup);};
- 接着我们重构一小段代码
#generateMarkupIngredient(ing) {return `<li class="recipe__ingredient"><svg class="recipe__icon"><use href="${icons}#icon-check"></use></svg><div class="recipe__quantity">${ing.quantity}</div><div class="recipe__description"><span class="recipe__unit">${ing.unit}</span>${ing.description}}</div></li>`;}
}
- 然后调用
<div class="recipe__ingredients"><h2 class="heading--2">Recipe ingredients</h2><ul class="recipe__ingredient-list">${this.#data.ingredients.map(this.#generateMarkupIngredient).join('')}</ul></div>
- 这样我们本节目的就完成了,视图层的代码如下
import icons from 'url:../../img/icons.svg';class RecipeView {#parentElement = document.querySelector('.recipe');#data;render(data) {this.#data = data;const markup = this.#generateMarkup();this.#clear();this.#parentElement.insertAdjacentHTML('afterbegin', markup);}#clear() {this.#parentElement.innerHTML = '';}renderSpinner = function () {const markup = `<div class="spinner"><svg><use href="${icons}#icon-loader"></use></svg></div>`;this.#parentElement.innerHTML = '';this.#parentElement.insertAdjacentHTML('afterbegin', markup);};#generateMarkup() {return `<figure class="recipe__fig"><img src="${this.#data.image}" alt="Tomato" class="recipe__img" /><h1 class="recipe__title"><span>${this.#data.title}</span></h1></figure><div class="recipe__details"><div class="recipe__info"><svg class="recipe__info-icon"><use href="${icons}#icon-clock"></use></svg><span class="recipe__info-data recipe__info-data--minutes">${this.#data.cookingTime}</span><span class="recipe__info-text">minutes</span></div><div class="recipe__info"><svg class="recipe__info-icon"><use href="${icons}#icon-users"></use></svg><span class="recipe__info-data recipe__info-data--people">${this.#data.servings}</span><span class="recipe__info-text">servings</span><div class="recipe__info-buttons"><button class="btn--tiny btn--increase-servings"><svg><use href="${icons}#icon-minus-circle"></use></svg></button><button class="btn--tiny btn--increase-servings"><svg><use href="${icons}#icon-plus-circle"></use></svg></button></div></div><div class="recipe__user-generated"><svg><use href="${icons}#icon-user"></use></svg></div><button class="btn--round"><svg class=""><use href="${icons}#icon-bookmark-fill"></use></svg></button></div><div class="recipe__ingredients"><h2 class="heading--2">Recipe ingredients</h2><ul class="recipe__ingredient-list">${this.#data.ingredients.map(this.#generateMarkupIngredient).join('')}</ul></div><div class="recipe__directions"><h2 class="heading--2">How to cook it</h2><p class="recipe__directions-text">This recipe was carefully designed and tested by<span class="recipe__publisher">${this.#data.publisher}</span>. Please check outdirections at their website.</p><aclass="btn--small recipe__btn"href="${this.#data.sourceUrl}"target="_blank"><span>Directions</span><svg class="search__icon"><use href="${icons}#icon-arrow-right"></use></svg></a></div>`;}#generateMarkupIngredient(ing) {return `<li class="recipe__ingredient"><svg class="recipe__icon"><use href="${icons}#icon-check"></use></svg><div class="recipe__quantity">${ing.quantity}</div><div class="recipe__description"><span class="recipe__unit">${ing.unit}</span>${ing.description}}</div></li>`;}
}export default new RecipeView();