首頁  >  文章  >  web前端  >  Vue shopCart 元件開發實例詳解

Vue shopCart 元件開發實例詳解

小云云
小云云原創
2018-01-31 10:10:321515瀏覽

本文主要跟大家介紹Vue shopCart 組件開發詳解,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧,希望能幫助大家。

一、shopCart元件

(1) goods 父元件與子元件shopCart 傳參


deliveryPrice:{ // 单价 从json seller 对象数据中获取
 type:Number,
 default:0
},
minPrice:{ // 最低起送价 从json seller 对象数据中获取
 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 的父組件)


<keep-alive>
 <router-view :sell="sellerObj"></router-view>
</keep-alive>

注意:sellerObj 是data 定義的物件裡用來接收data.json 數據,相當於實參

1-2.goods. vue (相對於跟元件的子元件且shopCart 的父元件)

透過props 屬性進行元件之間的通訊


props: {
  sell: Object // 相当于 形参
 },

1-3. shopCart.vue ( goods 的子元件)


<shopCart :delivery-price="sell.deliveryPrice" :min-price="sell.minPrice"></shopCart>

(2) 選取商品的運算功能

#1-1. 傳入使用者選取商品的集合

說明:從父元件會傳入一個使用者選取商品的數組,數組裡會存放著n 個對象,每個對象裡存放著該商品的價格和數量。


