vue 自定义指令

自定义指令

自定义focus

const focus = {
	inserted: function(el){
		el.focus();
	}
}

export default focus;

<input type="text" v-focus />

自定义test

import Vue from 'vue'
import App from './App.vue'
import focus from './directive/focus/index.js'

Vue.config.productionTip = false

Vue.directive('focus',focus);

Vue.directive('test',{
	// bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作.
	// inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中) .
	// update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。
	//		通过比较更新前后update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。
	//		通过比较更新前后的绑定值,可以忽略不必要的模板更新。
	// componentUpdated: 被绑定元素所在模板完成一次更新周期时调用.
	// unbind: 只调用一次,指令与元素解绑时调用 。
	bind:function(el, binding, vnode){
		debugger
		// el 指令所绑定的元素,可以用来直接操作 DOM.
		el
		var keys = []
		for(var i in vnode){
			keys.push(i)
		}
		// 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 钩子中可用
		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(', ')
	}
});
		
new Vue({
  render: h => h(App),
}).$mount('#app')

v-test 使用

<template>
	<div id="parent">
		<div v-test:msg.a.b="message"></div>
	</div>
</template>
<script>
	export default{
		name: 'directive',
		data(){
			return{
				message: 'some text'
			}
		}
		
	}
</script>

点击外部关闭的下拉菜单

<template>
	<div>
		<div class="main" v-clickoutside="handleClose">
			<button @click="show =! show">下拉</button>
			<div class="dropdown" v-show="show">
				<p>点击外部关闭的下拉菜单</p>
			</div>
		</div>
	</div>
</template>

<script>
	export default{
		data(){
			return{
				show:false
			}
		},
		methods:{
			handleClose(){
				this.show = false
			}
		}
	}
</script>

<style>
	.main{
		 120px;
	}
	button{
		display: block;
		 100%;
		color: #fff;
		background-color: #39f;
		border: 0;
		padding: 6px;
		text-align: center;
		border-radius: 4px;
		cursor: pointer;
		outline: none;
		position: relative;
	}
	button:active{
		top: 1px;
		left: 1px;
	}
	.dropdown{
		 100%;
		height: 150px;
		margin: 5px 0;
		background-color: #fff;
		border-radius: 4px;
		box-shadow: 0 1px 6px rgba(0,0,0,.2);
	}
	
</style>
Vue.directive('clickoutside',{
	bind:function(el, binding, vnode){
		function documentHandler(e){
			if(el.contains(e.target)){
				return false;
			}
			if(binding.expression){
				// 执行表达式
				binding.value(e)
			}
		}
		//在自定义指令中,不能再用 this.xxx 的形式在上下文中声明一个变量,
		//所以用了 el.__vueClickOutside__ 引用了 docurnentHandler
		el.__vueClickOutside__ = documentHandler;
		document.addEventListener('click',documentHandler)
	},
	unbind:function(el,binding){
		document.removeEventListener('click',el.__vueClickOutside__)
		//如果不移除, 当组件或元素销毁时,它仍然存在于内存中
		delete el.__vueClickOutside__;
	}
})

实时时间转换指令

var Time = {
	//获取当前时间戳
	getUnix() {
		var date = new Date();
		return date.getTime();
	},
	//获取今天 0 点 0分 0秒的时间戳
	getTodayUnix() {
		var date = new Date();
		date.setHours(0);
		date.setMinutes(0);
		date.setSeconds(0);
		date.setMilliseconds(0)
		return date.getTime();
	},
	//获取今年 1月 1 日 0点 0分 0秒的时间戳
	getUYearUnix() {
		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(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(timestamp) {
		var now = this.getUnix()
		var today = this.getTodayUnix()
		var year = this.getUYearUnix();
		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;
	}
}
export default Time

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__;
	}
})

<div v-time="timeNow"></div>
		<div v-time="timeBefore"></div>
<div v-time="timeBefore2"></div>
data(){
	  return{
		 timeNow:(new Date()).getTime(),
		 timeBefore: 1606800579180,
		 timeBefore2: 1488930695721
	  }
  }
原文地址:https://www.cnblogs.com/fly-book/p/14068233.html