08.vue-charp-08 自定义指令

vue

目录

  • 基本用法

    • 基本使用
    • 钩子函数参数
    • 自定义指令-传入对象

  • 开发一个可从外部关闭的下拉菜单
  • index.html

    • index.js
    • clickoutside.js
    • style.css

  • 开发一个实时时间转换指令v-time

    • index.html
    • index.js
    • time.js

自定义指令的选项是由几个钩子函数组成的,每个都是可选的。

  • bind:

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

  • inserted:

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

  • update:

    被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。

  • componentUpdated:

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

  • unbind:

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

基本使用

<body>

<div >

<input type="text" v-focus>

</div>

<script src="../lib/vue.2.6.11.js"></script>

<script>

//全局注册指令

Vue.directive('focus', {

inserted: function (el, binding, vnode, oldVnode) {

console.log("focus->el:", el);

console.log("focus->binding:", binding);

console.log("focus->vnode:", vnode);

console.log("focus->oldVnode:", oldVnode);

// 聚焦元素

el.focus();

}

})

var app = new Vue({

el: '#app'

})

</script>

</body>

钩子函数参数

每个钩子函数都有几个参数可用,比如上面我们用到了el。它们的含义如下:el 指令所绑定的元素,可以用来直接操作DOM。

  • binding 一个对象,包含以下属性:

    • name 指令名,不包括v-前缀。
    • value 指令的绑定值,例如v-my-directive="1 + 1",value的值是2。
    • oldValue 指令绑定的前一个值,仅在update和componentUpdated钩子中可用。无论值是否改变都可用。
    • expression 绑定值的字符串形式。例如v-my-directive="1 + 1",expression的值是"1 + 1"。
    • arg 传给指令的参数。例如v-my-directive:foo,arg的值是foo。
    • modifiers 一个包含修饰符的对象。例如v-my-directive.foo.bar,修饰符对象modifiers的值是{ foo: true, bar: true }。

  • vnode Vue编译生成的虚拟节点,在进阶篇中介绍。
  • oldVnode 上一个虚拟节点仅在update和componentUpdated 钩子中可用。

<body>

<div >

<div v-test:msg.a.b="message"></div>

</div>

<script src="../lib/vue.2.6.11.js"></script>

<script>

Vue.directive('test', {

bind: function (el, binding, vnode) {

var keys = [];

for (var i in vnode) {

keys.push(i);

}

el.innerHTML =

'name: ' + binding.name + '<br>' +

'value: ' + binding.value + '<br>' +

'expression: ' + binding.expression + '<br>' +

'argument: ' + binding.arg + '<br>' +

'modifiers: ' + JSON.stringify(binding.modifiers) + '<br>' +

'vnode keys: ' + keys.join(', ')

}

});

var app = new Vue({

el: '#app',

data: {

message: 'some text'

}

})

</script>

</body>

自定义指令-传入对象

<body>

<div >

<div v-test="{msg: 'hello', name: 'Aresn'}"></div>

</div>

<script src="../lib/vue.2.6.11.js"></script>

<script>

Vue.directive('test', {

bind: function (el, binding, vnode) {

console.log(binding.value.msg);

console.log(binding.value.name);

el.innerHTML =

'binding.value.msg: ' + binding.value.msg + '<br>' +

'binding.value.name: ' + binding.value.name + '<br>';

}

});

var app = new Vue({

el: '#app'

})

</script>

</body>

开发一个可从外部关闭的下拉菜单

点击用户头像和名称,会弹出一个下拉菜单,然后点击页面中其他空白区域(除了菜单本身外),菜单就关闭了。

index.html

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>Vue 示例:从外部关闭的下拉菜单</title>

<link rel="stylesheet" type="text/css" href="style.css">

</head>

<body>

<div v-cloak>

<div class="main" v-clickoutside="handleClose">

<button @click="show = !show">点击显示下拉菜单</button>

<div class="dropdown" v-show="show">

<p>下拉框的内容,点击外面区域可以关闭</p>

</div>

</div>

</div>

<script src="../../lib/vue.2.6.11.js"></script>

<script src="clickoutside.js"></script>

<script src="index.js"></script>

</body>

</html>

index.js

var app = new Vue({

el: '#app',

data: {

show: false

},

methods: {

handleClose: function () {

this.show = false;

}

}

});

clickoutside.js

Vue.directive("clickoutside", {

bind: function (el, binding, vnode) {

function documentHandler(e) {

if (el.contains(e.target)) { //第一个是判断点击的区域是否是指令所在的元素内部,

return false;

}

if (binding.expression) { //在该自定义指令中,表达式应该是一个函数

binding.value(e); //binding.value()就是用来执行当前上下文 methods中指定的函数的

}

}

//与Vue 1.x不同的是,在自定义指令中,不能再用this.xxx的形式在上下文中声明一个变量,

//所以用了el.__vueClickOutside__引用了documentHandler,

//这样就可以在unbind钩子里移除对document的click事件监听。如果不移除,当组件或元素销毁时,它仍然存在于内存中

el.__vueClickOutside__ = documentHandler;

document.addEventListener('click', documentHandler);

},

unbind: function (el, binding) {

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

delete el.__vueClickOutside__;

}

});

style.css

[v-cloak] {

display: none;

}

.main{

width: 125px;

}

button{

display: block;

width: 100%;

color: #fff;

background-color: #39f;

border: 0;

padding: 6px;

text-align: center;

font-size: 12px;

border-radius: 4px;

cursor: pointer;

outline: none;

position: relative;

}

button:active{

top: 1px;

left: 1px;

}

.dropdown{

width: 100%;

height: 150px;

margin: 5px 0;

font-size: 12px;

background-color: #fff;

border-radius: 4px;

box-shadow: 0 1px 6px rgba(0,0,0,.2);

}

.dropdown p{

display: inline-block;

padding: 6px;

}

开发一个实时时间转换指令v-time

本示例就来实现这样一个自定义指令v-time,将表达式传入的时间戳实时转换为相对时间,

示例所用的时间戳都是毫秒级的,时间转换的逻辑:

  • 1分钟以前,显示“刚刚”。
  • 1分钟~1小时之间,显示“xx分钟前”。
  • 1小时~1天之间,显示“xx小时前”。
  • 1天~1个月(31天)之间,显示“xx天前”。
  • 大于1个月,显示“xx年xx月xx日”。

index.html

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>Vue 示例:实时时间转换器</title>

<link rel="stylesheet" type="text/css" href="style.css">

</head>

<body>

<div v-cloak>

<div v-time="timeNow"></div>

<div v-time="timeBefore"></div>

</div>

<script src="../../lib/vue.2.6.11.js"></script>

<script src="time.js"></script>

<script src="index.js"></script>

</body>

</html>

index.js

var app = new Vue({

el: '#app',

data: {

timeNow: (new Date()).getTime(),

timeBefore: 1488930695721

}

});

time.js

var Time = {

// 获取当前时间戳

getUnix: function () {

var date = new Date();

return date.getTime();

},

// 获取今天0点0分0秒的时间戳

getTodayUnix: function () {

var date = new Date();

date.setHours(0);

date.setMinutes(0);

date.setSeconds(0);

date.setMilliseconds(0);

return date.getTime();

},

// 获取今年1月1日0点0分0秒的时间戳

getYearUnix: function () {

var date = new Date();

date.setMonth(0);

date.setDate(1);

date.setHours(0);

date.setMinutes(0);

date.setSeconds(0);

date.setMilliseconds(0);

return date.getTime();

},

// 获取标准年月日

getLastDate: function (time) {

var date = new Date(time);

var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;

var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();

return date.getFullYear() + '-' + month + "-" + day;

},

// 转换时间

getFormatTime: function (timestamp) {

var now = this.getUnix(); //当前时间戳

var today = this.getTodayUnix(); //今天0点时间戳

var year = this.getYearUnix(); //今年0点时间戳

var timer = (now - timestamp) / 1000; //转换为秒级时间戳

var tip = '';

if (timer <= 0) {

tip = '刚刚';

} else if (Math.floor(timer / 60) <= 0) {

tip = '刚刚';

} else if (timer < 3600) {

tip = Math.floor(timer / 60) + '分钟前';

} else if (timer >= 3600 && (timestamp - today >= 0)) {

tip = Math.floor(timer / 3600) + '小时前';

} else if (timer / 86400 <= 31) {

tip = Math.ceil(timer / 86400) + '天前';

} else {

tip = this.getLastDate(timestamp);

}

return tip;

}

};

Vue.directive('time', {

bind: function (el, binding) {

el.innerHTML = Time.getFormatTime(binding.value);

el.__timeout__ = setInterval(function () {

el.innerHTML = Time.getFormatTime(binding.value);

}, 60000);

},

unbind: function (el) {

clearInterval(el.__timeout__);

delete el.__timeout__;

}

});

以上是 08.vue-charp-08 自定义指令 的全部内容, 来源链接: utcz.com/z/378931.html

回到顶部