Maison  >  Article  >  interface Web  >  Comment implémenter le menu latéral QQ à l'aide du framework Vue Mobile UI (tutoriel détaillé)

Comment implémenter le menu latéral QQ à l'aide du framework Vue Mobile UI (tutoriel détaillé)

亚连
亚连original
2018-05-31 16:05:422355parcourir

Cet article présente principalement le framework vue mobile UI pour implémenter le composant de menu latéral de type QQ. Il est très bon et a une valeur de référence. Les amis dans le besoin peuvent s'y référer

Des entretiens récents ont révélé que de nombreux fronts. Je n'ai jamais eu d'expérience dans l'écriture de plug-ins. J'ai essentiellement utilisé Baidu sur Internet. J'ai donc l'intention d'écrire une série d'articles pour apprendre à des frères qui n'ont jamais écrit de composants comment écrire des plug-ins étape par étape. Cette série d'articles est tous basée sur VUE et le contenu principal est le même. Après l'avoir compris, vous pouvez rapidement le réécrire en composants tels que React, Angular ou Small Programs. Cet article est le premier et concerne un composant de menu latéral similaire à QQ.

Affichage des effets

Laissons tout le monde jeter un œil à l'affichage des effets pour savoir ce que nous voulons faire. L'image est un peu floue. . Commençons par :

Commencer à créer

Structure DOM

Il devrait y avoir deux conteneurs dans la structure globale : 1. Conteneur de menu 2. Conteneur de page principale donc la structure actuelle du DOM est la suivante :

<template>
 <p class="r-slide-menu">
 <p class="r-slide-menu-wrap"></p>
 <p class="r-slide-menu-content"></p>
 </p>
</template>

Afin de rendre personnalisable le contenu du menu et le contenu du thème, nous ajoutons deux emplacements aux deux conteneurs : le contenu principal est placé dans l'emplacement par défaut, et le menu est placé dans l'emplacement du menu :

<template>
 <p class="r-slide-menu">
 <p class="r-slide-menu-wrap">
  <slot name="menu"></slot>
 </p>
 <p class="r-slide-menu-content">
  <slot></slot>
 </p>
 </p>
</template>

style css

Scss est utilisé dans mon projet, le code est le suivant :

<style lang="scss">
@mixin one-screen {
 position: absolute;
 left:0;
 top:0;
 width:100%;
 height:100%;
 overflow: hidden;
}

.r-slide-menu{
 @include one-screen;
 &-wrap, &-content{
 @include one-screen;
 }
 &-transition{
 -webkit-transition: transform .3s;
 transition: transform .3s;
 }
}
</style>

À ce stade, nous avons deux conteneurs absolument positionnés

javascript

Commençons maintenant l'écriture formelle du code. Nous clarifions d'abord la logique d'interaction suivante :

  • Lorsque le doigt glisse vers la gauche et la droite, le conteneur principal et le conteneur de menu se déplacent avec le mouvement du doigt

  • Lorsque le doigt se déplace plus loin que le menu La page ne peut pas continuer à glisser vers la droite lorsque la largeur du conteneur

  • Lorsque le doigt se déplace vers la gauche pour que la distance de déplacement entre le menu et la page revient à zéro, la page ne peut pas continuer à se déplacer vers la gauche

  • Lorsque le doigt est relâché de l'écran, si la page glisse au-delà d'une certaine distance (proportion de toute la largeur du menu), tout le menu sera ouvert. S'il est inférieur à une certaine distance, le menu sera fermé

Il faut donc maintenant pouvoir paramétrer la personnalisation. largeur du menu lors de l'utilisation du composant et le rapport entre la valeur critique qui déclenche la fermeture du menu et la largeur du menu. En même temps, nous devons ajouter un événement tactile au conteneur principal. le conteneur de menu et le conteneur principal. Ajoutez un style pour contrôler leur mouvement, et contrôlez le mouvement du conteneur en contrôlant ce style

