99行代码实现vue左滑删除

2018-04-16  本文已影响54人  TOPro

文档先欠着

demo

<template lang="pug">
    slide-out
        左滑我就可以看见删除
    template(slot="actions")
        button(text="删除", @click="toast('点我删除')")
</template>



源码

<template lang="pug">
    .slide-out.root( @touchstart="startHandler" ,@touchmove="moveHandler" ,@touchend="endHandler" ,@click="clickHandler" ,:class="[viewMode]" )
        .so-scroller(:style="{left:offsetX}")
            .so-content
                slot
            .so-actions(ref="actions")
                slot(name="actions")
                    span.blank-label 没有操作
</template>
<script type="text/javascript">
    const MODE_IN   =   "normal";
    const MODE_OUT  =   "expanded";
    const DISTANCE  =       45;
    const INSTANCE_POLL = new Map();
    export default {
        name:"SlideOut",
        data(){
            return {
                actionsWidth:0,
                viewMode:MODE_IN
            }
        },
        computed:{
            offsetX(){return (this.viewMode == MODE_IN?0:-this.actionsWidth) + "px"}
        },
        methods:{
            freshSize(){
                this.actionsWidth = this.$refs.actions.offsetWidth;
            },
            startHandler(){
                this._startX = event.touches[0].clientX;
                this._startSlide = true;
            },
            moveHandler(){
                var m = this;
                if(!m._startSlide) return;
                this._currentX = event.touches[0].clientX;
                this._distance = this._currentX - this._startX;
                if(Math.abs(m._distance) > DISTANCE) {
                    m.viewMode = m._distance<0?MODE_OUT:MODE_IN;
                    console.log(m.viewMode,m._distance<0?MODE_OUT:MODE_IN);
                    this._startSlide = false;
                }
            },
            endHandler(){
                this._startSlide = false;
            },

            clickHandler(e){
                var m = this;
                return m.$emit("click",e);
            }
        },
        mounted(){
            var m = this;
            m.freshSize();
            m.$watch("viewMode",v=>{
                if(v==MODE_OUT) INSTANCE_POLL.forEach(el=>{
                    if(el.$$$id!=this.$$$id) el.viewMode=MODE_IN
                })
            })
        },
        created(){
            this.$$$id = INSTANCE_POLL.size;
            INSTANCE_POLL.set(this.$$$id,this)
        },
        beforeDestroy(){
            INSTANCE_POLL.delete(this.$$$id)
        }
    }
</script>
<style scoped type="text/css" lang="less">
    .root{overflow: hidden;}
    .so-content{
        display: flex;
        align-items: center;
    }
    .so-content,.so-scroller,.so-actions{
        height: 100%;
    }
    .so-scroller{
        position: relative;
        transition:left 0.618s cubic-bezier(1.000, 0.000, 0.000, 1.000)
    }
    .so-actions{
        position: absolute;
        top: 0;
        right: 0;
        transform:translateX(100%);
        display: flex;
        align-items: stretch;
        white-space: nowrap;
    }
    .blank-label{
        color: #666;
        display: flex;
        align-items: center;
    }
</style>

上一篇下一篇

猜你喜欢

热点阅读