前言:
本文给大家讲解,美食杰项目中首页实现的效果,和具体代码。
具体实现思路:
- 向后端请求数据,获取数据,渲染数据
- 引入 element-ui
- 刷新后加载新图片
步骤:
头部代码中包含了一部分登录功能,这个功能在本文没有实现,想要知道的,可以看我发布的实现登录注册功能的文章。
在 加载图片页面代码中,使用了节流 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>
总结:
总结:
以上就是 美食杰项目 中 首页的具体实现方法,不懂得也可以在评论区里问我,以后会持续发布一些新的功能,敬请关注。