<template>
 <p class="r-slide-menu">
 <p class="r-slide-menu-wrap" :style="wrapStyle">
  <slot name="menu"></slot>
 </p>
 <p class="r-slide-menu-content" :style="contentStyle"
 @touchstart="touchstart"
 @touchmove="touchmove"
 @touchend="touchend">
  <slot></slot>
 </p>
 </p>
</template>
<script>
export default {
 props: {
 width: {
  type: String,
  default: &#39;250&#39;
 },
 ratio: {
  type: Number,
  default: 2
 }
 },
 data () {
 return {
  isMoving: false,
  transitionClass: &#39;&#39;,
  startPoint: {
  X: 0,
  y: 0
  },
  oldPoint: {
  x: 0,
  y: 0
  },
  move: {
  x: 0,
  y: 0
  }
 }
 },
 computed: {
 wrapStyle () {
  let style = {
  width: `${this.width}px`,
  left: `-${this.width / this.ratio}px`,
  transform: `translate3d(${this.move.x / this.ratio}px, 0px, 0px)`
  }
  return style
 },
 contentStyle () {
  let style = {
  transform: `translate3d(${this.move.x}px, 0px, 0px)`
  }
  return style
 }
 },
 methods: {
 touchstart (e) {},
 touchmove (e) {},
 touchend (e) {}
 }
}

