iT邦幫忙

0

使用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


尚未有邦友留言

立即登入留言