如何制作营养膳食计算器_如何创建随机膳食生成器

如何制作营养膳食计算器

Last week I decided to take on a new challenge. I called it: The #100Days100Projects Challenge.

上周,我决定接受一个新的挑战。 我称之为: #100Days100Projects挑战。

The purpose of the challenge is to create one project every single day. Think of it as a next step for the #100DaysOfCode challenge.

挑战的目的是每天创建一个项目。 将其视为#100DaysOfCode挑战的下一步。

A project can be either:

一个项目可以是:

  • an app

    一个应用
  • a component

    一个组件
  • a website

    一个网站
  • a game

    一个游戏
  • a library

    图书馆

    and so on...

    等等...

The programming language used is also not important, but I need to complete the project by 11:59 PM (my time), otherwise I'm "punishing" myself by giving away $5 for 5 people ($25 total) - first 5 people who point it out on Twitter that I missed the deadline.

所使用的编程语言也不重要,但是我需要在11:59 PM(我的时间)之前完成该项目,否则我将通过“惩罚”我的方式,即每5人赠送5美元(总计25美元)-前5个人在Twitter上指出我错过了截止日期。

If you want to join, you can read more about this challenge and the other variants it has here.

如果您想加入,可以在此处阅读有关此挑战及其其他变体的更多信息。

Note: you don't have to give away $5 if you fail, just set some other "punishment" for yourself. Also, there are other variants with less days (7Days7Projects and 30Days30Projects) if you don't feel like taking on the 100Days challenge.

注意 :如果失败,您不必捐出$ 5,只需为自己设置其他“惩罚”即可。 另外,如果您不想参加100Days挑战,那么还有其他几天的变体会更少( 7Days7Projects30Days30Projects )。



For the first project in the #100Days100Projects I thought about working with a public API in order to get some data that would be displayed in a webpage - an usual thing to do with an API.

对于#100Days100Projects中的第一个项目,我考虑过使用公共API来获取一些可以在网页上显示的数据-这是与API共同的事情。

For that I chose to use TheMealDB's public API in order to get some random meals by pressing a button. Something straightforward!

为此,我选择使用TheMealDB的公共API,以便通过按一下按钮获得一些随机食物。 简单明了!

Check out the live version of what we're going to build in this article over on CodePen:

在CodePen上查看我们将在本文中构建的实时版本:

As always let's start at the beginning:

与往常一样,让我们​​从头开始:

HTML (The HTML)

Feeling hungry?

Get a random meal by clicking below

We have a little text, but the two most important parts are:

我们有一点文字,但是两个最重要的部分是:

  • the #get_meal button and

    #get_meal按钮和

  • the #meal div

    #meal div

We're going to use the button to make a request to the API. This will send back some data that we're going to put into the #meal div which acts as a container - in this case.

我们将使用button向API发出请求。 这将发回一些数据,我们将把它们放入用作容器的#meal div中(在这种情况下)。

Usually after the HTML I'll go right into the CSS. But we don't yet have the entire markup as it will be populated in the JavaScript section, so that's what we're going to do next.

通常在HTML之后,我会直接进入CSS。 但是我们还没有完整的标记,因为它将在JavaScript部分中进行填充,所以这就是我们下一步要做的。

JavaScript (The JavaScript)

As mentioned above, we need the button and that container div:

如上所述,我们需要button和那个容器div

const get_meal_btn = document.getElementById('get_meal');
const meal_container = document.getElementById('meal');

Next, before we dive more into the code, let's see what the API is going to return. For that please open the following URL: https://www.themealdb.com/api/json/v1/1/random.php.

接下来,在深入研究代码之前,让我们看看API将会返回什么。 为此,请打开以下URL: https : //www.themealdb.com/api/json/v1/1/random.php 。

As you can see from the URL, we are getting a random meal from this API (refresh to see the randomness). When we're making a GET request to that endpoint (like accessing it from the browser), it sends back a JSON response, which we can parse in order to retrieve the data we want.

正如您从URL中看到的那样,我们从此API中获得了随机餐点(刷新以查看随机性 )。 当我们向该端点发出GET请求(例如从浏览器访问它)时,它将发送回JSON响应,我们可以对其进行解析以检索所需的数据。

The data looks something like this:

数据看起来像这样:

