饿了么 vue 项目总结

项目效果预览 ele效果预览
项目源码地址 ele源码
跟着慕课网黄轶老师 敲饿了么 vue 项目

作者项目源代码地址

项目完成之后 npm run build

这本来是写在最后面一段的,我现在把他写在了最前面,方便我们事先知道,整个项目做完之后是什么样子的

  • 项目完成之后在 根目录 下 npm run build (就是 npm run dev 的那个目录)
  • 会在根目录下生成一个 dist 目录,其中包含着 index.html 和一个css目录,一个js目录
  • 按官方说,这个 dist 目录必须 http server 环境下才能运行
  • 下个 xampp 在本地服务下访问

访问时出现了以下几个问题:

  1. css js 引用路径出错 (将 cofig目录下的 index.js 里的 assetsPublicPath:'./' 这样设置即可)
  2. 由于视频上是写了一个 node 后端服务,访问本地的 data.json 文件,然后用 vue-resource 访问这个 node 服务才请求到的接口
    打包之后,访问不到这个 node 服务了,自然就出错了
    如何解决:我在朋友的帮助下,知道了 easy-mock这个东西,然后 把data.json 文件 用 easy-mock 制作成了 一个 http 接口
    后来因为 github 不能访问 http 接口,又把 http 改成了 https(我最后打包的项目放在了 gitpages上了)

项目启动

添加静态资源文件,修改 build、dev-serve.js mock模拟数据,
添加 meta 标签
碰到 换台机器 报错-没有 modules ,暂时解决方法,删除整个 node_modules,然后重新 npm install

建立好 es6 书写, stylus书写方法,增加了tab导航栏,配置好了路由

学习了 1px 边框制作(不过感觉用处不大)
编写 stylus mixin 函数并在引用
(注意:引入外界stylus样式文件时:只能用 @import 在style标签里引用
且路径不可以在 webpack.base.conf.js alias别名)全局通用样式,字体文件,图标文件
可以用统一在同级目录下用一个 index.styl
文件作为出口,在其内部 用 @import './minix.styl' 引入
然后在再 webpack.base.conf.js  统一配置 alias 别名
之后再在 main.js  引入这个 index.styl 文件 即可使用这些样式文件
如:import 'common/stylus/index.styl'stylus 文件书写1.尽量使用类 css 语法即 {}2.尽量避免拷贝代码,产生多余的空格缩进问题
做完之后好好学习一下 flex 布局
display:flex  flex:1
完成 header 组件 ,goods组件 完成布局

better-scroll 的用法

