vue-tutorial icon indicating copy to clipboard operation
vue-tutorial copied to clipboard

vue自定义指令

Open Wscats opened this issue 9 years ago • 3 comments

全局定义

我们可以用Vue.directive来全局定义一个指令,定义完之后我们就可以在对应html结构前缀v-加上directive名字来激活这个指令

  • bind:只调用一次,在指令第一次绑定到元素上时调用。
  • update: 在 bind 之后立即以初始值为参数第一次调用,之后每当绑定值变化时调用,参数为新值与旧值。
  • unbind:只调用一次,在指令从元素上解绑时调用。
Vue.directive('cclick', {
	//bind就是先帮我们绑定,但不去执行这个test()函数,而updata则是绑定完后执行一次,后面每次更新都去执行一次
	bind: function(value) {
		var self = this;
		//指令的名字,不包含前缀 v-cclick:click="test()"中的cclick
		console.log(this.name)
		//指令的表达式,不包括参数和过滤器 v-cclick:click="test()"中的test()
		console.log(this.expression)
		//指令的参数 v-cclick:click="test()"中的click
		console.log(this.arg)
		this.el.addEventListener(this.arg, function(e) {
			self.expression.substring(0, self.expression.length - 2);
			//把test()转化为test,方便我们后面调用
			//console.log(self.expression.substring(0, self.expression.length - 2));
			//如果v-cclick:click="test",注意test没有加括号的时候我们就可以这样写
			//self.vm[self.expression]()
			self.vm[self.expression.substring(0, self.expression.length - 2)]()
		});
	},
})
var demo = new Vue({
	el: '#demo',
	data: {
		name: 'wsscat'
	},
	methods: {
		test: function() {
			console.log("test test")
		}
	},
})

视图如下

<body id="demo">
	<button v-cclick:click="test()">Ok</button>
</body>

注意这里我们该指令对应的标签受demo构造器控制,我们可以用this.expression获取函数的名字,然后用this.vm来拿到构造器里面的数据进而触发我们想要触发的方法

在这里要注意的是如果把逻辑放在了update里面定义的话test()会首先先自执行一次 当然其实我们直接这样写<button v-cclick:click="test">Ok</button>_test_没有了两个大括号,我们获取这个函数名再去执行就更加方便了,我们就可以直接这样来执行函数了self.vm[self.expression]()

局部定义

我们还可以在构造起里面定义指令,这样就不会担心影响到其他构造器的指令了,只要在加上属性directives就可以对它进行定义了

var demo = new Vue({
	el: '#demo',
	data: {
		msg: 'hello!',
		name: 'wsscat'
	},
	directives: {
		wsscat: {
			bind: function() {
				console.log("wsscat")
			},
			update: function(newValue, oldValue) {
				console.log('new:' + newValue);
				console.log('old:' + oldValue);
				this.el.style.color = 'blue';
				if(newValue == 'red') {
					this.el.style.color = 'red';
				} else if(newValue == 'yellow') {
					this.el.style.color = 'yellow';
				} else {
					this.el.style.color = 'green';
				}
			}
		}
	}
})

视图如下

<input v-model="name" />
<p v-wsscat="name">{{name}}</p>

上面的代码我们把逻辑写在update里面,因为我们这里的name值会一直变化,第一次进来先触发一次update里面的逻辑,后面每一次name的变化都会触发update里面的逻辑,我们这里在输入框对应输入red,yellow都会有颜色的变化,所以这里update符合需求

Wscats avatar Oct 09 '16 16:10 Wscats

获取指令所在的标签其他属性值

添加属性params,并接收一个带属性的数组,我们就可以在里面用this.params获取对应的值

directives: {
	wsscat: {
		params: ['a', 'b'],
		bind: function() {
			console.log("wsscat")
		},
		console.log(this.params)
	}
}

视图

<p v-wsscat="name" a="1" b="arr">{{name}}</p>

Wscats avatar Oct 09 '16 23:10 Wscats

自定义Touch指令

new Vue({
	el: '#demo',
	data: {
		name: 'wsscat'
	},
	methods: {

	},
	//私有的指令
	directives: {
		touch: {
			params: ['a', 'b'],
			bind: function(value) {
				console.log(this.params)

				function direction() {
					if(Math.abs(xStart - xEnd) >= Math.abs(yStart - yEnd)) {
						if(xStart >= xEnd) {
							console.log("left")
						} else {
							console.log("right")
						}
					} else {
						if(yStart >= yEnd) {
							console.log("up")
						} else {
							console.log("down")
						}
					}
				}
				var xStart, xEnd, yStart, yEnd;
				this.el.addEventListener('touchstart', function(e) {
					//console.log("start:")
					//console.log(e)
					xStart = e.targetTouches[0].pageX;
					yStart = e.targetTouches[0].pageY;
				});
				this.el.addEventListener('touchend', function(e) {
					//console.log("end")
					//console.log(e)
					xEnd = e.changedTouches[0].pageX;
					yEnd = e.changedTouches[0].pageY
					direction(xStart, xEnd, yStart, yEnd)
				})
			}
		}
	}
})

视图

<div id="demo">
        <p class="A1" v-touch='name' :a="name" b="abc">{{name}}</p>
</div>

Wscats avatar Oct 11 '16 03:10 Wscats

123

jackwanggui avatar Dec 30 '18 09:12 jackwanggui