组件一创建 首先判断有没有定位 没有定位则调用后端的接口进行定位
created() {
let {lat, lng} = this.address;
if (!lat || !lng) {//如果没有定位 进行定位
this.getLocation();//定位
}
}
getLocation() { //获取当前定位
this.$store.dispatch('location');//调用vuex的location方法
}
location({commit}) {
location().then((response) => {//异步 location方法来源于api中的location方法
if (response.data.status === 200) {//200表示地址获取成功
let data = response.data.data;//取得数据
//调用了给地址重新赋值的方法types.RECORD_ADDRESS 把拿到的data数据中的address和location赋值给address
commit(types.RECORD_ADDRESS, {address: data.address, ...data.location}); //保存地址和经纬度到VUEX中
commit(types.LOCATION_READY, true);//定位完成 拉取商店
}
})
}
location(data){//定位当前位置
let req = {data}
req.url = 'v1/location'
return _get(req)
}
_get(req){
return axios.get(req.url, {params: req.data})
}
顶部导航条:复用head组件
定位搜索
左边用router-link包裹 点击后跳转到location页面 传参数将fromIndex设为true 表示是从首页跳转过去的 里面左右两边都是iconfont 中间显示地址
<router-link to="/location?fromIndex=true" class="location">
<i class="iconfont"></i>
<span class="address">{{address.address}}</span>
<i class="iconfont"></i>
</router-link>
右边用router-link包裹 点击后跳转到search页面 里面是一个iconfont和写死的文字
<router-link to="/search" class="search">
<i class="iconfont"></i>
<span>请输入商家 商品名</span>
</router-link>
导航轮播图nav组件
向右滑动:
附近商家
<span class="line"></span>
<h2>附近商家</h2>
<span class="line"></span>
.line {
vertical-align: middle;
display: inline-block;
@include px2rem(width, 70);
height: 0;
border-bottom: 1px solid #000;
}
商家列表nearby-shops组件
组件一创建 就去获取地址 这里我们是把地址写死了的 因为学校ip太多 有时候获取不到地址 获取到地址后发送请求获取餐馆信息
created() {
let {lat, lng} = this.address;
if (lat && lng) {
this.shopLists = [];
this.firstFetch();
} else {
this.$store.dispatch('location');
}
}
firstFetch() {
let _this = this;
//获取餐馆列表
this.page = 1;
this.getRestaurants(this.page, this.limit, function (data) {
_this.page++;
_this.shopLists = data;
_this.$nextTick(() => {//dom渲染完成 初始化better-scroll
//better-scroll 默认会阻止浏览器的原生 click 事件,所以须添加以下配置:click: true
//当 probeType 为 2 的时候,会在屏幕滑动的过程中实时的派发 scroll 事件
_this.BScrollEvent = new BScroll(_this.scrollWrapper, {click: true, probeType: 2});
_this.listenScroll();//监听scroll事件
})
})
}
getRestaurants(page, limit, callback) { //获取餐馆列表
if (this.noMore || this.preventRepeat) return;
this.preventRepeat = true;
let offset = (page - 1) * limit;
let {lat, lng} = this.address;
getRestaurants({offset, limit, lng, lat}).then((response) => {
let data = response.data.data;
this.preventRepeat = false;
this.noMore = data.length < this.limit;
callback(data);
});
}
listenScroll() {
let _this = this;
_this.BScrollEvent.on('scroll', function (obj) {//如果到达底部 请求加载更多数据
//scrollHeight(文档内容实际高度,包括超出视窗的溢出部分)、scrollTop(滚动条滚动距离)、
// clientHeight(窗口可视范围高度)。当 clientHeight + scrollTop >= scrollHeight 时,
// 表示已经抵达内容的底部了,可以加载更多内容。
if (Math.abs(obj.y) + _this.scrollWrapper.clientHeight >= _this.scrollWrapper.childNodes[0].clientHeight - 30) {
if (!_this.loading) { //避免加载过程中 重复请求
_this.loading = true;
_this.getRestaurants(_this.page, _this.limit, function (data) {//请求加载更多
_this.page++;
data.forEach((el) => {
_this.shopLists.push(el);
});
//DOM重新渲染完毕后 重新计算better-scroll
_this.$nextTick(() => {
_this.loading = false;
_this.BScrollEvent.refresh();
})
})
}
}
})
}
<ul>
<li>综合排序 <i class="iconfont icon-sort"></i></li>
<li>销量最高</li>
<li>距离最近</li>
<li>筛选</li>
</ul>
ul中使用flex布局
- 因为点击店铺会跳转到相应的店铺组件 所以每个店铺都需要用
router-link
包裹 携带的参数是店铺的id 我们遍历shopLists并展示在router-link
中 - 一个店铺分为两大部分 左边取出遍历到的元素的图片展示出来
- 右边先取出遍历到的元素的name展示出来 取出遍历到的元素的score传给star组件 取出遍历到的元素的月售订单数展示出来 取出遍历到的元素的分钟数、距离展示出来 取出遍历到的元素的起送价、配送费、人均价格并展示出来
- 接下来遍历遍历到的元素的折扣信息并展示出来
<router-link
v-for="(item) in shopLists"
:to="{path:'store',query:{id:item.id}}"
:key="item.id"
tag="section">
<!--左边取出遍历到的元素的图片 展示出来-->
<div class="img-show">
<img :src="item.pic_url">
</div>
<!--右边店铺信息-->
<div class="detail">
<!--取出遍历到的元素的name展示出来-->
<h4>{{item.name}}</h4>
<div class="shops-message">
<!--取出遍历到的元素的score传给star组件 展示星级效果-->
<v-star :score="item.wm_poi_score"></v-star>
<!--取出遍历到的元素的月售订单数展示出来-->
<span class="sell-num">{{item.month_sales_tip}}</span>
<!--取出遍历到的元素的分钟数、距离展示出来-->
<div class="delivery-info">
<span class="deliver-time">{{item.delivery_time_tip}}/</span>
<span class="distance">{{item.distance}}</span>
</div>
</div>
<!--取出遍历到的元素的起送价、配送费、人均价格并展示出来-->
<div class="price-message">
<span>{{item.min_price_tip}} | </span>
<span>{{item.shipping_fee_tip}} | </span>
<span>{{item.average_price_tip}}</span>
</div>
<!--取出遍历到的元素的折扣信息并展示出来-->
<div class="active-message">
<ul>
<li v-for="(discount,index) in item.discounts2.slice(0, 1)" :key="index">
<div class="discount-left">
<!--展示图片-->
<img :src="discount.icon_url" class="icon">
<!--展示折扣信息-->
<span class="info">{{discount.info}}</span>
</div>
<!--没有shops这个组件 这里这样写是为了使用一下错误页面-->
<router-link to="/shops" v-if="index === 0">
<!--向下的那个图标-->
<i class="iconfont icon-entry"></i>
</router-link>
</li>
</ul>
</div>
</div>
</router-link>
- 每次上拉时 若还有数据 则显示请求加载更多 如果没有更多的数据了 显示已经到底了
<div class="loading-wrap" ref="loading">
<span class="loading" v-show="loading && !noMore">正在努力加载中…</span>
<span class="no-more" v-show="noMore">已经到底了</span>
</div>