Ensuite, nous mettra en œuvre notre fonction principale de traitement des événements tactiles, la logique de l'événement est la suivante :

  1. Le moment où le doigt est enfoncé, le point touché par le doigt actuel et la position du doigt actuel le conteneur principal est enregistré

  2. Lorsque le doigt bouge, obtenez la position du point mobile

  3. Calculez la distance des axes X et Y du courant mouvement du point du doigt, si la distance de mouvement X est supérieure à la distance de mouvement Y. Ensuite, il est déterminé comme étant un mouvement horizontal, sinon c'est un mouvement vertical

  4. S'il s'agit d'un mouvement horizontal , il est jugé que la distance de déplacement actuelle se situe dans un intervalle de mouvement raisonnable (0 à la largeur du menu), et si c'est le cas, changez la position des deux conteneurs (empêchez que d'autres événements sur la page soient déclenchés pendant le mouvement)

  5. Le doigt quitte l'écran : si la distance de déplacement cumulée dépasse la valeur critique, utilisez l'animation pour ouvrir le menu, sinon fermez le menu

touchstart (e) {
 this.oldPoint.x = e.touches[0].pageX
 this.oldPoint.y = e.touches[0].pageY
 this.startPoint.x = this.move.x
 this.startPoint.y = this.move.y
 this.setTransition()
},
touchmove (e) {
 let newPoint = {
 x: e.touches[0].pageX,
 y: e.touches[0].pageY
 }
 let moveX = newPoint.x - this.oldPoint.x
 let moveY = newPoint.y - this.oldPoint.y
 if (Math.abs(moveX) < Math.abs(moveY)) return false
 e.preventDefault()
 this.isMoving = true
 moveX = this.startPoint.x * 1 + moveX * 1
 moveY = this.startPoint.y * 1 + moveY * 1
 if (moveX >= this.width) {
 this.move.x = this.width
 } else if (moveX <= 0) {
 this.move.x = 0
 } else {
 this.move.x = moveX
 }
},
touchend (e) {
 this.setTransition(true)
 this.isMoving = false
 this.move.x = (this.move.x > this.width / this.ratio) ? this.width : 0
},
setTransition (isTransition = false) {
 this.transitionClass = isTransition ? &#39;r-slide-menu-transition&#39; : &#39;&#39;
}

Ci-dessus, il y a une fonction setTransition dans ce code principal. La fonction de cette fonction est de donner un message au conteneur lorsque le doigt part. Ajoutez un attribut de transition à l'élément pour autoriser. le conteneur doit avoir une animation de transition pour compléter l'animation de fermeture ou d'ouverture ; par conséquent, l'attribut de transition sur le conteneur doit être supprimé au moment où le doigt est enfoncé pour éviter la mauvaise expérience de glissement retardé du conteneur et du doigt. pendant le processus de glissement. Pour dernier rappel, la raison pour laquelle Translate3d est utilisé à la place de Translate dans le code est d'activer l'accélération 3D de l'animation sur les téléphones mobiles et d'améliorer la fluidité de l'animation. Le code final est le suivant :

<template>
 <p class="r-slide-menu">
 <p class="r-slide-menu-wrap" :class="transitionClass" :style="wrapStyle">
  <slot name="menu"></slot>
 </p>
 <p class="r-slide-menu-content" :class="transitionClass" :style="contentStyle"
  @touchstart="touchstart"
  @touchmove="touchmove"
  @touchend="touchend">
  <slot></slot>
 </p>
 </p>
</template>
<script>
export default {
 props: {
 width: {
  type: String,
  default: &#39;250&#39;
 },
 ratio: {
  type: Number,
  default: 2
 }
 },
 data () {
 return {
  isMoving: false,
  transitionClass: &#39;&#39;,
  startPoint: {
  X: 0,
  y: 0
  },
  oldPoint: {
  x: 0,
  y: 0
  },
  move: {
  x: 0,
  y: 0
  }
 }
 },
 computed: {
 wrapStyle () {
  let style = {
  width: `${this.width}px`,
  left: `-${this.width / this.ratio}px`,
  transform: `translate3d(${this.move.x / this.ratio}px, 0px, 0px)`
  }
  return style
 },
 contentStyle () {
  let style = {
  transform: `translate3d(${this.move.x}px, 0px, 0px)`
  }
  return style
 }
 },
 methods: {
 touchstart (e) {
  this.oldPoint.x = e.touches[0].pageX
  this.oldPoint.y = e.touches[0].pageY
  this.startPoint.x = this.move.x
  this.startPoint.y = this.move.y
  this.setTransition()
 },
 touchmove (e) {
  let newPoint = {
  x: e.touches[0].pageX,
  y: e.touches[0].pageY
  }
  let moveX = newPoint.x - this.oldPoint.x
  let moveY = newPoint.y - this.oldPoint.y
  if (Math.abs(moveX) < Math.abs(moveY)) return false
  e.preventDefault()
  this.isMoving = true
  moveX = this.startPoint.x * 1 + moveX * 1
  moveY = this.startPoint.y * 1 + moveY * 1
  if (moveX >= this.width) {
  this.move.x = this.width
  } else if (moveX <= 0) {
  this.move.x = 0
  } else {
  this.move.x = moveX
  }
 },
 touchend (e) {
  this.setTransition(true)
  this.isMoving = false
  this.move.x = (this.move.x > this.width / this.ratio) ? this.width : 0
 },
 // 点击切换
 switch () {
  this.setTransition(true)
  this.move.x = (this.move.x === 0) ? this.width : 0
 },
 setTransition (isTransition = false) {
  this.transitionClass = isTransition ? &#39;r-slide-menu-transition&#39; : &#39;&#39;
 }
 }
}
</script>
<style lang="scss">
@mixin one-screen {
 position: absolute;
 left:0;
 top:0;
 width:100%;
 height:100%;
 overflow: hidden;
}
.r-slide-menu{
 @include one-screen;
 &-wrap, &-content{
 @include one-screen;
 }
 &-transition{
 -webkit-transition: transform .3s;
 transition: transform .3s;
 }
}
</style>

Ce qui précède est ce que j'ai compilé pour tout le monde. J'espère qu'il sera utile à tout le monde à l'avenir.

Articles connexes :

Explication détaillée de l'utilisation d'Angular CLI pour générer du code à partir de plans

Explication détaillée de plusieurs éléments facilement négligés parties de la documentation Vue Analyse de

Une brève discussion sur la méthode simple d'utilisation de Baidu Maps sous Vue

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