tbody
для каждой пары строк. Переносите tbody
из компонента таблицы в компонент строки - будет там корневым элементом:<tbody>
<tr>... </tr>
<tr v-if="...">...</tr>
</tbody>
tr
сразу в компоненте таблицы:<tbody>
<template v-for="...">
<tr>... </tr>
<tr v-if="...">...</tr>
</template>
</body>
data: () => ({
formData: {},
formMeta: [
{ name: 'phone', title: 'Телефон', type: 'text', placeholder: 'Телефон' },
{ name: 'email', title: 'E-mail', type: 'text', placeholder: 'E-mail' },
{ name: 'address', title: 'Адрес', type: 'text', placeholder: 'Адрес' },
...
],
}),
this.$emit('save-contact', this.formData);
<div v-for="n in formMeta">
<span class="form__other-title">{{ n.title }}</span>
<div class="form__other-data">
<input
v-model="formData[n.name]"
:type="n.type"
:placeholder="n.placeholder"
>
</div>
</div>
работать с dom напрямую плохая практика
props: [ 'items', 'value' ],
data: () => ({
sliderStyles: null,
}),
<ul class="tabs">
<li
v-for="n in items"
:key="n.value"
@click="$emit('input', n.value)"
class="tabs-item"
>{{ n.text }}</li>
</ul>
<div
class="tabs-slider"
:style="sliderStyles"
></div>
.tabs-slider
) зададим абсолютное позиционирование и transition.mounted() {
this.$watch(
'value',
value => {
const index = this.items.findIndex(n => n.value === value);
const el = this.$el.querySelectorAll('.tabs-item')[index];
this.sliderStyles = el
? {
left: `${el.offsetLeft}px`,
width: `${el.offsetWidth}px`,
}
: null;
},
{
immediate: true,
}
);
},
const sortedArr = arr
.map(n => [ n, new Date(n.date.replace(/(\d+)\.(\d+)\.(\d+)/, '$3-$2-$1')) ])
.sort((a, b) => a[1] - b[1])
.map(n => n[0]);
const getMinimumUniqueSum = arr => [...arr]
.sort((a, b) => a - b)
.reduce((acc, n) => (acc[1] += acc[0] = Math.max(acc[0] + 1, n), acc), [ -Infinity, 0 ])
.pop();
const find = (arr, id) =>
(Array.isArray(arr) ? arr : []).reduce((found, n) =>
found || (n.id === id ? n : find(n.replies, id))
, null);
data: () => ({
opened: false,
}),
<div class="dropdown">
<div class="dropdown-header" @click="opened = !opened">
<slot name="header" :opened="opened">
{{ opened ? 'CLOSE' : 'OPEN' }}
</slot>
</div>
<div v-if="opened" class="dropdown-content">
<slot name="content"></slot>
</div>
</div>
IndexError: string index out of range
+ 1
делать.print([ chr(i + 96) * i for i in range(1, 27) ])
button с классами .tool и .название цвета
let color = '#000';
document.querySelector('селектор контейнера с кнопками').addEventListener('click', e => {
if (e.target.classList.contains('tool')) {
color = e.target.dataset.color;
}
});
document.querySelector('селектор контейнера с "пикселями"').addEventListener('click', e => {
if (e.target.classList.contains('pixel')) {
e.target.style.backgroundColor = color;
}
});
filterBox.forEach(n => {
n.classList.toggle('none', ![ 'all', n.dataset.work ].includes(filterBtn));
});
const container = document.querySelector('.side__nav');
const itemSelector = 'li';
const activeClass = 'is-active';
container.addEventListener('click', function(e) {
const item = e.target.closest(itemSelector);
if (item) {
this.querySelector(`${itemSelector}.${activeClass}`)?.classList.remove(activeClass);
item.classList.add(activeClass);
}
});
const items = container.querySelectorAll(itemSelector);
const onClick = e => items.forEach(n => n.classList.toggle(activeClass, n === e.currentTarget));
items.forEach(n => n.addEventListener('click', onClick));
const element = document.querySelector(`.js-filter-wrap a[data-filter="${конкретноеЗначение}"]`);
if (element) {
...
const element = [...elements].find(n => n.dataset.filter === конкретноеЗначение);
if (element) {
...
options: {
scales: {
yAxes: [
{ id: 'y1', position: 'left' },
{ id: 'y2', position: 'right' },
],
},
},
приложение делается на vue