vue2中怎么更优雅的使用节流,自定义options
一直以来在vue中写业务代码的时候,使用节流都是像下方这样:
<template>
<div>
<img alt="排序" src="./排序.png" @click="handleSortThrottle" />
</div>
</template>
<script>
import { throttle } from 'lodash';
export default {
data() {
return {
handleSortThrottle: null
};
},
created() {
this.handleSortThrottle = throttle(this.handleSort, 1000);
},
methods: {
handleSort() {
//...
}
}
};
</script>
如果组件中有多个操作需要进行节流,就会在created中定义多个节流的属性。
这样的写法一直困扰我,不能忍受它的不够优雅。
于是决定抽空来解决这个问题了。
思考
怎样使用才是优雅的方式?首先想到的是自定义节流的方法修饰符(template中使用的)。
像这样:<img @click.throttle="handleSort">
vue好像不能自定义方法或属性的修饰符。并且只能限于template中使用,指定等待时间也不方便。
再来看一下原来使用节流的方式:
// 在created生命周期中
this.handleSortThrottle = throttle(this.handleSort, 1000);
那么有没有办法不在created中做这一步呢?或者说有没有办法自动在created中做这些事情,只需要定义好哪些方法需要做节流,以及这些方法的节流时间。
使用自定义options
<template>
<div>
<img alt="排序" src="./排序.png" @click="handleSort" />
</div>
</template>
<script>
import { throttle } from 'lodash';
export default {
data() {
return {
handleSortThrottle: null
};
},
// 最好放在methods选项上方,数组中每一项是要进行节流的方法
throttles: ['handleSort'],
methods: {
handleSort() {
//...
}
}
};
</script>
上面在组件中去掉了created
,并且<img>
中的click
的处理方法也换成了methods
中的handleSort
。
现在来看一下怎么去实现throttles
这个自定义option。
import { throttle } from 'lodash';
export default function install(Vue) {
Vue.mixin({
// 在属性没有解析前拿到所有option
beforeCreate() {
const { throttles, methods } = this.$options;
if (!throttles?.length) return;
throttles.forEach(methodName => {
if (typeof methodName !== 'string') return;
let wait;
// methodName支持使用|来指定等待的时间,如:handleSort|3000
[methodName, wait = 1000] = methodName.split('|');
const method = methods[methodName];
if (!method) return;
// 最重要的一步:使用节流后的方法去替换原来的方法,那样在组件中使用的就是节流后的方法了。
methods[methodName] = throttle(method, wait);
});
}
});
}
上面的自定义option就完成了。但如果这个throttles
选项是用在mixin中的那就可能出问题了,因为每个option都要定义合并规则,默认是使用组件本身的选项。
现在来给这个自定义option实现合并策略。
export default function install(Vue) {
// Vue.config.optionMergeStrategies 存放vue组件中所有option的合并规则
// 现在给optionMergeStrategeis中添加一个throttles的选项的合并策略
// prev是mixin中的throttles选项,cur是组件中throttles选项
Vue.config.optionMergeStrategies.throttles = (prev, cur) => {
if (!prev) return cur;
if (!cur) return prev;
// 若mixin和组件中都定义了同一方法的节流方案,则使用组件的
// 组件中所有进行节流的方法
const methodNames = cur.map(methodName => {
[methodName] = methodName.split('|');
return methodName;
});
return cur.concat(
prev.filter(methodName => {
[methodName] = methodName.split('|');
return !methodNames.includes(methodName);
})
);
};
// 上面写过的创建全局mixin,这里省略
Vue.mixin({ ... });
}
然后,在main.js
文件中引入这个install
方法,使用Vue.use()
即可。
至此,一个根据时间节流的自定option方案就完成的。
更多思考与完善
仅仅是代码使用优雅吗?
能否通过自定义throttles
选项做更多呢?
节流一般是按时间来做的,有时需要的是等待上一次操作完成或失败后才允许下一次操作,这里大家自己去修改完成吧。
转载自:https://juejin.cn/post/7270912365166886966