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

news2025/8/11 21:08:54

目录

  • 前言:
  • 具体实现思路:
  • 步骤:
    • 1. 展示美食杰菜谱大全效果
    • 2. 引入element-ui
    • 3. 代码
  • 总结:

前言:

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


具体实现思路:

  1. 点击头部分类(一级路由),点击哪一个选中哪一个(二级路由)的第一个
  2. 点击左侧属性,如果(二级路由),选中则刷新时(一级路由)默认打开
  3. 根据前2两步的条件进行过滤,在右侧显示过滤后的内容
  4. 添加分页器效果
  5. 以上效果都可以使用 element-ui 实现

步骤:

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

在这里插入图片描述

美食杰菜谱大全


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>

总结:

总结:
以上就是 美食杰项目 中 首页的具体实现方法,不懂得也可以在评论区里问我,以后会持续发布一些新的功能,敬请关注。
我的其他文章:https://blog.csdn.net/weixin_62897746?type=blog

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/15326.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

金蝶苍穹开发工程师初级学习第一节

金蝶苍穹开发工程师初级学习第一节 ✨欢迎关注&#x1f5b1;点赞&#x1f380;收藏⭐留言✒ &#x1f52e;本文由京与旧铺原创&#xff0c;金蝶首发&#xff01; &#x1f618;系列专栏&#xff1a;低代码学习 &#x1f4bb;首发时间&#xff1a;&#x1f39e;2022年11月12日&a…

github action定时任务

需求 定时任务1 (8:00~13:00)&#xff0c;执行bash脚本定时任务2 (18:00)&#xff0c;修改定时任务1的执行时间 文档 workflows官方文档workflows action uses查询actions/checkoutv3About the GITHUB_TOKEN secret 问题之refusing to allow a GitHub App to create or upd…

MySQL:常用函数解析、开窗函数示例

数学函数 count() count()、count(field) 统计某个结果集中的总数量&#xff0c;field为要统计的字段。 SELECT count( 1 ) FROM db1.users 复制代码 sum() sum(field) 统计某个字段累计的总和&#xff0c;field为要统计的字段。 SELECT sum( price ) FROM order_info 复制…

Git 操作流程与命令汇总

1. 为什么要使用 git ? 在写项目时&#xff0c;会产生多个版本&#xff0c;以及多个同学协同配合的情况&#xff0c;为了很好的管理&#xff0c;推出了Git&#xff0c; 版本管理工具&#xff0c;持久化&#xff0c;多人化 2. 首先需要弄明白四个概念 工作区&#xff1a;仓库…

深入浅出mybatis分页

MyBatis 分页插件 PageHelper 如何使用&#xff1f; 如何使用分页插件 1&#xff1a;添加依赖 <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.5</ver…

基于springboot学生管理系统设计与实现

摘  要 目前&#xff0c;借助信息管理系统能够有效解决高校的信息管理问题&#xff0c;对于提高教育管理水平有着非常重要的作用。 因此&#xff0c;有必要建立一个与之相适应的管理信息系统。基于此&#xff0c;本文为了使教师高效地管理学生信息&#xff0c;需要对现代的学…

【LeetCode-中等】221. 最大正方形(详解)

题目 在一个由 0 和 1 组成的二维矩阵内&#xff0c;找到只包含 1 的最大正方形&#xff0c;并返回其面积。 力扣原题链接 方法1&#xff1a;暴力 暴力法一般不是最优解&#xff0c;但是可以拿来练手 由于正方形的面积等于边长的平方&#xff0c;因此要找到最大正方形的面积&…

【C++】C++基础知识(八)---结构体

C基础知识&#xff08;八&#xff09;1. 定义与使用2. 结构体数组3. 结构体指针4. 结构体嵌套5. 结构体作函数参数6. 结构体中const使用场景7. 结构体使用案例1. 定义与使用 结构体定义&#xff1a; ------结构体属于用户自定义的数据类型&#xff0c;允许用户存储不同的数据类…

元宇宙持续升温,金蝶推出数字员工破圈而来

作者 | 伍杏玲 “金小蝶&#xff0c;请分析今年企业销售事业部的业绩”。 话音刚落&#xff0c;大屏幕展开一张张账务报表&#xff0c;一位身着西装&#xff0c;举止大方得体的数字人条理清晰地回复&#xff1a;“截至今年10月&#xff0c;企业销售事业部在签单金额、新签收入…

