美食杰项目(二)首页

news2025/8/8 10:43:15

目录

  • 前言
  • 具体样式
  • 代码思路
  • 加载样式
  • 相应组件
  • 相应代码
  • 总结:

前言

  • 本节给大家讲的是美食杰项目的首页的主要功能和具体样式

具体样式

在这里插入图片描述

代码思路

1.点击首页跳转到首页页面
2.在父组件将轮播图所需的图片请求出来,再传给轮播组件
3.在父组件将商品列表的数据请求出来,再传给商品列表组件
4.由于商品数据过多所以需要商品懒加载,根据滚动事件触发,按需加载

加载样式

在这里插入图片描述

相应组件

  • 首页组件
    在这里插入图片描述
    • banner为轮播图组件
    • loding为加载动画的组件
    • menus为总页面
  • 公用组件
    由于其余组件也有要用到商品列表所以要把商品列表封装起来公用
    • 公用的组件在这里插入图片描述
    • 由于首屏就要加载出首页所以要写到浏览器的默认显式路由组件里面

相应代码

  • menus组件相关代码
//html
<template>
  <div class="home">
    <!-- 将轮播图的数据传给轮播组件 -->
    <Banners :banner="banners"></Banners>
    <!-- 将列表的数据传给列表组件 -->
    <getmenu :list="list"></getmenu>
    <!-- 动态改变加载动画 -->
    <loading @Scroll="Scroll" ref="Loading"></loading>
  </div>
</template>
//js
<script>
// 引入相应的组件
import Banners from "@/views/menu-cars/banners.vue";
import getmenu from "@/components/getmenu.vue";
import loading from "@/views/menu-cars/loading.vue";
// 引入封装好的接口
import { getBanner, getMenus } from "@/connector/api";
export default {
  name: "menus",
  // 写变量接收值
  data() {
    return {
      banners: [],
      list: [],
      page: 0,
      total: 0,
      page_size: 0,
    };
  },
  components: {
    Banners,
    getmenu,
    loading,
  },
 mounted() {
    // 获取轮播图的内容
    getBanner().then(({ data }) => {
      //   console.log(data);
      // 赋值给 banner
      this.banners = data.list;
    });
    // 根据页数获取已发布菜品的内容
    getMenus({ page: this.pages }).then(({ data }) => {
      // console.log(data);
      // 内容
      this.list= data.list;
      // 总数
      this.total = data.total;
      // 一页几条
      this.page_size = data.page_size;
    });
  },
  // 点击时触发
  methods: {
    Scroll() {
      // 页数 + 1
      this.page++;
      // 判断当前页数是否等于最后的页数
      if (this.page == Math.ceil(this.total / this.page_size)) {
        // 等于则关闭 加载图片
        this.$refs.Loading.loading = false;
        // 下面的代码不在执行
        return;
      }
      // 显示 加载图片
      this.$refs.Loading.loading = true;
      // 根据页数获取已发布菜品的内容
      getMenus({ page: this.page }).then(({ data }) => {
        // console.log(loading);
        // 追加到 list里面
        this.list.push(...data.list);
        // 关闭 加载图片
        this.$refs.Loading.loading = false;
      });
    },
  },
};
};
</script>

  • banners相关代码:
<template>
 <div class="home-content">
   <!-- 根据element ui的具体样式实现轮播效果 -->
   <el-carousel :interval="4000" type="card" height="200px">
     <el-carousel-item v-for="item in banner" :key="item.menuId">
       <img :src="item.product_pic_url" alt="" />
     </el-carousel-item>
   </el-carousel>
 </div>
</template>

<script>
export default {
 name: "HomeView",
 // props接受父组件传过来的数据
 props: {
   banner: {
     type: Array,
     default: () => [],
   },
 },
 data() {
   return {
   };
 },
 mounted() {},
};
</script>

