Vue Mobile UI framework implements QQ side menu components and vueui

Source: Internet
Author: User

Vue Mobile UI framework implements QQ side menu components and vueui

A recent interview found that many front-end programmers have never written plug-ins, and are basically Baidu on the Internet. Therefore, I plan to write a series of articles and teach some of my colleagues who have never written components How to Write plug-ins. All the articles in this series are based on VUE and the core content is the same. After that, you can quickly rewrite them to components such as react, angular, or applets. This is the first article, which is about a side menu component similar to QQ.

Effect display

Let's take a look at the results and see what we are going to do. The pictures are a bit blurred. Let's look at them first:

Start production

DOM Structure

There should be two containers in the overall structure: 1. Menu container 2. Homepage container; therefore, the current DOM structure is as follows:

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

To customize the menu content and topic content, we add two slot slots to the two containers: The subject content in the default slot and the menu content in the menu slot:

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

Css style

Scss is used in my project. The Code is as follows:

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

Now we get two absolutely positioned containers.

Javascript

Now we have officially written the code. First, let's clarify the interaction logic:

  • When the fingers slide left and right, the main container and menu container move with the fingers.
  • When the finger movement distance exceeds the menu container width, the page cannot continue to slide to the right
  • When you move your finger to the left, the page cannot be moved to the left when the distance between the menu and the page is set to zero.
  • When the finger is released from the screen, if the page slides beyond a certain distance (the ratio of the entire menu width), the entire menu is opened. If the distance is smaller than a certain distance, the menu is closed.

So now we need to be able to customize the menu width and the ratio of the critical value and menu width that trigger the menu collapse when using components, and add a touch event to the main container, finally, we add a style for the menu container and the main container to control their movement, and control the movement of the container by controlling the style.

<template> <div class="r-slide-menu"> <div class="r-slide-menu-wrap" :style="wrapStyle">  <slot name="menu"></slot> </div> <div class="r-slide-menu-content" :style="contentStyle" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend">  <slot></slot> </div> </div></template><script>export default { props: { width: {  type: String,  default: '250' }, ratio: {  type: Number,  default: 2 } }, data () { return {  isMoving: false,  transitionClass: '',  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) {} }}

Next, we will implement our core touch event processing function. The Event Logic is as follows:

  1. Click the finger instantly to record the point touched by the current finger and the location of the current main container.
  2. The position of the moving point is obtained when the finger moves.
  3. Calculates the distance between X and Y axes of the point where the current finger is located. If the distance between X and Y is greater than the distance between Y, it is regarded as transverse motion; otherwise, it is vertical motion.
  4. If the horizontal movement is performed, the current moving distance is determined to move in a reasonable range (from 0 to the menu width, if yes, the location of the two containers is changed (preventing other events on the page from being triggered during moving)
  5. Finger off the screen: If the accumulated movement distance exceeds the threshold, use an animation to open the menu. Otherwise, close the 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 ? 'r-slide-menu-transition' : ''}

Above, this core code contains a setTransition function, which is used to add the transition attribute to the container element when the finger leaves, so that the container has a transition animation to complete the close or open the animation; therefore, the transition attribute on the container needs to be removed when the finger is pressed to avoid the poor experience of container and finger sliding delay during the sliding process. Finally, the reason why the Code uses translate3d instead of translate is to start 3D animation acceleration for mobile phones and improve the smoothness of the animation. The final code is as follows:

<Template> <div class = "r-slide-menu"> <div class = "r-slide-menu-wrap": class = "transitionClass ": style = "wrapStyle"> <slot name = "menu"> </slot> </div> <div class = "r-slide-menu-content ": class = "transitionClass ": style = "contentStyle" @ touchstart = "touchstart" @ touchmove = "touchmove" @ touchend = "touchend"> <slot> </div> </template> <script> export default {props: {width: {type: String, default: '20140901'}, ratio: {type: Number, default: 2 }}, data () {return {isMoving: false, transitionClass: '', 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 st Yle = {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 move Y = 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 th Is. move. x = (this. move. x> this. width/this. ratio )? This. width: 0}, // click switch () {this. setTransition (true) this. move. x = (this. move. x = 0 )? This. width: 0}, setTransition (isTransition = false) {this. transitionClass = isTransition? 'R-slide-menu-transition ': ''}}</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. 3 s; transition: transform. 3 s ;}}</style>

Summary

The above section describes how to implement the QQ side menu component in the vue Mobile UI framework. I hope it will be helpful to you. If you have any questions, please leave a message for me, the editor will reply to you in a timely manner. Thank you very much for your support for the help House website!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.