本案例基于vue自定义指令和原生js的写法实现的。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue拖拽</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style type="text/css">
body{
margin: 0;
padding: 0;
}
.squal{
width: 200px;
height: 200px;
background: red;
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div id="out">
<div class="squal" v-move>1</div>
<div class="squal" v-move>2</div>
<div class="squal" v-move>3</div>
<div class="squal" v-move>4</div>
</div>
</body>
<script type="text/javascript">
Vue.directive("move",{
inserted:function(a){
//鼠标按下事件
a.onmousedown = function(e){
var disX=e.clientX-a.offsetLeft;
var disY=e.clientY-a.offsetTop;
if(a.setCapture){
a.setCapture();
}
//鼠标移动事件-----给文档流绑定移动事件
document.onmousemove=function(e){
var L=e.clientX-disX;
var T=e.clientY-disY;
/* if(L<0){
L=0;
}else if(L>document.documentElement.clientWidth-oBox.offsetWidth){
L=document.documentElement.clientWidth-oBox.offsetWidth
}
if(T<0){
T=0;
}else if(T>document.documentElement.clientHeight-oBox.offsetHeight){
T=document.documentElement.clientHeight-oBox.offsetHeight
}
*/
L=Math.min(Math.max(L,0),document.documentElement.clientWidth-a.offsetWidth)
T=Math.min(Math.max(T,0),document.documentElement.clientHeight-a.offsetHeight)
a.style.left=L+"px";
a.style.top=T+"px";
}
//鼠标离开事件
document.onmouseup=function(){
document.onmousemove=document.onmousedown=null;
if(a.releaseCapture){
a.releaseCapture();//拖动后在解除事件锁定
}
}
}
}
})
var vm = new Vue({
el:"#out"
})
</script>
</html>
关键代码
<script type="text/javascript">
Vue.directive("move",function(a,b){
a.onmousedown=function(e){
var disx = e.clientX - a.offsetLeft;
var disy = e.clientY - a.offsetTop;
document.onmousemove=function(e){
var L = e.clientX - disx;
var T = e.clientY - disy;
a.style.left = L+"px";
a.style.top = T+"px"
}
document.onmouseup = function(){
document.onmousemove = document.onmousedown = null;
}
}
})
var vm = new Vue({
el:"#out"
})
</script>
自定义指令总结:
- 写法
- 全局写法 Vue.directive(名字',{inserted:function(el){ /*这个元素插入父元素的时候执行的操作*/ el.focus(); } })
- 私有属性写法 directives:{'focus':{ inserted:function(el){ /*这个元素插入父元素的时候执行*/ el.focus(); }}}
其中,function中可以写两个参数,第一个参数指向给定自定义指令的元素,比如上例中的参数a就是指向class为squal的div;
第二个参数是绑定的自定义属性后面传的参数,形式不同,传参也不同,可以参见下面一张图。
- 自定义指令里面的钩子函数
- bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
- inserted: 被绑定元素插入父节点时调用。(bind与该生命周期钩子函数作用十分类似)
- update: 被绑定元素所在模板更新时调用,不论绑定值是否变化。通过比较更新前后的绑定值,可忽略不必要的模板更新。
- componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
- 简写形式
- Vue.directive('bgcolor',function(el,binding){el.style.background=binding.value; })
- directives:{ /*简写 表示bind 和update的时候都会执行*/'color':function(el,binding){el.style.color=binding.value;}}
关于自定义写法的代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>自定义指令</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="out">
<p v-color="tit">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quasi iure necessitatibus autem officia voluptatem. Molestias nobis fuga quibusdam sint deserunt iure atque id quidem dignissimos accusamus temporibus praesentium voluptatem modi.</p>
<p v-color>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis facere temporibus dignissimos rerum atque suscipit commodi. Harum nostrum incidunt atque doloremque odit eos reprehenderit nisi vel deleniti ab autem quos.</p>
<p v-col>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere asperiores nesciunt ea quae laudantium adipisci illum sunt doloremque vel sapiente a nostrum cupiditate officia ullam similique illo reiciendis ut natus.</p>
<p v-col="blue">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut repudiandae accusamus nobis quis alias. Modi est consequuntur repellat illo rerum a culpa enim dignissimos odio libero nam error. Rem quibusdam.</p>
<p v-bgcolor>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugiat nemo quos consequuntur quod ea inventore mollitia cupiditate assumenda pariatur dolor qui blanditiis ab necessitatibus quae illo deserunt officiis harum atque?</p>
<p v-rgb>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium hic itaque sapiente molestias temporibus obcaecati deleniti eligendi vero laboriosam eius natus illum veniam earum! Repudiandae maiores voluptates dolore libero nostrum.</p>
</div>
</body>
<script type="text/javascript">
//自定义指令写法一
Vue.directive("color",{
inserted:function(a,b){
// console.log(a,b.value)
a.style.color = "yellow"
a.style.color = b.value
}
});
//简写形式一
Vue.directive("bgcolor",function(a){
a.style.background="yellow";
a.style.opacity = 0.1
})
var app = new Vue({
el:"#out",
data:{
tit:"red",
blue:"blue"
},
//自定义指令写法二
directives:{
"col":{
inserted(a,b){
// console.log(a)
a.style.color = "pink"
a.style.background=b.value
}
},
简写形式二
'rgb':function(a){
a.style.background="pink"
}
}
})
</script>
</html>
关于自定义指令中钩子函数的写法见下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="out">
<p v-color.aaa>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae nam eos ad esse adipisci sequi sit quis sapiente labore nihil. Accusamus aut deleniti doloribus incidunt ex reiciendis id similique dolore.</p>
<p v-bac="str">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Id sit reiciendis illum quisquam voluptates autem nostrum aspernatur! Maiores voluptatibus ipsum modi harum illo amet ab tempora architecto blanditiis corporis dolores!</p>
<h3>{{str}}</h3>
<p v-col="str">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur asperiores dicta excepturi magni quisquam aliquam magnam eaque voluptate soluta eveniet facilis ipsum quidem iusto accusamus impedit libero numquam minus quasi!</p>
<button @click="tap()">变更功能</button>
</div>
</body>
<script type="text/javascript">
Vue.directive('color',{
inserted:function(a,b){
a.style.color='blue'
// console.log(b)
}
})
Vue.directive('col',function(a,b){
a.style.color=b.value
})
var vm=new Vue({
el:'#out',
data:{
str:'red'
},
directives:{
'bac':{
inserted:function(a,b){
// a.style.background='yellow'
// console.log(b)
a.style.background=b.value
},
update:function(a,b){
a.style.background=b.value
console.log(b)
}
}
},
methods:{
tap(){
this.str='green'
}
}
})
</script>
</html>