const text = (el => (el.innerHTML = html, el.innerText))(document.createElement('div'));
const text = new DOMParser().parseFromString(html, 'text/html').body.textContent;
const fragment = document.createRange().createContextualFragment(html);
const iter = document.createNodeIterator(fragment, NodeFilter.SHOW_TEXT);
const texts = [];
for (let n; n = iter.nextNode(); texts.push(n.nodeValue)) ;
v-for="o in getOptions2(index)"
на v-for="o in user.options"
; в обработчик change первого селекта передаёте текущий объект: @change="changeUser(user)"
, и соответственно, полученные данные кладёте в этот объект вместо options2 (их просто вырезаете):changeUser(user) {
fetch('https://jsonplaceholder.typicode.com/photos')
.then(r => r.json())
.then(d => this.$set(user, 'options', d));
},
3\d{2}
. Или ^3\d{2}$
. Или \b3\d{2}\b
. В зависимости от того, каковы входные данные, и что надо получить в результате. В хуке App.vue выглядит не очень уместно, хочется вынести эту логику в другое место.
Почему я не могу блокировать загрузку приложения до выполнения нужного мне действия (запрос на апи, возврат ответа и наполнение стора)?
store.dispatch('получитьДанные').then(() => {
new Vue({
el: '#app',
store,
router,
...
<div v-if="данные в хранилище есть">
основной контент приложения
</div>
<div v-else>
данные загружаются, надо подождать
</div>
this.$nextTick(() => {
const el = this.$refs.container;
el.scrollTop = el.scrollHeight;
});
И второй вопрос, если у меня в реальном проекте при таком коде не спускается никак, потому что идет погрузка через вкладки и используется keep-alive.
Вместо гамбургера отображается надпись "Меню"
<select v-model="user.name">
<option value="">Выбрать</option>
<option v-for="o in getOptions(index)" :value="o.value" v-text="o.label"></option>
</select>
getOptions(index) {
return this.options.filter(o => this.users.every((u, i) => u.name !== o.value || i === index));
},
<span class="prev" data-step="-1">Prev</span>
<span class="next" data-step="+1">Next</span>
eq
позволяет указывать отрицательные индексы, которые используются для отсчёта позиции элемента начиная с конца; в случае чистого js надо будет добавить к сумме количество элементов, чтобы потенциальное отрицательное значение стало положительным, и при этом не изменился остаток от деления.const itemSelector = 'li';
const buttonSelector = '[data-step]';
const activeClass = 'active';
$(buttonSelector).click(function() {
const { step } = this.dataset;
const $items = $(itemSelector);
const $active = $items.filter(`.${activeClass}`);
$active.removeClass(activeClass);
$items.eq(($active.index() + +step) % $items.length).addClass(activeClass);
});
// или
const items = document.querySelectorAll(itemSelector);
let index = 0;
document.querySelectorAll(buttonSelector).forEach(n => {
n.addEventListener('click', onClick);
});
function onClick({ currentTarget: { dataset: { step } } }) {
items[index].classList.remove(activeClass);
index = (index + items.length + +step) % items.length;
items[index].classList.add(activeClass);
}
.xxx {
background: silver;
display: inline-flex;
justify-content: center;
align-items: center;
font-size: 24px;
padding: 0.3em 0.6em;
position: relative;
}
.xxx::before {
content: "";
width: 1em;
height: 1em;
left: -0.2em;
top: -0.2em;
background: orange;
position: absolute;
z-index: -1;
}
watch: {
'$route.params.id': {
immediate: true,
handler() {
/*
* здесь идёт выполнение каких-то действий,
* направленных на обновление компонента - запрос данных, например...
* тут уж вам виднее, что это должно быть
*/
},
},
},
Math.min
или перебираем вручную и сравниваем):const minDigit = num =>
Number.isFinite(num)
? Math.min(...`${num}`.replace(/\D/g, ''))
: null;
// или
const minDigit = num =>
(String(num).match(/\d/g) || []).reduce((min, n) => {
return min === null || n < min ? +n : min;
}, null);
minDigit(1) // 1
minDigit(759486394) // 3
minDigit(-56.209) // 0
minDigit(Infinity) // null
minDigit(NaN) // null
minDigit('hello, world!!') // null
запрос на сервер отправляется два раза, хотя есть переменная, которая это блокирует
есть переменная end, статус которой проверяется постоянно
this.end = false
в finally (однако, само по себе это не гарантирует, что вы не сможете отправлять следующий запрос до окончания предыдущего). li
на его же текст:$('.breadcrumb').children().last().text((i, text) => text);
// или
document.querySelector('.breadcrumb').lastElementChild.innerText += '';
a
есть элементы, они не будут удалены):$('.breadcrumb > :last > *').replaceWith((i, html) => html);
// или
(el => el.replaceWith(...el.childNodes))
(document.querySelector('.breadcrumb > :last-child > *'));
const containerSelector = 'ul';
const buttonSelector = 'a';
const elementSelector = '.drop';
const $el = $(elementSelector);
$(containerSelector).on('click', buttonSelector, function(e) {
$(e.currentTarget).after($el);
// или
$(this).parent().append($el);
// или
$el.insertAfter(this);
});
const el = document.querySelector(elementSelector);
document.querySelector(containerSelector).addEventListener('click', ({ target: t }) => {
if (t = t.closest(buttonSelector)) {
t.after(el);
// или
t.insertAdjacentElement('afterend', el);
// или
t.parentNode.insertBefore(el, t.nextSibling);
// или
t.parentNode.append(el);
// или
t.parentNode.appendChild(el);
}
});
<span class="b-span" :class="{ 'b-span_active': active }">hello, world!!</span>
<button @click="onClick">click me</button>
data: () => ({
active: false,
time: 300,
}),
methods: {
onClick() {
setTimeout(() => this.active = true, this.time);
},
},
fade: true
из настроек слайдера, из обработчиков клика - второй параметр из вызова slickGoTo
(это который тоже true
). Кстати, а зачем отдельный обработчик каждой кнопке? - можно повесить один общий:const $slider = $('#slider').slick({
slidesToShow: 1,
slidesToScroll: 1,
adaptiveHeight: true,
dots: false,
prevArrow: false,
nextArrow: false,
speed: 900,
});
const $buttons = $('button').click(function() {
$slider.slick('slickGoTo', $buttons.index(this));
});