备注:此项目模拟 饿了吗。我用的是最新的Vue, 视频上的一些写法已被烧毁了。
规划代码
<div class="ball-container">
<transition name="drop"
v-for="ball in balls"
@before-enter="beforeDrop"
@enter="dropping"
@after-enter="afterDrop">
<div v-show="ball.show" class="ball" v-bind:css="false">
<div class="inner inner-hook" ></div>
</div>
</transition>
</div>
css代码(运用stylus写法)
.ball-container
.ball
position fixed
left 32px
bottom 22px
z-index 200
transition all 0.4s cubic-bezier(0.49,-0.29,0.75,0.41)
.inner
width 16px
height 16px
border-radius 50%
background-color rgb(0,160,220)
transition all 0.4s linear
js代码
data() {
return {
balls : [
{
show: false
},
{
show: false
},
{
show: false
},
{
show: false
},
{
show: false
}
],
dropBalls: []
};
},
methods: {
drop(el) {
for(let i = 0; i < this.balls.length; i++) {
let ball = this.balls[i];
if(!ball.show) {
ball.show = true;
ball.el = el;
this.dropBalls.push(ball);
return ;
}
}
}
beforeDrop(el) {
let count = this.balls.length;
while (count--) {
let ball = this.balls[count];
if(ball.show) {
let rect = ball.el.getBoundingClientRect();
let x = rect.left - 32;
let y = -(window.innerHeight - rect.top - 22);
el.style.webkitTransform = `translate3d(0,${y}px,0)`;
el.style.transform = `translate3d(0,${y}px,0)`;
let inner = el.getElementsByClassName('inner-hook')[0];
inner.style.webkitTransform = `translate3d(${x}px,0,0)`;
inner.style.transform = `translate3d(${x}px,0,0)`;
}
}
},
dropping(el) {
/* eslint-disable no-unused-vars */
let rf = el.offsetHeight;
this.$nextTick(() => {
el.style.webkitTransform = 'translate3d(0,0,0)';
el.style.transform = 'translate3d(0,0,0)';
let inner = el.getElementsByClassName('inner-hook')[0];
inner.style.webkitTransform = 'translate3d(0,0,0)';
inner.style.transform = 'translate3d(0,0,0)';
});
},
afterDrop(el){
let ball = this.dropBalls.shift();
if(ball) {
ball.show = false;
el.style.display = 'none';
}
}
}
getBoundingClientRect()。要领请浏览这篇文章
https://www.cnblogs.com/limei…
申明:
goods 是一个组件,内里包括menu(div) , foods(div), shopcart(购物车组件)。个中foods 包括cartcontrol(即小球组件)
组件之间的通讯:
申明:菜单和商品
第1个题目:小球,须要猎取所点击的商品的数量。
应用Vue的props,将foods值通报给cartcontrol。然则如许有个题目。即子组件更新,没法同步回父组件。且,在子组件中,对food注册了一个count属性,此属性也没法同步回父组件(goods)。
解决要领:
导入全局的Vue。
应用Vue.set(target,key,value); 对 target注册count;
第2个题目:小球点击,将所点击过的商品数量通报给 shopcart。
在goods的 computed:{} 定义一个要领,将该要领以props的体式格局,通报给shopcart。
由于,shopcart,对通报过去的数据仅数据运算(不会转变)。因而不必同步会父组件。
第3个题目:购物车小球做抛物线活动。
关于购物车小球做抛物线活动。起首,落点都在购物车,小球则是随机的。要做抛物线活动,就要猎取,所点击的 + 号的x,y位置。其次,抛物线活动,只要在enter–> enter-to这段时期有,在leave–> leave-to 时期是没有的,因而,须要用Vue供应的钩子函数。
猎取 + 号x,y 位置:
小球(cartcontrol)是子组件。须要把数据通报给 goods(父组件)。能够运用Vuex,或许直接运用事宜总线。关于饿了吗demo。直接运用事宜总线。
建立一个 空的Vue。在 cartcontrol 中 ,经由过程 Bus.$emit(key, … arg); 注册一个监听,然后再父组件 经由过程Bus.$on(key, function(… arg));监听此要领。将所操纵的 dom 对象通报过去即可
Vue供应的钩子
这里要申明一点,Vue在他的官网,关于只要过分的js,done是必需的,当我加上done的时刻,after-enter要领没法被执行。
另有1个题目,Vue官网引荐,只要过分结果,在做过分动画的元素上加上v-bind:class=’false’。之前没加,涌现了,小球只能在第1次点击的处所做过分结果。