Vue copy QQ left swipe to delete components

background

A few days ago when doing the Vue project development, because before writing code is a little small bug, others some reaction IOS sliding click above a bit of a problem, so let me help to solve, I looked at the previous code is tedious, redundancy, simply direct themselves to a set of written, for your reference, if there is a better way, welcome to timely communication

Let’s have a look at the effect picture, after all, there is no picture, there is no truth

rendering

Implementation approach

Specific implementation ideas are as follows:

  • In terms of layout, I used REM + Flex layout. For specific structure and style, please refer to my code. It is worth noting that the delete button at the back is placed at the end of each line by positioning, which is beyond hiding
  • Swipe left and swipe right are throughtouchstarttouchendEvents are judged by sliding to start and end horizontallyxIf the offset is greater than a certain threshold, it is considered as a left slide, and if it is less than a certain threshold, it is considered as a right slide
  • Swipe left and swipe right through the parent, respectivelyliElements of thetranslateThe offset changes, and the way I do that is I declare the style in advance by changing the current parentlithetypeValue for style switching
  • When clicking a slider, first determine whether all the current slider is inSlipping out of shapeIf so, you must restore all slider states first. If not, click to take effect. Here I just pop up onealter, the specific business can be filled in according to the actual situation
  • Delete is relatively simple, when the slider is drawn, the delete button appears, click the button, get the current array index value, through the arrayspliceMethod to delete the corresponding array value

The specific implementation

The Html code

<div class="container"> <div class="page-title"> Slide component </div> <ul> <li class="list-item "v-for="(item,index) in list" data-type="0"> <div class="list-box" @touchstart.capture="touchStart" @touchend.capture="touchEnd" @click="skip"> <img class="list-img" :src="item.imgUrl" alt=""> <div class="list-content"> <p class="title">{{item.title}}</p> <p class="tips">{{item.tips}}</p> <p class="time">{{item.time}}</p> </div> </div> <div class="delete" @click="deleteItem" :data-index="index"> Delete </div> </li> </ul> </div>Copy the code

Note: my data here is all local mock ~

Css style code

.page-title{ text-align: center; font-size: 17px; padding: 10px 15px; position: relative; } .page-title:after{ content: " "; position: absolute; left: 0; bottom: 0; right: 0; height: 1px; border-bottom: 1px solid #ccc; color: #ccc; -webkit-transform-origin: 0 100%; transform-origin: 0 100%; - its - transform: scaleY (0.5); The transform: scaleY (0.5); z-index: 2; } .list-item{ position: relative; Height: 1.6 rem; - its - the transition: all 0.2 s; The transition: all 0.2 s; }. The list - item [data - type = "0"] {the transform: translate3d (0, 0); }. The list - item [data - type = "1"] {the transform: translate3d (- 2 rem, 0, 0); } .list-item:after{ content: " "; position: absolute; Left: 0.2 rem; bottom: 0; right: 0; height: 1px; border-bottom: 1px solid #ccc; color: #ccc; -webkit-transform-origin: 0 100%; transform-origin: 0 100%; - its - transform: scaleY (0.5); The transform: scaleY (0.5); z-index: 2; }. The list - box {padding: 0.2 rem; background: #fff; display: flex; align-items: center; -webkit-box-sizing: border-box; box-sizing: border-box; justify-content: flex-end; position: absolute; top: 0; right: 0; bottom: 0; left: 0; font-size: 0; } .list-item .list-img{ display: block; width: 1rem; height: 1rem; }.list-item. list-content{padding: 0.1rem 0 0.1rem 0.2rem; position: relative; flex: 1; flex-direction: column; align-items: flex-start; justify-content: center; overflow: hidden; } .list-item .title{ display: block; color: #333; overflow: hidden; font-size: 15px; font-weight: bold; text-overflow: ellipsis; white-space: nowrap; } .list-item .tips{ display: block; overflow: hidden; font-size: 12px; color: #999; line-height: 20px; text-overflow: ellipsis; white-space: nowrap; } .list-item .time{ display: block; font-size: 12px; position: absolute; right: 0; Top: 0.1 rem; color: #666; } .list-item .delete{ width: 2rem; Height: 1.6 rem; background: #ff4949; font-size: 17px; color: #fff; text-align: center; The line - height: 1.6 rem; position: absolute; top:0; right: -2rem; }Copy the code

This is the core style code, as well as part of the style reset code in app.vue. I put the script to calculate the font size of the root HTML in index.html ~

Js code

Export default{name: 'index', data () {return {list: [{title: 'Chrome updated ', imgUrl: '/ static/images/Chrome. PNG', tips: 'no longer support Flash video playback, the time:' 8:30 am '}, {title: 'film new information, imgUrl: 'Operation Red Sea' has become a box office hit in China since its release, and many Chinese say they have a new attitude towards Chinese films. ', time: '12:00am'}, {title: 'focus on two meetings, build the Chinese dream, imgUrl:'. / static/images/video. PNG ', tips: 'two stories, time:' then in the afternoon '}, {title: 'WeChat team, imgUrl: '. / static/images/Wechat. PNG ', tips: 'you have abnormal login account, if not the operation, please change the password', the time: 'yesterday'}], startX: 0, endX: 0,}}, methods: {skip(){this.checkslide ()){this.restslide (); }else{ alert('You click the slide! ')}}, // Slide start touchStart(e){this.startx = e.touches[0].clientx; }, / / sliding end touchEnd (e) {/ / the current sliding parent elements let parentElement = e.c. with our fabrication: urrentTarget. The parentElement; [0].touches [0].touches [0].touches; / / left slide the if (parentElement. Dataset. Type = = 0 && enclosing startX - this. EndX > 30) {enclosing restSlide (); parentElement.dataset.type = 1; } / / right slide the if (parentElement. Dataset. Type = = 1 && enclosing startX - this. EndX < - 30) {enclosing restSlide (); parentElement.dataset.type = 0; } this.startX = 0; this.endX = 0; }, / / whether the current have a slider in the sliding state checkSlide () {let listItems = document. QuerySelectorAll (' list - item '); for( let i = 0 ; i < listItems.length ; i++){ if( listItems[i].dataset.type == 1 ) { return true; } } return false; }, / / reset sliding state restSlide () {let listItems = document. QuerySelectorAll (' list - item '); // reset for(let I = 0; i < listItems.length ; i++){ listItems[i].dataset.type = 0; }}, / / delete called deleteItem (e) {/ / let the current index index = e.c. with our fabrication: urrentTarget. Dataset. The index; / / reset this. RestSlide (); / / remove this. List. Splice (index, 1); }}}Copy the code

Js code is so some, each function has a note, I believe that can understand, not much explanation.

conclusion

How, is it also as difficult as imagined, as long as clear thinking, implementation is not so difficult, of course, WHAT I write here is just one of my implementation ideas, maybe you will have a better way to achieve, why not share?

I have hosted the complete code on Github, welcome star and issue~