Recipe summary

      summary:

                tab by default, different dishes displayed under the menu are displayed. The primary routing menu corresponds to various dishes under the secondary routing menu

                The routing menu on the left filters out the dish information on the right according to different dish names

                The tab bar is mainly displayed on the right, and the corresponding dishes are displayed during switching, as well as the dishes filtered on the left

Code function realization:

        tab switch list and function implementation. When clicking switch, the dish information on the right will also change

        

 

Left menu filter list: click the selected keyword to filter out the corresponding dishes

  The menu list on the right is used to display the dishes filtered in the tab menu bar and the menu bar on the left. When clicking a certain keyword to filter dishes, if there is no matching dish in the dish, let it display a text to increase the user experience

For example, in the effect picture below, when you click "cook", a text is displayed to let others know that there is no corresponding dish under the currently selected keyword

 

Mask layer: each time data is obtained from the back end, a mask layer is set before data is obtained to avoid the feeling of sudden appearance of data

 

All codes

<template>
    <div class="recipe">
        <!-- v-model="activeName" -->
        <!-- Recipe classification start -->

        <!--tab Switch menu-->
        <el-tabs v-model="classifyName" type="border-card"
        @tab-click='tabClick()'>
            <el-tab-pane 
                :label="item.parent_name" 
                v-for='item in classify'
                :key='item.parent_type'
                :name='item.parent_type'>
                <div class="recipe-link">
                 <!-- query Pass the value to the original query Bring it here in the original query Add the currently selected classify of option attribute -->
                    <router-link 
                        :to="{query:{...$route.query,classify:option.type}}" 
                        v-for='option in item.list'
                        :key='option.type'
                        :class="{active:classifyType === option.type }"
                    >
                    <!--Judge current options.type And classifyType Are they equal 
                    If equal, bind the currently clicked element active
                    This will achieve the effect that whoever clicks will change his background -->
                    {{option.name}}
                    </router-link>
                </div>
            </el-tab-pane>
        </el-tabs>
        <!-- Recipe classification end -->
        <h2>Home style tastes good and gives you the warmth of your home</h2>
        <el-container>
        <!-- Left menu list -->
            <el-aside width="220px" class="recipe-aside">
                <div class="filter-box">
                    <h4>screen</h4>
                    <!-- v-model="activeName" -->
                    <!-- screen start -->
                    <el-collapse v-model="properActiveName">
                        <el-collapse-item
                            v-for='item in propType'
                            :key='item.parent_type'
                            :title="item.parent_name"
                            :name='item.parent_type'
                        >
                            <div class="filter-tags" >
                                <el-tag type="info"
                                    v-for='option in item.list'
                                    :key='option.type'
                                    @click="selectedTag(option)"
                                    :class="{'tag-selected':propertyType[option.title] === option.type}"
                                    >
                                    {{option.name}}
                                </el-tag>
                            </div>
                        </el-collapse-item>
                    </el-collapse>
                    <!-- screen end -->
                </div>
            </el-aside>
            <el-main class="filter-menus-box">
               <div class="menu-empty" 
                    v-show='!list.length && !loading' >The menu information is not filtered out temporarily. Please select other filtering criteria</div>
                    <!--Same below if loading       or!list.length || loading && !loading -->
                <!--Work display-->
                <menu-card style="min-height: 75%;" :info="list"></menu-card>
                <!-- Pagination display -->
                <div style="text-align: right;"  v-show='!loading'>
                    <el-pagination
                            style="display: inline-block;"
                            :page-size="5"
                            layout="total, prev, pager, next"
                            :total="total"
                            :current-page.sync='page'
                            @current-change="handlerSelect"
                            :hide-on-single-page='true'
                            >
                    </el-pagination>
                </div>
            </el-main>
        </el-container>
    </div>
