v-for
индексы, которые затем проверяйте в v-if
ячеек с rowspan'ами - рендерить их нужно только при нулевых значениях.objects[0]
? Неужели в objects
может быть только один элемент? Заверните то, что сейчас есть в ещё один template
, в котором будет v-for
по элементам objects
.v-for
.methods: {
rowspan: attr1 => attr1.reduce((acc, n) => acc + n.attr3.length + 1, 0),
},
<template v-for="obj in objects">
<template v-for="{ road, attr1, TOTAL } in obj.data">
<template v-for="({ attr2, attr3, attr4 }, iAttr1) in attr1">
<tr v-for="(attr3Item, iAttr3) in attr3">
<td :rowspan="rowspan(attr1)" v-if="!iAttr1 && !iAttr3">{{ road }}</td>
<td :rowspan="attr3.length" v-if="!iAttr3">{{ attr2 }}</td>
<td>{{ attr3Item.road }}</td>
<td>{{ attr3Item.cargo }}</td>
<td>{{ attr3Item.amount }}</td>
<td>{{ attr3Item.wo_nds }}</td>
</tr>
<tr>
<td colspan="2">Итого {{ attr2 }}:</td>
<td>{{ attr4.cargo }}</td>
<td>{{ attr4.amount }}</td>
<td>{{ attr4.wo_nds }}</td>
</tr>
</template>
<tr>
<td colspan="3">Итого {{ road }}:</td>
<td>{{ TOTAL.cargo }}</td>
<td>{{ TOTAL.amount }}</td>
<td>{{ TOTAL.wo_nds }}</td>
</tr>
</template>
</template>
Winner
не количество голосов, а элемент smiles
целиком. Да, Math.max
получить его не поможет, придётся самостоятельно перебирать массив в поисках максимума.const Winner = ({ winner }) => winner
? <div>{winner.text}: {winner.value}</div>
: null;
class App extends React.Component {
state = {
winner: null,
smiles: [ 128540, 128520, 128640, 128526, 128566 ].map((n, i) => ({
id: i + 1,
text: String.fromCodePoint(n),
value: 0,
})),
}
vote(index) {
this.setState(({ smiles }) => ({
winner: null,
smiles: smiles.map((n, i) => i === index
? { ...n, value: n.value + 1 }
: n
),
}));
}
showWinner = () => {
this.setState(({ smiles }) => ({
winner: smiles.reduce((max, n) => max.value > n.value ? max : n),
}));
}
render() {
const { smiles, winner } = this.state;
return (
<div>
<ul>
{smiles.map((n, i) => (
<li key={n.id}>
<button onClick={() => this.vote(i)}>{n.text}: {n.value}</button>
</li>
))}
</ul>
<button onClick={this.showWinner}>show winner</button>
<Winner winner={winner} />
</div>
);
}
}
v-bind:header="user"
v-slot:header="{ user }"
header
, а использовать пытаетесь user
. checkWinner(id) { console.log({[id]: Math.max(...Object.values(this.state))})
onClick={checkWinner}
[object Object]
- дефолтное строковое представление объекта. Всё. useEffect(() => {
const timeoutID = setTimeout(nextSlide, 3000);
return () => clearTimeout(timeoutID);
}, [ currentIndex ]);
const filters = reactive({});
<input v-model="filters.search">
watch(
() => filters.search,
debounce(search => store.commit('setFilters', { search }), 1500)
);
watch(
store.state.filters,
val => Object.assign(filters, val), { immediate: true }
);
setProducts(products => products.map(n => {
const card = n.cards.find(m => m.id === id);
return card
? {
...n,
cards: n.cards.map(m => m === card
? { ...m, quantity: newQuantity }
: m
),
}
: n
}));
const buttonSelector = '.added';
const itemSelector = '.added-block';
const activeClass = '_active';
const notActiveSelector = `${itemSelector}:not(.${activeClass})`;
const newActiveCount = 2;
function onButtonClick(button) {
const items = [...button.parentNode.querySelectorAll(notActiveSelector)];
items.slice(0, newActiveCount).forEach(n => n.classList.add(activeClass));
button.disabled = items.length <= newActiveCount;
}
document.querySelectorAll(buttonSelector).forEach(function(n) {
n.addEventListener('click', this);
}, e => onButtonClick(e.currentTarget));
document.addEventListener('click', e => {
const button = e.target.closest(buttonSelector);
if (button) {
onButtonClick(button);
}
});
Thev-enter
transition class has been renamed tov-enter-from
<RatingSelect v-model="rating" />
const props = defineProps({
modelValue: {
type: Number,
required: true,
},
maxRating: {
type: Number,
default: 10,
},
});
const emit = defineEmits([ 'update:modelValue' ]);
const selected = computed({
get: () => props.modelValue,
set: val => emit('update:modelValue', val),
});
<li v-for="n in maxRating">
<label>
<input type="radio" :value="n" v-model="selected">
{{ n }}
</label>
</li>
function App() {
const [ count, setCount ] = useState(() => +localStorage.getItem('count') || 0);
useEffect(() => {
localStorage.setItem('count', count);
}, [ count ]);
const onClick = e => setCount(count => count + +e.target.dataset.change);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={onClick} data-change="+1">+</button>
<button onClick={onClick} data-change="-1">-</button>
</div>
);
}
data: () => ({
buttons: [
{ className: 'btn1', text: 'Limit' },
{ className: 'btn2', text: 'Market' },
],
active: 0,
}),
<button
v-for="(n, i) in buttons"
v-text="n.text"
:class="[ 'btn', n.className, { 'active-btn': i === active } ]"
@click="active = i"
></button>
btn*
действительно идут по порядку)data: () => ({
buttons: [ 'Limit', 'Market' ],
active: 'Limit',
}),
<button
v-for="(n, i) in buttons"
:class="`btn btn${i + 1} ${n === active ? 'active-btn' : ''}`"
@click="active = n"
>{{ n }}</button>