原生js實現一個側滑刪除取消組件(item slide)

組件,本質上是解決某個問題封裝的類,在此記錄原生js實現側滑刪除javascript

 

先上效果圖

 

 

實現思路

1. 肯定渲染的數據結構css

2. 思考劃分佈局,總的有兩個主要的模塊:內容區域和按鈕區域html

  2.1 內容區域保持寬度永遠佔滿設備的寬度java

  2.2 內容區域和按鈕區域之和的寬度等於每一行item的總寬度css3

3. 每行超出的item的部分設置overflow: hidden; 經過touch相關的API事件監聽手勢是左滑仍是右滑性能優化

4. 左滑的時候經過改變元素的一個特定屬性來代表左滑,右滑同理數據結構

5. 經過css3 slector提早寫好左滑狀況和右滑狀況下的樣式,這裏的樣式主要是改變item的左右偏移app

6. 建立元素的時候作的一些性能優化,儘可能減小reflow,reflow的來源是因爲dom的改變引發的,因此能夠思考先將全部元素都寫好後一次性插入,減小dom的變化,減小reflowdom

7. 左滑和右滑的樣式的動畫優化,讓滑動更天然,這裏使用了過分效果ide

 

總體代碼

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximun-scale=1.0, user-scalable=0">
    <title>item slide</title>
    <style type="text/css">
        body,p {
            margin: 0;
        }
        .list-container {
            padding: 0;
            overflow: hidden;
            margin: 0;
        }
        .item-container {
            list-style: none;
            border-bottom: 0.5px solid #9e9e9e73;
            width: calc(100% + 10em);
            display: flex;
            align-items: stretch;
            transition: all ease-in-out 0.2s;
        }
        .left-contianer {
            padding: 10px 10px;
            flex: 100%;
        }
        .delete-container,
        .cancle-container {
            width: 5em;
            background: #f44336;
            position: relative;
        }

        .delete-Content,
        .cancle-Content {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: white;
        }

        .delete-container{
            border-right: 0.5px solid #ffffff80;
        }
        
        .item-container[data-type = "1"]{
            transform: translate3d(-10em, 0, 0);
        }

        .item-container[data-type = "0"]{
            transform: translate3d(0, 0, 0);
        }
    </style>
</head>
<body>
    <ul class="list-container"></ul>

    <script type="text/javascript">

        let list = [
            {
                remark:'1111111',
                value: '1111111dsdsdsdsdadsd'
            },
            {
                remark: '2222222',
                value: '2222222ssdsdadsdsadsa'
            },
            {
                remark: '3333333',
                value: '3333333sfsdsddsdsd'
            }
        ];

        class ItemSlide {
            constructor(obj){
                this.data = obj['data'] ? obj['data'] : [];
                this.name = obj['name'] ? obj['name'] : 'name';
                this.value = obj['value'] ? obj['value'] : 'value';
                this.startX = 0;
                this.endX = 0;
            }

            init(){
                this.listContainer = document.querySelector('.list-container');
                this.fragment = document.createDocumentFragment();
                this.render();
            }

            render(){
                this.data.map((v, i) => {
                    let item = document.createElement('li');
                    item.classList.add('item-container');
                    item.setAttribute('resource-id', i);
                    item.addEventListener('touchstart', this.touchStart.bind(this));
                    item.addEventListener('touchend', this.touchEnd.bind(this))

                    let leftContianer = document.createElement('div');
                    leftContianer.classList.add('left-contianer');

                    let name = document.createElement('p');
                    name.textContent = v[this.name];

                    let address = document.createElement('p');
                    address.textContent = v[this.value];

                    leftContianer.appendChild(name);
                    leftContianer.appendChild(address);
                    
                    let deleteBtn = document.createElement('div');
                    deleteBtn.classList.add('delete-container');
                    deleteBtn.addEventListener('click', this.delItem.bind(this), true);
                    

                    let deleteContent = document.createElement('span');
                    deleteContent.textContent = 'delete';
                    deleteContent.classList.add('delete-Content');
                    deleteBtn.appendChild(deleteContent);

                    let cancleBtn = document.createElement('div');
                    cancleBtn.classList.add('cancle-container');

                    let cancleContent = document.createElement('span');
                    cancleContent.textContent = 'cancle';
                    cancleContent.classList.add('cancle-Content');
                    cancleBtn.appendChild(cancleContent);

                    item.appendChild(leftContianer);
                    item.appendChild(deleteBtn);
                    item.appendChild(cancleBtn);

                    this.fragment.appendChild(item);
                });
                this.listContainer.appendChild(this.fragment);
            }

            touchStart(e) {
                this.startX = e.touches[0].clientX;
            }

            touchEnd(e) {
                const liEl = e.target.parentElement.parentElement;

                this.endX = e.changedTouches[0].clientX;
                let distance = this.startX - this.endX;

                // 左滑
                if(distance > 0) {
                    this.setSlide(liEl);
                // 右滑
                }else if(distance < 0) {
                    this.resetSlide(liEl);
                }
            }

            setSlide(el){
                el.setAttribute('data-type', "1");
            }

            resetSlide(el) {
                el.setAttribute('data-type', "0");
            }

            delItem(e){
                const parentEl = this.findParent(e, 'resource-id');
                this.listContainer.removeChild(parentEl);
            }

            findParent(childEl, attr){
                const parentEl = childEl.target ?
                     childEl.target.parentElement : 
                     childEl.parentElement;
                const id = parentEl.getAttribute(attr);
                if(id) {
                    return parentEl;
                }
                 return this.findParent(parentEl, attr);
            }

        }

        new ItemSlide({
            data: list,
            name: 'remark'
        }).init();
    </script>
</body>
</html>

 

 PS: 

代碼中的建立節點感受寫得有點冗餘,若是有剛簡便而且要考慮到性能的好寫法歡迎留言👍

相關文章
相關標籤/搜索