</template>
<script>
    import MenuCard from '@/components/menu-card.vue'
    import {getClassify, getProperty, getMenus} from '@/service/api';

    export default {
        components: {MenuCard},
        data() {
            return {
                classify:[],    // Store all data of tab switching
                propType:[],    // Store all data for attributes
                classifyType:"1-1",     // tab selected items for switching (secondary routing)
                classifyName:'1',       // Define the value when refreshing the tab (Level 1 routing)
                propertyType:{},        // Classification of storage properties. For example: {craft:1-4,flavor=2-1}
                properActiveName:[],    // Record all attribute classifications
                list:[],       // Store right subject data
                total:0,    // PageCount 
                loading:false, // Show mask layer
                page:1,     // the number of pages
            }
        },
        watch: {
            $route: {
                handler(){
                    const {classify,page} = this.$route.query ;
                    console.log(typeof page)
                    // console.log(this.$route.query,classify)
                    if(classify){
                        // Take out the attribute stored in classify and assign it to this.classifyType
                        // Exists in the currently selected item
                        this.classifyType = classify ; // 1-1 value of secondary menu
                        this.classifyName = classify[0] ; //  1 value of the first level menu
                        this.page = Number(page) ;
                    }
                this.getThisMenus()
                },
                immediate:true,
            }
           
        },
        mounted() {
            getClassify().then(({data})=>{
                // console.log(data)
                this.classify = data ;
                //  console.log(!this.$route.query.classify)
                // If query has no parameters, define an initial value for it, and define the first level and second level in the data as an initial value
                //Simply put, if there are no parameters, take them from the back end and finally save them back to the route
                if(!this.$route.query.classify){
                    this.classifyType = this.classify[0].list[0].type ; // 1-1
                    this.classifyName = this.classify[0].parent_type ; //  1
                    // Save the value of the returned component into the route
                    this.$router.push({
                        query:{
                            classify:this.classifyType,
                            // page:1
                        }
                    })
                }
            });
            getProperty().then(({data})=>{
                this.propType = data ;
                const {query} = this.$route ;
                
                this.propertyType = this.propType.reduce((k,item)=>{
                    // item.title: craft, difficulty, taste, number of people 
                    k[item.title] = query[item.title] ? query[item.title] : "" ;
                    // console.log(item)
                    if(k[item.title]){
                        this.properActiveName.push(k[item.title][0]) ;
                        // console.log(k[item.title][0],this.properActiveName)
                    }
                    return k ;
                },{})
                // console.log(query,this.propertyType)
            })
        },
        methods: {
            selectedTag(val){
                let query = {...this.$route.query}
                // Judge whether to click. If yes, cancel. Otherwise, select
                if(this.propertyType[val.title] === val.type){
                    this.propertyType[val.title] = "" ;
                    delete query[val.title]
                }else{
                    this.propertyType[val.title] = val.type ;
                    query[val.title] = val.type
                }
                this.$router.push({
                    query
                    // query:{
                    //     ...this.$route.query,
                    //     [val.title]:val.type
                    // }
                })
            },
            getThisMenus(){
                const query = {...this.$route.query}
                const params = {
                    page:query.page || '1',
                    classify:query.classify
                }
                delete query.page ;
                delete query.classify ;
                if(Object.keys(query).length){
                    params.property = {
                        ...query
                    }
                }
                this.loading = true ;
                let loading = null ;
                this.$nextTick(()=>{
                    loading = this.$loading({
                        lock:true,
                        target:".filter-menus-box",
                        text:'Loading...',
                        spinner:'el-icon-loading',
                        background:'rgba(0,0,0,0.5)'
                    })
                
                }) ;
                // When filtering dishes, clear its current dish data, and then obtain the filtered dish data, otherwise it will cause existing problems                
                  The product suddenly switches to filtered data,It will give people a bad experience
                this.list = [] ;  // Clear the data to display the re requested data
                // Request data on the right
                getMenus(params).then(({data})=>{
                    // console.log(data)
                       
                        if(this.loading){
                            loading.close()
                         }
                         this.loading = false ;
                         this.list = data.list ;
                         this.total = data.total ;
                         this.page = data.current_page ;
                     // If the loading after obtaining the filtered data is always false, re assign it to make its value true
                        if(this.loading === false){
                                this.loading = true ;
                            }
                })
            },
            handlerSelect(){
                this.$router.push({
                    query:{
                        ...this.$route.query,
                        page:this.page
                    }
                })
            },
            tabClick(){
                const classifNames = this.classifyName ;
                const item = this.classify.find(item => item.parent_type === classifNames)
                // console.log(item)
                // item is the first level route (overall data) currently selected or clicked
                if(item){
                    this.classifyName = item.parent_type ; // type of first level routing menu
                    this.classifyType = item.list[1].type ; // type of secondary routing menu
                    this.$router.push({
                        query:{
                            ...this.$route.query,
                            classify:this.classifyType
                        }
                    })
                }
            }
        }
    }
</script>

Summary: finally, a small bug in the mask layer will appear. When the routing menu is frequently switched, the dishes will be displayed on the right        
          The mask layer of the list will make the whole page in the bug that is being refreshed by the mask layer, or enter the recipe from other pages   This bug also occurs when

  About my solution:

         v-show='! list.length || loading && ! loading'         js is used here Logical operator

        Here, I add another condition to the original condition. It will be triggered only when the first two conditions are met. If the first two conditions are not met, it will look at the later conditions

        <el-main class="filter-menus-box">
               <div class="menu-empty" 
                    v-show='!list.length || loading && !loading' >The menu information has not been filtered out for the time being,                    
                     Please select another filter</div>
                <!--Work display-->
                <menu-card style="min-height: 75%;" :info="list"></menu-card>
                <!-- Pagination display -->
                <div style="text-align: right;"  v-show='!loading'>
                    <el-pagination
                            style="display: inline-block;"
                            :page-size="5"
                            layout="total, prev, pager, next"
                            :total="total"
                            :current-page.sync='page'
                            @current-change="handlerSelect"
                            :hide-on-single-page='true'
                            >
                    </el-pagination>
                </div>
            </el-main> 


            

        After the filtered data is obtained, the loading event is executed. Its value is false. When the loading value is false, the loading will always be executed and will not stop. If its value is always false, its value will be changed to true

             getMenus(params).then(({data})=>{
                    // console.log(data)
                       
                        if(this.loading){
                            loading.close()
                         }
                         this.loading = false ;
                         this.list = data.list ;
                         this.total = data.total ;
                         this.page = data.current_page ;
                     // If the loading after obtaining the filtered data is always false, re assign it to make its value true
                        if(this.loading === false){
                                this.loading = true ;
                            }
                })

Tags: Javascript Vue

Posted on Mon, 11 Oct 2021 19:20:48 -0400 by webwired