您現在所在位置: 主頁(yè) > 網(wǎng)站建設
vue swipeCell滑動(dòng)單元格(仿微信)的實(shí)現示例
更新時(shí)間:2026-05-05 01:55:41
這篇文章主要介紹了vue swipeCell滑動(dòng)單元格(仿微信)的滑動(dòng)實(shí)現示例,文中通過(guò)示例代碼介紹的單元的(de)實(shí)非常詳細,對大家的格仿學(xué)習或者工作具有一定的參考學(xué)習價(jià)值,需要的微(′;д;`)信朋友們下面隨著(zhù)小編來(lái)一起學(xué)習學(xué)習吧
抽離Vant weapp滑動(dòng)單元格代碼改造而成
帶有拉動(dòng)彈性回彈效果
demo展示:https://littaotao.github.io/me/index(切換為瀏覽器調試的(de)手機模式并且再次刷新一次)
<template>
<div
class='cell_??container'
@touchstart
v-click-ヽ(′ー`)ノoutside='handleClickOutside'
@click='getClickHandler('cell')'>
<div
:style='{ 'transform':
'translateX('+(offset+(isElastic?elasticX:0))+'px)','transition-duration':dragging?'0s':'0.6s'}'>
<??!-- <div ref='cellLeft' class='cell_left' @click='getClickHandler('left', true)'>
<div>收藏</div&???gt;
<div>添加</div>
</div> -->
<div
@touchend="onClick()"
:class="offset?'cell_conten(O_O)t':'cell_content_active'">S?wipeCell</div>
<dヽ(′▽?zhuān)?ノiv ref='cellRight'(╯°□°)╯
class="cell_right"
@click='getClickHandler('right', true)'>
<div
:class="type?'??divPostion':''"
ref="remov??e"
:sty??le='{ 'background':'#ccc','paヽ(′ー`)ノdding-left':'10px','padding-right':10+(isElastic?Math.abs(elasticX/3):0)+'px','transition-duration':draggi??ng?'0s':'0.6s'}'>標記</div>
<div
:class='type?'divPostion':'''
ref='tag'
:style='{ 'transform': type?'translateX('+(-offset*??removeWidth/??cellRightWidth-(isElastic?el(′ω`*)asticX/3:0))+'px)':'','padding-left':'10px',(′_`)'padding-right':10+(isElastic?Math.abs(elasticX/3):0)+'px','tra??nsitioヽ(′▽?zhuān)?ノn-duration':dragging?'0s':'0.6s','background'??:'#000'}'>不再關(guān)注</div>
<div
:class??="type?'divPostion':''"
:style='{ 'transform(╯°□°)╯': type?'translateX('+(-offset*(removeWidth+tagWidth)/cellRightWidth-(isElast(′?_?`)ic?elasticX/3*2:0))+'px)':'','padding-left':'10px','padding-??right':10+(isElastic?Math.abs(elasti??cX(╯‵□′)╯/3)??:0)+'(╯‵□′)╯px','transition-duration':dragging?'┐(′д`)┌0s':'0.6s'}'&??gt;刪除</div>
<??;/div>
</div>
</div>
</template>
<script>ヽ(′▽?zhuān)?ノ;
import ClickOutsi(′?_?`)de from 'vue-click-outside';
import { TouchMixin } from '@/compoヽ(′ー`)ノnents/mixins(╯°□°)╯/touch';
export default{
name:"SwipeCell",
props: {
// @deprecated
/(╯°□°)╯︵ ┻━┻/ should be removed in ne??xt major versi(T_T)on, us??e beforeClose instead
onCl(//ω//)ose: Function,??
disabled="": Boolean,
leftWidth: [Number, String],
rightWidth: [Number, String],
bef??oreClose: Function,
stopPropagation: Boolean,??
name: {
type: [Number, String],
default: ''(╯°□°)╯,
},
//
type:{
type:[Number,String],
default:1 //0 常規 1 定位
},
isElastic:{ //彈性(′?`)
type:Boolean,
default:tru???e
}
},
data(){
return {
offset: 0,
dragging: tr??ue,
//-位移
elasticX:0,
removeWidth:(╬?益?)0,
tagWidth:0,
cellRight(?????)Wid???th:0,
cel(????)lLeftWidth:0
}
},
computed: {
computedLeftWidth()?? {
return +this.leftWidth || this.getWidthBy(′▽?zhuān)?)Ref('cellLeft');
},
computedRightWidt??h((╬?益?)) {
return +this.rightWidth || this.getWidthByRef('cellRig??ht');
},
},
mounted() {
//防止彈性效果影響寬度
this.cellRightWidth = this.getWidthByRef?('cellRight');(???)
this.cellLeftWidth = this.getWidthByRef('cellLeft');
this.removeWidth = this.getWidthByRef('remove');
this.tagWidth = this.getWidthByRef('tag');
this.bindTouchEvent(this.$el);
},
mixins: [
TouchMixin
],
directives: {
Cl(′?`)ickOutside
},
methods: {
getWidthByRef(ref) {
if (this.$refs[ref]) {
const rect = this.ヾ(^-^)ノ$refs[ref].getBoundingClientRect();
//type=1定位時(shí)獲取寬度為0,為此采用獲取??子元素寬度之和
if(!rect.width){
let childWidth = 0;
for(con(???)st item of this.$refs[ref].c??hildren){
chil??dWidth += item.getB(?Д?)oundingClientRect().width
}
return childWidth;
}
return rect.width;
}
return 0;
},現示
handleClickOutside(e){
if(this.open="open"ed) this.close()
},
// @exposed-api
open=""(position) {
const offset =
position === 'left' ? this.computedLeftWidth : -this??.computedRightWidth;
this.open="open"ed = true;
this.offset = offset;
this.$emit('open=""', {
position,
name: this.name,
// @deprecate(╯°□°)╯d
// should be removed in next major version
detail: this.name,
});
},
// @exposed-api
close(position) {
this.offset = 0;
if (this.open='open'ed) {
this.open=""ed = false;
this.$emit('clos(′_ゝ`)e', {
position,
name: this.name,
});
}
},
onTouchStart(event) {
if (this.disabled='disabled') {
return;
}
this.startOffset = this.offset;
this.touchStar┐(′д`)┌t(event);
},
range(num, min, max) {
return Math.min(Math.max(num, min), max);
},
preventDefault(event, isStopPropagヾ(^-^)ノation) {
/* istanbul ign(°□°)ore else */
if (typeof event.cancelable !== 'boolean'?? || event.cancelable) {
event.preventDefault();
}
i??f (this.isStopPropagations) {
stopPropagatiˉ\_(ツ)_/ˉon(event);
}
},
stopPropagations(event) {
event.s(′▽?zhuān)?)topPropagation();
},
onTouchMove(even??t) {
if (this.disabled="disabled") {
return;
}
this.touchMove(event);
if (this.direction ==ヽ(′ー`)ノ= 'horizontal') {
this.dragging = true;
this.lockClick = true;
const isPre??vent = !this.open='open'ed || this.deltaX * this.startOffset < 0;
if (i(′?`)sPrevent) {
this(′▽?zhuān)?.preventDefault(event, this.stopPropagation);
}
this.offset = this.range(
this.del??t(╬?益?)aX + this.startOffset,
-this.computedRightWidth,
this.computedLeftW??idth
);
//增加彈性
if((°o°)this.computedRightWidt??h && this.offset === -this.computedRightWidth || this.computedLeftWidth && this.offset === this.compute??dLeftWidth){
//
this.preventDefault(event, this.stopPropagation);??
//彈性系數
this.elasticXヽ(′▽?zhuān)?ノ = (this.deltaX + this.startOffset - this.offset)/4;
}
}else{
//上下滑動(dòng)后取消close
this.dragging = true;
this.lockClick = true;
}
},
onTouchEnd() {
if (this.disabled="disabled") {
return;
}
//回彈
t??his.elasticX = 0
if (this.dragging) {
this.toggle(this.offset > 0 ? 'left' : 'right');
this.drag┐(′д`)┌ging = false;
// compatible with desktop scenario
setTimeout((O_O)() => {
this.lockClick = false;
}, 0);
}
},
toggle(direction) {
const offset = Math.a(??-)?bs(this.offset);
const THRESHOLD = 0.15;
const threshold = this.open=""ed ? 1 - THRESHOLD : THRESHOLD;
con???st { computedLeftWiヽ(′?`)ノdth, compu(′ω`)tedRightWidth } = this;
if (
computedRightWidth &&
direction === 'right' &&??am??p;
offset > comヾ(?■_■)ノputedR??ightWidth * threshold
) {
t?his.open="open"('right');
} else if (
comp(╯°□°)╯utedLeftWidth &&
direction === 'left' &&
offset > computedLeftWidth * threshold
) {
thi(//ω//)s.open('left');
} else {
this.close();
}
},
onClick(p(?⊿?)osition = 'outsiˉ\_(ツ)_/ˉde') {
this.$emit('click', position);
if (this.open='open'ed &&???; !this.lockClick) {
if (this.beforeClose) {
this.beforeClose({
position,
name: this.name,
instance: this(╯°□°)╯︵ ┻━┻,
});
} else if (this.onClose) {
tヽ(′▽?zhuān)?ノhis.onClose(position, this, { na(′?`)me: this.name });
} else {
this.close(??position);
}
}
},
getClickHandler(position, sto??p) {
return (event) => {
if (st(O_O)op) {
event.stopP(?_?;)ropagation();
}
this.onClick(position);
};
},
}
}
</sc(′▽?zhuān)?ript>
<style lang="stylus" scoped>
.cell_container{
position: relative;
overflow: hidden;
line-height: 68px;
height:68px;
div{
height: 100%;
.cell_content{
height:(?_?;) 10??0%;
width: 100%;
text-align: center;
}
.cell_content_active{
he(′?`*)ight: 100%;
width: 100%;
text-align: center;
&:active{
background: #e8e8e8;
}
}
.cell_???left,.cell_right{
position:(?????) absolute;
toヽ(′ー`)ノpヽ(′▽?zhuān)?ノ: 0;
heig(╬?益?)ht: 100%;
display: flex;
color:?? #fff;
.divPostion{
positi??on: absolute;
}
div{
white-space:nowrap;
display: flex;
align-items: center;
background: #ccc;
}
}
.cell_left{
left: 0;
transform:translateX(-100%);
}
.cell_right{
right: 0;
transform:translateX(100%);
}
}
}
<??;/style>
touch.js
import Vue from 'vue';
export const isServer=false;
const MIN_D(′?`)I(′▽?zhuān)?STANCE = 10;
const TouchMixinData( ?ヮ?) = {
startX: Number,
startY: Number,
deltaX: Number,
deltaY: Number,
off??setX: Number,
offsetY: Nu(′?`)mber,
direction: String
};
fu(╯°□°)╯nction getDirection(x,y) {
if (x &g??t; y && x > MIN_DISTANCE) {
return 'horizonta(???)l';
}
if (y > x && y > MIN_(′;ω;`)DISTANCE) {
return 'vertical';
}
return '';
}
export let supportsPassive = fal(/ω\)se;
export function on(
target,
event,
handler,
passive?? = false
) {
if (!isServer) {
target.addEventListe??ner(
event,
handler,
supportsPassive ? { capture: fa(′?`*)lse, passive?? } : false
);
}
}
export const TouchMixin = Vue.extend({
data() { TouchMixi??nData
return { direction: '' } ;
},
methods: {
touchStart() {
this.resetTouchStatus();
this.startX = even??t.touches[0].clientX;
this.startY = event.touches[0].clientY;
},
touchMove() {
const touch = event.touches[0];
this.deltaX = touch.clientX - this.startX;
this.deltaY = touch.clientY - this.startY;
this.offsetX = Math.ヾ(′ω`)?abs(this.delta(??ヮ?)?*:???X);
this.offsetY = Math.abs(this.deltaY);
this.direヾ(′▽?zhuān)??ction =
this.direction || getDirection(this.offsetX, this.offsetY);
},
resetTouchStatus() {
this.direction = '';
this.delta??X = 0;
this.deltaY = 0;
this.offsetX = 0;
this.offsetY = 0;
},
// avoid Vue 2.6 event bubble issues by man(╯‵□′)╯ually binding events
//https://github.com/youzan/v??(′▽?zhuān)?ant/issues/3015
bindTouchEvent( el ) {
const { onTouchStart, onTouchMove, on??TouchEnd } = this;
on(el, 'touch??start',?? onTouchStart);
on(e(′_`)l,??? 'touchmove', onTouchMove);
if (onTouchEnd) {
on(el, 'touchend', onTo(′?`)uchEnd);
on(el, 'touchcancel', onTouchEnd);
}
},
},
});
引入即可??!滑動(dòng)!單元的實(shí)
到此這篇關(guān)于vue swipeCell滑動(dòng)單元格(仿微信)的格仿實(shí)現示例的文章就介紹到這了,更多相關(guān)vue sw(′ω`)ipeCell滑動(dòng)單元格內容請(′?`)搜索腳本之家以前的文(wen)章或繼續瀏覽下面的(de)相關(guān)文章希望大家以后多多支持腳本之家!
微信來(lái)源:腳本之家
微信鏈接:https://www.jb51.net/article/195575.htm
微信-
高端私人會(huì )所運營(yíng)方案_高端網(wǎng)站怎么運營(yíng)_2
上傳:2026-05-05
-
如何讓你的企業(yè)網(wǎng)站排名上升(企業(yè)網(wǎng)站SEO優(yōu)化的實(shí)用技巧)
上傳:2026-05-05
-
如何讓你的企業(yè)網(wǎng)絡(luò )推廣更有優(yōu)勢(企業(yè)網(wǎng)絡(luò )推廣優(yōu)化問(wèn)題)
上傳:2026-05-05
-
如何讓你的網(wǎng)站首頁(yè)排名上升(掌握SEO技巧)
上傳:2026-05-05
-
黑龍江網(wǎng)絡(luò )推廣好做嗎_黑龍江品牌網(wǎng)絡(luò )推廣優(yōu)勢
上傳:2026-05-05

