expanded-item
:<v-data-table
:headers="mainTableHeaders"
:items="mainTableItems"
item-key="mainTableItemKey"
show-expand
>
<template #expanded-item="{ headers, item }">
<td :colspan="headers.length">
<v-data-table
:headers="nestedTableHeaders"
:items="item.nestedTableItems"
></v-data-table>
</td>
</template>
</v-data-table>
при клике на строчку
show-expand
, добавляем обработчик клика, где отображение дополнительного контента будет переключаться вручную:methods: {
onRowClick(item, row) {
row.expand(!row.isExpanded);
},
...
<v-data-table
@click:row="onRowClick"
...
class DB {
info = null;
...
const Episodes = observer(() => {
useEffect(() => {
...
}, [ DB.info ]);
...
return <Episodes />;
на return DB.info && <Episodes />;
. <div data-filter="service">
<div class="sign">Streaming service</div>
<div class="item">Netflix</div>
<div class="item">HBO Max</div>
<div class="item">Hulu</div>
</div>
<div data-filter="genre">
<div class="sign">Movie genre</div>
<div class="item">Comedy</div>
<div class="item">Action</div>
<div class="item">Horror</div>
<div class="item">Drama</div>
<div class="item">Fantasy</div>
</div>
<li class="card" data-service="Netflix" data-genre="Comedy">
const cardSelector = '.card';
const hiddenCardClass = 'hidden';
const filterSelector = '[data-filter]';
const filterItemSelector = `${filterSelector} .item`;
const activeFilterItemClass = 'item_active';
document.querySelector('.filters').addEventListener('click', e => {
const item = e.target.closest(filterItemSelector);
if (!item) {
return;
}
item.closest(filterSelector).querySelectorAll(filterItemSelector).forEach(n => {
n.classList[n === item ? 'toggle' : 'remove'](activeFilterItemClass);
});
const values = Array.from(
e.currentTarget.querySelectorAll(`.${activeFilterItemClass}`),
n => [ n.closest(filterSelector).dataset.filter, n.innerText ]
);
document.querySelectorAll(cardSelector).forEach(n => {
n.classList.toggle(hiddenCardClass, values.some(m => n.dataset[m[0]] !== m[1]));
});
});
v-text-field
подобной возможности не предоставляет, так что придётся закостылить.<v-text-field @click.native="onClick">
methods: {
onClick({ target: t }) {
if (
t.classList.contains('v-messages__message') &&
t.closest('.v-messages.error--text')
) {
// ну да, кликнули по сообщению об ошибке
}
},
},
v-model
, обновил данные в компоненте; устанавливаете отформатированное значение. Для предотвращения рекурсивной обработки событий input проверяете isTrusted:function updateValue(el) {
el.value = el.value, из которого удалено всё, кроме цифр;
el.dispatchEvent(new Event('input'));
el.value = форматированное значение el.value;
}
function onInput(e) {
if (e.isTrusted) {
updateValue(e.target);
}
}
Vue.directive('number', {
bind(el) {
el.addEventListener('input', onInput);
updateValue(el);
},
update(el) {
updateValue(el);
},
unbind(el) {
el.removeEventListener('input', onInput);
},
});
с минимальным количеством действий
v-for="el in link"
на v-for="el in [].concat(link)"
. return getValue(objectValus[prop], property);
const getValue = (obj, key) => Object
.values(obj ?? {})
.reduce((found, n) => found ?? getValue(n, key), obj?.[key]);
transition-duration: 0ms;
.transition: none;
.true
, не нужна анимация - false
. Как-то так. function solve(arr) {
const last = arr.reduce((acc, n, i) => (acc[n] = i, acc), {});
return arr.filter((n, i) => last[n] === i);
}
function solve(arr) {
const last = new Map(arr.map((n, i) => [ n, i ]));
arr.length -= arr.reduce((acc, n, i, a) => (
a[i - acc] = n,
acc + (i !== last.get(n))
), 0);
return arr;
}
const solve = arr => (
arr.splice(0, arr.length, ...[...new Set(arr.reverse())].reverse()),
arr
);
const grouped = props.mainPage.room.reduce((acc, n) => (
(acc[n.storey] ??= []).push(n),
acc
), {});
{Object.entries(grouped).map(([ groupName, group ]) => (
<div className="group" key={groupName}>
<h3>{groupName}</h3>
{group.map(n => <NumberRoom key={n.id} {...n} />)}
</div>
))}
(function() {
function func(arg) {
console.log(arg, this);
}
let arg = 1;
const f1 = () => func(arg);
const f2 = func.bind(this, arg);
arg = 2;
f1();
f2();
}).call('hello, world!!');