环境:
vue@2.6.6
问题:
- 绑定函数传参
- 传参多个多样
- 参数动态变化
方案:
1. 采用传对象方式(binding.value)
<el-button v-mydirective="{ fn: myFn, args: x }" type="text" size="small">测试</el-button>
const mydirective = {
inserted: function (el, binding) {
const args = binding.value.args;
const fn = binding.value.fn;
el.onclick = fn(args);
}
}
export default mydirective
以上解决了问题1. 绑定函数传参
,对于问题2. 传参多个多样
可以给args一个对象,或者用数组
<el-button v-mydirective="{ fn: myFn, args: {x, y} }" type="text" size="small">测试</el-button>
<script>
export default {
data() {
return {
x: 1,
y: 2,
}
},
methods: {
myFn({x, y}) {
console.log(x);
console.log(y);
}
}
}
</script>
const mydirective = {
inserted: function (el, binding) {
const args = binding.value.args;
const fn = binding.value.fn;
el.onclick = fn(args);
}
}
export default mydirective;
<el-button v-mydirective="{ fn: myFn, args: [x, y] }" type="text" size="small">测试</el-button>
<script>
export default {
data() {
return {
x: 1,
y: 2,
}
},
methods: {
myFn(x, y) {
console.log(x);
console.log(y);
}
}
}
</script>
const mydirective = {
inserted: function (el, binding) {
const args = binding.value.args;
const fn = binding.value.fn;
el.onclick = fn(...args);
}
}
export default mydirective;
对于问题3. 参数动态变化
,需要增加钩子函数update
或者componentUpdated
<el-button v-mydirective="{ fn: myFn, args: [x, y] }" type="text" size="small">测试</el-button>
<script>
export default {
data() {
return {
x: 1,
y: 2,
}
},
methods: {
myFn(x, y) {
console.log(x);
console.log(y);
}
}
}
</script>
const mydirective = {
inserted: function (el, binding) {
const args = binding.value.args;
const fn = binding.value.fn;
el.onclick = fn(...args);
},
update: function (el, binding) {
const args = binding.value.args;
const fn = binding.value.fn;
el.onclick = fn(...args);
},
}
export default mydirective;
update
时候重置绑定的onclick
函数,不能使用addEventListener
、removeEventListener
,因为移除不成功会导致执行两次。
2. 指令的参数(binding.arg)
<el-button v-mydirective:[x]="myFn" type="text" size="small">测试</el-button>
const mydirective = {
inserted: function (el, binding) {
const args = binding.arg;
const fn = binding.value;
el.onclick = fn(args);
}
}
export default mydirective
以上解决了问题1. 绑定函数传参
,对于问题2. 传参多个多样
可以给指令参数一个对象,或者用数组
<el-button v-mydirective:[{x,y}]="myFn" type="text" size="small">测试</el-button>
<script>
export default {
data() {
return {
x: 1,
y: 2,
}
},
methods: {
myFn({x, y}) {
console.log(x);
console.log(y);
}
}
}
</script>
const mydirective = {
inserted: function (el, binding) {
const args = binding.arg;
const fn = binding.value;
el.onclick = fn(args);
}
}
export default mydirective;
<el-button v-mydirective:[[x,y]]="myFn" type="text" size="small">测试</el-button>
<script>
export default {
data() {
return {
x: 1,
y: 2,
}
},
methods: {
myFn(x, y) {
console.log(x);
console.log(y);
}
}
}
</script>
const mydirective = {
inserted: function (el, binding) {
const args = binding.arg;
const fn = binding.value;
el.onclick = fn(...args);
}
}
export default mydirective;
对于问题3. 参数动态变化
,需要增加钩子函数update
或者componentUpdated
<el-button v-mydirective:[[x,y]]="myFn" type="text" size="small">测试</el-button>
<script>
export default {
data() {
return {
x: 1,
y: 2,
}
},
methods: {
myFn(x, y) {
console.log(x);
console.log(y);
}
}
}
</script>
const mydirective = {
inserted: function (el, binding) {
const args = binding.arg;
const fn = binding.value;
el.onclick = fn(...args);
},
update: function (el, binding) {
const args = binding.arg;
const fn = binding.value;
el.onclick = fn(...args);
},
}
export default mydirective;
update
时候重置绑定的onclick
函数,不能使用addEventListener
、removeEventListener
,因为移除不成功会导致执行两次。与第一种类似
注意:
- 指令参数中不能有空格
- 指令参数中不能有字符串(需要在data中定义成变量才可以使用)
3. 采用传箭头函数(binding.value)
<el-button v-mydirective="() => myFn(x)" type="text" size="small">测试</el-button>
const mydirective = {
inserted: function (el, binding) {
const fn = binding.value;
el.onclick = fn;
}
}
export default mydirective
以上解决了问题1. 绑定函数传参
和问题3. 参数动态变化
,对于问题2. 传参多个多样
可以很随意了
<el-button v-mydirective="() => myFn({x,y})" type="text" size="small">测试</el-button>
<script>
export default {
data() {
return {
x: 1,
y: 2,
}
},
methods: {
myFn({x, y}) {
console.log(x);
console.log(y);
}
}
}
</script>
const mydirective = {
inserted: function (el, binding) {
const fn = binding.value;
el.onclick = fn;
}
}
export default mydirective;
<el-button v-mydirective="() => myFn(x,y)" type="text" size="small">测试</el-button>
<script>
export default {
data() {
return {
x: 1,
y: 2,
}
},
methods: {
myFn(x, y) {
console.log(x);
console.log(y);
}
}
}
</script>
const mydirective = {
inserted: function (el, binding) {
const fn = binding.value;
el.onclick = fn;
}
}
export default mydirective;
注意:
-
(elementUI的table组件为例)表格中使用该指令,翻页之后存在动态参数(scope.row)没更新问题,此时需要给表格增加
row-key="id"
,id为数据唯一的键,确保翻页之后每一行都更新<el-table ... row-key="id"> <el-table-column prop="title" label="名称"></el-table-column> <el-table-column prop="" label="操作"> <template slot-scope="scope"> <el-button v-mydirective="() => edit(scope.row)" type="text" size="small">编辑</el-button> </template> </el-table-column> </el-table>
-
可以使用
addEventListener
,但是其他生命周期里面removeEventListener
移除不成功 -
当vue2.X使用v-if切换显示,并且没有给key时,会造成执行了两个不同事件,点击取消按钮有可能执行save和cancel(1. 页面缓存2.第一次进入显示保存,第二次进入显示取消)。原因是vue为了提高性能共用一个dom节点导致。
<el-button v-if="edit" v-mydirective="() => save()" type="text" size="small">保存</el-button> <el-button v-if="!edit" v-mydirective="() => cancel()" type="text" size="small">取消</el-button>
-
要想移除事件可以在
unbind
生命周期里面el.onclick=null;
,此办法并不能移除addEventListener
的事件