Maison  >  Article  >  interface Web  >  Explication détaillée des exemples de développement de composants Vue shopCart

Explication détaillée des exemples de développement de composants Vue shopCart

小云云
小云云original
2018-01-31 10:10:321511parcourir

Cet article vous présente principalement l'explication détaillée du développement du composant Vue shopCart. L'éditeur pense que c'est assez bon, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur pour y jeter un œil, j'espère que cela pourra aider tout le monde.

1. Composant shopCart

(1) composant parent de marchandises et sous-composant shopCart passant les paramètres


deliveryPrice:{ // 单价 从json seller 对象数据中获取
 type:Number,
 default:0
},
minPrice:{ // 最低起送价 从json seller 对象数据中获取
 type:Number,
 default:20
}

Les données de deliveryPrice et minPrice sont obtenues à partir de l'objet vendeur dans les données data.json. Par conséquent, les données de l'objet vendeur doivent être obtenues dans le composant marchandises, sinon une erreur sera signalée :

[Vue warn] : Erreur de rendu : "TypeError : Impossible de lire la propriété 'deliveryPrice' of undefined"

Solution : Le composant router-view dans le composant racine App.vue obtient les données du vendeur et les transmet au composant marchandises

1-1.app.vue (le composant racine est également le composant parent des marchandises) )


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

Remarque : sellerObj est l'objet défini par data et est utilisé pour recevoir des données data.json, ce qui équivaut aux paramètres réels

1-2.goods.vue (par rapport au composant enfant du composant et au composant parent de shopCart)

Communication entre les composants via les attributs props


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

1-3.shopCart.vue (sous-composant de marchandises)


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

(2) Sélectionnez la fonction de calcul du produit

1-1. Pass Entrez la collection de produits sélectionnés par l'utilisateur

Description : Un tableau de produits sélectionnés par l'utilisateur sera transmis à partir du composant parent. . Le tableau stockera n objets, et chaque objet stockera le prix et la quantité du produit.


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

1-2. Utilisez les attributs calculés pour sélectionner les modifications de la quantité de produit, du prix total du produit, modifier dynamiquement les descriptions et d'autres fonctions


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;
    }
 }  
}
De cette façon, il est rendu dans le modèle


<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>
Styles associés


&.active
  color white
  
&.enough
  background #00b43c
  color white
Résumé : grâce à l'apprentissage ci-dessus, nous pouvons constater que les changements dans selectFoods() jouent un rôle clé. Ses changements entraîneront des changements dans le DOM et seront éventuellement reflétés dans l'interface, et nous le faisons. pas besoin de prêter attention à l'implémentation spécifique à l'intérieur du DOM. C'est l'un des grands avantages de vue. Ce serait un peu compliqué d'utiliser jQuery pour compléter ces fonctions.

2. Composant cartControl

Description : Ce composant contrôle la boule du panier. Cela implique l'animation de la balle

(1) Nouveau nombre d'attributs

Description :

Ajouter un nombre d'attributs aux aliments sous les marchandises pour stocker les articles sélectionnés par l'utilisateur Numéro des produits, calcul du prix total du produit et évolution des badges associés (affichage du nombre de produits sélectionnés par l'utilisateur)

Méthode : importer Vue depuis 'vue' utiliser l'interface définie et ajouter des attributs via vue.set() , il peut être détecté lorsqu'il change, afin que le composant parent puisse obtenir la valeur de comptage (utilisée lors du parcours des produits sélectionnés)


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) Bouton Ajouter Réaliser la transition

L'effet que nous voulons obtenir est le suivant : lorsque vous cliquez sur le bouton Ajouter, le bouton apparaît et certains effets d'animation sont accompagnés de changements de rotation, de translation et de transparence


<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. Animation de balle parabolique

Contrôlez la balle à travers deux couches, et le le calque externe contrôle une direction Le calque interne contrôle le changement dans l'autre direction (écrire deux calques pour avoir un effet parabole), en utilisant une disposition fixe (animation par rapport à la fenêtre)

Émission et réception d'événements

Transfert de valeur entre composants-1

Transfert de valeur entre composants-2

Extension

Transfert Vue1.0 entre composants

  1. Utilisez $on() pour écouter les événements

  2. Utilisez $emit() pour déclencher des événements dessus ; 🎜 >Utilisez $dispatch() pour distribuer les événements, et les événements remontent le long de la chaîne parent

  3. Utilisez $broadcast() pour diffuser les événements, et les événements sont propagés vers le bas vers tous les descendants

  4. (1) Transférer des données entre les composants Vue2.0
  5. 1-1 Lorsque vous cliquez pour ajouter la quantité, envoyez un événement via l'attribut $emit dans addCount. méthode dans le composant cartControl, passez Entrez l'objet cliqué

1-2 Faites fonctionner le composant marchandises

Si le composant panier soumet le. événement addCart, il appelle la fonction 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);
}

Le composant parent utilise @add="addFood" pour écouter les événements déclenchés par le composant enfant vm.$emit, accepte les données transmises par le composant enfant via addFood() et informe que les données du composant parent ont changé.


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

1-3. Le composant parent accède au composant enfant vue fournit la référence d'interface


Copier le code

Le code est la suivante :
addFood(target) {
  this._drop(target);
}



Accès différentiel aux variables DOM


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


Le processus d'animation démarre, en utilisant la fonction hook fournie par 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;;
  }
 }


Recommandations associées :
<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>

Exemple de code de développement de composants d'en-tête Vue

Explication détaillée des composants Vue et du transfert de données

vuejs utilise des composants récursifs pour implémenter répertoires arborescents

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn