目录
- 前言
- 具体样式
- 代码思路
- 加载样式
- 相应组件
- 相应代码
- 总结:
前言
- 本节给大家讲的是美食杰项目的首页的主要功能和具体样式
具体样式
代码思路
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>
总结:
以上就是 美食杰项目中首页的具体样式和实现方法,不懂得也可以在评论区里问我,以后会持续发布一些新的功能,敬请关注。