Vue在自定义指令绑定的处理函数中传递参数
目录
- 在自定义指令绑定的处理函数中传递参数
- 需求背景
- 方式一:包装函数
- 方式二:利用动态参数
- 在自定义指令中的传递参数时value和expression的区别
- 注意点
- 总结
在自定义指令绑定的处理函数中传递参数
需求背景
现在需要为自定义指令绑定函数,并且需要向函数中传递参数,类似 v-on="handleFunc(arg1, arg2)"。
Vue 的指令预期得到的值是一个 JavaScript 表达式,除了 v-on 和 v-for 这两个特殊指令外,其他的指令会自动计算该表达式的值,将最终的计算结果传递给指令。
所以自定义的指令不能用 v-mydirective="handleFunc(arg1, arg2)" 的形式绑定函数值,因为 handleFunc(arg1, arg2) 作为一个 JavaScript 表达式会被立即执行,最终会将其返回值传递给指令。
那么当我们想要为自定义指令绑定函数值,又想为其传递参数该怎么办呢?
方式一:包装函数
利用指令的值预期得到一个 JavaScript 表达式的特性,可以为其值绑定一个包装后的函数,从而实现传递参数的目的。如下
<div v-mydirective="() => {handleFunc(arg1, arg2)}"><div>
在上面的示例中,v- mydirective 指令的值是一个字面量的箭头函数,该函数并不会立即执行,因为表达式中只是函数的声明,并没有调用。利用这种形式,就可以为自定义指令绑定函数值,并可以向函数中传递参数。
方式二:利用动态参数
Vue 从 2.6.0 开始,可以用方括号括起来的 JavaScript 表达式作为一个指令的参数,如下
<a v-bind:[attributeName]="url"> ... </a> <a v-on:[eventName]="doSomething"> ... </a>
利用动态参数,也可以向指令中传递其绑定的函数所需要的参数,如下
# template <div v-mydirective:[funcArg]="handleFunc"><div> # script export default { directives: { mydirective: { bind(el, binding, vnode) { let {expression, arg} = binding; if (expression && vnode.context[expression]) { vnode.context[expression](arg); } else { binding.value(arg) } }, } }, data() { return { funcArg: { a: 1, b: 2, c: 3 }, } }, methods: { handleFunc({a, b , c}) { console.log(a, b, c); }, } }
需要注意的是,利用动态参数时,handleFunc 只能接收一个参数,因为指令的参数只能传一个。
如果需要接收多个参数,可以像上例一样,传个对象进去,然后在处理函数中采用解构语法接收参数。
在自定义指令中的传递参数时value和expression的区别
在使用Vue的自定义指令的时候,有时候会在调用binding的value的值的时候会发现值显示未定义,但是我们确实传递了参数,在查看打印出来的参数的时候会发现参数出现在了expression对应的值中,而不是value,所以这时候这两个参数的区别就很有必要探究一下
首先做一个简单的案例来测试一下,在我们传递一个参数的时候,这两个参数的具体作用和现实的内容:
代码实现:
<template> <div> <p v-color="color">你好世界</p> </div> </template> <script> export default { name: "Demo_d", directives:{ color:{ bind(el,binding){ console.log(el) console.log(binding) } } }, data(){ return { color:'red' } } } </script> <style scoped> </style>
在上面的案例中,我们定义了一个自定义指令,指令的名字叫做color,并传递了一个参数,参数是Vue组件中的data节点中的变量,我们打印了两个形参,一个是挂载的对象,一个是用来接收参数的binding,下面我们来看看value和expression中对应的值是什么
显示效果:
可以看到在expression中的值是color,而在value中存储的值是red,那么我们就可以知道,expression中存储的是我们传递给指令的参数的原本的内容,是一个表达式,而value中的值才是我们真正需要的,这是在传递了一个变量的情况,那如果我们直接传递一个固定的值作为参数的时候是什么样的结果呢?
代码实现:
<template> <div> <p v-color="red">你好世界</p> </div> </template> <script> export default { name: "Demo_d", directives:{ color:{ bind(el,binding){ console.log(el) console.log(binding) } } }, data(){ return { color:'red' } } } </script> <style scoped> </style>
显示效果:
可以看到,在我们传递了一个data节点中不存在的值的时候,首先会报错,这个洋文报错的大致意思是作为参数传递的这个变量没有定义就被使用了,而且在组件中没有这个变量的其它形式的定义。
意思就是我们明明传递了一个值,但是Vue仍然将其作为一个表达式的形式来解析了,而且可以看到expression中的值是我们传递进去的参数的名字,而value中却没有参数,就导致了我们明明传递了参数而value中没有任何参数的问题,那么如果我们想要传递一个字面值,而不是作为表达式的形式被解析的时候需要怎么做呢?
很简单,当我们想要传递一个字面值,而希望Vue不要以表达式的形式去解析的时候,用单引号将值包裹起来就可以作为一个字符串的字面值的形式进行解析了。
代码实现:
<template> <div> <p v-color="'red'">你好世界</p> </div> </template> <script> export default { name: "Demo_d", directives:{ color:{ bind(el,binding){ console.log(el) console.log(binding) } } }, data(){ return { color:'red' } } } </script> <style scoped> </style>
显示效果:
可以看到,在我们将传递的值用单引号进行包含之后,报错消失了,并且expression中的值是我们传递进去的带有单引号的参数,在value中的参数是我们真正需要的字面值
注意点
在传递参数的时候,如果不加单引号,Vue会将其以表达式的方式进行解析,会进行运算或在data节点中寻找变量的值,如果没有对应的变量值就会报错,且value中没有对应的数据。
如果想要将参数作为普通的字符串进行解析的时候,就需要将参数使用单引号进行包裹,就可以作为一个普通的字符串字面值进行解析
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。