const group = (arr, idKey, valKey) =>
Object.values(arr.reduce((acc, { [idKey]: id, [valKey]: val }) => (
(acc[id] = acc[id] ?? { [idKey]: id, [valKey]: [] })[valKey].push(val),
acc
), {}));
const groupedAddresses = useMemo(() => {
return group(addresses, 'city', 'address');
}, [ addresses ]);
<ul>
{groupedAddresses.map(n => (
<li>
<h3>{n.city}</h3>
<ul>{n.address.map(m => <li>{m}</li>)}</ul>
</li>
))}
</ul>
users.sort((a, b) => (a.age ?? Infinity) - (b.age ?? Infinity));
const sortedUsers = Object
.values(users.reduce((acc, n) => ((acc[n.age] = acc[n.age] ?? []).push(n), acc), {}))
.flat();
// или
const sorted = (arr, key) => arr
.map(n => [ n, key(n) ])
.sort((a, b) => a[1] - b[1])
.map(n => n[0]);
const sortedUsers = sorted(users, n => n.age ?? Infinity);
const unique = Object.values(arr.reduce((acc, n) => (acc[n.name] = n, acc), {}));
const names = unique.map(({ name }, i) => ({ id: -~i, name }));
const ages = unique.map((n, i) => ({ id: i + 1, age: n.age }));
const extractUnique = (arr, idKey, keys) =>
arr.reduce((acc, n) => {
if (!acc[1].has(n[idKey])) {
const id = acc[1].add(n[idKey]).size;
keys.forEach((k, i) => acc[0][i].push({ id, [k]: n[k] }));
}
return acc;
}, [ keys.map(() => []), new Set ])[0];
const [ names, ages ] = extractUnique(arr, 'name', [ 'name', 'age' ]);
<select id="city"></select>
<select id="warehouse"></select>
const citySelect = document.querySelector('#city');
const warehouseSelect = document.querySelector('#warehouse');
citySelect.addEventListener('change', function() {
updateSelectOptions(warehouseSelect, {
calledMethod: 'getWarehouses',
methodProperties: {
CityName: this.value,
},
});
});
updateSelectOptions(citySelect, {
calledMethod: 'getCities',
methodProperties: {
FindByString: '',
},
});
function updateSelectOptions(selectEl, queryData) {
fetch('https://api.novaposhta.ua/v2.0/json/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
modelName: 'Address',
apiKey: '',
...queryData,
}),
})
.then(r => r.json())
.then(r => selectEl.innerHTML = r.data
.map(n => `<option>${n.Description}</option>`)
.join('')
);
}
const includes = (a, b) => Object.entries(b).every(([ k, v ]) => Object.is(v, a[k]));
const check = (a, b) => Object.values(a).some(n => includes(n, b));
const result = check(parent, { a: '1', b: '1' });
if (localStorage.getItem('mediaObjViewSeen') === true) {
Ключи и значения всегда строки
data: () => ({
view: localStorage.getItem('view') || 'CardsView',
// ...
}),
watch: {
view: val => localStorage.setItem('view', val),
},
data: () => ({
views: [
{
name: 'CardsView',
btnClass: 'btn-left',
img: '...',
},
{
name: 'MediaObjView',
btnClass: 'btn-right',
img: '...',
},
],
// ...
}),
<button
v-for="n in views"
:class="[ n.btnClass, view === n.name ? 'btn-active' : '' ]"
@click="view = n.name"
>
<img :src="n.img">
</button>
view
в TweetPreview
, используете его значение как имя компонента:<component
:is="view"
:tweet="tweet"
/>
const wrapper = document.querySelector('.block');
const blockSelector = '.block_one';
const activeClass = 'active';
wrapper.addEventListener('mouseover', onHover);
wrapper.addEventListener('mouseout', onHover);
function onHover({ type, target }) {
const block = type === 'mouseover' && target.closest(blockSelector);
this.querySelectorAll(blockSelector).forEach(n => {
n.classList.toggle(activeClass, !!block && n !== block);
});
}
.block:has(.block_one:hover) .block_one:not(:hover) {
/* сюда переносим стили того класса, который через js добавлялся */
}
computed: {
task() {
return new Proxy(this.value, {
set: (target, prop, value) => {
this.$emit('input', { ...target, [prop]: value });
return true;
},
});
},
},
v-model
соответствующих полей ввода):<input type="checkbox" v-model="task.done">
<button v-if="task.done" @click="$emit('delete')">delete</button>
<task-element
v-for="(n, i) in todos"
v-model="todos[i]"
@delete="todos.splice(i, 1)"
></task-element>
document.querySelectorAll('.number').forEach(n => {
n.innerText = n.innerText.replace(/\d+/g, m => (+m).toLocaleString());
});
for (const n of document.getElementsByClassName('number')) {
n.textContent = n.textContent.replace(/\d(?=(\d{3})+(\D|$))/g, '$& ');
}
$headers = array_column($data[0]['pages'], 'name');
$columns = array_column($data[0]['pages'], 'attribute');
$rowCount = max(array_map('count', $columns));
$headersHTML = implode('', array_map(function($n) {
return "<th>$n</th>";
}, $headers));
$rowsHTML = implode('', array_map(function($i) use($columns) {
return "
<tr>".implode('', array_map(function($n) use($i) {
return "<td>".($n[$i] ?? '')."</td>";
}, $columns))."
</tr>";
}, range(0, $rowCount - 1)));
echo "
<table>
<thead>
<tr>$headersHTML</tr>
</thead>
<tbody>$rowsHTML</tbody>
</table>";
fetch('https://api.novaposhta.ua/v2.0/json/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
modelName: 'Address',
calledMethod: 'getWarehouses',
methodProperties: {
CityName: document.querySelector('.myCityName').textContent,
},
apiKey: '',
}),
})
.then(r => r.json())
.then(r => {
document.querySelector('.mySelect').innerHTML = r.data
.map(n => `<option>${n.Description}</option>`)
.join('');
});
setInterval(tesla.moveRight,30)
setInterval(tesla.moveRight.bind(tesla), 30)
setInterval(() => tesla.moveRight(), 30)
class Car {
...
moveRight = () => {
...
}
}
Библиотеки и фреймворки (React, Vue, Redux...) даются очень тяжело.
Нравится работать с чистым js