宝哥软件园

Vue实用教程模仿肯德基送货上门App

编辑:宝哥软件园 来源:互联网 时间:2021-08-21

Vue已经学习了一段时间,所以我想用Vue写一个项目来练手。半个月后,我几乎看不到它,直到今天。

因为不知道手机App的界面怎么弄,肯德基电脑上的官网真的是.一言难尽,项目的所有数据都是我拍的然后用EasyMock写的,所以有需要的同学可以自带。

产品主页外卖页面

技术栈

vue webpack vuex axios

文件目录

app . vuemain.jsassetslogo.pngcomponentscart control . vuecode . vue优惠券. vuemine header . vuescroll . vueshop header . vues idebar . vuesubmit bar . vue外卖. vue钱包. vuetabs其他. vue外向. vue自助. vue Vgold.vuepages home

定义的组件

更好的滚动

因为每个页面都需要滑动,所以滚动组件是在开始时打包的,如果您以后使用它,您可以引入它

template div ref=' wrapper ' slot/slot/div/templatescriptionbscroll来自更好的滚动;' const DIRECTION_H='水平;' const DIRECTION_V='垂直;导出默认{ name: 'scroll ',prop : {/* * * 1滚动的时候会派发卷起事件,会节流。 * 2 滚动的时候实时派发卷起事件,不会节流。 * 3 除了实时派发卷起事件,在偷窃的情况下仍然能实时派发卷起事件*/探针类型: {类型:数字,默认值: 1 },/** *点击列表是否派发点击事件*/click: { type:布尔值,default: true },/** *是否开启横向滚动*/scrollX: { type:布尔值,default: false },/** *是否派发滚动事件*/listenScroll: { type:布尔值,default: false },/** *列表的数据*/data: { type: Array,default: null },上拉: { type:布尔值,default: false },下拉: { type:布尔值,default: false }、beforeScroll: { type:布尔值、default: false }、/** *当数据更新后,刷新卷起的延时*/刷新延迟: { type : Number,default: 20 },direction: { type: String,default: DIRECTION_V } },methods: { _initScroll() { if(!这个参考文献。包装){ return }这个。滚动=新的b croll(这.$refs.wrapper,{ probeType: this.probeType,click: this.click,eventpassthrough : this。DIRECTION===DIRECTION _ V?DIRECTION _ H : DIRECTION _ V })//是否派发滚动事件如果(这个。{这个。卷轴。on(' scroll ',(pos)={ this .$emit('scroll ',pos) }) } //是否派发滚动到底部事件,用于上拉加载如果(这个。果肉){这个。卷轴。on(' scrollEnd ',()={ if(this。卷轴。y=(这个。卷轴。maxscrolly 50)){这个.$ emit(' scroltoend ')} })}//是否派发顶部下拉事件,用于下拉刷新如果(这个。下拉){ this.scroll.on('touchend ',(pos)={ //下拉动作如果(位置y 50){ 0这个$emit('下拉')} }) } //是否派发列表滚动开始的事件如果(这个。滚动前){这个。卷轴。on('在滚动开始前',()={ this .$ emit(' BeforeSColl ')})} },disable() { //代理更好的滚动的使残废方法这个。滚动这个。卷轴。disable()},enable() { //代理更好的滚动的使能够方法这个。滚动这个。卷轴。enable()},refresh() { //代理更好的滚动的恢复精神方法这个。滚动这个。卷轴。refresh()},scrollTo() { //代理更好的滚动的滚动到指定位置方法这个。滚动这个。卷轴。去。应用(这个。scroll,arguments) },scrolltetoelement(){//代理更好的滚动的scrollToElement方法这个。滚动这个。滚动到元素。应用(这个。滚动,参数)},},挂载(){ setTimeout(()={ this ._initScroll() },20) },watch : { data(){ setTimeout(()={ this。refresh()},this . refresh delay()},}/scriptstyle/styleslot插槽是一块模板,显示不显示,以及怎样显示由父组件来决定,也就是把你想要滑动的区域插进去,剩下的内容都是官方文档定义好的,复制一遍就好了

固定头部

头部相对页面是固定的,这里我把头部都封装成了组件,在主页面引入头部,要滑动的部分放入上面定义好的卷起组件即可

侧边栏以及弹出框

起初我的想法是用路由器链路直接跳转,然后发现这样做页面会自带导航栏,于是我决定通过半铸钢钢性铸铁(铸造半钢)动态绑定来实现它

模板' div class='侧边栏' div class='侧边栏-con ' : class=' { show bar : show侧边栏} ' div class=' nav bar _ left ' @ click=' backTo ' img src=' http :/pages/我的/动物园。png ' alt=' '/div van-tree-select : height=' 850 ' : items=' items ' : main-active-index=' main active index ' : active-id=' active id ' @ nav click=' onnav click ' @ item click=' one pick mclick '/div/template样式用的是相关用户界面组件,最外面绑定了一个动态样式展示吧,然后把整体的初始位置设在屏幕之外,当传入参数为真实的时再回来,用状态管理管理它的状态。侧边栏-con {位置:绝对;top : 0;左侧:-400像素;transform : translateZ(0);opa城市3360 0;宽度: 100%;z指数: 1002;高度: 100%;飞越:汽车;过渡:全部0.3s轻松;}.显示栏{ transform : translateX(400 px);opa城市3360 1;}Vuex状态管理

const状态={ showsidebar : false } const突变={[键入.COM_SHOW_SIDE_BAR](状态,状态){ state。显示侧栏=status } } const actions={ setSHOW侧栏({提交},状态){提交(类型.COM_SHOW_SIDE_BAR,status)} } const getter={ SHOW SIDE BAR : state=state。显示侧栏}用mapGetter拿到对象,然后传给计算属性,对象可以直接使用

computed: {.mapgetter([' show侧栏']) },当需要显示的时候使用派遣将参数传入这个$商店。调度('设置显示侧边栏,真)

整体代码

模板' div class='侧边栏' div class='侧边栏-con ' : class=' { show bar : show侧边栏} ' div class=' nav bar _ left ' @ click=' backTo ' img src=' http :/pages/我的/动物园。png ' alt=' '/div van-tree-select : height=' 850 ' : items=' items ' : main-active-index=' main active index ' : active-id=' activeId ' @ nav click=' onnav click ' @ item click=' onemclick '/div/div/templatest import { tree select }来自vant ';从“vuex”导入{ MapGetters };导出默认的{data() { return { },],//左侧高亮元素的索引mainActiveIndex: 0,//被选中元素的id active id : { 1 };},computed: {.mapgetter([' show侧边栏]) },方法: { onNavClick(index){ this。mainactiveindex=index},onItemClick(数据){这个。activeID=数据。id;这个$emit('active ',data.text)这个$商店。调度(' setshow侧边栏,false) },backTo(){ this .$商店。调度(' setshow侧边栏,false) },}}/scriptstyle作用域。侧边栏-con {位置:绝对;top : 0;左侧:-400像素;transform : translateZ(0);opa城市3360 0;宽度: 100%;z指数: 1002;高度: 100%;飞越:汽车;过渡:全部0.3s轻松;}.显示栏{ transform : translateX(400 px);opa城市3360 1;}.nav bar _ left {底色: # da3a 35}.navbar _左img { width: 25px高度: 25px左边距: 3大众;边距-top : 5px;}/样式外卖点餐

这里参考的是慕课网黄奕大大的课程,课程地址

商品展示

模板' div class='外卖:class=' {外卖:秀外卖} ' div class=' goods ' div class=' header ' div class=' nav bar _ left ' @ click=' backTo ' img src=' http :/pages/商店/动物园。png ' alt=' '/div class='约会div class='btn' div class='yy '预约div class=' Kcoffee 'K咖啡/div/div class=' bag '路由器-链接样式='color: #000 '到='/优惠券div class='bagtext '卡包p3/p张/div/router-link/div/div/class=' good list ' div class=' menu-wrapper ' ul Li v-for='(item,index)in goods ' : key=' index ' class=' menu-item ' : class=' { ' current ' : current index===index } ' @ click=' selectMenu(index,$ event)' span class=' text border-1px '(item。name } }/span/Li/ul $ event)div class=' icon ' img : src=' http : food。image '/div class=' content ' H2 class=' name ' { food。名称} }/H2 div class=' price ' span class=' now ' { food。price } }/span/div class=' cart control-wrapper ' cart control @ add=' addFood ' : food=' food '/cart control/div/div/Li/ul/ul/div/div提交-吧台裁判这里通过当前值的索引和指数做对比,来确认是否添加目前的类,通过添加目前的类来实现当前页面的区域的样式变化,他们之间的对比关系也就是菜单区域和食品区域的显示区域的对比关系

需要注意的是某视频剪辑软件传递原生事件使用$事件

从“更好滚动”导入购物车控件得脚本导入./cartcontrol "从导入提交栏"。/Submit bar ' import { mapgeters }从vuex '导出默认{ name : ' output },data() { return { goods: [],listhheight :[],scrolly : 0 { 0 } },components: { cartcontrol,submitBar },computed: {.mapgetter([' show外卖]),CurrentDex(){ for(让I=0;我喜欢这个。列表高度。长度;I){ 0让height1=this.listHeight[i - 1]让height2=this.listHeight[i] if(!身高2 | |(这个。scrolly=身高1这个。scrolly height 2)){ return I } } return 0 },选择foods(){ let foods=[]this。商品。foreach(good={ good。食物。食物。计数){食物。push(food)} })})return foods } },methods: { backTo () { this .$商店。调度(' setshow外卖,false) },选择菜单(索引,事件){ if(!事件_ construct){ return;}让foodList=这个.$ refs.foodList让El=Food LiST[index];这个。美食街。scrollttetoelement(El,300);},选择食物(食物,活动){ if(!事件_ construct){ return;} this.selectedFood=food},init scroll(){ this。meunscroll=new BScroll(今年.$refs.menuWrapper,{ click : true })这。foods croll=new b croll(今年.$ refs.foodsWrapper,{ click: true,probe type : 3 })这。食物呱呱叫。on(' scroll ',pos={ this。scrolly=数学。ABS(数学。圆形(位置。y))})},_计算高度(){让食物清单=这个.$refs.foodList让高度=0表示(让I=0;I food list . lentii){ let item=food list[I]height=item。客户身高这个。列表高度。push(height)} },created () { this .$ http。get(' https://www。简单的模仿。com/mock/5ca 49494 ea 0 DC 52 BF3 b 67 f4e/示例/外卖')。然后(RES={ if(RES . data。errno===0){ this。货物=资源数据。这个数据.$nextTick(()={ this ._initScroll()这个_ calculatehead()})} })} } }脚本购物车

模板设计类='提交栏' van-Submit-bar : loading=' setloading ' : price=' total price ' button-text='提交订单@ submit=' onSubmit ' div class=' shopping cart ' @ click=' toggle list ' img src=' http :/./images/gwc。png ' alt=' span v-if=' selectfoods。长度0“{ select foods。长度} }/span/div/van-submit-bar转换名称=' fold ' div class=' shot cart-list ' v-show=' listshow ' div class=' list-header ' h1 class=' title '购物车/h1 span class='empty ' @单击='空'清空/span/div class=' list-content ' ref=' list content ' ul Li class=' food ' v-for='(food,index)in selectFoods ' : key=' index ' span class=' name ' { food。name } }/span div class=' price ' span{ { food。价格*食物。count } }/span/div class=' cart control-wrapper ' cart control @ add=' addFood ' : food=' food '/cart control/div/Li/ul/ul购物车列表的显示和隐藏以及清空按钮是通过数据折叠来决定的,购物车列表是通过计算属性列表显示来实现,清空按钮也是通过设置数数属性来实现,这样都达到了不用操作数字正射影像图就可以改变数字正射影像图行为的效果。

从“万特”脚本导入{提交栏};从"更好滚动"中导入BScroll从""导入cartcontrol ./cart control ';导出默认值{ prop s : { select food s 3360 { type : Array,default() { return [ { price: 10,count: 1 } ] },},data(){ return { set load : false,fold: true } },computed : { total count(){ let count=0 this。选择食物。foreach((食物)={ count=食物。count })返回count },totalPrice () {让total=0 this .这个。总数){这个。fold=true返回false }让show=!如果(显示)这个,请折叠$nextTick(()={ if(!这个。卷轴){这个。滚动=新的滚动(这.$refs.listContent,{单击: true })} else { this。卷轴。refresh()} })} return show } },methods : { toggles list(){ console。日志(这个。totalcount)if(!这个。total count){ return;} this.fold=!这个。折叠;},OnSubmit(){ this。set loading=true },empty(){ this。选择食物。foreach((食物)={食物。计数=0;});},HideList(){ this。fold=true},addFood() {},components 3360 { cart control } }/script操作按钮

这个模块主要通过三个小模块实现,删除按钮,显示数量块,增加按钮

模板div class='cartcontrol '过渡名称='移动' div class=' cart-reduce ' v-show=' food。count 0 ' @ click=' decase cart ' div class=' inner ' img width=' 15px ' height=' 15px ' src=' http :/./图片/健。png ' alt=' '/div/div/transition div class=' cart-count ' v-show=' food。计数0“{食物。count } }/div class=' cart-add ' @ click=' addCart ' img width=' 15px ' height=' 15px ' src=' http 3360././images/add。png ' alt=' '/div/div/TemplateAddCart以及减少购物车方法,默认会传入事件原生数字正射影像图事件食物数据是从父组件传入的,所以对这个数据的修改,也能够反应到父组件,也因为购物车的数据也是从父组件传入的,使用同一个食物数据,从而关联到购物车的购买数量统计。

脚本导出默认{ name: 'cartcontrol ',prop : { food : { type : Object } },data(){ return } },methods : { AddCart(event){ console。日志(事件)if(!事件_ construct){ return } if(!这个,食物,数数$set(this.food,count,1) } else { this.food.count } this .$emit('add ',event.target) },decase cart(event){ if(!事件_ construct){ return } if(this。食物。计数){这个。食物。count-} },}/script异步问题

变量' : key=' index ' div class=' title ' div class=' strip '/div p { { item[0]} '中的' variable ' v-for='(item,index ).name } }/p div class=' strip '/div/div class=' variable _ img ' div class=' variable _ title ' img : src=' http : item[0].urll ' alt=' '/div ref=' list wrapper ' class=' index ' div class=' variable _ list ' div class=' variable _ box ' v-for='(u,I)in item。slice(1)' : key=' I ' img : src=' http : u . URL ' alt=' '/div/div/div这里循环嵌套,整个数字正射影像图结构都是循环出来的,而更好的滚动需要操作数字正射影像图结构,要实现横向滑动效果,难免会有异步问题。

可是无论我使用。然后或者$nextTick都无法挂载更好的滚动,查阅了大量文档也无法解决,最后只能使用原生的溢出-X,若是有解决办法,欢迎提出,感激不尽!

结语

总的来说这个项目还有很多不足,实现的功能也很少,后续我会继续改进。

如果这篇文章对你有帮助,不妨点个赞吧!

开源代码库地址

总结

以上是肯德基送货上门App的副本,是边肖介绍的Vue实用教程。希望对大家有帮助。如果你有任何问题,请给我留言,边肖会及时回复你。非常感谢您对我们网站的支持!如果你觉得这篇文章对你有帮助,请转载,请注明出处,谢谢!

更多资讯
游戏推荐
更多+