// есть вариант применить рекурсию
const flatTree = (tree, childrenKey) =>
(tree instanceof Array ? tree : []).reduce((acc, n) => (
acc.push(n, ...flatTree(n[childrenKey], childrenKey)),
acc
), []);
// а можно обойтись и без неё
const flatTree = function*(tree, childrenKey) {
const stack = [];
for (let [ i, arr ] = this(tree); ++i < arr.length || stack.length;) {
if (i === arr.length) {
[ i, arr ] = stack.pop();
} else {
yield arr[i];
stack.push([ i, arr ]);
[ i, arr ] = this(arr[i][childrenKey]);
}
}
}.bind(x => [ -1, Array.isArray(x) ? x : [] ]);v-for по его значению:computed: {
users() {
// если использовать обычную функцию
return flatTree(this.elements, 'children');
// или, генератор
return [...flatTree(this.elements, 'children')];
},
},<option v-for="n in users" :key="n.id">{{ n.name }}</option>
<gmap-map
ref="map"
...const bounds = new google.maps.LatLngBounds();
массивКоординатВашихЛокаций.forEach(n => bounds.extend(n));
this.$refs.map.fitBounds(bounds);
не хочу дублировать код в v-slot:fastFilters, но как мне сделать так, чтоб по определенному флагу на фильтрах он появлялся и в fastFilters
<toolbar>
<slot name="fastFilters">
<slot name="filters" v-if="а здесь ваш флаг">
</toolbar>
<div class="filters">
<slot name="filters">
</div>
props: {
modelValue: {
type: String,
default: '',
},
},
emits: [ 'update:modelValue' ],
setup(props, { emit }) {
const value = ref('');
watchEffect(() => value.value = props.modelValue);
return {
value,
onInput: e => emit('update:modelValue', value.value = e.target.value),
};
},<input :value="value" @input="onInput">
computed: {
cartTotalCost() {
return this.cart_data.reduce((acc, n) => acc + n.price * n.amount, 0);
},
...
isValid() {
return Object.values(obj).flatMap(Object.values).every(n => n.valid);
},objects() {
return Object.values(this.obj).flatMap(Object.values);
},
isValid() {
return this.objects.every(n => n.valid);
},
<router-link :to="`/Product/${item}`">{{ item }}</router-link>
data: () => ({
handle: null,
...
}),
mounted() {
const mql = matchMedia('(max-width: 768px)');
const onChange = () => this.handle = mql.matches ? '.image' : null;
onChange();
mql.addEventListener('change', onChange);
this.$on('hook:beforeDestroy', () => mql.removeEventListener('change', onChange));
},<draggable
:options="{ handle, ... }"
...
>
computed: {
deadlineText() {
const today = new Date().setHours(0, 0, 0, 0);
const deadline = new Date(this.task.deadline).setHours(0, 0, 0, 0);
return [ 'Уже было', 'Сегодня', 'Жди' ][1 + Math.sign(deadline - today)];
},
},
data: () => ({
selected: [ null, null, null ],
...
}),computed: {
selectData() {
const data = Array.from({ length: this.selected.length }, () => []);
for (let { items } = this.selectors, i = 0; items && i < data.length; i++) {
data[i] = items;
items = items.find(n => n.value === this.selected[i])?.childs;
}
return data;
},
...
},methods: {
resetSelected(index) {
for (let i = index; i < this.selected.length; i++) {
this.selected[i] = null;
}
},
...
},<v-col v-for="(n, i) in selected" cols="4">
<v-select
:items="selectData[i]"
item-text="title"
item-value="value"
v-model="selected[i]"
@change="resetSelected(i + 1)"
></v-select>
</v-col>
В документации не нашел ответа, как и похожего решения.
mounted() {
this.fetchPosts()
},watch: {
'$route.query.page': {
immediate: true,
handler: 'fetchPosts',
},
},
<script setup>
import { Navigation, Pagination, Scrollbar, A11y } from 'swiper';
import { Swiper, SwiperSlide } from 'swiper/vue';
const onSwiper = (swiper) => console.log(swiper);
const onSlideChange = () => console.log('slide change');
const modules = [ Navigation, Pagination, Scrollbar, A11y ];
</script>
<style>
@import 'swiper/css';
@import 'swiper/css/navigation';
@import 'swiper/css/pagination';
@import 'swiper/css/scrollbar';
</style>
Вроде делаю как в документации
get the Swiper instance in components inside of Swiper
import { ref } from 'vue';setup() {
const swiper = ref();
return {
swiper,
onSwiper: instance => swiper.value = instance,
...
};
},<swiper
@swiper="onSwiper"
...
>