美食杰项目 -- 首页(一)

news2024/9/20 9:07:16

目录

  • 前言:
  • 具体实现思路:
  • 步骤:
    • 1. 展示美食杰项目首页效果
    • 2. 引入 element-ui
    • 3. 头部代码
    • 4. 首页内容总代码
    • 5. 轮播图代码
    • 6. 已发布菜品内容代码
    • 7. 加载图片页面代码
  • 总结:

前言:

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


具体实现思路:

  1. 向后端请求数据,获取数据,渲染数据
  2. 引入 element-ui
  3. 刷新后加载新图片

步骤:

头部代码中包含了一部分登录功能,这个功能在本文没有实现,想要知道的,可以看我发布的实现登录注册功能的文章。

在 加载图片页面代码中,使用了节流 throttle-debounce,节流的具体使用可以看官方文档。

点击跳转至节流的官方文档:https://www.npmjs.com/package/throttle-debounce

点击跳转至 element-ui 官方文档:https://element.eleme.cn/#/zh-CN/component/installation


1. 展示美食杰项目首页效果

实现后效果展示

美食杰首页


2. 引入 element-ui

  • 下载 element-ui
npm i element-ui -S
  • 在 main.js 中引入 element-ui
import Vue from 'vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);

3. 头部代码

<template>
  <div class="box">
    <div class="top">
      <div class="center">
        <a href="" class="left">
          <img src="@/assets/logos.png" alt="" />
        </a>
        <!-- 判断是否登录,不登录则显示 -->
        <div class="right" v-if="!islogin">
          <router-link :to="{ name: 'login' }">登录</router-link>
          <router-link :to="{ name: 'login' }">注册</router-link>
        </div>
        <!-- 判断是否登录,登录则显示 -->
        <div class="right rights" v-if="islogin">
          <router-link :to="{ name: 'MyHomepage' }">
            <img :src="userInfo.avatar" alt="" />
          </router-link>
          <router-link :to="{ name: 'MyHomepage' }">{{
            userInfo.name
          }}</router-link>
          <router-link to="PublishRecipes">发布菜谱</router-link>
          <button @click="quit">退出</button>
        </div>
      </div>
    </div>
    <div class="bottom">
      <el-menu
        :default-active="activeIndex"
        class="el-menu-demo center"
        mode="horizontal"
      >
        <el-menu-item index="1" class="el-menu-item">
          <router-link :to="{ name: 'page' }">首页</router-link>
        </el-menu-item>
        <el-menu-item index="2">
          <router-link :to="{ name: 'recipes' }">菜谱大全</router-link>
        </el-menu-item>
      </el-menu>
    </div>
  </div>
</template>

<script>
import { mapGetters, mapState } from "vuex";
import { login_out } from "@/connector/api";
export default {
  data() {
    return {
      activeIndex: "1",
      activeIndex2: "1",
    };
  },
  computed: {
    // 获取 vuex 里的内容
    ...mapGetters(["islogin"]),
    ...mapState(["userInfo"]),
  },
  methods: {
    // 点击退出登录
    quit() {
      login_out().then((data) => {
        if (data.code === 0) {
          // 删除本地存储的 token
          localStorage.removeItem("token");
          // 跳转至首页
          window.location.href = "/";
        }
      });
    },
  },
};
</script>

<style lang="scss" scoped>
.box {
  width: 100%;
  .top {
    width: 100%;
    height: 129px;
    background-color: #c90000;
    .center {
      width: 990px;
      height: 100%;
      margin: 0 auto;
      display: flex;
      justify-content: space-between;
      align-items: center;
      .left {
        width: 213.75px;
      }
      .right {
        width: 213.75px;
        a {
          font-size: 12px;
          text-decoration: none;
          color: #fff;
          margin-left: 5px;
        }
      }
      .rights {
        display: flex;
        align-items: center;
        a {
          img {
            width: 36px;
            height: 36px;
          }
        }
        button {
          font-size: 12px;
          color: #fff;
          margin-left: 5px;
          border: none;
          background-color: #c90000;
        }
      }
    }
  }
  .bottom {
    width: 100%;
    height: 60px;
    background-color: #ffffff;
    .center {
      width: 990px;
      height: 100%;
      margin: 0 auto;
      line-height: 60px;
      .el-menu-item {
        a {
          display: inline-block;
          width: 100%;
          height: 100%;
          text-decoration: none;
        }
      }
    }
  }
}
</style>

