Vue shopCartコンポーネントの開発事例を詳しく解説

小云云
リリース: 2018-01-31 10:10:32
オリジナル
1554 人が閲覧しました

この記事では主にVueのshopCartコンポーネント開発の詳細な説明を紹介していますが、編集者が非常に優れていると感じたので、参考として共有します。編集者をフォローして見てみましょう。皆さんのお役に立てれば幸いです。

1. shopCartコンポーネント

(1)商品の親コンポーネントとサブコンポーネントのshopCartの渡しパラメータ


deliveryPrice:{ // 单价 从json seller 对象数据中获取
 type:Number,
 default:0
},
minPrice:{ // 最低起送价 从json seller 对象数据中获取
 type:Number,
 default:20
}
ログイン後にコピー

deliveryPriceとminPriceのデータはdata.jsonデータ内のsellerオブジェクトから取得します。したがって、販売者オブジェクトのデータは商品コンポーネントで取得する必要があります。取得しないと、エラーが報告されます:

[Vue warn]: レンダリング時のエラー: "TypeError: Cannot read property 'deliveryPrice' of unknown"

解決策: ルートコンポーネント App.vue のルータービューコンポーネントは販売者のデータを取得し、商品コンポーネント

1-1.app.vue (ルートコンポーネントは商品の親コンポーネントでもあります) に渡します


<keep-alive>
 <router-view :sell="sellerObj"></router-view>
</keep-alive>
ログイン後にコピー

注: sellObj は、data.json データを受信するために使用される data によって定義されたオブジェクトであり、実際のパラメーター

1-2.goods.vue (コンポーネントのサブコンポーネントおよび shopCart の親コンポーネントに関連) に相当します

props属性によるコンポーネント間の通信


props: {
  sell: Object // 相当于 形参
 },
ログイン後にコピー

1-3.shopCart.vue(商品のサブコンポーネント)


<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;
    }
 }  
}
ログイン後にコピー

このようにして、テンプレートにレンダリングされます


<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 の大きな利点の 1 つです。 jQuery を使用してこれらの機能を実行するのは少し複雑になります。

2. CartControl コンポーネント

説明: このコンポーネントはショッピング カート ボールを制御します。ボールのアニメーションが含まれます

(1) 属性カウントを追加します

手順:

商品の下の食品に属性カウントを追加します。これは、ユーザーが選択した商品の数を保存するために使用され、商品の合計価格を計算します。製品と関連付けられたバッジ ( ユーザーが選択した製品の数の変化を表示します

方法: 'vue' から Vue をインポートします。set インターフェイスを使用し、vue.set() を通じて属性を追加します。変更されると、検出され、親コンポーネントがカウント値を取得できるようにします (選択した製品をトラバースするときに使用されます)


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) トランジションを実装するボタンを追加します

達成したい効果は次のとおりです: 追加ボタンクリックすると、縮小ボタンが表示され、回転、移動、および透明度の変化のアニメーション効果が伴います


<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>
ログイン後にコピー


3. 放物線ボールアニメーション

は、2つのレイヤーを通してボールを制御します。変更 (放物線効果を持たせるために 2 つのレイヤーを作成)、固定レイアウト (ビューポートを基準としたアニメーション) を使用します

イベントの発行と受信

コンポーネント間で渡される値。 -1

コンポーネント間で渡される値 -2

Extension

Vue1.0 コンポーネントの転送

$on() を使用してイベントをリッスンします
  1. $emit() を使用してイベントをトリガーします;
  2. $dispatch() を使用してイベントをディスパッチし、イベントは親チェーンに沿ってバブルします。
  3. は $broadcast() を使用してイベントをブロードキャストし、イベントはすべての子孫に伝播されます
  4. ( 1) Vue2.0 コンポーネント間でデータを転送します
1-1。数量を追加するためにクリックすると、cartControl コンポーネントの addCount メソッドの $emit 属性を通じてイベントを送出し、クリックされたオブジェクトを渡します

 .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)
ログイン後にコピー

1-2.商品コンポーネントを操作する

ショッピングカートコンポーネントがaddCartイベントを送信する場合 add関数を呼び出す

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);
}
ログイン後にコピー

親コンポーネントは、子コンポーネントによってトリガーされるイベントをリッスンするために @add="addFood" を使用しますvm.$emit は、addFood() を通じて子コンポーネントから渡されたデータを受け取り、データの変更を親コンポーネントに通知します。

 <cart-control :foodsele=&#39;food&#39; @add="addFood"></cart-control>
ログイン後にコピー

1-3. 親コンポーネントは子コンポーネントの vue にアクセスします ref を提供します

コードをコピーします

コードは次のとおりです:

addFood(target) {
  this._drop(target);
}
ログイン後にコピー



_drop(target) {
  // 体验优化,异步执行下落动画
  this.$nextTick(() => {
   this.$refs.shopCart.balldrop(target);// 将target传入shopCart子组件中的balldrop方法,所以drop方法能获得用户点击按钮的元素,即能获取点击按钮的位置
  });
}
ログイン後にコピー

vue


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;
    }
   }        
 }
}
ログイン後にコピー

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;;
  }
 }
ログイン後にコピー

関連おすすめ:

Vueヘッダーコンポーネントの開発サンプルコード

Vueコンポーネントとデータ転送の詳細な説明

vuejsは再帰コンポーネントを使用してツリーディレクトリを実装します

以上がVue shopCartコンポーネントの開発事例を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!