{
	meals: [
		{
			idMeal: '52873',
			strMeal: 'Beef Dumpling Stew',
			strDrinkAlternate: null,
			strCategory: 'Beef',
			strArea: 'British',
			strInstructions: 'Long description',
			strMealThumb:
				'https://www.themealdb.com/images/media/meals/uyqrrv1511553350.jpg',
			strTags: 'Stew,Baking',
			strYoutube: 'https://www.youtube.com/watch?v=6NgheY-r5t0',
			strIngredient1: 'Olive Oil',
			strIngredient2: 'Butter',
			strIngredient3: 'Beef',
			strIngredient4: 'Plain Flour',
			strIngredient5: 'Garlic',
			strIngredient6: 'Onions',
			strIngredient7: 'Celery',
			strIngredient8: 'Carrots',
			strIngredient9: 'Leek',
			strIngredient10: 'Swede',
			strIngredient11: 'Red Wine',
			strIngredient12: 'Beef Stock',
			strIngredient13: 'Bay Leaf',
			strIngredient14: 'Thyme',
			strIngredient15: 'Parsley',
			strIngredient16: 'Plain Flour',
			strIngredient17: 'Baking Powder',
			strIngredient18: 'Suet',
			strIngredient19: 'Water',
			strIngredient20: '',
			strMeasure1: '2 tbs',
			strMeasure2: '25g',
			strMeasure3: '750g',
			strMeasure4: '2 tblsp ',
			strMeasure5: '2 cloves minced',
			strMeasure6: '175g',
			strMeasure7: '150g',
			strMeasure8: '150g',
			strMeasure9: '2 chopped',
			strMeasure10: '200g',
			strMeasure11: '150ml',
			strMeasure12: '500g',
			strMeasure13: '2',
			strMeasure14: '3 tbs',
			strMeasure15: '3 tblsp chopped',
			strMeasure16: '125g',
			strMeasure17: '1 tsp ',
			strMeasure18: '60g',
			strMeasure19: 'Splash',
			strMeasure20: '',
			strSource:
				'https://www.bbc.co.uk/food/recipes/beefstewwithdumpling_87333',
			dateModified: null
		}
	];
}

Basically we get back an array of meals, but with only one item in it - the randomly generated one. And this item has all the data we want to showcase in our little application. Things like:

