项目需求:选择广告的投放时段
最终实现效果:
主要总结实现点击拖拽选择区域的效果(封装成一个vue组件),具体数据请求与渲染依具体情况而定。
主要思路:要实现鼠标拖拽选择区域的效果,主要是表格中td元素的mousedown,mouseover,mouseup事件的处理。
- 在mousedown事件中记录起始点,高亮当前选中元素
- 在mouseover事件中渲染选中区域
- mouseup事件,数据的重置处理。
需要注意的点:
- 在vue中,当给元素绑定三个事件后,mouseove事件会在鼠标经过元素时立即触发,所以需要设置一个标志位,在mousedown事件触发后,mouseover事件才会被触发。
- 拖拽过程中存在反复拖拽的问题,应该以最后一次的位置为准,之前即时渲染的区域应该及时清除,所以应该记录下拖拽的最大值,在渲染区域之前,清除无用区域。
- 拖拽到表格区域外的处理,如果拖拽带表格区域外,标志位不能及时重置,元素的mouseover事件会一直被触发,所以监听整个dom元素的mouseleave事件,及时重置标志位。
功能相关代码:
1 Vue.component("drag-component",{ 2 props:['data'], 3 template: '<table class="time_table table" v-on:mouseleave="mouseleave">'+ 4 '<thead><tr><th rowspan="2">日期/时间</th></tr><tr><th class="unselectable" v-for="num in numData">{{num}}</th>'+ 5 '</tr></thead><tbody> <tr v-for="(options,index) in timeData" >'+ 6 '<th scope="row">{{options.date}}</th>'+ 7 '<td v-for="(timeItem,key) in options.time":class="[{ \'active_select\': timeItem.isSelected}]" v-on:mousedown="mousedown(index,key)" v-on:mouseover="mouseover(index,key)" v-on:mouseup="mouseup"></td></tr></tbody></table>', 8 data: function(){ 9 return { 10 numData:[0,1,2,3,4,5,6,7,8,9,10], 11 timeData:this.data, 12 selectFlag:false, //当参数为true时,mouseover事件生效 13 max:{ 14 x:0, 15 y:0 16 } 17 } 18 }, 19 methods:{ 20 mousedown:function(index,key){ 21 this.selectStart=[]; 22 this.selectFlag=true; 23 if(this.timeData[index].time[key].value==false){ 24 if(this.timeData[index].time[key].isSelected){ 25 this.timeData[index].time[key].isSelected=false; 26 }else { 27 this.$set(this.timeData[index].time[key],"isSelected",true); 28 } 29 } 30 this.selectStart.push({ 31 index:index, 32 key:key 33 }); 34 }, 35 mouseover:function(index,key){ 36 // x 垂直方向 y 水平方向 37 if(this.selectFlag){ 38 if(index>=this.max.x){ 39 this.max.x=index; 40 } 41 if(key>=this.max.y){ 42 this.max.y=key; 43 } 44 var start={ 45 x:this.selectStart[0].index, 46 y:this.selectStart[0].key 47 }; 48 var end={ 49 x:index, 50 y:key 51 }; 52 for(var i=end.x;i<=this.max.x;i++){ 53 for(var j=end.y;j<=this.max.y;j++){ 54 this.$set(this.timeData[i].time[j], "isSelected", false); 55 } 56 } 57 /* 渲染选中的区域 */ 58 for(var i=start.x;i<=end.x;i++){ 59 for(var j=start.y;j<=end.y;j++){ 60 this.$set(this.timeData[i].time[j], "isSelected", true); 61 } 62 } 63 64 } 65 }, 66 mouseup:function () { 67 this.selectFlag=false; 68 this.max={ 69 x:0, 70 y:0 71 } 72 }, 73 mouseleave:function () { 74 this.selectFlag=false; 75 } 76 } 77 });
调用部分:
css部分(以需求为准,简单写了下样式):
.time_table { border:1px solid #ccc; border-collapse:collapse; } .time_table th,.time_table td { border: 1px solid #ccc; width: 30px; height: 40px; } .active_select { background: cornflowerblue; }