老样纸,先上图:
先上代码:
html模板代码:
<div class="slide-item-wrapper"> <div class="slide-item" ref="slide"> <div class="content" ref="content"> <div ng-transclude="content"></div> </div> <div class="side" ref="side"> <div ng-transclude="side"></div> </div> </div> </div>
指令代码:
/* * created by weishengjian * date 20180319 */ /*示例代码*/ /* <slide-item> <slide-content> <ons-list-item>dlasdjalkj</ons-list-item> </slide-content> <slide-side> <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label> <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label> <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label> </slide-side> </slide-item> <slide-item> <slide-content> <ons-list-item>dlasdjalkj</ons-list-item> </slide-content> <slide-side> <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label> <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label> <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label> </slide-side> </slide-item> <slide-item> <slide-content> <ons-list-item>dlasdjalkj</ons-list-item> </slide-content> <slide-side> <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label> <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label> </slide-side> </slide-item> <slide-item> <slide-content> <ons-list-item>dlasdjalkj</ons-list-item> </slide-content> <slide-side> <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label> </slide-side> </slide-item> */ app.directive('slideItem', function ($rootScope) { return { restrict: 'E', replace: false, templateUrl: 'js/directives/slide-item/slide.item.template.html', scope: false, transclude: { 'side': '?slideSide', 'content': '?slideContent', }, controller: function () { !$rootScope.closeAllSlideItem && ($rootScope.closeAllSlideItem = function () { var slides = document.getElementsByClassName("slide-item"); for (var i = 0; i < slides.length; i++) { var slide = slides[i]; slide.style.left = 0 + 'px'; slide.style['transition'] = 'all 0.4s'; slide.currentShow = false; } }); }, link: { post: function (scope, element, attrs) { var refs = getRefs(element); var side = refs.side; var slide = refs.slide; var content = refs.content; var slideWidth = side.offsetWidth; side.style.right = -slideWidth + 'px'; slide._touch = {}; slide.currentShow = false; var touchstart = function (e) { refs = getRefs(element); side = refs.side; slide = refs.slide; content = refs.content; slideWidth = side.offsetWidth; slide._touch.initialized = true; var touch = e.touches[0]; slide._touch.startX = touch.pageX; slide._touch.startY = touch.pageY; }; var touchmove = function (e) { if (!slide._touch.initialized) return; var touch = e.touches[0]; var deltaX = touch.pageX - slide._touch.startX; var deltaY = touch.pageY - slide._touch.startY; /*如果在纵轴上得偏差大于在横轴上得偏差,则不应该左右滑动*/ if (Math.abs(deltaY) > Math.abs(deltaX)) return; var left = slide.currentShow ? -slideWidth : 0; var offsetWidth = Math.max(Math.min(0, left + deltaX), -slideWidth); slide._touch.percent = 1 - Math.abs(offsetWidth) / slideWidth; slide.style['transition'] = 'all 0.2s'; slide.style.left = offsetWidth + 'px'; }; var touchend = function (e) { $rootScope.closeAllSlideItem(); if (!slide._touch.initialized) return; var touch = e.changedTouches[0]; var deltaX = touch.pageX - slide._touch.startX; var deltaY = touch.pageY - slide._touch.startY; /*如果在纵轴上得偏差大于在横轴上得偏差,则不应该左右滑动*/ if (Math.abs(deltaY) > Math.abs(deltaX)) return; var percent = Math.abs(deltaX) / slideWidth; //滑动幅度 var offsetWidth; if (deltaX > 0) { //右滑 if (percent > 0.2) { //消失 offsetWidth = 0; slide.currentShow = false; } else { offsetWidth = -slideWidth; slide.currentShow = true; } } else { //左滑 if (percent > 0.2) { //消失 offsetWidth = -slideWidth; slide.currentShow = true; } else { offsetWidth = 0; slide.currentShow = false; } } slide.style.left = offsetWidth + 'px'; slide.style['transition'] = 'all 0.4s'; }; content.addEventListener('touchstart', touchstart); content.addEventListener('touchmove', touchmove); content.addEventListener('touchend', touchend); } } } });
refs函数:
/* * 在指令中,获取作用域范围内的所有用了ref属性标记的节点,如果ref值相同,通过 getRefs(element).别名 结果是一个数组,如果ref值只有一个,测获取的就是一个对象 * element:在指令中,$element对象,也就是指令本身对象 */ function getRefs(element) { var refs = ($(element).find("[ref]")); var result = {}; for (var i = 0; i < refs.length; i++) { var item = $(refs[i]); var refName = item.attr('ref'); if (!(refName in result)) result[refName] = []; result[refName].push(item[0]); } for (var key in result) { if (result[key].length == 1) result[key] = result[key][0]; } return result; }
这里面是用了jquery的,在使用这个指令之前,记得先引入jquery。
这个指令的核心在于两点,一点是使用了transclude,还有一点是,将一些状态信息保存在dom节点中。
首先是transclude,有slide-side(存放侧滑内容)以及slide-content(主体内容),有一个div.slide-item包裹着这两个div,在滑动的时候,是整个slide-item滑动,如果同学们只想slide-side滑动的话,需要调整一下代码。
还有一个核心点是,将状态信息存到dom节点,我这里信息就是存到dom节点中的,这里最主要的_touch对象就是存在slide-item这个dom对象,因为侧滑的时候是有状态的,当然你在声明指令的时候可以建立一个自己的作用域,scope为true或者一个对象,但是这样的话,slide-content以及slide-side中获取的数据就有可能会不正常,我这里为了完全不影响作用域,就将一些数据存在了dom对象中。
……漏了样式代码:
.slide-item-wrapper { width: 100%; .slide-item { position: relative; .side { height: 100%; position: absolute; top: 0px; div, slide-side { display: inline-block; height: 100%; .side-item { height: 100%; display: inline-flex; align-items: center; justify-content: center; width: 64px; float: left; ons-icon { font-size: 32px; } } } } } }这个less代码,可以拿到less在线编译工具编译一下,或者自行转译一下也可以,不是很多