美食杰项目 -- 菜谱大全(二)

简介: 美食杰项目 -- 菜谱大全(二)

前言:

本文给大家讲解,美食杰项目中菜谱大全实现的效果,和具体代码。


具体实现思路:

点击头部分类(一级路由),点击哪一个选中哪一个(二级路由)的第一个

点击左侧属性,如果(二级路由),选中则刷新时(一级路由)默认打开

根据前2两步的条件进行过滤,在右侧显示过滤后的内容

添加分页器效果

以上效果都可以使用 element-ui 实现

步骤:

1. 展示美食杰菜谱大全效果

4b0ed18b05cf415fbcfb84a9282a1730.png

image.png


2. 引入element-ui

点击跳转至 element-ui 中 Tabs 标签页使用方法:https://element.eleme.cn/#/zh-CN/component/tabs


点击跳转至 element-ui 中 Collapse 折叠面板使用方法:https://element.eleme.cn/#/zh-CN/component/collapse


点击跳转至 element-ui 中 分页使用方法:https://element.eleme.cn/#/zh-CN/component/pagination


点击跳转至 element-ui 中 加载使用方法:https://element.eleme.cn/#/zh-CN/component/loading

3. 代码

<template>
  <div class="box">
    <!-- top -->
    <el-tabs
      v-model="classifyName"
      type="card"
      @tab-click="handleClick"
      class="el-tabs"
    >
      <el-tab-pane
        v-for="item in list"
        :key="item.parent_type"
        :label="item.parent_name"
        :name="item.parent_type"
        class="el-tab-pane"
      >
        <div>
          <router-link
            v-for="option in item.list"
            :key="option.type"
            :to="{
              query: { ...$route.query, classify: option.type, page: 1 },
            }"
            :class="{ active: option.type === classifyType }"
            >{{ option.name }}</router-link
          >
        </div>
      </el-tab-pane>
    </el-tabs>
    <!-- left -->
    <p class="title">家常好味道,给你家一般的温暖</p>
    <div class="left">
      <el-collapse v-model="activeNames">
        <h4>筛选</h4>
        <el-collapse-item
          v-for="item in property"
          :key="item.parent_type"
          :title="item.parent_name"
          :name="item.parent_type"
        >
          <div>
            <span
              type="info"
              v-for="option in item.list"
              :key="option.type"
              :class="{ active: activeType[option.title] == option.type }"
              @click="selectedTag(option)"
              >{{ option.name }}</span
            >
          </div>
        </el-collapse-item>
      </el-collapse>
    </div>
    <div class="right roll">
      <div class="menu-empty" v-show="loading">
        暂时没有过滤出菜谱信息,请选择其他的筛选条件
      </div>
      <Roll :menus="menus" :id="170"></Roll>
    </div>
    <div class="block">
      <el-pagination
        layout="total,prev, pager, next"
        :total="total"
        :page-size="page_size"
        :current-page.sync="page"
        @size-change="handleCurrentChange"
        @current-change="handleCurrentChange"
        @prev-click="handleCurrentChange"
        @next-click="handleCurrentChange"
        hide-on-single-page="true"
      >
      </el-pagination>
    </div>
  </div>