props:{       // 通过父组件传过来的 ( 相当于形参 )
 selefoodsArr:{   // 用户选中的商品存放在一个数组里  接收的是 data.json数据的 goods(数组)
 type:Array, // 当父组件传过来的 类型是对象或者 是数组时, default 就是一个函数
 default (){
 return []  // 返回数组 存放着选中 商品 对应的 goods下的 foods 数组(由 父组件 的 实参 决定的返回值)
 }
}

1-2. 利用計算屬性選取商品數量的變化,商品總價,動態改變描述等功能


computed:{
 totalPrice (){     //计算总价,超过起送额度后提示可付款
 let total=0   // 定义一个返回值
 this.selefoodsArr.forEach((rfoods) =>{ // 遍历 这个 goods 数组 取到 价格 和 数量 (当然在这里数据库没有count 这个属性,稍后 我们会利用 vue.set() 新建一个count 属性)
  total += rfoods.price * rfoods.count // 形参 rfoods 实参 是 foods
 });
 return total;
 },
 totalCount (){   // //计算选中的food数量,在购物车图标处显示,采用绝对定位,top:0;right:0;显示在购物车图标右上角  
 let count=0
 this.selefoodsArr.forEach((rfoods) =>{ // 形参 rfoods 实参 是 foods
  count += rfoods.count
 });
 return count;
 },
 payDesc (){    //控制底部右边内容随food的变化而变化,payDesc()控制显示内容,enough 添加类调整显示样式
 let diff = this.minPrice - this.totalPrice
    if (!this.totalPrice) {
     return `¥${this.minPrice}起送`
    } else if (diff > 0) {
     return `还差¥${diff}元`
    } else {
     return &#39;去结算&#39;
    }
 }  
}

這樣就渲染到template 裡了


<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="{&#39;active&#39;:totalCount}">
   <i class="icon-shopping_cart"></i>
  </p>
 </p>
 <!--同理: 总价 不为0 字体高亮-->
 <p class="price" :class="{&#39;active&#39;:totalPrice}">
  ¥{{totalPrice}}
 </p>
 <!--配送费 data.json 提供-->
 <p class="desc">
  另需要配送费¥{{deliveryPrice}}元
 </p>
  </p>
  <!--根据条件  动态 改变样式-->
  <p class="content-right" :class="{&#39;enough&#39;:totalPrice>=minPrice}">  
 {{payDesc}}  
 </p>
 </p>
</p>

相關樣式


&.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值(遍歷選取的商品時使用)


methods:{
 addCart(event){ // 点击count 加,
  //console.log(event.target);
 if (!event._constructed) { // 去掉自带click事件的点击
    return;
   }
 if(!this.foodsele.count){
 Vue.set(this.foodsele, &#39;count&#39;, 1)
 }else{
 this.foodsele.count++
 }  
 },
 decreaseCart (event){ // 点击减少
 if (!event._constructed) { // 去掉自带click事件的点击
    return;
    }
 if(this.foodsele.count){
 this.foodsele.count --
  } 
  }
}

(2)新增按鈕實作transtion過渡

我們要實現的效果是:當點擊新增按鈕時,減少按鈕出現並伴隨著旋轉、平移以及透明度變化的一些動畫效果


<transition name=&#39;move&#39;> <!--平移动画-->  
 <p class="cart-decrease" v-show="foodsele.count" @click=&#39;decreaseCart($event)&#39;>
  <span class="icon-remove_circle_outline inner"></span><!--旋转、透明度动画--> 
  </p>
</transition>


 .cart-decrease
  display inline-block
  padding 6px
  transition: all .4s linear  /*过渡效果的 CSS 属性的名称、过渡效果需要多少时间、速度效果的速度曲线*/  
  .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) /* 这样可以开启硬件加速,动画更流畅,3D旋转,X轴位移24px */
   .inner   
    display inline-block  /* 设置成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元件間傳遞

  1. #使用$on()監聽事件;

  2. 使用$emit()在它上面觸發事件;

  3. 使用$dispatch()派發事件,事件沿著父鏈冒泡;

  4. 使用$broadcast()廣播事件,事件向下傳導給所有的後代

(1) Vue2.0 元件之間傳遞資料

1-1. 當點擊新增數量時在cartControl 元件裡的addCount 方法裡透過$emit 屬性派發一個事件, 傳入點擊的物件


addCart(event){ // 点击count 加,
//  console.log(event.target);
 if (!event._constructed) { // 去掉自带click事件的点击
    return;
   }
 if(!this.foodsele.count){
 Vue.set(this.foodsele, &#39;count&#39;, 1)
 }else{
 this.foodsele.count++
 }
// 当点击 添加数量时 通过 $emit 属性 提交一个名为 add 给父组件
// 子组件通过 $emit触发 add事件 ,将参数传递给父组件
 this.$emit(&#39;add&#39;, event.target);
}

1-2. 操作goods 元件

#購物車元件如果提交了addCart事件就呼叫add函數


 <cart-control :foodsele=&#39;food&#39; @add="addFood"></cart-control>

父元件使用@add="addFood"監聽由子元件vm.$emit觸發的事件,透過addFood()接受從子元件傳遞過來的數據,通知父元件資料改變了。


addFood(target) {
  this._drop(target);
}

1-3. 父元件存取子元件vue 提供了介面ref

複製程式碼 程式碼如下:


c9cb38f6d0313394adb8ae386a769cf916806ed5fafa880e2b2d16b7e7eeba31


_drop(target) {
  // 体验优化,异步执行下落动画
  this.$nextTick(() => {
   this.$refs.shopCart.balldrop(target);// 将target传入shopCart子组件中的balldrop方法,所以drop方法能获得用户点击按钮的元素,即能获取点击按钮的位置
  });
}
區別存取DOM 變數

1-3.操作shopCart 元件


#

data (){ // 定义一个数组 来 控制小球的状态  定义多个对象,表示页面中做多同时运动的小球
 return{ // 定义 5 个 小球  
 balls:[{show:false},{show:false},{show:false},{show:false},{show:false}],
 dropBalls:[] // 接收下落小球
  }
}

methods:{
 balldrop(ele) {
// console.log(el) 取到点击 对象
   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 提供的鉤子函數


beforeEnter (el){ //找到所以设为true的小球
 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  // 点击的按钮与小球(fixed)之间x方向的差值
  let y=-(window.innerHeight-pos.top-22)
  el.style.display = &#39;&#39;;  //设置初始位置前,手动置空,覆盖之前的display:none,使其显示
       el.style.webkitTransform = `translate3d(0,${y}px,0)`; //外层元素做纵向的动画,y是变量
       el.style.transform = `translate3d(0,${y}px,0)`;
       let inner = el.getElementsByClassName(&#39;inner_hook&#39;)[0];//内层元素做横向动画,inner-hook(用于js选择的样式名加上-hook,表明只是用                                   //于js选择的,没有真实的样式含义)
       inner.style.webkitTransform = `translate3d(${x}px,0,0)`;
       inner.style.transform = `translate3d(${x}px,0,0)`;
 }
 }
 },
   enter(el) { 
   /* eslint-disable no-unused-vars */
   let rf = el.offsetHeight;
   this.$nextTick(() => {//异步执行
   el.style.webkitTransform = &#39;translate3d(0,0,0)&#39;;  //重置回来
   el.style.transform = &#39;translate3d(0,0,0)&#39;;
   let inner = el.getElementsByClassName(&#39;inner_hook&#39;)[0];
   inner.style.webkitTransform = &#39;translate3d(0,0,0)&#39;;
   inner.style.transform = &#39;translate3d(0,0,0)&#39;;
  });
 },
 afterEnter(el) {
  let ball = this.dropBalls.shift(); //取到做完动画的球,再置为false,即重置,它还可以接着被利用
  if (ball) {
   ball.show = false;
   el.style.display = &#39;none&#39;;
  }
 }

#

<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>

&.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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn