Vue shopCart 組件開發詳解,vueshopcart

來源:互聯網
上載者:User

Vue shopCart 組件開發詳解,vueshopcart

一、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 '去結算'    } }  }

這樣就渲染到 template 裡了

<div class="shopCart"> <div class="content">  <div class="content-left"> <div class="logo-wrapper">  <!--徽章 展示選中商品的個數--> <div class="badge" v-show="totalCount"> {{totalCount}} </div> <!--購物車 表徵圖 選擇商品和未選擇商品 時 動態改變 樣式 條件:只要選擇了商品即總價不為0 ,樣式變-->   <div class="logo" :class="{'active':totalCount}">   <i class="icon-shopping_cart"></i>  </div> </div> <!--同理: 總價 不為0 字型高亮--> <div class="price" :class="{'active':totalPrice}">  ¥{{totalPrice}} </div> <!--配送費 data.json 提供--> <div class="desc">  另需要配送費¥{{deliveryPrice}}元 </div>  </div>  <!--根據條件  動態 改變樣式-->  <div class="content-right" :class="{'enough':totalPrice>=minPrice}">   {{payDesc}}   </div> </div></div>

相關樣式

&.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, 'count', 1) }else{ this.foodsele.count++ }   }, decreaseCart (event){ // 點擊減少 if (!event._constructed) { // 去掉內建click事件的點擊    return;    } if(this.foodsele.count){ this.foodsele.count --  }   }}

(2)添加按鈕 實現transtion 過渡

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

<transition name='move'> <!--平移動畫-->   <div class="cart-decrease" v-show="foodsele.count" @click='decreaseCart($event)'>  <span class="icon-remove_circle_outline inner"></span><!--旋轉、透明度動畫-->   </div></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, 'count', 1) }else{ this.foodsele.count++ }// 當點擊 添加數量時 通過 $emit 屬性 提交一個名為 add 給父組件// 子組件通過 $emit觸發 add事件 ,將參數傳遞給父組件 this.$emit('add', event.target);}

1-2. 操作 goods 組件

購物車組件如果提交了addCart事件就調用add函數

 <cart-control :foodsele='food' @add="addFood"></cart-control>

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

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

1-3. 父組件訪問子組件 vue 提供了介面 ref

複製代碼 代碼如下:
<shopCart ref="shopCart" :delivery-price="sell.deliveryPrice" :min-price="sell.minPrice" :selefoods-arr='selectfoods'  ></shopCart>

_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 = '';  //設定初始位置前,手動置空,覆蓋之前的display:none,使其顯示       el.style.webkitTransform = `translate3d(0,${y}px,0)`; //外層元素做縱向的動畫,y是變數       el.style.transform = `translate3d(0,${y}px,0)`;       let inner = el.getElementsByClassName('inner_hook')[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 = '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(); //取到做完動畫的球,再置為false,即重設,它還可以接著被利用  if (ball) {   ball.show = false;   el.style.display = 'none';  } }
<div class="ball-container">  <div v-for="ball in balls">   <transition name="drop" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">    <div class="ball" v-show="ball.show">     <div class="inner inner_hook"></div>    </div>   </transition>  </div></div>
&.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

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援幫客之家。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.