使用Vue框架串接TheMealDB API

根据TheMealDB APIList all meal categories可看到有很多餐点分类,不过这次用到那麽多分类,所以等下会在data中定义会用到的餐点分类。

父组件MenusDetails.vue

<script>
export default{
    data(){
        return{
            mealCategory:[],
            categories:[
                        {type:'starter'},
                        {type:'chicken'},
                        {type:'beef'},
                        {type:'pork'},
                        {type:'seafood'},
                        {type:'pasta'},
                        {type:'lamb'},
                        {type:'goat'},
                        {type:'dessert'}
            ]
        }
    },
    created(){
        this.getMealData(this.categories[8]);
    },
    methods:{
        //get category data
        async getMealData(category){
            const dataUrl = `https://www.themealdb.com/api/json/v1/1/filter.php?c=${category.type}`;
            try{
                const response = await fetch(dataUrl);
                const data = await response.json();
                this.mealCategory = data.meals;
            }catch(e){
                console.log(e);
            }
        },
        menuName(category){
            this.getMealData(category);
        }
     }
}
</script>

1.fetch API:https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
https://devhints.io/js-fetch
2.Async/Await:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
https://javascript.info/async-await
https://dmitripavlutin.com/javascript-fetch-async-await/

然後使用v-for在HTML中渲染出画面

<!-- menus details -->
<div class="menusdetails__content">
    <div class="row">
        <div class="col-1-of-3" v-for="meal in mealCategory" :key="meal.index">
            <div class="card">
                <div class="card__side">
                    <div class="card__img-box">
                        <img :src=meal.strMealThumb alt="">
                    </div>
                    <h4 class="card__heading">
                        <span class="card__heading-span">
                            {{meal.strMeal}}
                        </span>
                    </h4>
                    <div class="card__cta">
                        <a href="javascript:void(0);" :data-id=meal.idMeal class="btn btn--2" @click="getMealDetails($event)">get details</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

将get details按钮利用HTML5的自定义属性绑定每道餐点的id,让用户点进去後可看到餐点的详细材料,这边使用getMealDetails($event)方法根据每道餐点的id串接餐点材料的API

<script>
export default{
    data(){
        return{
            mealDetails:[],
        }
    },
    methods:{
        async getMealDetails(e){
            let id = e.target.getAttribute('data-id');
            const dataUrl = `https://www.themealdb.com/api/json/v1/1/lookup.php?i=${id}`;
            try{
                const response = await fetch(dataUrl);
                const data = await response.json();
                this.mealDetails = data.meals;
            }catch(e){
                console.log(e);
            }
        }
    }
}
</script>

再将mealDetails的资料传到子组件Popup.vue即可

<template>
    ...
    <Popup :details="mealDetails"></Popup>
</template>

子组件Popup.vue
先在props设定接收父组件的details数据为Array,然後使用computed处理一下mealDetails资料里的strIngredient数据

<script>
export default {
    props:{
        details:Array
    },
    computed:{
        getIngredients(){
            //console.log(this.details['strIngredient1'])
            return this.details.map(el => {
                //console.log(el.strIngredient1)
                let result = [];
                for(let i=1;i<=30;i++){
                    if(el[`strIngredient${i}`] == ''){
                        break;
                    }
                    result.push(el[`strIngredient${i}`]);
                }
                return result;
            })
        
        }
    }
}
</script>

然後一样使用v-for在HTML上渲染出页面

<div class="popup__dialog" v-for="detail in details" :key="detail.id">
    <a href="#" class="popup__close" @click="closePopup">×</a>
    <div class="popup__box">
        <div class="popup__logobox">
            <img class="popup__logo" :src=detail.strMealThumb :alt=detail.strMeal>
        </div>
        <div class="popup__text">
            <h1 class="popup__heading">
                {{detail.strMeal}}
            </h1>
            <h1 class="popup__heading">
                Area:{{detail.strArea}}
            </h1>
            <h1 class="popup__heading">
                Ingredient:
            </h1>
            <h1 class="popup__heading">
                <p class="popup__heading" v-for="ingredient in getIngredients" :key="ingredient.index">
                    {{ingredient.toString()}}
                </p>
            </h1>
        </div>
    </div>
</div>

1.HTML5中的资料属性:https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes
https://pjchender.blogspot.com/2017/01/html-5-data-attribute.html
2.Array.prototype.map():https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

参考资料:
1.TheMealDB API:https://www.themealdb.com/api.php
2.meal-search-api-vanilla-js:https://github.com/prabinmagar/meal-search-api-vanilla-js
3.Recipe-Catalogue:https://github.com/ampaire/Recipe-Catalogue


<<:  【杂谈】 今天就来点闲聊吧③ - 铁人赛观察之有意思的系列

>>:  Node-RED学习心得(安装篇)

Ruby on Rails RESTful 网址设计

REST 是 Representational State Transfer 的缩写,中⽂翻译成「具...

【Day07】Git 版本控制 - Sourcetree

什麽是 Sourcetree? 简单来说,就是一个可以用 GUI 介面来管理版本控制内容的软件。 可...

[Day14] THM Root Me

网址 : https://tryhackme.com/room/rrootme IP : 10.1...

Day 29 洞悉消费者的心

消费者每天搜寻的字词中,根据 Google 的统计,每天有 15% 以上的新的搜寻字词出现。因此编辑...

Day 30 Python3 + selenium 撷取网站状态快照

Python3 + selenium 撷取网站状态快照 系统更新与软件服务预装 $ sudo apt...