Newbee移动商城
前言
Newbee是一个有另一个博主@我是十三 的开源项目,其中对移动端的优化和一些规范非常值得我们学习,下面的一些就是我自己个人对Newbee项目前后端分离部分的前端做的一些个人分析和见解,有不对的请大家指出来。
HOME界面知识点解析
轮播图 token 状态管理
HTML 讲解
我们先看划分的
<div>
<!-- 头部栏 -->
<header class="home-header wrap" :class="{ active: headerScroll }">
<!-- 左边 -->
<router-link tag="i" to="./category"
><i class="nbicon nbmenu2"></i
></router-link>
<!-- 中间 -->
<div class="header-search">
<span class="app-name">新蜂商城</span>
<i class="iconfont icon-search"></i>
<router-link
tag="span"
class="search-title"
to="./product-list?from=home"
>山河无恙,人间皆安</router-link
>
</div>
<!-- 右边 -->
<router-link class="login" tag="span" to="./login" v-if="!isLogin"
>登录</router-link
>
<router-link class="login" tag="span" to="./user" v-else>
<van-icon name="manager-o" />
</router-link>
</header>
<!-- 导航栏fixed -->
<nav-bar></nav-bar>
<!-- 轮播图 -->
<swiper :list="swiperList"></swiper>
<!-- 分类展示 -->
<div class="category-list">
<div v-for="item in categoryList" v-bind:key="item.categoryId">
<img :src="item.imgUrl" />
<span>{{ item.name }}</span>
</div>
</div>
<!-- 商品展示 -->
<div class="good">
<header class="good-header">新品上线</header>
<div class="good-box">
<div
class="good-item"
v-for="item in newGoodses"
:key="item.goodsId"
@click="goToDetail(item)"
>
<img :src="prefix(item.goodsCoverImg)" alt="" />
<div class="good-desc">
<div class="title">{{ item.goodsName }}</div>
<div class="price">¥ {{ item.sellingPrice }}</div>
</div>
</div>
</div>
</div>
<div class="good">
<header class="good-header">热门商品</header>
<div class="good-box">
<div
class="good-item"
v-for="item in hots"
:key="item.goodsId"
@click="goToDetail(item)"
>
<img :src="prefix(item.goodsCoverImg)" alt="" />
<div class="good-desc">
<div class="title">{{ item.goodsName }}</div>
<div class="price">¥ {{ item.sellingPrice }}</div>
</div>
</div>
</div>
</div>
<div class="good" :style="{ paddingBottom: '100px' }">
<header class="good-header">最新推荐</header>
<div class="good-box">
<div
class="good-item"
v-for="item in recommends"
:key="item.goodsId"
@click="goToDetail(item)"
>
<img :src="prefix(item.goodsCoverImg)" alt="" />
<div class="good-desc">
<div class="title">{{ item.goodsName }}</div>
<div class="price">¥ {{ item.sellingPrice }}</div>
</div>
</div>
</div>
</div>
</div>
newbee-mall的结构很清晰从上至下的模块化,比较适合新人去学习,
1. 头部模块:=>header
三个route-link组成各自跳转到功能路由,用户登录状态根据isLogin状态显示,没什么多说的
css略
2. 导航栏:=>navBar
这里建议分离做父子路由嵌套,这样的好处可以减少组件复用,如果对理解比较困难可以向项目中做的
直接复用就可以
解决防范
APP.vue =><router-view> </router-view>
layout.vue=> <templet>
<router-view>动态可选择窗口</router-view>
<nav-bar> 导航栏</nav-bar>
</templet>
layout布局组件其实是很大的约束了我们的布局规范
3. 轮播图:=>swiper
vant ui 略
4. goodsList=>goods
各种的goods进行展示,
一般不超过10条加载,
css:flex布局进行约束
img: prefix可以做为baseURL使用,个人建议使用vuex状态管理工具去请求使用,这样增加了baseUrl的灵活性
JavaScript区块
import navBar from "@/components/NavBar";
import swiper from "@/components/Swiper";
import { getHome } from "../service/home";
import { getUserInfo } from "../service/user";
import { getLocal } from "@/common/js/utils";
import { Toast } from "vant";
export default {
name: "home",
data() {
return {
swiperList: [], //轮播图数据
isLogin: false, //是否登录
headerScroll: false, //头部是否滚动
hots: [], //热门商品list
newGoodses: [], //新商品的list
recommends: [], //最新推荐
categoryList: [
{
name: "新蜂超市",
imgUrl: "//s.weituibao.com/1583585285461/cs.png",
categoryId: 100001
},
{
name: "新蜂服饰",
imgUrl: "//s.weituibao.com/1583585285468/fs.png",
categoryId: 100003
},
{
name: "全球购",
imgUrl: "//s.weituibao.com/1583585285470/qq.png",
categoryId: 100002
},
{
name: "新蜂生鲜",
imgUrl: "//s.weituibao.com/1583585285472/sx.png",
categoryId: 100004
},
{
name: "新蜂到家",
imgUrl: "//s.weituibao.com/1583585285467/dj.png",
categoryId: 100005
},
{
name: "充值缴费",
imgUrl: "//s.weituibao.com/1583585285465/cz.png",
categoryId: 100006
},
{
name: "9.9元拼",
imgUrl: "//s.weituibao.com/1583585285469/pt.png",
categoryId: 100007
},
{
name: "领劵",
imgUrl: "//s.weituibao.com/1583585285468/juan.png",
categoryId: 100008
},
{
name: "省钱",
imgUrl: "//s.weituibao.com/1583585285471/sq.png",
categoryId: 100009
},
{
name: "全部",
imgUrl: "//s.weituibao.com/1583585285470/qb.png",
categoryId: 100010
}
]
};
},
components: {
navBar,
swiper
},
//挂载钩子函数
async mounted() {
//获取token
const token = getLocal("token");
//如果有token显示登录状态
if (token) {
this.isLogin = true;
}
//挂载全局事件流
window.addEventListener("scroll", this.pageScroll);
//开启转圈圈加载icon
Toast.loading({
message: "加载中...",
forbidClick: true
});
//建议抽离别写在一起 首页数据
const { data } = await getHome();
this.swiperList = data.carousels;
this.newGoodses = data.newGoodses;
this.hots = data.hotGoodses;
this.recommends = data.recommendGoodses;
Toast.clear();
},
methods: {
//滑动监听 加入到事件流中
pageScroll() {
let scrollTop =
window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop;
scrollTop > 100
? (this.headerScroll = true)
: (this.headerScroll = false);
},
//跳转详情
goToDetail(item) {
this.$router.push({ path: `product/${item.goodsId}` });
}
}
};
- 数据请求:这里直接用了异步请求挂载到了周期函数里,个人建议不要这么做,getList方法请在方法区(methods)定义
- token验证:个人建议vuex控制用户状态view页面只需要判断状态,这样做到状态业务逻辑模块和用户模块的耦合
- 路由跳转:没有什么多说的
- 全局滑动监听:建议多写一个销毁生命周期方法,进行监听的提出,不要使用匿名函数
CSS部分:
less预编译器的函数处理以及flex布局引用,请移步less官网和阮一峰老师的flex引用
转载和鸣谢
鸣谢新蜂商城对开源社区做的贡献,站在巨人肩膀上才能看的更远,@我是十三 大大
以下是开源项目github地址:
newbee-mall 在 GitHub 和国内的码云都创建了代码仓库,如果有人访问 GitHub 比较慢的话,建议在 Gitee 上查看该项目,两个仓库会保持同步更新。
-
newbee-mall in GitHub : github.com/newbee-ltd/…
-
newbee-mall in Gitee : gitee.com/newbee-ltd/…