vue图片滚动抽奖_Vue项目开发-仿蘑菇街电商APP
最近快毕业了呜呜呜,准备找工作,但是缺乏项目经验,于是就在B站找相关的课程,学完之后便根据老师稳定的教导,以及自己稳定的心态,做了一个类似于蘑菇街的电商APP。(后端数据接口由老师提供,老师叫coderwhy,前端讲得真的很不错)。
附上项目码云地址:https://gitee.com/wu_yuxin/SuperMall.git 如果觉得有用的话,麻烦点个星星,拜托了(╥╯^╰╥)。
蘑菇街作为中国最大女性购物社区,其APP的设计水平也毋庸置疑的
(1)准备工作
在阅读大神的博客时有人问里面使用的美工素材怎么得到的,其实很简单,下载一个APP,把APK格式修改成rar后解压,你会在目录下看到所有的素材。
(2)开始工作 项目目录:
由于是自己的练手之作,所以,莫得启动页面
下面是首页:
详情页
分类页
个人页面:
一. FeatureView
- 独立组件封装FeatureView
- div>a>img
二. TabControl
- 独立组件的封装
- props -> titles
- div>根据titles v-for遍历 div -> span{{title}}
- css相关
- 选中哪一个tab, 哪一个tab的文字颜色变色, 下面border-bottom
- currentIndex
<template><div class="tab-control"><div v-for="(item, index) in titles":key="(item,index)" class="tab-control-item":class="{active: index===currentIndex}"@click="itemClick(index)"><span>{{item}}</span></div></div>
</template>
<script>
export default {name: 'TabControl',props:{titles:{type:Array,default(){return [];}}},data() { return {currentIndex:0,}},methods:{itemClick(index){this.currentIndex = index;this.$emit('tabClick', index);}}}
</script>
<style scoped>
.tab-control{display: flex;text-align: center;font-size: 15px;height: 40px;line-height: 40px;background-color: #fff;
}
.tab-control-item{flex: 1;
}
.tab-control-item span{padding: 5px;
}
.active{color: #ff5777;}
.active span{border-bottom: 3px solid var(--color-tint);
}
</style>
三. 首页商品数据的请求
3.1. 设计数据结构, 用于保存数据
goods: {
pop: page/list
new: page/list
sell: page/list
}
3.2. 发送数据请求
- 在home.js中封装getHomeGoods(type, page)
- 在Home.vue中, 又在methods中getHomeGoods(type)
- 调用getHomeGoods('pop')/getHomeGoods('new')/getHomeGoods('sell')
- page: 动态的获取对应的page
- 获取到数据: res
- this.goods[type].list.push(...res.data.list)
- this.goods[type].page += 1
goods: {
pop: page1:/list[30]
new: page1/list[30]
sell: page1/list[30]
}
四. 对商品数据进行展示
4.1. 封装GoodsList.vue组件
- props: goods -> list[30]
- v-for goods -> GoodsListItem[30]
- GoodListItem(组件) -> GoodsItem(数据)
4.2. 封装GoodsListItem.vue组件
- props: goodsItem
- goodsItem 取出数据, 并且使用正确的div/span/img基本标签进行展示
五. 对滚动进行重构: Better-Scroll
5.1. 在index.html中使用Better-Scroll
- const bscroll = new BScroll(el, { })
- 注意: wrapper -> content -> 很多内容
- 1.监听滚动
- probeType: 0/1/2(手指滚动)/3(只要是滚动)
- bscroll .on('scroll', (position) => {})
- 2.上拉加载
- pullUpLoad: true
- bscroll .on('pullingUp', () => {})
- 3.click: false
- button可以监听点击
- div不可以
5.2. 在Vue项目中使用Better-Scroll
- 在Profile.vue中简单的演示
- 对Better-Scroll进行封装: Scroll.vue
- Home.vue和Scroll.vue之间进行通信
- Home.vue将probeType设置为3
- Scroll.vue需要通过$emit, 实时将事件发送到Home.vue
六. 回到顶部BackTop
6.1. 对BackTop.vue组件的封装
6.2. 如何监听组件的点击
- 直接监听back-top的点击, 但是可以直接监听?
- 不可以, 必须添加修饰.native
- 回到顶部
- scroll对象, scroll.scrollTo(x, y, time)
- this.$refs.scroll.scrollTo(0, 0, 500)
6.3. BackTop组件的显示和隐藏
- isShowBackTop: false
- 监听滚动, 拿到滚动的位置:
- -position.y > 1000 -> isShowBackTop: true
- isShowBackTop = -position.y > 1000
七. 解决首页中可滚动区域的问题
- Better-Scroll在决定有多少区域可以滚动时, 是根据scrollerHeight属性决定
- scrollerHeight属性是根据放Better-Scroll的content中的子组件的高度
- 但是我们的首页中, 刚开始在计算scrollerHeight属性时, 是没有将图片计算在内的
- 所以, 计算出来的告诉是错误的(1300+)
- 后来图片加载进来之后有了新的高度, 但是scrollerHeight属性并没有进行更新.
- 所以滚动出现了问题
- 如何解决这个问题了?
- 监听每一张图片是否加载完成, 只要有一张图片加载完成了, 执行一次refresh()
- 如何监听图片加载完成了?
- 原生的js监听图片: img.onload = function() {}
- Vue中监听: @load='方法'
- 调用scroll的refresh()
- 如何将GoodsListItem.vue中的事件传入到Home.vue中
- 因为涉及到非父子组件的通信, 所以这里我们选择了事件总线
- bus ->总线
- Vue.prototype.$bus = new Vue()
- this.bus.emit('事件名称', 参数)
- this.bus.on('事件名称', 回调函数(参数))
- 因为涉及到非父子组件的通信, 所以这里我们选择了事件总线
- 问题一: refresh找不到的问题
- 第一: 在Scroll.vue中, 调用this.scroll的方法之前, 判断this.scroll对象是否有值
- 第二: 在mounted生命周期函数中使用 this.$refs.scroll而不是created中
- 问题二: 对于refresh非常频繁的问题, 进行防抖操作
- 防抖debounce/节流throttle(课下研究一下)
- 防抖函数起作用的过程:
- 如果我们直接执行refresh, 那么refresh函数会被执行30次.
- 可以将refresh函数传入到debounce函数中, 生成一个新的函数.
- 之后在调用非常频繁的时候, 就使用新生成的函数.
- 而新生成的函数, 并不会非常频繁的调用, 如果下一次执行来的非常快, 那么会将上一次取消掉
debounce(func, delay) {let timer = nullreturn function (...args) {if (timer) clearTimeout(timer)timer = setTimeout(() => {func.apply(this, args)}, delay)}},
八. 上拉加载更多的功能
loadMore(){this.getHomeGoods(this.currentType);this.$refs.scroll.refresh();}
九. tabControl的吸顶效果
9.1. 获取到tabControl的offsetTop
- 必须知道滚动到多少时, 开始有吸顶效果, 这个时候就需要获取tabControl的offsetTop
- 但是, 如果直接在mounted中获取tabControl的offsetTop, 那么值是不正确.
- 如何获取正确的值了?
- 监听HomeSwiper中img的加载完成.
- 加载完成后, 发出事件, 在Home.vue中, 获取正确的值.
- 补充:
- 为了不让HomeSwiper多次发出事件,
- 可以使用isLoad的变量进行状态的记录.
- 注意: 这里不进行多次调用和debounce的区别
9.2. 监听滚动, 动态的改变tabControl的样式
- 问题:动态的改变tabControl的样式时, 会出现两个问题:
- 问题一: 下面的商品内容, 会突然上移
- 问题二: tabControl虽然设置了fixed, 但是也随着Better-Scroll一起滚出去了.
- 其他方案来解决停留问题.
- 在最上面, 多复制了一份PlaceHolderTabControl组件对象, 利用它来实现停留效果.
- 当用户滚动到一定位置时, PlaceHolderTabControl显示出来.
- 当用户滚动没有达到一定位置时, PlaceHolderTabControl隐藏起来.
十. 让Home保持原来的状态
10.1. 让Home不要随意销毁掉
- keep-alive
10.2. 让Home中的内容保持原来的位置
- 离开时, 保存一个位置信息saveY.
- 进来时, 将位置设置为原来保存的位置saveY信息即可.
- 注意: 最好回来时, 进行一次refresh()
非父子组件通信:
https://www.jb51.net/article/132371.htm
我们在用Vue进行前端开发的时候,往往会遇到有很多个组件内,他们都有类似的data,类似的方法。这些大量重复的代码,如果正常编写出来,代码既不美观也不优雅,而且看起来也相当复杂。所以vue官方提供了一个极其好用的方式来解决这个问题
那就是mixin
先来看看官方的介绍
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
在Java开发中 如果我们遇到两个类有大量相似代码的时候,我们通常会定义一个父类,来讲这些重复代码写在一起,然后再让这两个类来继承父类的代码和方法。
class Animal{run(){}
}
class Person extends Animal{//run(){}
}
class Dog extends Animal{//run(){}
}
而在Vue中,每个组件export出来的是对象,所以不能像类那样继承,于是Vue提供了类似于类的继承的方法 mixin
使用方法,在这里贴上自己项目的部分代码。
定义一个mixin.js 文件
import {debounce} from './utils';
export const itemListenerMixin = {data(){return {itemImgListener: null,}},methods:{
},mounted(){let newRefresh = debounce(this.$refs.scroll.refresh, 100)
this.itemImgListener = () => {newRefresh()}
this.$bus.$on('itemImgLoad', this.itemImgListener)console.log("我是混入的东西")}
}
mixin 里就跟一个正常的Vue的组件没有任何的区别,可以定义data,methods,生命周期函数等等。跟Java里面的父类和子类完全一样。只是调用的方法不一样而已。
两个调用mixin.js的组件
Detail.vue
import {itemListenerMixin} from "common/mixin";
mixins: [itemListenerMixin],
//其余代码均省略
Home.vue
import {itemListenerMixin} from "common/mixin";
mixins: [itemListenerMixin],
//其余代码均省略
只需要这样一小段代码,就可以调用到mixin.js 内定义的组件了。
而且在两个组件内,作用完全一样
当我们在组件上应用Mixin的时候,有可能组件与Mixin中都定义了相同的生命周期钩子,这时候钩子的执行顺序的问题凸显了出来。默认Mixin上会首先被注册,组件上的接着注册,这样我们就可以在组件中按需要重写Mixin中的语句。组件拥有最终发言权。当发生冲突并且这个组件就不得不“决定”哪个胜出的时候,这一点就显得特别重要,否则,所有的东西都被放在一个数组当中执行,Mixin将要被先推入数组,其次才是组件。
const myMixin = {mounted() {console.log('mixin!')}
}
new Vue({el: '#app',mixins: [myMixin],mounted() {console.log('Vue instance!')}
});
//Output in console> mixin!> Vue instance!
//mixin
const myMixin = {methods: {sayHello: function() {console.log('mixin!')}
},mounted() {this.sayHello()}
}
//vue instance or component
new Vue({el: '#app',mixins: [myMixin],methods: {sayHello: function() {console.log('Vue instance!')}
},
mounted() {this.sayHello()}
})
// Output in console
> Vue instance!
> Vue instance!
我们可以看到,当他们之间没有发生同名冲突的时候,两个都正常打印了。而当他们发生冲突之后。你可以看到这里打印了两个Vue instance。这是因为第一个函数被调用之后,并没有被销毁,而是被重写了。然后被调用了两次
当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合。
选项合并
- 数据对象(data)在内部会进行递归合并,在和组件的数据发生冲突时以组件数据优先。
- 同名钩子函数(created,mounted...)将混合为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
- 值为对象的选项(methods, components 和 directives)将被混合为同一个对象。两个对象键名冲突时,取组件对象的键值对。
需要注意的是
谨慎使用全局混入对象,因为会影响到每个单独创建的 Vue 实例 (包括第三方模板)。大多数情况下,只应当应用于自定义选项。也可以将其用作 Plugins 以避免产生重复应用
所以Vue对mixin 设定了 自定义选项合并策略
自定义选项将使用默认策略,即简单地覆盖已有值。如果想让自定义选项以自定义逻辑合并,可以向
Vue.config.optionMergeStrategies
添加一个函数:
Vue.config.optionMergeStrategies.myOption = function (toVal, fromVal) {// 返回合并后的值
}
对于多数值为对象的选项,可以使用与 methods
相同的合并策略:
var strategies = Vue.config.optionMergeStrategies
strategies.myOption = strategies.methods
vue图片滚动抽奖_Vue项目开发-仿蘑菇街电商APP相关推荐
- b站coderwhy老师_Vue项目开发-仿蘑菇街电商APP
最近快毕业了呜呜呜,准备找工作,但是缺乏项目经验,于是就在B站找相关的课程,学完之后便根据老师稳定的教导,以及自己稳定的心态,做了一个类似于蘑菇街的电商APP.(后端数据接口由老师提供,老师叫code ...
- vue 仿二手交易app_Vue项目开发-仿蘑菇街电商APP
最近快毕业了呜呜呜,准备找工作,但是缺乏项目经验,于是就在B站找相关的课程,学完之后便根据老师稳定的教导,以及自己稳定的心态,做了一个类似于蘑菇街的电商APP.(后端数据接口由老师提供,老师叫code ...
- Vue项目开发-仿蘑菇街电商APP
最近快毕业了呜呜呜,准备找工作,但是缺乏项目经验,于是就在B站找相关的课程,学完之后便根据老师稳定的教导,以及自己稳定的心态,做了一个类似于蘑菇街的电商APP.(后端数据接口由老师提供,老师叫code ...
- 区块链项目【拼爹爹电商app】开源
区块链项目[拼爹爹电商app]开源 ===================================================== [作者]:牛哥 qq和wx:1325821989 邮箱: ...
- APICloud AVM多端开发 |《生鲜电商app开发》项目源码深度解析
此项目为生鲜电商app开发类应用,主要功能包括商品列表.商品详情展示.购物车.登录注册.个人中心等. 项目源码在 https://github.com/apicloudcom/avm-simple 仓 ...
- 如何开发一款电商app小程序
开发一款电商小程序首先要明确主要功能方向,电商平台三个方向前端商城.管理端(平台管理后台Pc端)以及供应商中心(PC端). 一.前端商城功能包含: 1.用户注册与登陆(用户通过手机号作为唯一标识进行注 ...
- 服装电商APP软件开发平台作用
服装电商APP开发,服装电商软件开发,服装电商APP开发平台,服装电商软件开发作用.服装产品的存有,让用户可以按照自己的喜爱开展变装小说,与此同时,因为网上购物方法的时兴,服装电商APP软件开发也应时 ...
- ios一个app调起另一个app_电商app开发价格:制作一个电商app需要多少钱?
智能手机的发展,带动了各式各样手机app的市场,现在大家网购大多数都是通过电商app实现,再加上分销.配送等模式发展,自建电商app成为很多企业的选择,电商app开发成本大概多少?制作一个电商app需 ...
- 美妆电商APP开发解决方案
随着移动互联网的发展,人们可以在网络上获得各种信息,很多人对化妆护肤有很大的需求,用户需要多次实践才能在生活中找到适合自己的化妆品.为了满足用户浏览和购物需求,美容电子企业APP开发出现在人们的生活中 ...
最新文章
- 08-01-json-loggin-模块
- 三行代码实现快速排序
- Insomni'hack teaser 2019 - Misc - curlpipebash
- ECharts-图表回执组件
- ElasticSearch+NLog实现.net core分布式日志管理
- Linux基础(5)--Linux常用命令表
- OS学习笔记32—使用Storyboard实现复杂界面
- stol函数在linux下使用,linux socket编程(一)
- 51单片机c语言教程第二章,51单片机C语言教程-郭天祥-PDF转word版第二章.pdf
- 【python路上小记】匹配11位电话正则表达式
- 相关常用单位转换 mil 英里 英尺 .......
- Ansys HFSS仿真
- 挠场的科学丨五、二十一世纪的挠力文明
- bootstrap-tagsinput操作标签对象,实现从表格中选人和移除
- 京东广告受众基础属性预估
- 2018 rust卡石头教程_rust地上的石头怎么捡 | 手游网游页游攻略大全
- Aquatone -- 子域名探测
- php相同数据合并单元格,jQuery_基于jQuery的合并表格中相同文本的相邻单元格的代码,ONE
已经生成的数据表格大致 - phpStudy...
- 十一、Cadence ic 617以及assura使用总结
- 计算机图像技术及其应用,计算机图像处理技术及其应用领域
热门文章
- 888. 公平的糖果棒交换
- 想成为架构师,你必须掌握的CAP细节
- 9-4 节点取余分区
- c程序语言符号的作用,c语言宏定义中的#,##,#@及\符号的作用
- sap脚本运行_如何使用Python脚本运行SAP?
- python序列操作_序列操作
- jde多目标_《和平精英》PEL职业联赛S3赛季:DKG战队获第四周周冠军,JDE“逆风翻盘”...
- 谷歌云服务器支持udp,谷歌浏览器扩展使用UDP
- tomcat7 java_java开发环境配置(windows下JDK7+tomcat7)
- 解决 Qt5 报错 This application failed to start because it could not find or load the Qt platform plugin