<style lang="scss" scoped>
.home-content {
 width: 990px;
 margin: 0 auto;
 .el-carousel__item img {
   width: 200px;
   height: 200px;
 }

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

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

  • loading相关页面
<template>
 <div class="loading">
   <i class="el-icon-loading" v-loading="isLoading" ref="wallfull"></i>
 </div>
</template>

<script>
export default {
 name: "loading",
 data() {
   return {
     isLoading: false,
   };
 },
 mounted() {
   // 利用事件监听监听滚动事件
   window.addEventListener("scroll", this.gun);
 },
 methods: {
   // 滚动事件
   gun() {
     // 判断是否滚动
     if (this.isLoading) return;
     // 判断i标签的底部距离是否达到页面的可视高度 达到则执行滚动事件
     if (
       this.$refs.wallfull.getBoundingClientRect().bottom <
       document.documentElement.clientHeight
     ) {
       console.log("滚动了");
       this.$emit("Scroll");
     }
   },
 },
};
</script>

<style lang="scss" scoped>
.loading {
 text-align: center;
}
</style>

  • getmenu相关代码
<template>
  <div class="menu-main" ref="wallfull">
    <!-- v-for循环渲染数据 -->
    <div class="Selected">
      <router-link
        class="conts"
        v-for="item of list"
        :key="item._id"
        :to="{ name: 'detail', query: { menuId: item.menuId } }"
      >
        <div class="conts">
          <img class="conts-img" :src="item.product_pic_url" alt="" />
          <p>{{ item.title }}</p>
          <p>{{ item.comments_len }}评论</p>
          <router-link
            :to="{ name: 'space', query: { userId: item.userId } }"
            >{{ item.name }}</router-link
          >
        </div>
      </router-link>
    </div>
  </div>
</template>

<script>
export default {
  // props接受父组件传过来的数据
  props: {
    list: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {};
  },
  // mounted() {
  //   console.log(this.list);
  // },
  methods: {},
};
</script>

<style lang="scss" scoped>
.menu-main {
  width: 990px;
  margin: 0 auto;
  h3 {
    text-align: center;
    margin: 10px 0px;
  }
  .Selected {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    // align-items: center;
    .conts {
      width: 232px;
      height: 336px;
      background: #fff;
      margin-bottom: 20px;
      .conts-img {
        width: 232px;
        height: 232px;
      }
      p {
        margin: 5px 10px;
      }
    }
  }
}
</style>

  • header页面相关代码
<template>
  <div class="tou">
    <div class="tou-top">
      <div class="login">
        <el-row type="flex" justify="start" align="middle">
          <el-col :span="6">
            <a href="" class="login"></a>
          </el-col>
          <el-col :span="10" :offset="2"></el-col>
          <el-col :span="6" :offset="3" class="avatar-box" v-if="isLogin">
            <router-link :to="{ name: 'space' }">
              <el-avatar
                style="vertical-align: middle"
                shape="square"
                :src="userInfo.avatar"
              />
            </router-link>
            <router-link :to="{ name: 'space' }" class="user-name">{{
              userInfo.name
            }}</router-link>
            <router-link :to="{ name: 'publish' }" class="collection"
              >发布菜谱</router-link
            >
            <span class="collection" @click="loginout">退出</span>
          </el-col>
          <el-col :span="6" :offset="3" class="avatar-box2" v-if="!isLogin">
            <router-link to="/login">登录</router-link>
            <router-link to="/login">注册</router-link>
          </el-col>
        </el-row>
      </div>
    </div>
    <div class="nav">
      <div class="nav-cont">
        <router-link to="/">首页</router-link>
        <router-link to="/recipe">菜谱大全</router-link>
      </div>
    </div>
  </div>
</template>

<script>
import { login_out } from "@/connector/api";
export default {
  // 将用户的基本信息从vuex里面拿出来
  computed: {
    isLogin() {
      return this.$store.getters.isLogin;
    },
    userInfo() {
      return this.$store.state.userInfo;
    },
  },
  // mounted() {
  //   console.log(this.userInfo);
  // },
  methods: {
    // 点击退出登录
    loginout() {
      console.log(123);
      // 这是element ui里面的提示框方法 直接复用即可
      this.$confirm("确定要退出吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "waring",
      }).then(async () => {
        // 利用接口退出
        await login_out();
        // 将token值删除
        localStorage.removeItem("token");
        // 跳转到首页
        window.location.href = "/";
      });
      // login_out();
    },
  },
};
</script>

