Home >Web Front-end >JS Tutorial >How to use Vue's shopCart component

How to use Vue's shopCart component

php中世界最好的语言
php中世界最好的语言Original
2018-03-23 10:46:272028browse

This time I will bring you how to use Vue's shopCart component. What are the things to note when using Vue's shopCart component? The following is a practical case, let's take a look.

1. shopCart component

(1) goods parent component and sub-component shopCart pass parameters

deliveryPrice:{ // 单价 从json seller 对象数据中获取
 type:Number,
 default:0
},
minPrice:{ // 最低起送价 从json seller 对象数据中获取
 type:Number,
 default:20
}
The data of deliveryPrice and minPrice are all from data Obtained from the seller object in .json data. Therefore, the data of the seller object must be obtained in the goods component, otherwise an error will be reported:

[Vue warn]: Error in render: "TypeError: Cannot read property 'deliveryPrice' of undefined"

Solution: The router-view component in the root component App.vue obtains the seller data and passes it to the goods component

1-1.app.vue (the root component is also the parent component of goods )

<keep-alive>
 <router-view :sell="sellerObj"></router-view>
</keep-alive>
Note: sellerObj is used to receive data.json data in the object defined by data, which is equivalent to the actual parameter

1-2.goods.vue (relative to the subcomponent of the component) And the parent component of shopCart)

communicates between components through props attributes

props: {
  sell: Object // 相当于 形参
 },
1-3.shopCart.vue (subcomponent of goods)

<shopCart :delivery-price="sell.deliveryPrice" :min-price="sell.minPrice"></shopCart>
(2 ) Calculation function of selected products

1-1. Pass in the collection of products selected by the user

Instructions: An array of products selected by the user will be passed in from the parent component, and n will be stored in the array objects, each object stores the price and quantity of the product.

props:{       // 通过父组件传过来的 ( 相当于形参 )
 selefoodsArr:{   // 用户选中的商品存放在一个数组里  接收的是 data.json数据的 goods(数组)
 type:Array, // 当父组件传过来的 类型是对象或者 是数组时, default 就是一个函数
 default (){
 return []  // 返回数组 存放着选中 商品 对应的 goods下的 foods 数组(由 父组件 的 实参 决定的返回值)
 }
}
1-2. Use calculated attributes to select changes in product quantity, total product price, dynamically change descriptions and other functions

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 '去结算'
    }
 }  
}
This will be rendered into the 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>
Related styles

&.active
  color white
  
&.enough
  background #00b43c
  color white
Summary: Through the above learning, we can find that changes in selectFoods() play a key role. Its changes will cause changes in the DOM, and will eventually be reflected in the interface, and we do not need to pay attention to the internals of the DOM. The specific implementation, this is a major benefit of vue. It would be a little complicated to use jQuery to complete these functions.

2. cartControl component

Description: This component controls the shopping cart ball. Which involves the animation of the ball

(1) Add the new attribute count

Description:

Add an attribute count to foods under goods to store the items selected by the user Number of products, calculation of the total price of the product, and changes in associated badges (displaying the number of products selected by the user)

Method: import Vue from 'vue'; use the set interface and add attributes through vue.set() , it can be detected when it changes, so that the parent component can obtain the count value (used when traversing the selected products)

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) Add a button to implement transition

We want The effect achieved is: when the add button is clicked, the button appearance is reduced and some animation effects are accompanied by rotation, translation and transparency changes

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

3. Parabolic ball animation

Control the ball through two layers. The outer layer controls the change in one direction, and the inner layer controls the change in the other direction (write two layers to have a parabola effect), using a fixed layout (an animation relative to the viewport) )

Event emission and reception

Value passing between components-1

Value passing between components-2

Extension

Transfer between Vue1.0 components

  1. Use $on() to listen for events;

  2. Use $emit() to Events are triggered on it;

  3. Use $dispatch() to dispatch events, and events bubble along the parent chain;

  4. Use $broadcast() Broadcast events, and the events are propagated downward to all descendants

(1) Pass data between Vue2.0 components

1-1. When you click to add the quantity, The addCount method in the cartControl component dispatches an event through the $emit attribute, passing in the clicked object

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. Operating the goods component

The shopping cart component will be called if the addCart event is submitted add function

 <cart-control :foodsele=&#39;food&#39; @add="addFood"></cart-control>
The parent component uses @add="addFood" to listen to events triggered by the child component vm.$emit, accepts the data passed from the child component through addFood(), and notifies the parent component of data changes.

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

1-3. 父组件访问子组件 vue 提供了接口 ref

复制代码 代码如下:


_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 = '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';
  }
 }
<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

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

微信小程序开发图片压缩功能

js动态操作表格

JS中Object对象的原型的使用方法

The above is the detailed content of How to use Vue's shopCart component. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn