false
, всё выбрано - true
, для остальных вариантов undefined
, при котором в true
будет выставляться indeterminate. Также у него будет сеттер - если попытаться назначить true
, то выбранными должны стать все чекбоксы; если false
, то никто.const items = ref([
{ id: 69, title: 'hello, world!!' },
{ id: 187, title: 'fuck the world' },
{ id: 666, title: 'fuck everything' },
]);
const checked = ref([ 187 ]);
const isAllChecked = computed({
get: () => ({
0: false,
[items.value.length]: true,
})[checked.value.length],
set: val => checked.value = val ? items.value.map(n => n.id) : [],
});
<div>
<label>
<input
type="checkbox"
v-model="isAllChecked"
:indeterminate.prop="isAllChecked === undefined"
>
<b>Check all</b>
</label>
</div>
<div v-for="n in items" :key="n.id">
<label>
<input type="checkbox" v-model="checked" :value="n.id">
{{ n.title }}
</label>
</div>
/[^\/]+(?=\/$)/.exec(str)[0]
str.match(/[^\/]+/g).pop()
str.split('/').at(-2)
clearInterval из функции stopTheTimer результата необходимого не показал
data() { <...> }, mounted() { <...> }, stopTheTimer() { clearInterval(this.interval); }
Хук get не позволяет получить параметры вызова метода
function sequence(functions) {
return new Proxy(functions, {
get(target, key) {
const val = target[key];
return val instanceof Function
? (...args) => {
console.log(`${key} called with arguments: `, args);
return val.apply(target, args);
}
: val;
},
});
}
const uniqueWithSum = arr =>
arr.reduce((acc, n) => {
const keys = n.slice(0, -1);
const item = acc.find(m => m.length === n.length && keys.every((k, i) => k === m[i]));
(item ?? (acc[acc.length] = [ ...keys, 0 ]))[keys.length] += n[keys.length];
return acc;
}, []);
const uniqueWithSum = (function(arr) {
const indexTree = new Map;
return arr.reduce((acc, [...keys]) => {
const val = keys.pop();
const indexes = keys.reduce((p, c) => p.set(c, p.get(c) ?? new Map).get(c), indexTree);
const index = indexes.set(this, indexes.get(this) ?? ~-acc.push([ ...keys, 0 ])).get(this);
acc[index][keys.length] += val;
return acc;
}, []);
}).bind(Symbol());
const uniqueWithSum = arr =>
[...arr.reduce((acc, n) => {
const end = n.length - 1;
const key = n.reduce((p, c, i) => i === end ? p : p.set(c, p.get(c) ?? new Map).get(c), acc[0]);
acc[1].set(key, acc[1].get(key) ?? n.map((m, i) => i !== end && m)).get(key)[end] += n[end];
return acc;
}, [ new Map, new Map ])[1].values()];
v-model
:props: {
modelValue: {
type: String,
default: '',
},
...
<select
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
>
<option
v-for="n in options"
v-text="n.label"
:value="n.value"
></option>
</select>
data: () => ({
selected: Array(10).fill(null),
...
}),
methods: {
getValue(index) {
this.active = index;
console.log(this.selected[index]);
},
},
<div
v-for="(n, i) in selected"
class="test__item"
:class="{ test__item_active: i === active }"
>
<span @click="getValue(i)">элемент списка</span>
<Select v-model="selected[i]" :options="options" />
</div>
const profilesSorting = computed(() => profiles
.value
.filter(n => n.id === filters.value.id)
.sort(...)
.slice(...)
);
const replaceKeys = (value, replacer) =>
value instanceof Object
? value instanceof Array
? value.map(n => replaceKeys(n, replacer))
: Object.fromEntries(Object
.entries(value)
.map(n => [ replacer(n[0]), replaceKeys(n[1], replacer) ])
)
: value;
const newObj = replaceKeys(obj, k => `${k}_upd`);
function replaceKeys(value, replacer) {
const stack = [];
const clones = new Map;
const getClone = val => val instanceof Object
? (clones.has(val) || stack.push([ val, clones.set(val, val.constructor()).get(val) ]),
clones.get(val))
: val;
for (getClone(value); stack.length;) {
const [ source, target ] = stack.pop();
const isArray = Array.isArray(source);
for (const k in source) if (Object.hasOwn(source, k)) {
target[isArray ? k : replacer(k)] = getClone(source[k]);
}
}
return getClone(value);
}
выбранным оказывается последний добавленный элемент, несмотря на то, что всем добавленным элементам в GetSelected я вернул ' '
v-model
? const regex = /#[a-f\d]+;$/i;
const replacement = '<span class="color" style="background: $&"></span>';
document.querySelectorAll('селектор сами сообразите').forEach(n => {
n.innerHTML = n.innerText.replace(regex, replacement);
});
const result = arr.reduce((acc, n, i, a) => (
n === a[i - 1] + 1 || acc.push([]),
acc.at(-1).push(n),
acc
), []);
function groupAdjacent(
data,
{
key = n => n,
newGroup = (c, p) => c !== p,
} = {}
) {
const result = [];
const getVal = key instanceof Function ? key : n => n[key];
let prev = null;
let i = -1;
for (const n of data) {
const curr = getVal(n, ++i);
if (!result.length || newGroup(curr, prev)) {
result.push([]);
}
result.at(-1).push(n);
prev = curr;
}
return result;
}
const result = groupAdjacent(arr, { newGroup: (c, p) => c !== -~p });
// или
const result = groupAdjacent(arr, { key: (n, i) => n - i });
.product
. Вместо первого .product
нужен тот, внутри которого находится нажатая кнопка:document.querySelector('.wrapper_product')
---> event.target
$value = array_combine($data['value_index'], $data['value'])[min($data['value_index'])];
$value = $data['value'][array_search(min($data['value_index']), $data['value_index'])];
$index = 0;
for ($i = 1; $i < count($data['value_index']); $i++) {
if ($data['value_index'][$i] < $data['value_index'][$index]) {
$index = $i;
}
}
$value = $data['value'][$index];
menu.addEventListener('click', ({ target: t }) => {
if (t.tagName === 'SPAN') {
const parent = t.parentNode;
parent.classList.toggle('active');
for (const n of menu.querySelectorAll('.active')) {
if (n !== parent) {
n.classList.toggle('active', n.contains(parent));
}
}
}
});
- .menu_list_item.active .submenu {
+ .active > .submenu {
- .submenu_list_item.active .product {
+ .active > .product {
const container = document.querySelector('#menu');
const itemSelector = 'li';
const buttonSelector = `${itemSelector} span`;
const activeClass = 'active';
container.addEventListener('click', function(e) {
const item = e.target.closest(buttonSelector)?.closest(itemSelector);
if (item) {
item.classList.toggle(activeClass);
this.querySelectorAll(`.${activeClass}`).forEach(n => {
if (n !== item) {
n.classList.toggle(activeClass, n.contains(item));
}
});
}
});
const items = document.querySelectorAll('.faq__input');
const onChange = ({ target: t }) => t
.closest('.faq__items')
.querySelectorAll('.faq__question--top')
.forEach(n => n.classList.toggle('active', n.nextElementSibling.checked));
items.forEach(n => n.addEventListener('change', onChange));
.faq__item
вместо .faq__question--top
. Если в будущем задумаете стилизовать внутри выбранного .faq__item
элементы, находящиеся за пределами .faq__question--top
, то не придётся переписывать js-код.const itemSelector = '.faq__item';
const radioSelector = '.faq__input';
const activeClass = 'active';
const toggleActiveClass = radioGroupName => document
.querySelectorAll(`${radioSelector}[name="${radioGroupName}"]`)
.forEach(n => n.closest(itemSelector).classList.toggle(activeClass, n.checked));
document.querySelectorAll(radioSelector).forEach(function(n) {
n.addEventListener('change', this);
}, e => toggleActiveClass(e.target.name));
document.addEventListener('change', ({ target: t }) => {
if (t.matches(radioSelector)) {
toggleActiveClass(t.name);
}
});
$values = array_column($array2, 'value');
$result = array_filter($array1, fn($n) => in_array($n->code, $values));
из дочернего мне нужно передать именно ключ b в родительский
this.$emit('do-something')
.<child-component :object="objects.a" @do-something="doSomething('a')" />
<child-component :object="objects.b" @do-something="doSomething('b')" />
<!--> или <-->
<child-component v-for="(v, k) in objects" :object="v" @do-something="doSomething(k)" />
methods: {
doSomething(key) {
// чего-то делаете
},
...
затем пройтись по objects и при совпадении ключей (a, b или c) выполнить действия над значением
<child-component :object="objects.a" @do-something="doSomething(objects.a)" />
<child-component :object="objects.b" @do-something="doSomething(objects.b)" />
<!--> или <-->
<child-component v-for="n in objects" :object="n" @do-something="doSomething(n)" />
this.$emit('do-something', this.object)
. Тогда не придётся дублировать обращение к нему в родителе:<child-component :object="objects.a" @do-something="doSomething" />
<child-component :object="objects.b" @do-something="doSomething" />
<!--> или <-->
<child-component v-for="n in objects" :object="n" @do-something="doSomething" />
function createTree({
arr,
idKey = 'id',
parentKey = 'parentId',
childrenKey = 'children',
}) {
const tree = Object.fromEntries(arr.map(n => [ n[idKey], { ...n, [childrenKey]: [] } ]));
return Object.values(tree).filter(n => !tree[n[parentKey]]?.[childrenKey].push(n));
}
v-tree
, выводящий древовидные данные:props: {
items: {
type: Array,
default: () => [],
},
maxdepth: {
type: Number,
default: Infinity,
},
},
<ul v-if="Array.isArray(items) && items.length && maxdepth">
<li v-for="n in items" :key="n.id">
{{ n.value }}
<v-tree :items="n.children" :maxdepth="maxdepth - 1" />
</li>
</ul>