基本上,我们取回一meals ,但其中只有一个-随机产生的。 并且此项目具有我们要在我们的小应用程序中展示的所有数据。 像:

  • meal name (under strMeal)

    餐名(在strMeal下)

  • meal caterogy (under strCategory)

    膳食分类(在strCategory下)

  • meal image (under strMealThumb)

    膳食图像(在strMealThumb下)

  • a youtube video with the recipe (under strYoutube)

    带有配方的youtube视频(在strYoutube )

  • the ingredients and the measures (under strIngredientsX and strMeasureX - X representing the nth ingredient and it's measure).This is a little bit awkward as I would expect here to have an array with this information, but they choose to add it as object props. On well... The important thing to note is that there are a maximum of 20 ingredients / measures, although they aren't all filled in - some of them might be empty so we need to account for that.

    成分和度量(在strIngredientsXstrMeasureX下-X代表第n个成分及其度量)。这有点尴尬,因为我希望在这里具有一个包含此信息的数组,但是他们选择将其添加为对象道具。 好吧...要注意的重要一点是,虽然还没有全部填写,但最多有20种成分/度量-其中有些可能是空的,因此我们需要对此加以考虑。

Now that we have the button we're going to add an event listener for the click event. Inside we're going to make a request to the API:

现在我们有了按钮,我们将为click事件添加一个事件侦听器。 在内部,我们将向API发出请求:

get_meal_btn.addEventListener('click', () => {
	fetch('https://www.themealdb.com/api/json/v1/1/random.php')
		.then(res => res.json())
		.then(res => {
			createMeal(res.meals[0]);
		})
		.catch(e => {
			console.warn(e);
		});
});

We're using the fetch API to do the request. We just have to pass in the url of the API we want to make a GET request to, and we're going to get back a promise.

我们正在使用访存 API来执行请求。 我们只需要传递要发出GET请求的API的URL,我们就可以收回承诺。

Once this is resolved we have a response (res). This res isn't yet in the state we want it to be, so we're going to call the .json() method on it. Then finally we have the beautiful object. Yay!

解决此问题后,我们将做出回应( res )。 此res尚未处于我们想要的状态,因此我们将对其调用.json()方法。 最后,我们有了美丽的物体。 好极了!

As mentioned above, the API returns the meals array but only with an item in it. So we're going to pass that item (at index 0) into our createMeal function, which we'll define next.

如上所述,API返回的meals数组,但其中仅包含一个项目。 因此,我们将将该项目(在索引0 )传递到我们的createMeal函数中,我们将在下面定义它。

I'm going to paste the entire block of code below and we're going to go into detail afterwards, so hold on for a second.

我将在下面粘贴整个代码块,然后再进行详细介绍,因此请稍等片刻。

const createMeal = meal => {
	const ingredients = [];

	// Get all ingredients from the object. Up to 20
	for (let i = 1; i <= 20; i++) {
		if (meal[`strIngredient${i}`]) {
			ingredients.push(
				`${meal[`strIngredient${i}`]} - ${meal[`strMeasure${i}`]}`
			);
		} else {
			// Stop if there are no more ingredients
			break;
		}
	}

	const newInnerHTML = `
		
Meal Image ${ meal.strCategory ? `

Category: ${meal.strCategory}

` : '' } ${meal.strArea ? `

Area: ${meal.strArea}

` : ''} ${ meal.strTags ? `

Tags: ${meal.strTags .split(',') .join(', ')}

` : '' }
Ingredients:
    ${ingredients.map(ingredient => `
  • ${ingredient}
  • `).join('')}

${meal.strMeal}

${meal.strInstructions}

${ meal.strYoutube ? `
Video Recipe
` : '' } `; meal_container.innerHTML = newInnerHTML; };

Basically the entire function's purpose is to get the JSON response, parse it, and transform it into an HTML component. For that we need to do a couple of things, as the data is not yet formated exactly the way we want it to be.

基本上,整个功能的目的是获取JSON响应,对其进行解析并将其转换为HTML组件。 为此,我们需要做几件事情,因为数据尚未按照我们希望的方式完全格式化。

First, we're getting all the ingredients and their measures. As mentioned above there are a maximum of 20 ingredients, but they are separated into their own properties in the object like: strIngredient1, strIngredient2, etc... (I still don't know why they did that, but... ).

首先,我们要掌握所有要素措施 。 如上所述,最多有20种成分,但是它们在对象中分成了自己的属性,例如: strIngredient1strIngredient2等(我仍然不知道为什么这样做,但是...) 。

So, we're creating a for loop which goes from 1 to 20 and checks if the meal has that corresponding ingredient-measure pair. If it does, we're putting it into the ingredients array. If there aren't any more ingredients we're stopping the for loop with a break condition.

因此,我们正在创建一个从120for循环,并检查meal是否具有相应的ingredient - measure对。 如果是这样,我们会将其放入ingredients数组。 如果没有更多的成分,我们将使用break条件停止for循环。

Next, we're creating the newInnerHTML string which is going to hold the entire HTML markup. In it we are parsing the remaining properties that we want to be displayed.

接下来,我们将创建newInnerHTML字符串,该字符串将保留整个HTML标记。 在其中,我们正在解析要显示的其余属性。

Note that some of the properties might not be available. So for that we're using the ternary operator to check if we have the data to display the corresponding tag. If we don't have it then we're returning an empty string and nothing will be displayed on the page. The category and the area are examples of these type of properties.

请注意 ,某些属性可能不可用。 为此,我们使用三元运算符来检查是否有数据显示相应的标签。 如果没有它,那么我们将返回一个空字符串,并且页面上将不会显示任何内容。 categoryarea是这些类型的属性的示例。

The tags are coming in a string divided by a comma like: 'tag1,tag2,tag3'. So we need to split it by that comma, and join it back by a comma and a space as it looks nicer ('tag1, tag2, tag3' ❤️). Or at least for me does.