</template>
<script>
import Roll from "@/views/home-page/roll.vue";
import { getClassify, getProperty, getMenus } from "@/connector/api";
export default {
  components: {
    Roll,
  },
  data() {
    return {
      // top
      // 存储分类中的所有数据
      list: [],
      // 定义刷新tab时的值(一级路由)
      classifyName: 1,
      // tab切换的选中项(二级路由),里面存的谁,谁就是点击项让谁发生改变
      classifyType: "1-1",
      // 存储属性的分类,例如:{craft:1-4,flavor=2-1}
      activeNames: [],
      // 记录所有的属性分类
      activeType: {},
      // 存储属性中的所有数据
      property: [],
      // 存储右侧主体
      menus: [],
      // 每页显示几个
      page_size: 0,
      // 总页数
      total: 0,
      // 页数
      page: 0,
      // 遮罩层
      loading: false,
    };
  },
  // 监听事件
  watch: {
    // 路由改变时执行
    $route: {
      handler() {
        // 获取路由 query 参数里的 classify
        const { classify } = this.$route.query;
        // console.log(classify[0]);
        // 判断是否有内容
        if (classify) {
          // 有则把 classify 的值赋值给 classifyType ,第一个值赋值给 classifyName
          this.classifyName = classify[0];
          this.classifyType = classify;
          // 调用 getMenus 获取符合条件的菜谱
          this.getMenus();
          // 调用 getClassify 获取所有菜谱分类
          this.getClassify();
        }
      },
      immediate: true,
    },
  },
  // 进入当前页面时执行
  mounted() {
    // 给 url 地址添加 query 参数
    this.$router.push({
      query: {
        // 留存
        ...this.$route.query,
        classify: "1-1",
        // 如果有值则显示,没有则为 1
        page: this.page || 1,
      },
    });
    // 获取所有属性分类
    getProperty().then(({ data }) => {
      // console.log(data);
      this.property = data;
      // 获取所有 query 参数
      const { query } = this.$route;
      // reduce 用来迭代一个数组,并且把它累积到一个值中
      this.activeType = this.property.reduce((o, item) => {
        // 判断所有属性在 query 中是否存在,存在则赋值,不存在则为空
        o[item.title] = query[item.title] ? query[item.title] : "";
        // 判断是否为空
        if (o[item.title]) {
          // 不为空则添加至 activeNames
          this.activeNames.push(o[item.title][0]);
        }
        // 把值返回给 activeType
        return o;
      }, {});
    });
  },
  // 触发时执行
  methods: {
    // 获取所有菜谱分类
    getClassify() {
      getClassify().then(({ data }) => {
        this.list = data;
        // console.log(...this.$route.query);
      });
    },
    // 点击头部(一级路由)时触发
    handleClick(tab, event) {
      // console.log(tab.name, event);
      // tab.name 值为第几个(下标)
      this.classifyName = Number(tab.name);
      this.classifyType = tab.name + "-1";
      // 改变 query 参数
      // 点击(一级路由)第几个,则选中(二级路由)第一个
      this.$router.push({
        ...this.$route.query,
        query: {
          classify: tab.name + "-1",
          page: 1,
        },
      });
    },
    // 点击左侧筛选(二级路由)
    selectedTag(option) {
      // option 点击的具体信息
      // 获取路由中所有 query 参数
      let query = { ...this.$route.query };
      // 判断该属性是否选中
      if (this.activeType[option.title] == option.type) {
        // 选中则取消选中
        this.activeType[option.title] = "";
        delete query[option.title];
      } else {
        // 否则选中
        this.activeType[option.title] = option.type;
        query[option.title] = option.type;
      }
      // 路由也跟着改变
      this.$router.push({
        query,
      });
    },
    // 获取右侧数据
    getMenus() {
      // 获取路由中所有 query 参数
      const query = { ...this.$route.query };
      // 新建一个对象
      const param = {
        // 存在则使用,不存在则为一
        page: query.page || 1,
        classify: query.classify,
      };
      // 让 page 的值,跟随 query 中 page 的值
      this.page = query.page;
      // 删除 page 和 classify
      delete query.page;
      delete query.classify;
      // 判断是否还有值
      if (Object.keys(query).length) {
        // 有则添加到 param.property
        param.property = {
          ...query,
        };
      }
      // 打开遮罩层
      this.loading = true;
      // 声明一个变量为空
      let loading = null;
      // 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
      this.$nextTick(() => {
        // element-ui 里的遮罩层
        loading = this.$loading({
          target: ".roll",
          text: "Loading...",
          spinner: "el-icon-loading",
          background: "rgba(0, 0, 0, 0.8)",
        });
      });
      // 防止数据重复,list 为空
      this.list = [];
      // console.log(param.property);
      getMenus(param).then(({ data }) => {
        // console.log(data);
        // 所有菜谱的属性
        this.menus = data.list;
        // 总数
        this.total = data.total;
        // 一页多少个
        this.page_size = data.page_size;
        // 第几页
        this.page = data.current_page;
        // 关闭遮罩层
        loading.close();
        // 判断是否有值
        if (data.list.length) {
          // 有的话关闭遮罩层
          this.loading = false;
        }
      });
    },
    // 点击页数时执行
    handleCurrentChange(val) {
      // val:点击的页码
      // console.log({ ...this.$route.query });
      // 改变 query 中的页数
      this.$router.push({
        query: {
          ...this.$route.query,
          page: val,
        },
      });
    },
  },
};
</script>
<style lang="scss" scoped>
.box {
  width: 990px;
  margin: 20px auto 0;
  position: relative;
  .el-tabs {
    background-color: #fff;
    .el-tab-pane {
      div {
        display: flex;
        padding: 0 15px 15px;
        a {
          display: inline-block;
          font-size: 12px;
          padding: 0px 8px;
          height: 28px;
          line-height: 28px;
          color: #333;
          text-decoration: none;
        }
        .active {
          background: #ff3232;
          color: #fff;
        }
      }
    }
  }
  .title {
    text-align: center;
    margin: 50px 0;
  }
  .left {
    width: 200px;
    background-color: #fff;
    span {
      width: 70px;
      padding: 8px 0;
      margin: 10px;
      display: inline-block;
      text-align: center;
      border-radius: 10px;
      background-color: gainsboro;
      text-decoration: none;
      color: #333;
    }
    .active {
      background: #ff3232;
      color: #fff;
    }
  }
  .right {
    display: flex;
    flex-wrap: wrap;
    width: 700px;
    // background-color: red;
    position: absolute;
    top: 185px;
    right: 0;
    // overflow: hidden;
    .menu-empty {
      margin: 30px auto 0;
    }
  }
  .block {
    position: absolute;
    bottom: -300px;
    right: 0;
  }
}
</style>

总结:

总结:

以上就是 美食杰项目 中 菜谱大全的具体实现方法,不懂得也可以在评论区里问我,以后会持续发布一些新的功能,敬请关注。

相关文章
使用 bookdown 构建新年日记本
使用 bookdown 构建新年日记本
117 0
美食杰项目 -- 登录注册(三)
美食杰项目 -- 登录注册(三)
美食杰项目 -- 登录注册(三)
|
前端开发 JavaScript UED
「CSS畅想」何以解忧,美食足矣,用技术给好友开发了一个零食盲盒小游戏
前端技术从业者与非技术好友互动,用技术给好友开发了一个零食盲盒小游戏
262 1
|
JavaScript
美食杰项目 -- 菜品信息(五)
美食杰项目 -- 菜品信息(五)
美食杰项目 -- 菜品信息(五)
|
算法 程序员 Python
端午抗疫宣传公益小游戏-用Python为粽子宝宝戴口罩
由于新冠疫情影响,为避免户外威胁,我选择了居家以程序员的方式纪念这个端午。 虽然气温较高,疫情也得到了有效的控制,但为了他人和自身的身体健康,仍然需要在人流密集的公共场所佩戴好口罩😷。 由此,我以**为粽子宝宝戴口罩**😷为主题,花费4个小时(构思,素材收集,编码, 记录),制作了一个公益小游戏。科普防疫戴口罩。纪念这个端午!
195 0
端午抗疫宣传公益小游戏-用Python为粽子宝宝戴口罩