vue 모 바 일 UI 프레임 워 크 구현 QQ 사 이 드 메뉴 구성 요소

최근 면접 에서 많은 전단 프로그래머 들 이 플러그 인 을 써 본 적 이 없고 기본적으로 인터넷 바 이 두 인 것 으로 나 타 났 다.그래서 일련의 글 을 쓰 려 고 합 니 다.구성 요 소 를 쓰 지 않 은 형제들 에 게 플러그 인 을 쓰 는 방법 을 가르쳐 주 려 고 합 니 다.이 시 리 즈 는 모두 VUE 를 바탕 으로 핵심 내용 이 똑 같 습 니 다.회의 가 끝 난 후에 여러분 은 react,angular 또는 애플 릿 등 구성 요소 로 빠르게 바 꿀 수 있 습 니 다.이 글 은 첫 번 째 편 으로 QQ 와 유사 한 사 이 드 메뉴 구성 요 소 를 썼 다.
효과 전시
먼저 효 과 를 보 여 드 리 겠 습 니 다.우리 가 해 야 할 일이 어떤 모습 인지 알 고 그림 이 약간 모호 합 니 다.여러분 은 먼저 아 쉬 운 대로 하 세 요.

제작 을 시작 하 다
DOM 구조
전체 구조 에 두 개의 용기 가 존재 해 야 합 니 다.1.메뉴 용기 2.홈 페이지 용기;따라서 현재 DOM 구 조 는 다음 과 같다.

<template>
 <div class="r-slide-menu">
 <div class="r-slide-menu-wrap"></div>
 <div class="r-slide-menu-content"></div>
 </div>
</template>
메뉴 내용 과 테마 내용 을 맞 출 수 있 도록 두 용기 에 두 개의 슬롯 슬롯 을 추가 합 니 다.기본 슬롯 에 주체 내용 을 설치 하고 메뉴 를 menu 슬롯 에 배치 합 니 다.

<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 스타일
제 프로젝트 에 scss 를 사 용 했 습 니 다.코드 는 다음 과 같 습 니 다.

<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>
이때 우 리 는 두 개의 절대적 인 포 지 셔 닝 용 기 를 얻 었 다.
javascript
지금부터 정식 코드 를 작 성 했 습 니 다.우선 상호작용 논 리 를 정리 하 겠 습 니 다.
4.567917.손가락 이 좌우 로 미 끄 러 질 때 주체 용기 와 메뉴 용 기 는 모두 손가락 을 따라 운동 한다4.567917.손가락 이 움 직 이 는 거리 가 메뉴 용기 의 너 비 를 초과 할 때 페이지 는 계속 오른쪽으로 미 끄 러 질 수 없습니다4.567917.손가락 이 왼쪽으로 이동 하여 메뉴 와 페이지 의 이동 거 리 를 0 으로 돌 릴 때 페이지 는 계속 왼쪽으로 이동 할 수 없습니다4.567917.손가락 이 화면 을 벗 어 날 때 페이지 가 일정한 거리(전체 메뉴 너비 의 비율)를 초과 하면 전체 메뉴 를 열 고 일정한 거리 보다 작 으 면 메뉴 를 닫 습 니 다그래서 지금 우 리 는 구성 요 소 를 사용 할 때 맞 춤 형 메뉴 너비 와 트리거 메뉴 가 닫 힌 임계값 과 메뉴 너비 의 비율 을 입력 할 수 있 고 주체 용기 에 touch 이 벤트 를 추가 해 야 합 니 다.마지막 으로 메뉴 용기 와 주체 용기 에 각각 운동 을 제어 하 는 style 을 추가 하고 이 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) {}
 }
}
다음은 우리 의 가장 핵심 적 인 터치 이벤트 처리 함 수 를 실현 합 니 다.이벤트 의 논 리 는 다음 과 같 습 니 다.
4.567917.손가락 을 누 르 는 순간 현재 손가락 이 만 지 는 점 과 현재 주 용기 의 위 치 를 기록 합 니 다4.567917.손가락 이 움 직 일 때 이동 하 는 점 의 위 치 를 얻는다4.567917.현재 손가락 이 있 는 곳 에서 이동 하 는 X,Y 축 거 리 를 계산 하고 X 가 이동 하 는 거리 가 Y 이동 하 는 거리 보다 크 면 가로 운동 으로 판정 하 며 그렇지 않 으 면 세로 운동 이다4.567917.가로 운동 을 하면 현재 이동 하 는 거리 가 합 리 적 인 이동 구간(0 에서 메뉴 너비)에서 이동 하 는 것 이 라 고 판단 하고,만약 그렇다면 두 용기 의 위 치 를 바 꿉 니 다(이동 과정 에서 페이지 의 다른 사건 의 촉발 을 막 습 니 다)4.567917.손가락 으로 화면 을 떠 나 기:누적 이동 거리 가 임계값 을 초과 하면 애니메이션 으로 메뉴 를 엽 니 다.그렇지 않 으 면 메뉴 를 닫 습 니 다

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' : ''
}
위 에서 이 핵심 코드 에는 setTransition 함수 가 있 습 니 다.이 함수 의 역할 은 손가락 이 떠 날 때 용기 요소 에 transition 속성 을 추가 하여 용기 에 과도 애니메이션 을 만들어 닫 거나 애니메이션 을 엽 니 다.따라서 손가락 을 누 르 는 순간 용기 에 있 는 이 transition 속성 을 제거 하고 미끄럼 과정 에서 용기 와 손가락 의 미끄럼 이 지연 되 는 나 쁜 체험 을 피해 야 한다.마지막 으로 코드 에서 translate 대신 translate 3d 를 사용 하 는 이 유 는 모 바 일 폰 의 애니메이션 3D 가속 화 를 시작 하여 애니메이션 의 유창 도 를 향상 시 키 기 위해 서 입 니 다.최종 코드 는 다음 과 같 습 니 다.

<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></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) {
  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 ? '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 .3s;
 transition: transform .3s;
 }
}
</style>
총결산
위 에서 말 한 것 은 편집장 이 소개 한 vue 모 바 일 UI 프레임 워 크 가 QQ 사 이 드 메뉴 구성 요 소 를 실현 하 는 것 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 메 시 지 를 남 겨 주세요.편집장 은 신속하게 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기