Дано:
Сложносоставной компонент кастомизации замены номера на странице.
Есть 2 колонки:
1 - настройки
2 - визуализатор замены номера
Что происходит?
Юзер меняет настройки визуализации (их прям прилично - есть и кастомизатор css и маска замены номера и отображение с расположением префикса, изменение текста префикса, отображение в модалке, изменение контента модалки) - настройки при изменении перерисовывают визуализатор.
Что самое интресное - настрока маски - селекты, в которых содержится статическая разметка. Разметка выбранного селекта падает в визуализатор и рендерится через v-html. Она, естесн, не реактивна, и методы визуализатора, кастомизирующие отображение маски ковыряют её напрямую через DOM.
Что не так?
Если открыть вкладку и всё сразу настроить - всё хорошо. Если оставить вкладку с настройками на пару часов (даже пару десятков минут) - вкладка умирает. Если открыть devtools, весь его инструментарий будет беспощадно лагать и виснуть. Подобное прослеживается далеко не на утюге и во всех браузерах.
Что я пытался сделать?
Ранее визуализатор перерисовывался через watch. То есть в компонент падали данные с настройками через props и эти пропсы отслеживались в визуализаторе. Я убрал все вотчеры и заменил их на эмиттеры. То есть при изменении настройки компонент этой настройки вызывает метод, описанный в основном компоненте раздела. В этом методе происходит поиск по компонентам и при нахождении визуализатора он эмитится с нужным методом в зависимости от настройки.
Дополнительно я поставил таймауты на все поля ввода, которые могут вызывать эмиты слишком часто. Стало чуть легче, но всё равно утечка осталась и вкладка тупит. Как можно оптимизировать ещё?
Немного кода: методы основного компонента родителя, эмитящие визуализатор при изменении настроек:
emitVisualPrefix: ->
that = @
if watchTimer
clearTimeout(watchTimer)
else
watchTimer = setTimeout(
->
that.$children.forEach (child) ->
if child.$options.name == 'visualizer'
child.$emit('initPrefixSettings')
,200)
emitInlinePrefix: ->
that = @
if watchTimer
clearTimeout(watchTimer)
else
watchTimer = setTimeout(
->
that.$children.forEach (child) ->
if child.$options.name == 'visualizer'
child.$emit('setInlinePrefix')
,200)
emitPositionPrefix: ->
that = @
if watchTimer
clearTimeout(watchTimer)
else
watchTimer = setTimeout(
->
that.$children.forEach (child) ->
if child.$options.name == 'visualizer'
child.$emit('setPositionPrefix')
,200)
Инициализация методов перерисовки статической разметки в визуализаторе выглядит вот так:
methods:
initSettings: ->
console.log('initSettings')
@setInlineStyles('init')
if @settings.coverTip.enabled
@setInlinePrefix()
@setPositionPrefix()
mounted: ->
@initSettings()
@$on 'setStyle', (type) ->
console.log('setStyle')
switch type
when 'inline'
@setInlineStyles()
@$on 'initPrefixSettings', ->
console.log('initPrefixSettings')
@setInlinePrefix()
@setPositionPrefix()
@$on 'setInlinePrefix', ->
console.log('setInlinePrefix')
@setInlinePrefix()
@$on 'setPositionPrefix', ->
console.log('setPositionPrefix')
@setPositionPrefix()
Что самое интересное - если initSettings() отменить, всё резко отвисает и утечка прекращается. Но без этого метода визуализатор не в состоянии применить настройки, прилетевшие с сервера