>指令有:只能输入正整数指令、 只能输入数字和两位小数点指令、按钮权限指令、触摸事件指令、全局loading指令
```
/*
** 自定义指令
*/
import Vue from 'vue'
import * as storage from '@/utils/storage'
/*==================|-- * 只能输入正整数指令 * start --|==================*/
// 使用方法: v-enter-number
Vue.directive('enterNumber', {
inserted: function (el) {
el.addEventListener("keypress", function (e) {
e = e || window.event;
let charcode = typeof e.charCode == 'number' ? e.charCode : e.keyCode;
let re = /\d/;
if (!re.test(String.fromCharCode(charcode)) && charcode > 9 && !e.ctrlKey) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}
});
let legalContent, //开启输入法之前的输入内容
LOCK = false; //是否开启中文输入法
el.addEventListener('compositionstart', (e) => {
legalContent = e.target.value; //保存中文输入法之前的内容
LOCK = true; //加上锁
}, false);
el.addEventListener('compositionend', (e) => {
e.target.value = legalContent;
LOCK = false; // 解锁
}, false);
el.addEventListener('input', (e) => {
if (!LOCK) {
e.target.value = e.target.value.replace(/\D/, '');
}
}, false);
},
update: function (el) {
el.addEventListener('paste', (e) => {
e.preventDefault();
}, false);
}
});
/*==================|-- * 只能输入正整数指令 * end --|==================*/
/*==================|-- * 只能输入正数(包含小数)指令 * start --|==================*/
// 使用方法: v-enter-number-point
Vue.directive('enterNumberPoint', {
inserted: function (el) {
// 用来处理中文输入法的情况 start
let input = el.getElementsByTagName("input")[0] //因为是用的el-input,所以这么拿到input
input.setAttribute("type", "number"); //设置类型是number,解决输入中文的问题,尝试过很多种方法,但最终发现,只有设置为number可以解决
input.setAttribute("step", "0.01"); //解决输入不了,如1.1这种的数据
// 用来处理中文输入法的情况 end
let isSelect = false
el.addEventListener("keypress", function (e) { //在控件有焦点的情况下按下键时发生
e = e || window.event;
let charcode = typeof e.charCode == 'number' ? e.charCode : e.keyCode;
let re = /\d/;
if (charcode == 46) {
if (e.target.value && e.target.value.includes('.')) {
e.preventDefault();
}
} else if (!re.test(String.fromCharCode(charcode)) && charcode > 9 && !e.ctrlKey) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
} else {
if (!isSelect) { //处于截断时候的bug
if (e.target.value && e.target.value.includes('.')) { //如果输入小数的时候
let len = e.target.value.toString().split(".")[1].length;
if (len === 2 || e.key === '.') {
e.preventDefault();
}
}
}
}
});
//失去焦点=>保留指定位小数
el.addEventListener("keyup", e => {
isSelect = false
// console.log('keyup', e, e.target.value)
}, false)
//选中
el.addEventListener("select", e => {
isSelect = true
// console.log('select', e, e.target.value)
}, false)
//点击
el.addEventListener("click", e => {
isSelect = false
// console.log('click', e, e.target.value)
}, false)
//失去焦点
el.addEventListener("focusout", e => {
isSelect = true
// console.log('focusout', e, e.target.value)
}, false)
let legalContent, //开启输入法之前的输入内容
LOCK = false; //是否开启中文输入法
el.addEventListener('compositionstart', (e) => {
legalContent = e.target.value; //保存中文输入法之前的内容
LOCK = true; //加上锁
isSelect = true
}, false);
el.addEventListener('compositionend', (e) => {
e.target.value = legalContent;
LOCK = false; // 解锁
isSelect = true
}, false);
el.addEventListener('input', (e) => {
if (LOCK) return 0;
if (!LOCK) {
setInputVal(e)
} else {
}
}, false);
function setInputVal (e) {
let dataLen = e.data ? e.data.length : 1
let len = e.key ? 1 : dataLen
if (e.target.value && e.target.value.includes('.')) { //如果输入小数的时候
if (!/^([1-9]+\d*|0{1})\.\d{0,2}$/.test(e.target.value)) {
e.target.value = e.target.value.slice(0, e.target.value.length - len)
}
} else { //如果输入整数的时候
if (!/^([1-9]+\d*|0{1})$/.test(e.target.value)) {
e.target.value = e.target.value.slice(0, e.target.value.length - len)
}
}
}
},
update: function (el) {
el.addEventListener('paste', (e) => {
console.log('paste')
e.preventDefault(); //禁止复制,防止不知道复制到是什么东西
}, false);
}
});
/*==================|-- * 只能输入正数(包含小数)指令 * end --|==================*/
/*==================|-- * 后台管理按钮权限指令 * start --|==================*/
// 使用方法: v-has="`/table/Table_Update`"
Vue.directive('has', {
bind: function (el, binding) {
if (!binding.value) {
return el.style.display = 'none';
}
if (!Vue.prototype.$_has(binding.value)) {
el.style.display = 'none';
}
}
});
//权限检查方法
Vue.prototype.$_has = function (value) {
let isExist = false;
let perms = storage.get('perms') || []
if (perms === undefined || perms === null || !perms) {
return false;
}
for (let item of perms) {
if (item && item.indexOf(value) > -1) {
isExist = true;
break;
}
}
// console.log('权限', perms)
return isExist;
};
/*==================|-- * 权限指令 * end --|==================*/
```
###监听触摸事件
```
import vue from 'vue'
/************* 事例 start **************
<div class="box"
v-tap="(e)=>vueTouch('点击',e)"
v-longtap="(e)=>vueTouch('长按',e)"
v-swipeleft="(e)=>vueTouch('左滑',e)"
v-swiperight="(e)=>vueTouch('右滑',e)"
v-swipeup="(e)=>vueTouch('上滑',e)"
v-swipedown="(e)=>vueTouch('下滑',e)"
>{{ name }}</div>
************* 事例 end **************/
function vueTouch(el, binding, type) {
var _this = this;
this.obj = el;
this.binding = binding;
this.touchType = type;
this.vueTouches = {
x: 0,
y: 0
};
this.vueMoves = true;
this.vueLeave = true;
this.longTouch = true;
this.vueCallBack = typeof (binding.value) == "object" ? binding.value.fn : binding.value;
this.obj.addEventListener("touchstart", function (e) {
_this.start(e);
}, false);
this.obj.addEventListener("touchend", function (e) {
_this.end(e);
}, false);
this.obj.addEventListener("touchmove", function (e) {
_this.move(e);
}, false);
};
vueTouch.prototype = {
start: function (e) {
this.vueMoves = true;
this.vueLeave = true;
this.longTouch = true;
this.vueTouches = {
x: e.changedTouches[0].pageX,
y: e.changedTouches[0].pageY
};
this.time = setTimeout(function () {
if (this.vueLeave && this.vueMoves) {
this.touchType == "longtap" && this.vueCallBack(this.binding.value, e);
this.longTouch = false;
};
}.bind(this), 500);
},
end: function (e) {
var disX = e.changedTouches[0].pageX - this.vueTouches.x;
var disY = e.changedTouches[0].pageY - this.vueTouches.y;
clearTimeout(this.time);
if (Math.abs(disX) > 10 || Math.abs(disY) > 100) {
this.touchType == "swipe" && this.vueCallBack(this.binding.value, e);
if (Math.abs(disX) > Math.abs(disY)) {
if (disX > 10) {
this.touchType == "swiperight" && this.vueCallBack(this.binding.value, e);
};
if (disX < -10) {
this.touchType == "swipeleft" && this.vueCallBack(this.binding.value, e);
};
} else {
if (disY > 10) {
this.touchType == "swipedown" && this.vueCallBack(this.binding.value, e);
};
if (disY < -10) {
this.touchType == "swipeup" && this.vueCallBack(this.binding.value, e);
};
};
} else {
if (this.longTouch && this.vueMoves) {
this.touchType == "tap" && this.vueCallBack(this.binding.value, e);
this.vueLeave = false
};
};
},
move: function (e) {
this.vueMoves = false;
}
};
vue.directive("tap", {
bind: function (el, binding) {
new vueTouch(el, binding, "tap");
}
});
vue.directive("swipe", {
bind: function (el, binding) {
new vueTouch(el, binding, "swipe");
}
});
vue.directive("swipeleft", {
bind: function (el, binding) {
new vueTouch(el, binding, "swipeleft");
}
});
vue.directive("swiperight", {
bind: function (el, binding) {
new vueTouch(el, binding, "swiperight");
}
});
vue.directive("swipedown", {
bind: function (el, binding) {
new vueTouch(el, binding, "swipedown");
}
});
vue.directive("swipeup", {
bind: function (el, binding) {
new vueTouch(el, binding, "swipeup");
}
});
vue.directive("longtap", {
bind: function (el, binding) {
new vueTouch(el, binding, "longtap");
}
});
// 自动聚焦
vue.directive("focus", {
inserted: function (el, value) {
if (value) {
console.log('自动聚焦')
el.focus();
}
}
});
```
###全局loading
```
///loading.less
@keyframes custom-loading-rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.custom-loading {
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
z-index: 100;
background-color: rgba(255, 255, 255, 0.5);
overflow: hidden;
}
.custom-loading .custom-loading-round {
width: 30px;
height: 30px;
border-radius: 50%;
border: 4px solid #f9c653;
border-left-color: transparent;
animation: custom-loading-rotate 1s linear infinite;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
```
```
import vue from 'vue'
import '@/assets/loading.less'
//使用方法: v-loading="isShowLoding"
vue.directive('loading', {
bind: (el, binding) => {
const tempDiv = document.createElement('div')
tempDiv.className = 'custom-loading'
const round = document.createElement('div')
round.className = 'custom-loading-round'
tempDiv.appendChild(round)
el.loadingElement = tempDiv
const curStyle = window.getComputedStyle(el)
const position = curStyle.position
if (position === 'absolute' || position === 'relative') {
el.style.position = position
} else {
el.style.position = 'relative'
}
if (binding.value) {
el.appendChild(tempDiv)
}
},
update: (el, binding) => {
if (binding.value) {
if (el.loadingElement.parentNode === null) {
el.appendChild(el.loadingElement)
}
} else {
if (el === el.loadingElement.parentNode) {
el.removeChild(el.loadingElement)
}
}
},
unbind: (el) => {
if (el.loadingElement.parentNode === el) {
el.removeChild(el.loadingElement)
}
el.loadingElement = null
}
})
```