4. 首页内容总代码

<template>
  <div class="box">
    <!-- :banner="banner" 是父传子事件,和它类似的也是 -->
    <!-- @Scroll="Scroll" 是子传父事件 -->
    <!-- ref="Loading" 可以获取子组件的内容 -->
    <!-- Banner:轮播图,Roll:内容,Loading:加载图片 -->
    <Banner :banner="banner"></Banner>
    <Roll :menus="menus"></Roll>
    <Loading @Scroll="Scroll" ref="Loading"></Loading>
    <div class="bottom">Copyright © 2019 - 2019</div>
  </div>
</template>

<script>
import Banner from "./banner.vue";
import Roll from "./roll.vue";
import Loading from "./loading.vue";
import { getMenus, getBanner } from "@/connector/api";
export default {
  components: {
    Banner,
    Roll,
    Loading,
  },
  data() {
    return {
      // 轮播图
      banner: [],
      // 已发布菜品
      menus: [],
      // 页数
      pages: 1,
      // 总数
      total: "",
      // 一页显示多少个
      page_size: "",
    };
  },
  // 进入时触发
  mounted() {
    // 获取轮播图的内容
    getBanner().then(({ data }) => {
      //   console.log(data);
      // 赋值给 banner
      this.banner = data.list;
    });
    // 根据页数获取已发布菜品的内容
    getMenus({ page: this.pages }).then(({ data }) => {
      // console.log(data);
      // 内容
      this.menus = data.list;
      // 总数
      this.total = data.total;
      // 一页几条
      this.page_size = data.page_size;
    });
  },
  // 点击时触发
  methods: {
    Scroll() {
      // 页数 + 1
      this.pages++;
      // 判断当前页数是否等于最后的页数
      if (this.pages == Math.ceil(this.total / this.page_size)) {
        // 等于则关闭 加载图片
        this.$refs.Loading.loading = false;
        // 下面的代码不在执行
        return;
      }
      // 显示 加载图片
      this.$refs.Loading.loading = true;
      // 根据页数获取已发布菜品的内容
      getMenus({ page: this.pages }).then(({ data }) => {
        // console.log(loading);
        // 追加到 menus 里面
        this.menus.push(...data.list);
        // 关闭 加载图片
        this.$refs.Loading.loading = false;
      });
    },
  },
};
</script>

<style lang="scss" scoped>
.box {
  width: 990px;
  margin: 20px auto 0;
  .bottom {
    text-align: center;
    margin-top: 20px;
  }
}
</style>

5. 轮播图代码

点击跳转至 element-ui 中轮播图使用方法:https://element.eleme.cn/#/zh-CN/component/carousel

<template>
  <div class="box">
    <!-- element-ui 里的轮播图 -->
    <el-carousel :interval="4000" type="card" height="300px">
      <el-carousel-item v-for="item in banner" :key="item._id">
        <router-link
          :to="{ name: 'DishesInformation', query: { menuId: item.menuId } }"
        >
          <img :src="item.product_pic_url" alt="" />
        </router-link>
      </el-carousel-item>
    </el-carousel>
  </div>
</template>

<script>
export default {
  // props 接收父组件传递过来的值
  props: {
    banner: {
      // type 元素类型
      type: Array,
      // default 默认值
      default: () => [],
    },
  },
};
</script>

<style>
.el-carousel__item a img {
  color: #475669;
  font-size: 14px;
  opacity: 0.75;
  line-height: 300px;
  margin: 0;
  width: 100%;
  height: 300px;
}

.el-carousel__item:nth-child(2n) {
  background-color: #99a9bf;
}

.el-carousel__item:nth-child(2n + 1) {
  background-color: #d3dce6;
}
</style>

6. 已发布菜品内容代码

<template>
  <div class="box">
    <!-- :class="{ h2: id === 234 }" 判断 id 是否为 234 不是的话使用前面的 class 标签 -->
    <h2 :class="{ h2: id !== 234 }">内容精选</h2>
    <ul class="banner">
      <li
        v-for="item in menus"
        :key="item._id"
        ref="list"
        :class="{ 'banner-li': id === 170 }"
      >
        <!-- 和上文大致意思相同 -->
        <router-link
          :to="{ name: 'DishesInformation', query: { menuId: item.menuId } }"
        >
          <img :src="item.product_pic_url" alt="" />
        </router-link>
        <div>
          <router-link
            :to="{ name: 'DishesInformation', query: { menuId: item.menuId } }"
          >
            <b>{{ item.title }}</b>
          </router-link>
          <p>{{ item.comments_len }} 评论</p>
          <router-link
            :to="{ name: 'MyHomepage', query: { userId: item.userId } }"
          >
            <p>{{ item.name }}</p>
          </router-link>
        </div>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  // props 接收父组件传递过来的值
  // type 元素类型
  // default 默认值
  props: {
    menus: {
      type: Array,
      default: () => [],
    },
    // 因为要在好几个地方使用所以传递过来一个值,用来判断在哪里使用
    id: {
      type: Number,
      default: 234,
    },
  },
};
</script>

<style lang="scss" scoped>
.box {
  width: 990px;
  padding: 0;
  h2 {
    text-align: center;
    font-weight: 400;
    padding: 20px 0;
  }
  .banner {
    display: flex;
    flex-wrap: wrap;
    padding: 0;
    width: 100%;
    li {
      display: inline-block;
      width: 234px;
      // width: 23.4%;
      height: 338px;
      list-style: none;
      background-color: #fff;
      margin: 0 0 20px 13px;
      border: 1px solid #ebeef5;
      a {
        text-decoration: none;
        img {
          width: 99.8%;
          height: 63%;
        }
        b {
          height: 24px;
          line-height: 24px;
          font-size: 12px;
          color: #333;
        }
        p {
          width: 95%;
          margin: 0 auto;
          font-size: 12px;
          height: 23px;
          line-height: 23px;
          color: #ff3232 !important;
        }
      }
      div {
        padding: 20px;
      }

      p {
        width: 204px;
        margin: 0 auto;
        font-size: 12px;
        height: 26px;
        line-height: 26px;
        color: #999;
      }
    }
    .banner-li {
      width: 160px !important;
      height: 264px;
    }
  }
  .h2 {
    display: none;
    padding: none;
  }
}
</style>

7. 加载图片页面代码

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

<template>
  <div class="box">
    <!-- element-ui 中加载的图片 -->
    <i
      v-loading="loading"
      element-loading-spinner="el-icon-loading"
      ref="loadings"
    >
    </i>
  </div>
</template>

