v-model
свойства checked элементов products. Отключить чекбокс - свойства disabled у вас уже есть, просто привяжите их значения к чекбоксам.<input
type="checkbox"
v-model="product.checked"
:disabled="product.disabled"
>
computed: {
totalPrice() {
return this.products.reduce((acc, n) => acc + n.checked * n.price, 0);
},
},
event.target.tagName != 'button'
В XML (и XML-подобных языках) возвращаемое значение будет в нижнем регистре, а в HTML - в верхнем.
event.target.classList.contains('remove-button')
// или
event.target.matches('.remove-button')
$('.show').click(function() {
$(this).hide().next('.var').slideDown().find('.hide').show();
});
$('.hide').click(function() {
$(this).hide().closest('.var').slideUp().prev('.show').show();
});
rating = Math.max(1, Math.ceil((e.clientX - горизонтальнаяКоординатаЭлемента) / ширинаЭлемента * 5))
{this.state.ad.map(n => (
<div key={n.id}>
<h2>{n.title}</h2>
<div>{n.images.map(src => <img src={src} />)}</div>
</div>
))}
const html = [...Array(3)].map((n, i) => `<div class="count">${++i}</div>`).join('');
document.querySelectorAll('.counts').forEach(n => n.insertAdjacentHTML('beforeend', html));
const counts = document.querySelectorAll('.counts');
for (let i = 0; i < counts.length; i++) {
for (let j = 0; j < 3; j++) {
const el = document.createElement('div');
el.className = 'count';
el.innerText = j + 1;
counts[i].appendChild(el);
}
}
const div = document.createElement('div');
div.classList.add('count');
const fragment = document.createDocumentFragment();
fragment.append(...Array.from({ length: 3 }, (n, i) => (
n = div.cloneNode(),
n.textContent = -~i,
n
)));
for (const n of document.querySelectorAll('.counts')) {
n.append(fragment.cloneNode(true));
}
state: {
page: 0,
perPage: 5,
total: 0,
posts: [],
loading: false,
},
getters: {
numPages: state => Math.ceil(state.total / state.perPage),
},
mutations: {
updateLoading: (state, loading) => state.loading = loading,
updatePosts: (state, { posts, total, page }) => Object.assign(state, { posts, total, page }),
},
actions: {
async fetchPosts({ state, commit }, page) {
commit('updateLoading', true);
const start = (page - 1) * state.perPage;
const end = page * state.perPage;
const url = `https://jsonplaceholder.typicode.com/posts?_start=${start}&_end=${end}`;
try {
const response = await fetch(url);
const posts = await response.json();
const total = response.headers.get('x-total-count');
commit('updatePosts', { posts, total, page });
} catch (e) {
console.error(e);
}
commit('updateLoading', false);
},
},
props: [ 'page', 'numPages' ],
methods: {
goTo(page) {
this.$emit('paginate', page);
},
next(step) {
this.goTo(this.page + step);
},
},
computed: {
isFirst() {
return this.page <= 1;
},
isLast() {
return this.page >= this.numPages;
},
},
<button @click="goTo(1)" :disabled="isFirst"><<</button>
<button @click="next(-1)" :disabled="isFirst"><</button>
{{ page }} / {{ numPages }}
<button @click="next(+1)" :disabled="isLast">></button>
<button @click="goTo(numPages)" :disabled="isLast">>></button>
v-model
:model: {
prop: 'page',
event: 'paginate',
},
computed: {
page: {
get() {
return this.$store.state.page;
},
set(page) {
this.$store.dispatch('fetchPosts', page);
},
},
<компонент-пагинации
v-model="page"
:num-pages="$store.getters.numPages"
/>
created() {
this.page = 1;
},
<div v-if="$store.state.loading">данные загружаются, ждите</div>
<компонент-для-отображения-данных v-else :данные="$store.state.posts" />
const siblings = Array.prototype.filter.call(
this.parentNode.children,
n => n !== this
);
const siblings = [];
for (let el = this; (el = el.previousElementSibling); siblings.unshift(el)) ;
for (let el = this; (el = el.nextElementSibling); siblings.push(el)) ;