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
лучше.