技术点:
定义了2个wrapper,分别是menu-wrapper和foods-wrapper,对应当前页面的架构,左右两边的区域
v-if和v-show的选择使用
v-for传递索引
vue传递原生事件$event
使用stylus的mixin处理一些border和img的问题
建立menu区域和foods区域的Y坐标对应关系,实现滚动foods区域会显示相应的menu区域,点击某个menu区域就显示某个固定的foods区域
flex布局的使用,实现foods区域的布局
技巧类:对一些需要js操作的class(但是又没有实际用途的)可以建立一个类似food-list-hook钩子类
font-size为0的技术点,处理行内元素的间隙问题
vue的$nextTick使用
vue的$refs的使用
vue的computed属性使用
vue的class绑定使用
在一些地方里面,使用table的垂直居中会很简单实现垂直居中
better-scroll的使用
html代码
//第一个区域,menu区域//第二个区域 food区域 //$refs的使用//第三个区域,shopcart区域//hook钩子类的使用(food-list-hook)
{ {item.name}}
{ {food.name}}
{ {food.description}}
月售{ {food.sellCount}}份 好评率{ {food.rating}}%¥{ {food.price}} ¥{ {food.price}}//第四个区域,隐藏的食物详情区域
备注:
v-for使用已经很常见了,不过这里需要了解,vue1和2有区别,现在是用vue2,所以index变量传递会变成现在这种模式
(item,index) in goods
vue传递原生事件使用$event
-
:class="{'current':currentIndex === index}"
是vue的绑定class的使用方法,通过绑定一个class变量来直接操作,并且这里的逻辑会跟js代码里面对应通过currentIndex和index做对比,来确认是否添加current类,他们之间的对比关系也就是menu区域和foods区域的显示区域的对比关系
通过添加current类来实现当前页面的区域的样式变化
currentIndex是一个计算属性,可以随时变化并且直接反应到dom上(看js里面逻辑)
-
官网已经说过
1. v-if 是“真正的”条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。2. v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。一般来说, v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件不太可能改变,则使用 v-if 较好。
-
$refs
的使用是vue操作dom的一种方式:ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。
如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素; 如果用在子组件上,引用就指向组件实例:
hook钩子类的使用,需要结合js里面的语法来看,这个类只是用来操作,不会产生dom的渲染,方便js控制清晰.
js代码
备注:
<food @add="addFood" :food="selectedFood" ref="food">
是通过selectFood方法写入到vue实例里面,然后传给子组件food<shopcart ref="shopcart" :selectFoods="selectFoods"
这里selectFoods被自动添加了count属性,是为了让购物车更加简单的计算已选择的food-
这里最关键的是menu和food两个区域的对应处理:
在vue实例生命周期的开始created分别加载
_initScroll
和_calculateHeight
通过
_calculateHeight
计算foods内部每一个块的高度,组成一个数组listHeight在_initScroll里面,设置了bscroll插件的一个监听事件scroll,将food区域当前的滚动到的位置的y坐标设置到一个vue实例属性scrollY
this.scrollY = Math.abs(Math.round(pos.y));
通过计算属性currentIndex,获取到food滚动区域对应的menu区域的子块的索引,然后通过设置一个class来做样式切换变化
:class="{'current':currentIndex === index}
,实现联动另外当点击menu 区域的时候,会触发selectMenu事件,也会根据点击到的menu子块的索引然后去触发food区域滚动到对应的高度区块区间
this.foodsScroll.scrollToElement(el, 300);
这样完成整个对应.
抛物线小球动画横跨多个vue组件(也可以说是横跨了多个DOM),整个动画会在里面说
better-scroll需要安装,npm安装,具体参看
-
关于在selectMenu中点击,在pc界面会出现两次事件,在移动端就只出现一次事件的问题:
-
原因:
bsScrooler会监听事件(例如touchmove,click之类),并且阻止默认事件(prevent stop),并且他只会监听移动端的,pc端的没有监听
-
在pc页面上 bsScroller也派发了一次click事件,原生也派发了一次click事件
//bsScroll的事件,有_constructed: trueMouseEvent {isTrusted: false, _constructed: true, screenX: 0, screenY: 0, clientX: 0…}//pc的事件MouseEvent {isTrusted: true, screenX: -1867, screenY: 520, clientX: 53, clientY: 400…}
-
解决:
针对bsScroole的事件,有_constructed: true,所以做处理,return掉非bsScroll的事件
-