数字化转型过程中,企业如何搭建好数据安全?

在企业数字化转型变革中&#xff0c;确保数据安全是企业的责任也是重任。“数据安全”关乎企业数字化发展和未来的商业模式及竞争力&#xff0c;如何在企业数字化转型过程中搭建好“数据安全”的保障&#xff1f; 一、建立数据安全保护意识 互联网时代&#xff0c;有各种各样、…

Vue--》详解Vue组件生命周期的三个阶段

目录 组件生命周期 创建阶段 beforeCreate阶段&#xff1a; created阶段&#xff1a; beforeMount阶段&#xff1a; mounted阶段&#xff1a; 运行阶段 beforeUpdate阶段&#xff1a; updated阶段&#xff1a; 销毁阶段 beforeDestroy阶段&#xff1a; destroyed阶…

windows工作窗口太多,需要频繁切换?摸鱼利器你必须了解下

当我们创作一份内容需要使用到不同窗口的信息时&#xff0c;无比苦恼的就是窗口需要频繁切换了&#xff0c;并且当我们需要参照某个窗口时&#xff0c;这时如果可以把窗口置顶甚至透明窗口效率翻倍&#xff01; WindowTop 是一款窗口自定义设置工具&#xff0c;可将任意窗口置…

[附源码]计算机毕业设计JAVA购买车票系统

[附源码]计算机毕业设计JAVA购买车票系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis M…

怎么把加密的PDF解密?安利几个办公小技巧

大家都知道给pdf文件加密是对文件的一种保护措施&#xff0c;但是如果我们需要对其进行频繁的编辑改动的话&#xff0c;加了密的pdf文件操作起来就很不方便&#xff0c;因为每次的打开都需要输入密码&#xff0c;这个操作其实很浪费时间&#xff0c;其实我只需要将其解密就好了…

用pageOffice文档控件实现 office文档在线编辑

第三方文档控件&#xff0c;pageOffice 系统开发中经常要处理办公文档&#xff0c;如果word&#xff0c;excel&#xff0c;ppt&#xff0c;编辑整理&#xff0c;保存&#xff0c;归档。 开发市场上也有很多第三文文档控件&#xff0c;多年的总结&#xff0c;还是认为pageOffi…

Unity学习之Shader

Shader 是用来实现图像渲染的&#xff0c;用来替代固定渲染管线的可编辑程序。其中Vertex Shader&#xff08;顶点着色器&#xff09;主要负责顶点的几何关系等的运算&#xff0c;Pixel Shader&#xff08;像素着色器&#xff09;主要负责片元颜色等的计算。顶点Shader负责改变…

【毕业设计】微信小程序商城购物系统

文章目录0 前言1 项目介绍1.1 代码工程结构1.2 前端技术1.3 后端技术1.4 实现功能1.4.1 会员管理1.4.2 商城配置1.4.3 商品编辑1.4.4 推广管理1.4.5 订单管理1.4.6 系统管理1.4.7 短信服务平台2 运行效果2.1 前端效果2.2 后端效果3 实现部分源码3.1 前端布局3.2 后端逻辑4 最后…

开箱评测:双十一刚买的云服务器,到底好不好用?

目录前言1. 何为HECS2. 核心特色2.1 易搭建2.2 更实惠2.3 易维护2.4 更安全3. 实践场景3.1 宝塔面板3.2 软件开发3.3 运维部署前言 对开发者和企业来说&#xff0c;双十一首先要购买什么&#xff1f;那必是云服务器。 云服务器&#xff08;Elastic Cloud Server, ECS&#xff…

数据结构:二叉树基础

文章目录一.二叉树的概念及结构1.1概念1.2特殊的二叉树二.二叉树的性质三.小练习3.13.23.3一.二叉树的概念及结构 不熟悉树这个结构的可以看看数据结构:树这篇文章。 1.1概念 一棵二叉树是结点的一个有限集合&#xff0c;该集合: 为空由一个根节点加上两棵别称为左子树和右…

Android动画之帧动画

在Android开发时&#xff0c;为了实现一些动态的炫酷的效果&#xff0c;我们常用到帧动画&#xff0c;View动画&#xff08;补间动画&#xff09;和属性动画&#xff0c;今天就来总结下我在使用帧动画的实现方式。 1、什么是帧动画&#xff1f; 帧动画就是顺序播放一组预先定…