<style lang="scss" scoped>
.tou {
  .tou-top {
    width: 100%;
    height: 80px;
    background: red;
    .login {
      width: 990px;
      height: 100%;
      margin: 0 auto;
      // background: #ccc;
      line-height: 80px;
      .avatar-box {
        width: 250px;
        height: 100%;
        display: flex;
        justify-content: space-between;
      }
      .avatar-box2 {
        width: 150px;
        height: 100%;
        display: flex;
        justify-content: space-between;
      }
    }
  }
  .nav {
    width: 100%;
    height: 50px;
    background: #fff;
    border-bottom: 1px solid #ddd;
    line-height: 50px;
    // text-align: ;
    .nav-cont {
      width: 990px;
      height: 100%;
      margin: 0 auto;
      a {
        margin: 0 10px;
      }
    }
  }
}
</style>

总结:

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

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

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

相关文章

找不到工作,软件测试真的不香了?

最近总是有人说测试先不要干&#xff0c;测试不好找工作。测试没有以前那么香了&#xff1f; 可是&#xff0c;这是真的么&#xff1f;什么样的人会说这样的话&#xff1f; 肯定不是现在还在岗的人说的&#xff0c;也不是已经拿到企业聘用offer的人说的。 因为他们都是优秀的…

交换机的工作原理以及搭建局域网划分VLAN

作者简介&#xff1a;一名99年软件运维应届毕业生&#xff0c;正在自学云计算课程。宣言&#xff1a;人生就是B&#xff08;birth&#xff09;和D&#xff08;death&#xff09;之间的C&#xff08;choise&#xff09;&#xff0c;做好每一个选择。创作不易&#xff0c;动动小手…

OneAuth 2022.11.23版本更新内容

2022.11.23版本更新内容&#xff1a; 新增IdP飞书 云目录增加对Group的支持GWA浏览器插件适配性优化自定义授权服务器优化&#xff0c;适应RBAC、ABAC等多种场景授权IdP 北森优化&#xff0c;适配自定义的属性租户的部分试用功能需要联系后台开通其他一些Bug的修复 标题新增 …

GIT

X.1 git上线后同步分支代码 上线后合并远端开发分支到远端master&#xff1a; 本地分支提交到远端分支&#xff0c;git上远端分账合并请求到远端master 上线后合并远端master到远端开发分支&#xff1a; 同步远端master到本地master&#xff0c;将本地master合并到本地开发分…

DM8级联异步备库搭建及故障模拟将异步切换为实时同步

目录 一、 搭建前准备 二、 主库配置 2.1 dmini配置 2.2 dmmal.ini配置 2.3 dmarch.ini配置 2.4 dmwatcher.ini配置 2.5 dmtimer.ini配置 三、 异步备库配置 3.1 dm.ini配置 3.2 dmmal.ini配置 3.3 dmarch.ini配置 3.4 dmwatcher.ini配置 3.5 dmtimer.ini配置 四、…

【计算机网络】HTTP/HTTPS协议基础知识汇总

目录 1.URL&#xff1a; 2.HTTP协议&#xff1a; 2.1抓包工具&#xff08;这里用fiddler&#xff09;&#xff1a; 2.2请求和响应的格式&#xff1a; 2.3方法的介绍&#xff1a; 2.4请求报头&#xff08;header&#xff09;&#xff1a; 2.5状态码&#xff1a; 2.6响应…

格式化DataFrame中的时间数据DataFrame.to_datetime()方法

小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 格式化DataFrame中的时间数据 DataFrame.to_datetime()方法 选择题 关于以下python代码说法错误的一项是? import pandas as pd data {"Date": [2022/12/01,2022/12/02]} df pd…

SQL Server如何获取GUID号

select newid() guid;--获取GUID select replace(newid(),-,) guid;--获取GUID 去掉- sqlserver newid()函数 NEWID (Transact-SQL) - SQL Server | Microsoft LearnNEWID (Transact-SQL)https://learn.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql?redirect…

在大厂工作是这样的

应上面的一个小伙伴要求&#xff0c;让一个朋友整理了他做华为的工作经历&#xff0c;写的有些零散&#xff0c;希望对有大公司情怀的人所有帮助。35岁那年&#xff0c;拿到华为的社招offer。看着邮箱里面的录取通知&#xff0c;心里有高兴也有失落&#xff0c;难受的是看着身边…

腾讯云COS+PicGo+Typora十分钟搭建自己的图床

