function sum(data) {
let result = 0;
for (const stack = [ data ]; stack.length;) {
const n = stack.pop();
stack.push(...(n instanceof Object ? Object.values(n) : []));
result += typeof n === 'number' ? n : 0;
}
return result;
} %cursor-pointer {
cursor:pointer;
}
.product {
&.grid .grid-product__text:not(._price),
&.grid .grid-product__text._price,
&.grid .grid-product__text .grid-product__text_inner {
color: inherit !important;
}
&._photo-name-transition {
._name,
._image {
@extend %cursor-pointer;
}
}
&._name-transition {
._name {
@extend %cursor-pointer;
}
}
&._photo-transition {
._image {
@extend %cursor-pointer;
}
}
}.product._photo-name-transition ._name,
.product._photo-name-transition ._image,
.product._name-transition ._name,
.product._photo-transition ._image {
cursor: pointer;
}
.product.grid .grid-product__text:not(._price),
.product.grid .grid-product__text._price,
.product.grid .grid-product__text .grid-product__text_inner {
color: inherit !important;
}
function collectValues(target, ...sources) {
const onInput = () => target.value = sources.map(n => n.value).join(', ');
sources.forEach(n => n.addEventListener('input', onInput));
return () => sources.forEach(n => n.removeEventListener('input', onInput));
}
collectValues(...document.querySelectorAll('input')); getMediaUrls пока не будет данных. getMediaUrls должно быть computed свойство mediaUrls; во-вторых: скрывайте в шаблоне отображение пока не появятся данные: v-if="currentProductData"/v-if="currentProductData.length" и показывайте вместо этого какой-нить loader, Vue не запросит то, что скрыто под v-if пока условие не станет верным.getMediaUrls в mounted и разрывать асинхронную цепочку. Вызывайте его сразу в getProductData, либо если currentProductData может меняться в иных случаях - сделайте, опять же, computed свойством. В крайнем случае можно вызывать его, повесив watch на currentProductData, но computed лучше.