better-scroll 实现列表滚动联动
1. 初始化 better-scroll_initScroll() {this.menuScroll = new BScroll(this.$refs.menuWrapper,{click:true        //默认派发点击事件});this.foodsScroll = new BScroll(this.$refs.foodsWrapper,{click:true,probeType:3   //实时侦测滚动});},2. 在 vue 钩子函数 created 内 this.$nextTick 回调里面调用 better-scroll初始化函数

菜单栏根据foodList列表滚动实时高亮

1. 通过 _calculateHeight 方法动态计算出 每个列表的标题 的 clientHeight 值,并将其推进一个 listHeight 数组
2. 当滚动 foods 列表时,会动态计算出 pos.y 的值,
3. 把这个 pos.y 的值在计算属性里判断 其在 listHeight 数组中对应的 index 值
4. 然后将菜单列表数组中的 index 值 设置为高亮

点击左侧菜单栏,右侧 foods 列表实时滚动到相应位置

1. 给 menu-item 绑定一个 setMenu(index) 方法
2. 然后根据这个 index 获取foodslist 里面对应的 li dom 元素
3. 利用 scrollToElement(el,100) api 自动将foodlist滚动到合适位置selectMenu(index) {// 因为有自动派发事件,所以需要阻止,if(!event._constructed) return; console.log(index);let foodList = this.$refs.foodList;  //通过 $refs.foodList获取当前dom元素let el = foodList[index];this.foodsScroll.scrollToElement(el,10);
}

购物车计算属性使用

1. 将 item.foods 数据 通过 props 属性传递到子组件(cartcontrol组件)2. 在 cartcontrol 组件内 执行  addCart、decreaseCart 方法改变  item.foods.count 的值如果 item.count 值不存在,使用  Vue.set(this.food,'count',1) ; 给foods增加 count 属性,如果直接增加 count 属性,不会产生响应式数据,必须用  Vue.set() 方法3. 在子组件改变 item.foods对象的值,相应的父组件内的 item的值会随之改变(js复杂数据类型地址引用)4. 在父组件 goods.vue 利用计算属性 动态的生成购物车数据,然后通过 props属性传递给 shopcart.vue 组件计算属性的计算出的值为响应式数据可以直接拿来使用,即在  v-for 中直接遍历  selectFoods // 选中的商品即购物车内的商品selectFoods() {let foods = [];this.goods.forEach((good) => {good.foods.forEach((food) => {if(food.count){foods.push(food);}})});console.log(foods);return foods;}

cartcontrol 增加和减少商品小球动画


1. 减少商品小球动画利用 vue transition 组件-过度动画 和 v-show 配合 可以给任何元素和组件添加 entering/leaving过度 条件渲染 (使用 v-if)条件展示 (使用v-show)动态组件组件根节点当插入或删除包含在 transition 组件中的元素时,Vue将做如下处理:1.自动嗅探目标元素是否应用了 css 过度或动画,如果是在恰当的时机添加/删除 css 类名2.如果过渡组件提供了 JavaScript钩子函数,这些钩子函数将在恰当的时机被调用3.如果没有找到钩子并且也没有检测到css动画,DOM操作(插入/删除)在下一帧中立即执行过度的 css 类名1. v-enter 定义进入过渡的开始状态,在元素插入式时生效,在下一帧移除2. v-enter-active 定义进入过渡的结束状态。在元素被插入时生效,在 transition/animation 完成之后移除3. v-leave 定义离开过度的开始状态。在离开过渡被触发时生效,在下一帧移除4. v-leave-active 定义离开过渡的结束状态,在离开过渡被触发时生效,在下一帧被移除html:<transition name="move"><!-- 父元素用于控制小球 透明度变化 --><div class="decrease" v-show="food.count>0"><!-- 子元素用于控制小球旋转变化 --><span class="inner icon-remove_circle_outline"></span>   </div></transition>css:<!-- 小球enter之后最终结束时的状态 -->.decrease{transition:all 0.4s linear;transform:translate3d(0,0,0);opacity:1;.inner{transition:all 0.4s linear;transform:rotate(0deg);}}<!-- 小球刚刚enter的状态和小球leave-active状态 -->&.move-enter,&.move-leave-active{transition:all 0.4s linear;transform:translate3d(24px,0,0);opacity:0;.inner{transform:rotate(180deg);}}
2. 增加小球动画实现过程:1、小球最终的落点都是一致的,在左下角购物车按钮处 (transform:translate(0,0,0))2、传递点击的 dom 对象在 cartcontrol 组件里点击 + 时, 将点击的 dom 元素,通过通过 $emit 派发给父组件 goods.vuethis.$emit('add',event.target);<div class="cart-wrapper"><!-- add自定义事件用于派发当前点击的dom元素,add为子组件方法,addFood为父组件方法 --><cartcontrol :food="food" @add="addFood"></cartcontrol></div>// 子组件$emit派发而来的事件addFood(target) {this._drop(target);  //传递 target},_drop(target) {// 体验优化,异步执行下落动画this.$nextTick(() => {//调用 shopcar 组件中的 drop 方法,向 shopcar组件 传入当前点击的 dom 对象this.$refs.shopcart.drop(target);});}3.在 shopcar 组件里,创建 小球 dom 结构<!-- 小球容器 --><div class="ball-container"><div v-for="ball in balls"><!-- 过度钩子函数 --><transition name="drop" v-on:before-enter="beforeDrop" v-on:enter="dropping" v-on:after-enter="afterDrop"><!--  外层纵向运动,内层横向运动--><div class="ball" v-show="ball.show"><div class="inner inner-hook"></div></div></transition></div></div>4. 创建 一个小球数组,内置5个对象(5个小球,均有 show 属性,初始值为false)以便在多次快速点击时,屏幕出现多个小球5个小球的初始位置 均在 左下角 购物车按钮处创建一个 dropBalls 数组用于存储 处在下落过程中的小球执行下落时 将 父组件传递过来的 dom 对象 当做一个属性 给 ball,方便 在下面的方法中计算 ball 的位置data() {return {// 创建5个小球用于动画balls:[{show:false},{show:false},{show:false},{show:false},{show:false}],dropBalls:[], // 存储下落小球}},5.执行 v-on:before-enter="beforeDrop"  过度前钩子函数设置 ball 初始位置,计算处 初始位置与目标位置的 差值 x,y ,将小球 transform :translate(x,y,0)到动画初始位置6.执行 v-on:enter="dropping"  过度中钩子函数手动触发浏览器重绘,将 ball 通过 transform :translate(0,0,0) 移动到目标位置7. 执行 v-on:after-enter="afterDrop"  过度结束钩子函数从存储下落小球的数组里 unshift 当前小球并将当前小球 display:none; show:false8.样式.ball-container{//外层 做纵向运动.ball{position:fixedleft:32pxbottom:22pxz-index:200//y 轴 贝塞尔曲线transition:all 2s cubic-bezier(0.49, -0.29, 0.75, 0.41)//内从做横向运动.inner{width:16pxheight:16pxborder-radius:50%background-color:rgb(0,160,220)//x 轴只需要线性缓动transition:all 2s linear}}

购物车列表的显示隐藏状态

    按钮控制 fold => fold 控制 => listShow , listShow => 控制状态显示 (在totalCount>0)在 data 选项里,定义一个 fold(折叠,true) 控制购物车的显示隐藏状态在 computed 计算属性里,定义一个 listshow 方法,来表示购物车列表的显示隐藏状态listShow() {if(!this.totalCount){  //假如所选商品为 0 ,return 掉结果,并将 fold 置为初始值this.fold = true;return false;}let show = !this.fold; // 否则,取 fold 的反值,靠 fold 的变化来 决定 列表显示与否return show;}在 method 方法里有个 toggleList 方法控制 fold 状态toggleList(){if(!this.totalCount){return;}this.fold = !this.fold;},

详情页组件

    将选中的商品 通过 props 传给 子组件<food @add="addFood" :food="seeFoodinfo" ref="food"></food>food 组件 通过 $emit 将food 组件添加购物车按钮传递给 父组件 以便实现小球动画addFood(target){console.log(target);//当前组件必须在父组件 引入处,bangding @add="xxx",继而执行 父组件的 xxx 方法this.$emit('add',target);},详情页 过渡动画<transition name="fade" ></transition>&.fly-enter-active, &.fly-leave-active {transition: all 0.2s linear}&.fly-enter, &.fly-leave-active {transform: translate3d(100%, 0, 0)}

ratingselect 组件(评价选择组件)

    1. 评价组件全部、推荐、吐槽 类似一个 tab 选项卡的栏目只看有内容的评价 筛选因为整个项目会有两个地方有这个东西,所以将其抽象为 ratingselect 组件组件书写:上边是一个 tab 选项卡1. 定义 三个常量 代表这三种状态const Positive = 0;     //推荐const Negative = 1;     //吐槽const All = 2;          //全部<div class="rating-type border-1px"><span @click="select(2,$event)" class="block positive" :class="{'active':selectType===2}">{{desc.all}} <span class="count">{{ratings.length}}</span></span></div>在点击事件中,将这三个状态,发送给 父组件由于这 三个选项 的 选中状态,是由父组件(food.vue)父组件通过 props 传递过来的,所以不可以在子组件中修改select(type,event){if(!event._constructed){return;}//不可以在子组件内,随意改变父组件传过来的值,通过 $emit 将子组件需要改变的值,发送给父组件,然后父组件在通过 props 传给 子组件,然后 view 就会发生相应的改变this.$emit('select',type);}父组件:使用子组件<ratingselect@select="selectRating"@onlyContent="toggleContent":ratings="food.ratings":selectType="selectType":onlyContent="onlyContent":desc="desc"></ratingselect>//在 父组件 methods 对象中 用 selectRating 方法接收子组件 emit 过来的值,赋值给 父组件 selectType 然后在通过 props传递给子组件,从而实现改变selectRating(type){this.selectType = type;this.$nextTick(()=> {this.scroll.refresh();})},//只看有内容的 评价 也是同理

food.vue 组件中的时间转换函数

    在 common 目录下创建一个公共工具函数 utils.js ,然后在需要用到的 组件中,进行 import 引入 utils.jsexport function formatDate(fmt){......}在 food 组件中使用,只需用 import 引入要使用到的 方法 即可import { format } from 'common/js/utils'在组件中即可直接使用 该方法

food.vue 里这种列表布局

    上下左右的间距,用 padding 撑开左边 用 flex 给个固定的尺寸 flex: 0 0 28px右侧 用 flex:1 ,右侧剩余空间 自动充满然后右侧内容自然流布局,上下 margin 分配右侧时间采用绝对定位布局:清晰简单明了一般情况下:列表中文字垂直居中的布局一般用 上下 padding 撑开,不要直接设置高度,用line-height居中文字高度用 line-height 撑开

商家页面(seller.vue) 商家实景页面

    商家实景左右滚动列表图片先根据图片尺寸和左右 margin 计算出 list 列表容器的 宽度,然后 用 better-scroll 进行左右滚动一般情况下,要在 vue mounted 之后就可以初始化 better-scroll 但是这时候,图片资源还没有请求到,所以无法得知 图片的 pics 的 length,继而无法得知,列表容器的宽度解决办法:vue 提供了一个 watch 对象,来用来监测数据的变化当 watch 监测到 seller 数据的变化,然后调用 _initPicScroll,初始化 better-scroll watch:{'seller'(){this.$nextTick(()=>{this._initPicScroll();})}},methods:{_initPicScroll() {if(this.seller.pics){let picWidth = 120;let margin = 6;let width = this.seller.pics.length * (picWidth + margin) - margin;this.$refs.picList.style.width = width + 'px';//better-scroll左右滚动this.picScroll = new BScroll(this.$refs.picWrapper,{scrollX: true,eventPassthrough: 'vertical'})}}}

利用localStorage 在本地收藏商家

    收藏商家是放在本地缓存 localStorage 里的#1. 在 common/js/utils 文件里创建两个公共函数函数 写入 localStorae 和 读取 localStorage # 2.  在点击收藏按钮时,调用存储 方法,首次进入页面时,调用 读取方法由于 确定收藏与否的 favorite 属性,是在 data 选项上被vue监测的,所以在data 选项上 favorite 是一个立即执行函数data:{favorite: ( () => {// 要读取的对象,key值,默认值return loadFromLocal(this.seller.id, 'favorite', false);    } )()}  

路由切换时,各组件会保持原来的状态

    # 在路由外连上加上  <keep-alive> 即可<!-- 路由外链 --><keep-alive><router-view :seller="seller"></router-view></keep-alive>

慕课网 饿了么 vue2.0 项目相关推荐

  1. vue设置html自动跳转路由器,vue2.0项目实现路由跳转的方法详解

    一.安装 1.安装路由vue-router: npm install vue-router vue项目的依赖文件node_modules存在vue-router依赖,说明安装成功 2.vue项目引入v ...

  2. Vue2.0项目安装Mint-UI - cmd篇

    Vue2.0项目如何安装引入Mint-UI? 这里讲一下如何通过cmd指令安装mint-ui到vue2.0项目. 步骤说明: 和以前一样,先cd到项目根目录 然后cmd:npm i mint-ui - ...

  3. 创建VUE项目,vue-cli2.0版本和3.0版本的区别,将vue2.0项目升级为vue3.0项目

    创建VUE项目,vue-cli2.0版本和3.0版本的区别,将vue2.0项目升级为vue3.0项目 使用vue-cli2.0版本创建vue项目 创建前的准备 开始创建 创建过程 项目正常创建 使用v ...

  4. webpack+Vue2.0项目基础工程文件配置

    随着Vue的流行,很多公司开始技术栈指向Vue,开始的时候用gulp+vue1.0做项目,一直到现在,webpack趋势也上来了,而且vue官网也是用webpack跟Vue结合去讲解实例,接下来大概说 ...

  5. 慕课网“小慕听书“ireader项目

    此项目源于慕课网 (https://www.imooc.com/) 功能: 可切换男音,女音,河南男方言三种音色以不同的语速,音量朗读文本内容 效果图: 思维导图: 基本代码: 绘制窗口大小,标题等( ...

  6. 仿着锤子科技官网进行的一个angular4.0项目~~~

    关于项目 关于angular4的一个项目,仿着锤子科技的官网写的,项目功能还没完全实现 代码我放在了GitHub上 biubiubiu传送门,在myTests仓库里,欢迎指正和交流,这个截的动图有点一 ...

  7. 在Vue2.0项目中与H5项目中获取、设置、清除cookie的一些注意点

    在vue中获取cookie 原生js方法没有直接获取cookie中值的,所以我在vue的项目中我自己写了个获取cookie值的方法(还有删除与设置cookie的方法还没去写,大家一起来补充完善) &l ...

  8. Vue2.0项目中使用sass(踩坑之路)

    今天用2.0创建项目的时候,使用scss一直不成功,一直报错------ 记录一下,防止下次踩坑 1.安装依赖包 vue的webpack项目中需要安装上node-sass.sass-loader和st ...

  9. vue2.0项目引入element-ui

    从新建vue项目到引入组件Element 一.新建项目 1.查看 node和npm是不是已经安装好命令:node -v npm -v (没有安装的先安装环境); 2.npm install -g cn ...

最新文章

  1. 寒假每日一题(提高组)【Week 1 完结】
  2. js原型和原型链_JS里的原型和原型链
  3. 《高性能JavaScript》第八章 编程实践
  4. Android编译系统环境过程初始化分析【转】
  5. 按钮配置之自定义按钮使用(一)——JEPLUS软件快速开发平台
  6. 数学告诉你家庭关系的奥秘
  7. 互联网晚报 | 11月11日 星期四 | 腾讯第三季度营收1424亿元;华为捐赠百万价值职业技能券;货拉拉成立司机权益保障委员会...
  8. java将图片(jpg/bmp/png)转16位bmp(RBG565)
  9. 首篇NLP图神经网络综述!127页文档让你全面了解这个领域
  10. java 内存管理 知乎_[知乎]Java 语言的 GC 为什么不实时释放内存?
  11. 利息高的网络贷款可以不还吗?
  12. 机器学习实战 Tricks
  13. 如何理解互斥锁、条件锁、读写锁以及自旋锁?(转载)
  14. 在Linux的Terminal中显示文本文件特定行的内容
  15. CCIE学习(18)——HSRP、VRRP和GLBP
  16. 产品沉思录 #Vol.20200315:交易平台研究
  17. 运筹优化算法工程师面试汇总
  18. 时间序列数据的正态性检验
  19. 从零开始javaweb项目——毕业设计参考指南
  20. 为什么说 Gumroad 是一家 “失败” 的创业公司?

热门文章

  1. Python操作Redis和Memcached
  2. OpenERP 中的on_change方法总结
  3. 有图有真相——关于“视频专辑:零基础学习C语言 ”
  4. 升级到NVelocity1.1版本
  5. 英美安全机构称俄罗斯正在暴力攻击全球数百家组织机构
  6. 美国 CISA 和 NIST 联合发布软件供应链攻击相关风险及缓解措施
  7. Sophos 修复 Cyberoam OS 中的 SQL 注入漏洞
  8. 常用容器管理器易受危险 exploit 攻击
  9. 京东物流首架全货机首航 久未露面的刘强东还发声推广
  10. 数据库连接池种类及性能