Подключаю этот плагин
https://github.com/river-lee/vue-fullpage#options
based on vue@2.x
import { createApp } from 'vue'
Обратите внимание: когда изменяете (а не заменяете) объект или массив, старое и новое значения при вызове коллбэка будут совпадать, так как они ссылаются на один и тот же объект или массив. Vue не сохраняет копии объекта на момент, предшествовавший изменениям.
watch: {
'obj.propName'(newValue, oldValue) {
...
},
},
obj.propName = value
, а будет obj = { ...obj, propName: value }
. Ну а дальше можно уже сравнивать свойства в старом и новом объектах, чтобы найти, какое конкретно было изменено. isOpen
с помощью директивы v-model
, замените :is-open="item.isOpen"
на v-model:is-open="item.isOpen"
.isOpen = !isOpen
на $emit('update:isOpen', !isOpen)
. computed: {
grouped() {
return this.arr.reduce((acc, n) => ((acc[n.group] ??= []).push(n), acc), {});
},
},
<v-expansion-panels>
<v-expansion-panel v-for="(items, groupName) in grouped">
<v-expansion-panel-header>{{ groupName }}</v-expansion-panel-header>
<v-expansion-panel-content>
<div v-for="n in items">{{ n.name }}</div>
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
const filter = (arr, str) => (arr || [])
.map(n => ({ ...n, children: filter(n.children, str) }))
.filter(n => n.name.includes(str) || n.children.length);
computed: {
filteredItems() {
return filter(this.items, this.search);
},
},
computed: {
total() {
return this.value1 * this.value2 + this.checkbox * 1000;
},
},
const tree = ref(null)
return {
tree,
...
<el-tree
ref="tree"
...
tree.value.getCheckedKeys()
. В App.vue я запрашиваю все продукты из БД
store.dispatch('GET_PRODUCTS').then(() => {
new Vue({ ... });
});
watch: {
'$store.state.products': {
immediate: true,
handler(products) {
if (products) {
// можно что-то сделать
}
},
},
},
data() {
return {
isChecked: false,
}
},
methods: {
toggleSwitch() {
this.isChecked = !this.isChecked
this.$emit('input', this.isChecked)
},
},
props: {
value: Boolean,
},
:class="{ 'ivu-switch-checked': isChecked }"
на :class="{ 'ivu-switch-checked': value }"
@click.prevent="toggleSwitch"
на @click.prevent="$emit('input', !value)"
elem.classList.add('check'); elem.querySelector('input[type="checkbox"]').remove();
Не могу закрыть поп-ап
dialog: [],
dialog[index]= false
При нажатии на кнопку, при выборе 3 изображения на превью открывается всегда первое.
data: () => ({
slide: null,
dialog: false,
...
}),
methods: {
openDialog(slideIndex) {
this.slide = slideIndex;
this.dialog = true;
},
...
},
v-row
v-col(v-for="(n, i) in pictures")
v-item
v-img(height="100", width="100", :src="n", @click="openDialog(i)")
v-col(hidden="")
v-dialog(v-model="dialog")
v-carousel(v-model="slide")
v-carousel-item(v-for="n in pictures")
v-img(:src="n")
v-btn(@click="dialog = false") close dialog
<posts :posts="$store.state.posts" />
<router-link :to="{ name: 'home', params: { posts } }">home</router-link>
this.$router.push({
name: 'home',
params: {
posts: this.posts,
},
});
router-link
или вызова $router.push
. При этом, если переход осуществляется не из корневого компонента, то, чтобы дотянуться до posts, придётся ещё и $root
использовать. В случае же, когда пользователь решит осуществить переход посредством адресной строки браузера, то ничего передать не получится.router-view
, тогда они будут переданы как параметры в компонент текущего маршрута: <router-view :posts="post" />
.$attrs
). Чтобы передавать что надо только куда надо, можно оформить параметры, передаваемые в router-view
, как вычисляемое свойство, значение которого будет зависеть от текущего маршрута:computed: {
routeParams() {
return что-то, в зависимости от this.$route;
},
},
<router-view v-bind="routeParams" />
tbody
для каждой пары строк. Переносите tbody
из компонента таблицы в компонент строки - будет там корневым элементом:<tbody>
<tr>... </tr>
<tr v-if="...">...</tr>
</tbody>
tr
сразу в компоненте таблицы:<tbody>
<template v-for="...">
<tr>... </tr>
<tr v-if="...">...</tr>
</template>
</body>
data: () => ({
formData: {},
formMeta: [
{ name: 'phone', title: 'Телефон', type: 'text', placeholder: 'Телефон' },
{ name: 'email', title: 'E-mail', type: 'text', placeholder: 'E-mail' },
{ name: 'address', title: 'Адрес', type: 'text', placeholder: 'Адрес' },
...
],
}),
this.$emit('save-contact', this.formData);
<div v-for="n in formMeta">
<span class="form__other-title">{{ n.title }}</span>
<div class="form__other-data">
<input
v-model="formData[n.name]"
:type="n.type"
:placeholder="n.placeholder"
>
</div>
</div>
работать с dom напрямую плохая практика
props: [ 'items', 'value' ],
data: () => ({
sliderStyles: null,
}),
<ul class="tabs">
<li
v-for="n in items"
:key="n.value"
@click="$emit('input', n.value)"
class="tabs-item"
>{{ n.text }}</li>
</ul>
<div
class="tabs-slider"
:style="sliderStyles"
></div>
.tabs-slider
) зададим абсолютное позиционирование и transition.mounted() {
this.$watch(
'value',
value => {
const index = this.items.findIndex(n => n.value === value);
const el = this.$el.querySelectorAll('.tabs-item')[index];
this.sliderStyles = el
? {
left: `${el.offsetLeft}px`,
width: `${el.offsetWidth}px`,
}
: null;
},
{
immediate: true,
}
);
},
data: () => ({
opened: false,
}),
<div class="dropdown">
<div class="dropdown-header" @click="opened = !opened">
<slot name="header" :opened="opened">
{{ opened ? 'CLOSE' : 'OPEN' }}
</slot>
</div>
<div v-if="opened" class="dropdown-content">
<slot name="content"></slot>
</div>
</div>
options: {
scales: {
yAxes: [
{ id: 'y1', position: 'left' },
{ id: 'y2', position: 'right' },
],
},
},
приложение делается на vue
@click="$store.commit('setCoords', marker.coords)"
.