&#x1f468;‍&#x1f4bb;个人主页&#xff1a; 才疏学浅的木子 &#x1f647;‍♂️ 本人也在学习阶段如若发现问题&#xff0c;请告知非常感谢 &#x1f647;‍♂️ &#x1f4d2; 本文来自专栏&#xff1a; 常见软件安装与运用 ❤️ 支持我&#xff1a;&#x1f44d;点赞…

[附源码]java毕业设计逸尘房屋销售管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

SSRF 漏洞笔记

什么是 SSRF 漏洞 SSRF&#xff08;Server-Side Request Forgery&#xff0c;服务端请求伪造&#xff09;是指攻击者向服务端发送包含恶意 URL 链接的请求&#xff0c;借由服务端去访问此 URL &#xff0c;以获取受保护网络内的资源的一种安全漏洞。SSRF 常被用于探测攻击者无…

引擎入门 | Unity UI简介–第1部分(9)

本期我们继续为大家进行Unity UI简介&#xff08;第一部分&#xff09;的后续教程 本篇内容 21.增加设置按钮 22.添加场景构建 文章末尾可免费获取教程源代码 本篇Unity UI简介&#xff08;第一部分&#xff09;篇幅较长&#xff0c;分为十篇&#xff0c;本篇为第九篇。 …

RK3568平台开发系列讲解(视频篇)视频编码的工作原理

🚀返回专栏总目录 文章目录 一、编码标准介绍二、编码器的工作编码原理介绍2.1、帧类型介绍2.2、消除时间上的冗余信息2.3、消除空间上的冗余信息沉淀、分享、成长,让自己和他人都能有所收获!😄 📢采集下来的内容最终是需要保存到一个视频文件中的,所以就需要用到视频…

折叠屏“世界杯”开哨,荣耀Magic Vs踢出关键一球

已经开幕的卡塔尔世界杯&#xff0c;点燃了全世界球员们的激情和球迷们的热情。有人关注比赛输赢结果&#xff0c;也有人在乎的是运动员高超的技法、球队成员的紧密配合、精彩的战略战术。折叠屏市场从2019元年至今&#xff0c;也来到了关键赛点。一方面&#xff0c;除苹果外重…

【零基础入门SpringMVC】第二期——匹配请求与获取请求参数

一、RequestMapping注解 该注解有什么作用呢&#xff1f; 将请求和处理请求的控制器方法关联起来 &#xff0c;建立映射关系当SpringMVC接收到指定的请求后&#xff0c;就会通过映射关系中对应的控制器方法处理请求 我们可以查看一下该注解的源码&#xff1a; // // Source …

MyBatis-Plus之DQL编程控制

增删改查四个操作中&#xff0c;查询是非常重要的也是非常复杂的操作&#xff0c;本次介绍的有&#xff1a; 条件查询方式查询投影查询条件设定字段映射与表名映射 1. 条件查询 1.1 条件查询的类 MyBatisPlus将书写复杂的SQL查询条件进行了封装&#xff0c;使用编程的形式完…

Docker的镜像管理

Docker的镜像管理Docker的镜像管理一、Docker的镜像管理命令1.1 搜索镜像1.2 获取镜像1.3 镜像加速下载1.4 查看镜像信息1.5 获取镜像详细信息1.6 为本地的镜像添加新的标签1.7 删除镜像1.8 批量删除镜像1.8 存出镜像&#xff1a;将镜像保存成为本地文件1.9 载入镜像&#xff1…

如何用人工智能帮你剪视频?

痛点制作视频已经好几年了&#xff0c;但是剪片子一直是让我比较头疼的事儿。以前我一直搞不清楚&#xff0c;视频为什么需要剪辑。曾经有一段儿&#xff0c;我是这么录视频的。如果讲的时候出现了磕绊&#xff0c;或者有些展示过程出现问题&#xff0c;我怎么办&#xff1f;我…

Kotlin 开发Android app(十一):Android控件RecyclerView

Android 中的控件非常的丰富&#xff0c;我们会陆陆续续的进行介绍&#xff0c;从第九节开始&#xff0c;关于Kotlin 的语法特性就差不多结束&#xff0c;后面如果有发现需要说明的语法&#xff0c;再进行相关的补充。 在Android的控件中&#xff0c;RecyclerView算是一个大控…