标签以字符串形式出现,并用逗号分隔,例如: 'tag1,tag2,tag3' 。 因此,我们需要用逗号splitsplit ,并用逗号和空格join其重新组合起来,因为它看起来更好( 'tag1, tag2, tag3' tag3'❤️)。 或者至少对我而言。

To show the ingredients, we're mapping over the array and we're creating an

  • for each ingredient/measure pair. At the end we're joining the array back to form a string. (This is something you would do in ReactJS but without the joining part ).

    为了显示ingredients ,我们在数组上进行映射,并为每个成分/度量对创建一个

  • 。 最后,我们将数组重新连接成一个字符串。 (这是你会在ReactJS做,但没有join荷兰国际集团的部分)。

    There is also a Youtube video string (maybe) which is returning the URL of the video. But in order for us to embed the video in the page we need to extract the video ID only. For that we're using .slice(-11) to get the last 11 characters of the string as this is where the ID is hiding .

    还有一个YouTube视频字符串 (也许)正在返回视频的URL。 但是为了使我们将视频嵌入页面,我们只需要提取视频ID。 为此,我们使用.slice(-11)来获取字符串的最后11个字符,因为这是ID隐藏的位置。

    And finally, we're setting this entire newInnerHTML to be the meal_container's innerHTML -> this will populate that div with all this information!

    最后,我们将整个newInnerHTML设置为meal_containerinnerHTML >这将使用所有这些信息填充该div!

    This entire process will repeat every time we're pressing the Get Meal button.

    每当我们按下“ Get Meal按钮时,整个过程都会重复。

    CSS (The CSS)

    The last part is to style it a little bit, right?

    最后一部分是样式设置,对吗?

    For the CSS I wanted to use something new so I tried out the SkeletonCSS library. It's useful if you have a small project and don't want to get overwhelmed with all those classes, as it only has a couple of them that take care of some basic styling (the button for example) and the responsive part.

    对于CSS,我想使用一些新的东西,所以我尝试了SkeletonCSS库。 如果您有一个小型项目,并且不想被所有这些类弄得不知所措,那么它很有用,因为它只有几个,它们负责一些基本的样式(例如按钮)和响应部分。

    @import url('https://fonts.googleapis.com/css?family=Muli&display=swap');
    
    * {
    	box-sizing: border-box;
    }
    
    body {
    	display: flex;
    	flex-direction: column;
    	justify-content: center;
    	align-items: center;
    	padding: 30px 0;
    	min-height: calc(100vh - 60px);
    }
    
    img {
    	max-width: 100%;
    }
    
    p {
    	margin-bottom: 5px;
    }
    
    h3 {
    	margin: 0;
    }
    
    h5 {
    	margin: 10px 0;
    }
    
    li {
    	margin-bottom: 0;
    }
    
    .meal {
    	margin: 20px 0;
    }
    
    .text-center {
    	text-align: center;
    }
    
    .videoWrapper {
    	position: relative;
    	padding-bottom: 56.25%;
    	padding-top: 25px;
    	height: 0;
    }
    
    .videoWrapper iframe {
    	position: absolute;
    	top: 0;
    	left: 0;
    	width: 100%;
    	height: 100%;
    }

    You can see that the CSS is pretty simple. The only part that's worth mentioning is the .videoWrapper CSS declaration. This makes sure that the YouTube embed is responsive. (Got this from CSS-Tricks - thanks guys! )

    您可以看到CSS非常简单。 唯一值得一提的部分是.videoWrapper CSS声明。 这样可以确保YouTube嵌入可以响应。 (从CSS-Tricks那里得到了-谢谢大家!)

    结论 (Conclusion)

    And voilà! We're done!

    和瞧! 大功告成!

    You should now know how to use a public API to get some data which you can then insert on the page easily! Well done!

    您现在应该知道如何使用公共API来获取一些数据,然后可以轻松地将其插入页面中! 做得好!

    This is the first project I did for the #100Days100Projects challenge. You can check out what other projects I've built and what are the rules of the challenge (if you might want to join) by clicking here.

    这是我为#100Days100Projects挑战所做的第一个项目。 您可以通过单击此处查看我建立了哪些其他项目以及挑战的规则(如果您想加入)。

    You can read more of my articles on www.florin-pop.com.

    您可以在www.florin-pop.com上阅读我的更多文章。

    Happy Coding!

    编码愉快!

    翻译自: https://www.freecodecamp.org/news/creating-a-random-meal-generator/

    如何制作营养膳食计算器

  • 你可能感兴趣的:(java,js,javascript,python,vue,ViewUI)