vue2.x自定义指令

直接复制粘贴代码即可使用:

点击表格显示输入框,点击其它空白处消失。

<!DOCTYPE html>

<html>

 

<head>

<meta charset="UTF-8" />

<title>Hello React!</title>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>

<style>

table{border-right:1px solid black;border-bottom:1px solid black}

table td{border-left:1px solid black;border-top:1px solid black;}

.skyblue{

background: skyblue;

}

/*

css 注释:

只对table td设置左与上边框;

对table设置右与下边框;

为了便于截图,我们将css 注释说明换行排版

*/

</style>

</head>

 

<body>

钩子函数

指令定义函数提供了几个钩子函数(可选):

 

bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。

 

inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。

 

update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。

 

componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。

 

unbind: 只调用一次, 指令与元素解绑时调用。

 

<div id="app">

<h2>点击表格</h2>

<div style="position: relative">

<table width="400" border="0" cellspacing="0" cellpadding="0" v-clickoutside="handleClose">

<tr>

<td width="105">站名</td>

<td width="100">网址</td>

<td width="100">说明</td>

<td width="100">说明</td>

 

</tr>

<tr ref="tableTr" class="table-d-tr" v-for="(item,k) in tableData" :key="k" :data-k="k">

<td style="color:#9F6CAF;font-weight:bold;padding:8px;line-height: 1.42857143;">

{{item['dataWeek']}}

</td>

<td v-for="j in 3" :data-j="j">

<span style="display: inline-block;width: 100%; height: 46px;line-height: 46px;" :class="{skyblue:item['date'+(j-1)].skyblue}"

@click="openInput(k, j, item, $event)">{{ item['date'+(j-1)].value }}</span>

</td>

</tr>

</table>

<div ref="childPopover" style="position: absolute;background: #fff;border: 1px solid blanchedalmond;text-align:center;box-sizing: border-box; box-shadow: 0px 1px 2px #9E9E9E;" v-show="childPopoverShow">

<input ref="popoverInput" type="text" style="width:60px;" v-model="popoverValue">

<div style=" margin-top: 3px;">

<button @click="applyOk">确定</button>

<button @click="applyCancel">取消</button>

 

</div>

</div>

</div>

 

</div>

<script>

 

Vue.directive('clickoutside', {

bind(el, binding, vnode) {

function documentHandler(e) {

// 这里判断点击的元素是否是本身,是本身,则返回

if (el.contains(e.target)) {

return false;

}

// 判断指令中是否绑定了函数

if (binding.expression) {

// 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法

binding.value(e);

}

}

// 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听

el.__vueClickOutside__ = documentHandler;

document.addEventListener("click", documentHandler);

},

unbind(el, binding) {

// 解除事件监听

document.removeEventListener("click", el.__vueClickOutside__);

delete el.__vueClickOutside__;

}

})

 

var vm = new Vue({

el: '#app',

data: {

childPopoverShow: false,

message: '自定义指令',

color: 'red',

popoverValue: '',

handleDate: [],

handleTempDate: [],

tableData: (function () {

let n = 7;

let arrs = [];

for (let index = 0; index < n; index++) {

let arr = {

dataWeek: getWeek(index + 1),

date0: {

value: "1",

skyblue: false

},

date1: {

value: "2",

skyblue: false

},

date2: {

value: "3",

skyblue: false

}

};

arrs[index] = arr;

}

return arrs;

 

function getWeek(d) {

switch (d) {

case 7:

return "星期日";

break;

case 1:

return "星期一";

break;

case 2:

return "星期二";

break;

case 3:

return "星期三";

break;

case 4:

return "星期四";

break;

case 5:

return "星期五";

break;

case 6:

return "星期六";

break;

}

}

})()

},

methods: {

openInput(k, j, item, event) {

//注意:event.currentTarget

let ele = event.currentTarget;

let w = ele.parentNode.offsetWidth;

let h = ele.parentNode.offsetHeight;

let a = JSON.stringify(this.tableData);

let obj = JSON.parse(a);

let left = ele.parentNode.offsetLeft;

if (this.handleDate.length != 0) {

let oldDateName = this.handleDate[0];

let oldK = this.handleDate[1];

this.handleTempDate = ["date" + (j - 1), k];

this.handleDate.length = 0;

obj[oldK][oldDateName]["skyblue"] = false;

} else {

if (this.handleTempDate.length != 0) {

// console.log(obj)

obj[this.handleTempDate[1]][this.handleTempDate[0]]["skyblue"] = false;

}

this.handleDate = ["date" + (j - 1), k];

}

 

if (this.handleColumn != k) {

obj = this.clearSkyblue(obj, this.handleColumn);

this.$set(this.tableData, this.handleColumn, obj[this.handleColumn]);

}

this.popoverValue = "";

this.handleColumn = k;

obj[k]["date" + (j - 1)]["skyblue"] = true;

 

this.$refs["childPopover"].style.left = left - (100 - w) / 2 + "px";

this.$refs['childPopover'].style.top = h * (k + 1.5) + 'px';

this.$refs["childPopover"].setAttribute("data-x", k);

this.$refs["childPopover"].setAttribute("data-y", j);

this.childPopoverShow = true;

this.$set(this.tableData, k, obj[k]);

setTimeout(() => {

this.$refs["popoverInput"].focus();

}, 100);

 

},

clearSkyblue(data, k) {

// for(let i = 0;i<data.length;i++){

if (!k || k == "") return data;

let element = data[k];

for (let j = 0; j < 3; j++) {

element["date" + j]["skyblue"] = false;

}

data[k] = element;

return data;

// }

},

 

handleClose(e) {

var isChildPopover = this.$refs["childPopover"].contains(e.target);

if (isChildPopover) {

return false;

}

this.applyCancel();

},

applyCancel() {

this.$refs["popoverInput"].blur();

this.childPopoverShow = false;

this.cancelSkyblue();

},

cancelSkyblue() {

for (let j = 0; j < this.tableData.length; j++) {

let element = this.tableData[j];

for (let i = 0; i < 3; i++) {

element["date" + i]["skyblue"] = false;

}

}

},

applyOk() {

let k = this.$refs["childPopover"].getAttribute("data-x");

let j = this.$refs["childPopover"].getAttribute("data-y");

let obj = JSON.parse(JSON.stringify(this.tableData));

// console.log(this.popoverValue)

if (this.popoverValue < 0 || this.popoverValue > 100 || this.popoverValue == "" || !this.popoverValue) {

this.applyCancel();

// this.$alert('商品上架数量在0~100之间', '友情提示', {

// confirmButtonText: '确定',

// type: 'warning'

// });

return false;

}

obj[k]["date" + (j - 1)]["value"] = this.popoverValue;

obj[k].dataWeek = this.getWeek(Number(k) + 1);

this.$set(this.tableData, k, obj[k]);

this.applyCancel();

},

getWeek(d) {

switch (d) {

case 7:

return "星期日";

break;

case 1:

return "星期一";

break;

case 2:

return "星期二";

break;

case 3:

return "星期三";

break;

case 4:

return "星期四";

break;

case 5:

return "星期五";

break;

case 6:

return "星期六";

break;

}

}

}

})

</script>

 

</body>

 

</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值