<script>
// 引入节流
import { throttle } from "throttle-debounce";
export default {
  data() {
    return {
      // 是否显示
      loading: false,
    };
  },
  // 进入当前页面时触发
  mounted() {
    // 使用节流
    this.handleScroll = throttle(300, this.handleScroll.bind(this));
    // 给当前页面全局绑定 滚动条 事件
    window.addEventListener("scroll", this.handleScroll);
  },
  // 离开当前页面时触发
  destroyed() {
    // 删除 滚动条 事件
    window.removeEventListener("scroll", this.handleScroll);
  },
  methods: {
    handleScroll() {
      // 为 true 则停止向下执行
      if (this.loading) return;
      // 判断 加载图片距离顶部的高 是否小于 可视窗口
      if (
        this.$refs.loadings.getBoundingClientRect().bottom <
        document.documentElement.clientHeight
      ) {
        // console.log("滚动到指定位置");
        // 小于则显示 加载图片
        this.loading = true;
        // 子传父事件
        this.$emit("Scroll");
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.box {
  text-align: center;
  height: 20px;
}
</style>

总结:

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

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

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

相关文章

Windows右键菜单美化(适用版本:Win7-Win11) 奇怪的美化教程 #1

在我的上篇文章中&#xff0c;只有 0% 的人点了赞 咋一人没有啊&#xff01; 所以如果觉得做的还行的话可以给我点个赞、收个藏&#xff0c;这对我真的很重要&#xff01;QWQ 祖传前言 众所周知&#xff0c; Windows11 整了个新的右键菜单 (而原来的右键菜单变成了 显示更多…

基于微信小程序的桥牌计分系统设计与实现-计算机毕业设计源码+LW文档

小程序开发说明 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Mave…

m基于MATLAB的FM调制收音机仿真实现

目录 1.算法概述 2.仿真效果预览 3.核心MATLAB代码预览 4.完整MATLAB程序 1.算法概述 那么FM调制端的基本原理图如下所示&#xff1a; FM解调 FM解调的基本原理框图为&#xff1a; 在不考虑频偏的情况下&#xff0c;FM解调运算就相当于FM调制的逆运算&#xff0c;任务的第…

二叉树的性质的结点数与高度的计算题

二叉树是一种特殊的树形结构&#xff0c;每个结点最多只有两棵子树&#xff0c;即度最大为2&#xff0c;且二叉树左右子树不能颠倒。 主要常见分类有&#xff1a; 满二叉树&#xff1a; 除了叶子结点外&#xff0c;每个结点的度数都是2&#xff0c;若高度为h&#xff0c;则一…

Redis的5大数据类型

Redis的5大数据类型 这里说的数据类型是value的数据类型&#xff0c;key的类型都是字符串。 5种数据类型&#xff1a; redis字符串&#xff08;String&#xff09;redis列表&#xff08;List&#xff09;redis集合&#xff08;Set&#xff09;redis哈希表&#xff08;Hash&a…

PMP®|对如何做好项目管理的几点建议

PMP|对如何做好项目管理的几点建议 来自一位从事工程项目管理多年&#xff0c;也接触过软件开发项目的资深人士针对如何做好项目管理泛泛提些建议。 1、明确项目组自身定位。不同公司对项目管理的理解不同&#xff0c;项目制的执行方式不同&#xff0c;项目组在各公司的地位…

使用springboot每日推送早安问候语到用户微信【部署篇】

上一篇介绍文章 上一篇介绍文章 https://blog.csdn.net/weixin_45206218/article/details/127872136代码仓库 代码仓库 https://gitee.com/stevezhaozps/daily-weather前期准备 一台云服务器云服务器安装MySQL8.x云服务器安装jdk8 数据库初始化 由于本项目使用的是springd…

LIVOX HAP激光雷达使用方法

一、Livox HAP介绍 Livox HAP 由 Livox 团队耗时两年精心打造&#xff0c;是 Livox 首款面向智能辅助驾驶市场研发的车规级激光雷达。HAP 于 2021 年在全新自建的车规级智能制造中心进行批量生产&#xff0c;可满足 74 项严苛的车规可靠性要求。HAP 已成功为小鹏汽车、一汽解放…

C#【必备技能篇】Release下的pdb文件有什么用,是否可以删除?

文章目录一、简介二、问答三、Release中删除pdb文件四、重要事项一、简介 英文全称&#xff1a;Program Database File 中文全称&#xff1a;程序数据库 文件 程序数据库 (PDB) 文件保存着调试和项目状态信息&#xff0c;使用这些信息可以对程序的调试配置进行增量链接。 在…

ORCID以及ResearcherID注册

ORCID以及ResearcherID注册 ORCID 网址&#xff1a; https://orcid.org/ 点击注册 开始注册 跟着流程走一遍 最后登录进入个人首页&#xff0c;可以看到自己的ORCID。 ResearcherID 网址&#xff1a;https://webofscience.com 注册 邮箱点击确认邮件后&#xff0c;登录进…

操作系统 | 实验七 SPOOLING技术

文章目录一、实验目的二、实验内容三、数据结构3.1 数据结构3.2 函数以及功能四、程序流程图五、实验代码六、实验结果七、实验体会总结一、实验目的 理解和掌握SPOOLING假脱机技术 二、实验内容 通过SPOOLING技术可将一台物理I/O设备虚拟为多台逻辑I/O设备&#xff0c;同样…

奇技淫巧第7期

终于腾出时间了&#xff0c;现在对3~11月份知识点作总结。 这段时间主要在写论文&#xff0c;跑案例分析。暑期的比赛另写了一个小系列&#xff0c;这里就不再写了。 总的来说&#xff0c;零散的代码知识点在积累几个月后还是要汇总回顾一下的。 文章目录Python 歪门邪道fnmatc…

SpringBoot SpringBoot 开发实用篇 3 测试 3.7 匹配响应体【JSON】

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇3 测试3.7 匹配响应体【JSON】3.7.1 问题引入3.7.2 匹配响应体【JSON…

力扣刷题day50|739每日温度、496下一个更大元素 I

文章目录739. 每日温度暴力思路单调栈思路什么时候用单调栈&#xff1f;解题思路496. 下一个更大元素 I思路单调栈739. 每日温度 力扣题目链接 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对…

[Games 101] Lecture 11-12 Geometry 2 (Curves and Surfaces)

Lecture 11-12 Geometry 2 (Curves and Surfaces) Curves Bzier Curves 贝塞尔曲线 使用一系列的控制点定义某个曲线&#xff0c;控制点定义曲线满足的一些性质可以定义出唯一的曲线&#xff0c;从 p0p_0p0​ 开始&#xff0c;p3p_3p3​ 结束 de Casteljau Algorithm 绘制贝…

Linux16 ---共享内存、操作函数、使用示例

一、共享内存 1、 共享内存为多个进程之间共享和传递数据提供了一种有效的方式。共享内存是先在物理内存上申请一块空间&#xff0c;多个进程可以将其映射到自己的虚拟地址空间中。 所有进程都可以访问共享内存中的地址&#xff0c;就好像它们是由 malloc 分配的一样。如果某…

(二)Easyexcel 的使用(读取数据到map集合中)

前面讲述了使用实体类的方式绑定excel表头的方式进行读取和写入操作&#xff0c;是比较简单的&#xff0c;那么由于表头可能会变&#xff0c;那么就不能使用绑定实体类的方式进行了&#xff0c;于是搜索百度一番&#xff0c;借鉴别人的博客&#xff0c;使用map集合的方式进行读…

一文详解Cookie 和 Session 会话技术

目录 Cookie Session 分布式下Seesion的不足 Cookie 定义&#xff1a;Cookie是服务器发送到浏览器&#xff0c;并保存在浏览器端的一小块数据。浏览器下次访问该服务器时&#xff0c;会自动携带该数据块&#xff0c;将其发送给服务器。 作用&#xff1a;由于HTTP是无状态的&…

tomcat修改默认端口详细步骤(包含运行测试)

前言&#xff1a; 在tomcat端口被占用或者需要把默认的8080端口换成其他的端口&#xff0c;就可以修改默认端口。 一、修改步骤 1.打开tomacat的文件位置--conf目录 2.找到server.xml右键打开方式选择记事本打开 3.找到这个文件的Connector port "8080" 大概位…

TVM 中文站正式上线!最全机器学习模型部署「参考书」它来了

内容一览&#xff1a; 近日&#xff0c;由 MLC 社区志愿者共同翻译校对的 TVM 中文文档正式发布&#xff0c;现已托管至超神经官网 Hyper.AI。 关键词&#xff1a; TVM 开源 机器学习编译器 本文首发自微信公众号&#xff1a;HyperAI超神经 面世5年&#xff0c;TVM成备受追捧的…