自定义指令文件:
import Vue from 'vue'
//自定义scrollerUpdate
Vue.directive('scrollUpdate', {
inserted: function(el, binding, vnode, oldVnode) {
let touchStarY=0, touchEndY=0, touchDistance=0,
pageDownTimer=null, newLiEle=null, updateState=0;
el.addEventListener('touchstart', async(e) => {
touchStarY = e.touches[0].clientY;
clearInterval(pageDownTimer);
})
el.addEventListener('touchmove', async(e) => {
touchEndY = e.touches[0].clientY;
touchDistance = touchEndY - touchStarY;
//console.log("touch滑动了", touchDistance);
let UpdateEle = document.getElementById("downUpdateEle");
if(touchDistance < 0){ //上拉
if(UpdateEle) el.removeChild(newLiEle)
}else{
if(el.scrollTop==0){
e.preventDefault(); //阻止浏览器的黑色背景
if(!UpdateEle){
//添加 li
newLiEle = document.createElement("li");
// 设置 li 属性: id、style;
newLiEle.setAttribute("id", "downUpdateEle");
newLiEle.setAttribute('style', 'list-style: none; background: #fefefe; color: #999999; font-size: 16px; opacity: 1;');
newLiEle.innerHTML = "下拉刷新";
el.insertBefore(newLiEle, el.firstChild);
}
newLiEle.style.lineHeight = touchDistance+'px';
if(touchDistance > 40){
newLiEle.innerHTML = "松开刷新";
newLiEle.style.lineHeight = '40px';
updateState = 1;
}
}
}
})
el.addEventListener('touchend', async() => {
if(updateState==1){ //刷新数据;
let expression_name = binding.expression;
let expression_fun = vnode.context[expression_name];
expression_fun && await expression_fun();
updateState = 0;
resetNewTopEle();
}else{ //不触发刷新数据
resetNewTopEle()
}
function resetNewTopEle(){
pageDownTimer = setInterval(()=>{
if(document.getElementById("downUpdateEle")){
//样式获取
let newLiLineheight = parseInt(newLiEle.style.lineHeight);
let newLiFontSize = parseInt(newLiEle.style.fontSize);
let newLiOpacity = newLiEle.style.opacity;
if(newLiLineheight<1){
el.removeChild(newLiEle)
clearInterval(pageDownTimer)
}else{
newLiEle.style.lineHeight = newLiLineheight/2+'px';
newLiEle.style.fontSize = newLiFontSize/2+'px';
newLiEle.style.opacity = newLiOpacity/2;
}
}
}, 70)
}
})
}
})
//自定义scrollMore
Vue.directive('scrollMore', {
inserted: function(el, binding, vnode, oldVnode) {
//console.log(el, binding, vnode)
let scrollHeight = el.offsetHeight,
expression_name = binding.expression,
expression_fun = vnode.context[expression_name];
el.addEventListener('scroll', async() => {
if(scrollHeight + el.scrollTop + 10 >= el.firstChild.clientHeight) {
try {
console.log("加载了.....")
expression_fun && await expression_fun();
} catch(error) {
console.log(error)
}
}
})
}
})
main.js中引入自定义指令文件:
页面中使用如下:
<!-- scroller
Created by TaoYe on 2019-03-06.
Copyright 2019 TaoYe. All rights reserved.
-->
<template>
<div class="container">
<div class="header">这里是头部</div>
<div class="section" v-scrollMore="loadingMore" v-scrollUpdate="updateData" :style="{height: scrollBoxHei}">
<ul>
<li class="list"> 自定义指令v-scroll: v-scroll </li>
<li class="list" v-for="(item,index) in listNum" :key="index">{{item}}</li>
</ul>
</div>
<div class="footer"@click="Top('回到顶部', $event)">回到顶部</div>
<loading v-if="showLoading"></loading>
</div>
</template>
<script>
import loading from '@/components/template/loading'
export default({
name: "scroller",
data(){
return{
titleMsg : "这里是自定义指令v-title",
listNum : 10,
showLoading : false,
scrollBoxHei: 0,
}
},
components: { loading },
created(){
let that = this;
that.scrollBoxHei = window.screen.height - 80 +'px'
},
methods:{
updateData(){
let that = this;
console.log("数据刷新!!!!")
that.showLoading = true;
that.listNum = 10;
setTimeout(()=>{
that.showLoading = false;
}, 1000)
},
loadingMore() {
let that = this;
that.showLoading = true;
that.listNum += 20;
setTimeout(()=>{
that.showLoading = false;
}, 1000)
},
Top(prompt, e) {
//console.log(prompt, e);
let aniTranVal = 50;
let scrollEle = document.getElementsByClassName('section')[0];
let toTopTimer = setInterval(()=>{
if(scrollEle.scrollTop > 0){
if(scrollEle.scrollTop>=aniTranVal*10){
scrollEle.scrollTop -= aniTranVal*(aniTranVal/10);
}else if(scrollEle.scrollTop>=aniTranVal){
scrollEle.scrollTop -= scrollEle.scrollTop/aniTranVal
}else{
scrollEle.scrollTop -= scrollEle.scrollTop/(aniTranVal/2);
}
}else if(scrollEle.scrollTop==0){
clearInterval(toTopTimer)
}
}, 10)
}
}
})
</script>
<style lang="less" scoped="scoped">
.container {
width: 100%;
height: 100%;
margin: 0 auto;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.header,
.footer {
width: 100%;
height: 40px;
line-height: 40px;
text-align: center;
background: #f1f1f1;
}
.section {
width: 100%;
flex: 1;
overflow-y: auto;
}
ul{
list-style: none;
padding: 0;
margin: 0;
}
.list {
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
border-bottom: 1px solid #ccc;
}
</style>
效果: