这篇文章主要为大家详细介绍了vue移动端UI框架实现QQ侧边菜单组件,具有一定的参考价值,可以用来参考一下。
感兴趣的小伙伴,下面一起跟随四海网的小编两巴掌来看看吧!
最近面试发现很多前端程序员都从来没有写过插件的经验,基本上都是网上百度。所以打算写一系列文章,手把手的教一些没有写过组件的兄弟们如何去写插件。本系列文章都基于VUE,核心内容都一样,会了之后大家可以快速的改写成react、angular或者是小程序等组件。这篇文章是第一篇,写的是一个类似QQ的侧边菜单组件。
先让大家看个效果展示,知道咱们要做的东西是个怎么样的样子,图片有点模糊,大家先将就点:
【图片暂缺】
整体结构中应该存在两个容器: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>
为了使得菜单内容和主题内容能够定制,我们再给两个容器中加入两个slot插槽:默认插槽中放置主体内容、菜单放置到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>
我项目中使用了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>
此时我们就得到了两个绝对定位的容器
现在开始正式的代码编写了,首先我们理清下交互逻辑:
所以现在咱们需要在使用组件的时候能够入参定制菜单宽度以及触发菜单收起关闭的临界值和菜单宽度的比例,同时需要给主体容器添加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) {}
}
}
接下来,我们来实现我们最核心的touch事件处理函数,事件的逻辑如下:
代码如下:
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属性去除,避免滑动过程中出现容器和手指滑动延迟的不良体验。 最后提醒下,代码中使用translate3d而非translate的原因是为了启动移动端手机的动画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侧边菜单组件,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对四海网网站的支持!
本文来自:http://www.q1010.com/184/5175-0.html
注:关于vue移动端UI框架实现QQ侧边菜单组件的内容就先介绍到这里,更多相关文章的可以留意四海网的其他信息。
关键词:vue.js
四海网收集整理一些常用的php代码,JS代码,数据库mysql等技术文章。