vue的自定义指令
- font-size的设置
- PC端拖拽
- 移动端拖拽
注意点:bind 和 inserted
共同点: dom插入都会调用,bind在inserted之前
不同点:
bind 时父节点为 null
inserted 时父节点存在。
bind是在dom树绘制前调用,inserted在dom树绘制后调用
bind: function (el) {
console.log('bind',el.parentNode) // null
},
inserted: function (el) {
console.log('inserted',el.parentNode) // <div>...</div>
}
注意:自定义指令的钩子里面没有vue实例,this指向undefined;
自定义指令的作用是用于对DOM元素进行底层操作
钩子函数
-
bind 类似于created 只调用一次,指令第一次绑定到元素时调用,此时被绑定元素在页面上还不存在;
-
inserted 类似于mounted ,被绑定元素插入到dom的时候执行,此时该元素在页面上已经存在了;
-
update 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新;
-
componentUpdated 被绑定元素所在模板完成一次更新周期时调用;
-
unbind 只调用一次,指令与元素解绑时调用;
钩子函数内的参数
-
el: 被绑定的元素,可以用来直接操作 DOM
el.innerHTML
、el.addEventListener
-
binding: 一个对象, 指的是指令本身
v-abc:xxx.a.b.c="abcde"
[arg] 动态指令参数
v-myDirectiveValue:[argument]="value"
注:具体看官网解释
未指明钩子函数时,默认bind和update中
const vm = new Vue({
el: "#app",
data: {
},
//自定义局部指令的时候,如果直接跟一个函数,没有写(bind inserted update)的时候,就相当于把该函数写到了bind和update中
directives:{
fontSize:function(el,binding){
el.style.fontSize = binding.value+'px'
}
}
})
font-size的设置
directives:{
fontSize:function(el,binding){
el.style.fontSize = binding.value+'px'
}
}
使用
<template>
<div>
<div v-fontSize='40'>牛奶</div>
</div>
</template>
<script>
export default {
name: 'homePage',
components:{
test
},
data() {
return {
test:''
}
},
created(){
},
computed:{
},
methods:{
},
mounted() {
console.log(this.$el);
// this.$el.style.backgroundColor = "green"
},
directives:{
fontSize:function(el,binding){
el.style.fontSize = binding.value+'px'
}
}
}
</script>
<style lang="scss" scoped>
</style>
<style scoped>
</style>
PC端拖拽
// 拖拽
Vue.directive('drag', { // 全局弹窗拖拽指令
bind: function (el, binding, vnode) {
console.log("parent",el.parentNode) // null
let oDiv = el;
let self = vnode.context;
oDiv.onmousedown = (e) => {
let disX = e.clientX - oDiv.offsetLeft;
let disY = e.clientY - oDiv.offsetTop;
document.onmousemove = (e) => {
let left = e.clientX - disX;
let top = e.clientY - disY;
if (!left && !top) {
oDiv.style.left = self.currentLeft;
oDiv.style.top = self.currentTop;
} else {
oDiv.style.left = left + "px";
oDiv.style.top = top + "px";
}
};
document.onmouseup = (e) => {
document.onmousemove = null;
document.onmouseup = null;
};
};
},
// inserted : function (el, binding, vnode) {
// console.log("parent",el.parentNode)
// let oDiv = el;
// let self = vnode.context;
// oDiv.onmousedown = (e) => {
// let disX = e.clientX - oDiv.offsetLeft;
// let disY = e.clientY - oDiv.offsetTop;
// console.log("1123",disX,disY);
// document.onmousemove = (e) => {
// let left = e.clientX - disX;
// let top = e.clientY - disY;
// if (!left && !top) {
// oDiv.style.left = self.currentLeft;
// oDiv.style.top = self.currentTop;
// } else {
// oDiv.style.left = left + "px";
// oDiv.style.top = top + "px";
// }
// };
// document.onmouseup = (e) => {
// document.onmousemove = null;
// document.onmouseup = null;
// };
// };
// },
})
移动端拖拽
全局指令写法如下
Vue.directive('drag', {
inserted(el) {
let switchPosition = {
x: 10,
y: 10,
startX: 0,
startY: 0,
endX: 0,
endY: 0
}
el.addEventListener('touchstart', function (e) {
console.log(e)
switchPosition .startX = e.touches[0].pageX
switchPosition .startY = e.touches[0].pageY
})
el.addEventListener('touchend', function (e) {
switchPosition .x = switchPosition .endX
switchPosition .y = switchPosition .endY
switchPosition .startX = 0
switchPosition .startY = 0
})
el.addEventListener('touchmove', function (e) {
if (e.touches.length > 0) {
let offsetX = e.touches[0].pageX - switchPosition .startX
let offsetY = e.touches[0].pageY - switchPosition .startY
let x = switchPosition .x - offsetX
let y = switchPosition .y - offsetY
if (x + el.offsetWidth > document.documentElement.offsetWidth) {
x = document.documentElement.offsetWidth - el.offsetWidth
}
if (y + el.offsetHeight > document.documentElement.offsetHeight) {
y = document.documentElement.offsetHeight - el.offsetHeight
}
if (x < 0) {
x = 0
}
if (y < 0) {
y = 0
}
el.style.right = x + 'px'
el.style.bottom = y + 'px'
switchPosition .endX = x
switchPosition .endY = y
e.preventDefault()
}
})
}
})
使用
<template>
<div>
<h1 v-drag class="drag"></h1>
</div>
</template>
<script>
export default {
name: 'homePage',
components:{
},
data() {
return {
}
},
created(){
},
computed:{
},
methods:{
},
mounted() {
console.log(this.$el);
// this.$el.style.backgroundColor = "green"
},
}
</script>
<style lang="scss" scoped>
</style>
<style scoped>
.drag{
width: 200px;
height: 200px;
background: #ccc;
text-align: center;
line-height: 200px;
color: #fff;
cursor:move;
position: fixed;
z-index: 99;
right: 10px;
bottom: 85px;
width: 40px;
height: 40px;
}
</style>