本文主要和大家介绍Vue shopCart 组件开发详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望能帮助到大家。
一、shopCart组件
(1) goods 父组件和 子组件 shopCart 传参
1 2 3 4 5 6 7 8 | deliveryPrice:{
type:Number,
default :0
},
minPrice:{
type:Number,
default :20
}
|
登录后复制
其中 deliveryPrice 和 minPrice 的数据都是从 data.json数据 中 seller 对象下 获得。所以在goods 组件中还要 获取到 seller对象 的数据,否则会报错:
[Vue warn]: Error in render: "TypeError: Cannot read property 'deliveryPrice' of undefined"
解决方法:根组件 App.vue 中 router-view 组件获取seller 数据,传到 goods 组件中
1-1.app.vue (根组件 也是 goods 的父组件)
1 2 3 | <keep-alive>
<router-view :sell= "sellerObj" ></router-view>
</keep-alive>
|
登录后复制
注意:sellerObj 是data 定义 的 对象里用来接收 data.json 数据,相当于 实参
1-2.goods.vue (相对于跟组件的子组件 且 shopCart 的父组件)
通过props 属性 进行组件之间的通信
1-3.shopCart.vue ( goods 的子组件)
1 | <shopCart :delivery-price= "sell.deliveryPrice" :min-price= "sell.minPrice" ></shopCart>
|
登录后复制
(2) 选中商品 的 计算功能
1-1. 传入用户选中商品的集合
说明:从父组件会 传入一个用户选中商品的 数组,数组里会存放着 n 个对象,每个对象里存放着该 商品的 价格 和 数量。
1 2 3 4 5 6 7 | props:{
selefoodsArr:{
type:Array,
default (){
return []
}
}
|
登录后复制
1-2. 利用计算属性 选中商品数量的变化,商品总价,动态改变描述等功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | computed:{
totalPrice (){
let total=0
this.selefoodsArr.forEach((rfoods) =>{
total += rfoods.price * rfoods. count
});
return total;
},
totalCount (){
let count =0
this.selefoodsArr.forEach((rfoods) =>{
count += rfoods. count
});
return count ;
},
payDesc (){
let diff = this.minPrice - this.totalPrice
if (!this.totalPrice) {
return `¥${this.minPrice}起送`
} else if (diff > 0) {
return `还差¥${diff}元`
} else {
return '去结算'
}
}
}
|
登录后复制
这样就渲染到 template 里了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <p class = "shopCart" >
<p class = "content" >
<p class = "content-left" >
<p class = "logo-wrapper" >
<!--徽章 展示选中商品的个数-->
<p class = "badge" v-show= "totalCount" >
{{totalCount}}
</p>
<!--购物车 图标 选择商品和未选择商品 时 动态改变 样式 条件:只要选择了商品即总价不为0 ,样式变-->
<p class = "logo" : class = "{'active':totalCount}" >
<i class = "icon-shopping_cart" ></i>
</p>
</p>
<!--同理: 总价 不为0 字体高亮-->
<p class = "price" : class = "{'active':totalPrice}" >
¥{{totalPrice}}
</p>
<!--配送费 data.json 提供-->
<p class = "desc" >
另需要配送费¥{{deliveryPrice}}元
</p>
</p>
<!--根据条件 动态 改变样式-->
<p class = "content-right" : class = "{'enough':totalPrice>=minPrice}" >
{{payDesc}}
</p>
</p>
</p>
|
登录后复制
相关样式
1 2 3 4 5 6 | &.active
color white
&.enough
background #00b43c
color white
|
登录后复制
总结:通过以上学习我们能发现,selectFoods()的变化起着关键作用,它的变化会引起DOM的变化,并最终体现到界面上,而我们不用关注DOM内部的具体实现,这就是vue的一大好处。如果采用jQuery完成这些功能会略显繁杂。
二、cartControl 组件
说明:这个组件是控制购物车小球的。其中涉及到小球的动画
(1) 新增属性 count
说明:
在goods 下的 foods 添加一个属性 count,用来存储用户选中的商品个数,计算商品总价 以及 关联徽章(显示用户选择商品的个数)的变化
方法:通过import Vue from 'vue';使用set接口,通过vue.set()添加属性,当它变化时就能被检测到,从而父组件能获取到count值(遍历选中的商品时使用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | methods:{
addCart(event){
if (!event._constructed) {
return ;
}
if (!this.foodsele. count ){
Vue.set(this.foodsele, ' count ', 1)
} else {
this.foodsele. count ++
}
},
decreaseCart (event){
if (!event._constructed) {
return ;
}
if (this.foodsele. count ){
this.foodsele. count --
}
}
}
|
登录后复制
(2)添加按钮 实现transtion 过渡
我们要实现的效果是:当点击添加按钮时,减少按钮出现 并伴随着 旋转、平移以及透明度变化的 一些 动画效果
1 2 3 4 5 | <transition name='move'> <!--平移动画-->
<p class = "cart-decrease" v-show= "foodsele.count" @click='decreaseCart( $event )'>
<span class = "icon-remove_circle_outline inner" ></span><!--旋转、透明度动画-->
</p>
</transition>
|
登录后复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | .cart-decrease
display inline-block
padding 6px
transition: all .4s linear
.inner
line-height 24px
font-size 24px
color rgb(0,160,220)
transition all 0.4s linear
&.move-enter-active, &.move-leave-active
transform translate3d(0,0,0)
.inner
display inline-block
transform rotate(0)
&.move-enter, &.move-leave-active
opacity: 0
transform translate3d(24px,0,0)
.inner
transform rotate(180deg)
|
登录后复制
三、抛物线小球动画
通过两个层来控制小球,外层控制一个方向的变化,内层控制另外一个方向的变化(写两层才会有抛物线的效果),采用fixed布局(是相对于视口的动画)
事件发射和接收
组件之间传值-1
组件之间传值-2
扩展
Vue1.0组件间传递
使用$on()监听事件;
使用$emit()在它上面触发事件;
使用$dispatch()派发事件,事件沿着父链冒泡;
使用$broadcast()广播事件,事件向下传导给所有的后代
(1) Vue2.0 组件之间传递数据
1-1. 当点击 添加数量时 在 cartControl 组件里的 addCount 方法里 通过 $emit 属性 派发一个事件 , 传入点击的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | addCart(event){
if (!event._constructed) {
return ;
}
if (!this.foodsele. count ){
Vue.set(this.foodsele, ' count ', 1)
} else {
this.foodsele. count ++
}
this. $emit ('add', event.target);
}
|
登录后复制
1-2. 操作 goods 组件
购物车组件如果提交了addCart事件就调用add函数
1 | <cart-control :foodsele='food' @add= "addFood" ></cart-control>
|
登录后复制
父组件使用 @add="addFood"监听由子组件vm.$emit触发的事件,通过addFood()接受从子组件传递过来的数据,通知父组件数据改变了。
1 2 3 | addFood(target) {
this._drop(target);
}
|
登录后复制
1-3. 父组件访问子组件 vue 提供了接口 ref
复制代码 代码如下:
1 2 3 4 5 6 | _drop(target) {
this. $nextTick (() => {
this. $refs .shopCart.balldrop(target);
});
}
|
登录后复制
区别 访问DOM 变量
1-3. 操作 shopCart 组件
1 2 3 4 5 6 | data (){
return {
balls:[{show:false},{show:false},{show:false},{show:false},{show:false}],
dropBalls:[]
}
}
|
登录后复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | methods:{
balldrop(ele) {
for ( var i=0;i<this.balls.length;i++){
let ball=this.balls[i]
if (!ball.show){
ball.show=true
ball.ele=ele
this.dropBalls.push(ball)
return ;
}
}
}
}
|
登录后复制
动画过程开始,利用vue 提供的钩子函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | beforeEnter (el){
let count =this.balls.length
while ( count --){
let ball = this.balls[ count ];
if (ball.show){
let pos=ball.el.getBoundingClientRect()
let x=pos.left-32
let y=-(window.innerHeight-pos.top-22)
el.style.display = '';
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)`;
}
}
},
enter(el) {
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)';
});
},
afterEnter(el) {
let ball = this.dropBalls.shift();
if (ball) {
ball.show = false;
el.style.display = 'none';
}
}
|
登录后复制
1 2 3 4 5 6 7 8 9 | <p class = "ball-container" >
<p v- for = "ball in balls" >
<transition name= "drop" @before-enter= "beforeEnter" @enter= "enter" @after-enter= "afterEnter" >
<p class = "ball" v-show= "ball.show" >
<p class = "inner inner_hook" ></p>
</p>
</transition>
</p>
</p>
|
登录后复制
1 2 3 4 5 6 7 8 | &.drop-enter,&.drop-enter-active
transition all 0.4s cubic-bezier(0.49,-0.29,0.75,0.41)
.inner
width 16px
height 16px
border-radius 50%
background rgb(0,160,220)
transition all 0.4s linear
|
登录后复制
相关推荐:
Vue header组件开发实例代码
Vue组件及数据传递详解
vuejs使用递归组件实现树形目录
以上是Vue shopCart 组件开发实例详解的详细内容。更多信息请关注PHP中文网其他相关文章!