performance - $emit 和 Watchers 的 VueJS 性能成本
问题描述
我已经构建了一个音乐应用程序(使用 Vue 和 ToneJS),用户可以在其中创建循环曲目,这些曲目会根据用户的选择以各种方式发生变化。这利用了一组相当复杂的缩放计数器机制。在构建了音乐功能之后,我正在制作一个“进度条”,它会显示下一次转换即将发生的时间。
目前,我这样做的方式是计算所需的总步数(每个音符是一个“步”),并将其与每个计数器的进度(在 Vuex 状态下)进行比较。就代码而言,这是很多精神开销。
执行此操作的更好方法可能是使用 $emit 每次前进一个步骤时发送一个“滴答”,这将由具有进度条的组件拾取并与所需的步骤进行比较。或者,在组件上使用观察者可以检测到更改并发送滴答声。
但是,我已经遇到了应用程序的一些计时性能问题,而计时对此至关重要。我是一个相对较新的开发人员,还不太了解性能。所以我想知道的是它的使用$emit
或观察者有多“昂贵”?由于它将连接到应用程序的“电机”,因此会不断地调用它。有没有可能使齿轮卡住的危险?
解决方案
First, you need to understand what their differences are!
Emitting an event with $emit
in vue.js
:
Vuejs
is using the publish-subscribe pattern for emitting the events. In software architecture, publish–subscribe is a messaging pattern where senders of messages, called publishers, do not program the messages to be sent directly to specific receivers, called subscribers..
Let's visualize this pattern:
Object1 will emit event fooEvent
. Other objects might register a subscriber to this event, so whenever any fooEvent
event emits the subscribers will be called.
This is how vuejs
register subscribers (source code on Github):
Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {
const vm: Component = this
if (Array.isArray(event)) {
for (let i = 0, l = event.length; i < l; i++) {
vm.$on(event[i], fn)
}
} else {
(vm._events[event] || (vm._events[event] = [])).push(fn)
// optimize hook:event cost by using a boolean flag marked at registration
// instead of a hash lookup
if (hookRE.test(event)) {
vm._hasHookEvent = true
}
}
In a nutshell it just store them in an array vm._events
:
(vm._events[event] || (vm._events[event] = [])).push(fn)
And this how it calls the subscribers (source-code on Github):
let cbs = vm._events[event]
if (cbs) {
cbs = cbs.length > 1 ? toArray(cbs) : cbs
const args = toArray(arguments, 1)
const info = `event handler for "${event}"`
for (let i = 0, l = cbs.length; i < l; i++) {
invokeWithErrorHandling(cbs[i], vm, args, vm, info)
}
It iterates over all subscribers and calls them one by one in registration order.
So? It doesn't cost anything big!
How watch works?:
Well, it's a long story if we are going to talk about in the source-code but here is the short one:
Whenever you mark a property to be watched inside Vuejs, it runs a big code to watch its changes and schedule it inside a scheduler! SO vue
understand the changes by pooling and checking if there is a change or not.
- This is how it creates a watcher (every-time you mark an object to be watched, it creates a new
Watcher
object for it). - The
run
method inside a watcher will be called by the scheduler. - And how it runs them.
So? It's quite heavy, isn't it?
So the summary of the results and my opinion according to the codes and my personal experience:
Emitting an event isn't such a heavy thing, it's very very lighter than a watcher.
推荐阅读
- python-3.x - 使用 buildozer 构建 apk 文件时出现错误“没有名为 'virtualenv.__main__' 的模块;'virtualenv' 不是包”
- javascript - 仅在单击的函数内部而不是在 Type Script 代码的 UI 中更新可淘汰可观察值
- git - 是否可以避免使用 ansible git 模块更改 remote_url?
- python - 在 Python 中获取 Bing 搜索结果
- amazon-web-services - Route 53 托管的 zome 记录指向旧的负载均衡器
- swift - TextField 接受有限的字符 SwiftUi
- laravel - 在laravel中将文件下载为未知文件
- java - Jhipster 和角度过滤器
- datepicker - 如何在使用 Apex Office Print 打印时更改日期选择器的格式掩码?
- yii - Yii 1.1 关系搜索问题