VUE 2 сортировка компонентов
Итак страница имеет
<div id="app"> <sort> <line uid="1"> бла бла бла — много html идет в слот </line> <line uid="2"> бла бла бла — много html идет в слот </line> <line uid="3"> бла бла бла — много html идет в слот </line> </sort> </div> В компоненте line кнопочка - наверх (вниз) по кнопочке улетает событие. Родитель (sort) ловит событие и меняет местами компоненты Вся эта колобаха генерится движком сайта. Вытаскивать все данные в Vue и там их сортить совсем не хочется. |
Это противоречит сути vue так-то. Именно отдельно данный и надо слать, не вижу проблем заменить этот мусор на json.
Но если оень хочется, то придётся ручками писать render функцию, ктоторая будет сортировать ноды упавшие в слот к <sort> |
Цитата:
Но локоть сильно близко. И вроде все дети есть ... и можно было бы их местами поменять... Или забить на эту задачу (и сделать смену на сервере в общем то админка) или приклеить туда jQuery и на нем махнуть местами два слоя... |
Кстати ты не можешь называть компонент "line" (если конечно не пошаманишь с конфигом Vue), т.к. такой элемент есть среди стандартных.
|
Цитата:
Поставить один элемент перед другим - одна строка. elem1.before (elem2) // elem2 поставить перед elem1 |
Можно вообще это всё обойти: использовать для sort - display:flex (row\coluum что надо) и проставлять детям order не трогая реальной разметки.)
|
С render функцией это можно сделать примерно так:
<div id="app">
<v-sort>
<v-line uid="1">1 бла бла бла — много html идет в слот </v-line>
<v-line uid="2">2 бла бла бла — много html идет в слот </v-line>
<v-line uid="3">3 бла бла бла — много html идет в слот </v-line>
</v-sort>
</div>
<script src="https://unpkg.com/vue@2"></script>
<script>
function addListener(options, type, listener) {
if (!options || !type || !listener)
return;
if (!options.listeners)
options.listeners = {};
if (!options.listeners[type])
options.listeners[type] = listener;
else if (Array.isArray(options.listeners[type]))
options.listeners[type].push(listener);
else
options.listeners[type] = [options.listeners[type], listener];
return options;
}
Vue.component('v-sort', {
data() {
return {
keyCounter: 0,
events: ['up', 'down'],
children: []
}
},
render(h) {
return h('div', this.children.map(
({vNode, key}) => h('div', { key }, [vNode])
));
},
created() {
this.children = this.getChildren();
},
methods: {
getNewKey() {
return this.keyCounter++;
},
getChildren() {
const vNodes = this.$slots.default?.filter(vNode => vNode.componentOptions);
if (!vNodes?.length)
return [];
return vNodes.map(vNode => {
const key = this.getNewKey();
this.events.forEach(event => addListener(
vNode.componentOptions,
event,
(...args) => this[event](key, ...args)
));
return {
key,
vNode
};
});
},
findIndexByKey(key) {
return this.children.findIndex(child => key === child.key);
},
up(key) {
const index = this.findIndexByKey(key);
if (index < 1) return;
this.children.splice(index - 1, 2, this.children[index], this.children[index - 1]);
},
down(key) {
const index = this.findIndexByKey(key);
if (index === -1 || index > this.children.length - 2) return;
this.children.splice(index, 2, this.children[index + 1], this.children[index]);
}
}
})
Vue.component('v-line', {
template: `<p>
<button @click="$emit('up')">up</button>
<slot/>
<button @click="$emit('down')">down</button>
</p>`
});
new Vue().$mount('#app')
</script>
Конечно гораздо лучше было бы если бы не нужно было слушать события из подкомпонентов, а просто рисовать кнопки прямо из компонента sort.) |
Нереально круто!
В общем посмотрел я на твою колобаху и понял, мне проще переписать в стандартной модели ВУ. А вообще нереально круто. |
Aetae,
если я каким-то хитрым способом изменю порядок в this.children, что нужно сделать чтоб новые изменения вступили в силу? |
Вот чем мне не нравятся все фрейворки, так это тем, что простейшие вещи (почесать левое ухо) надо делать хрен знает как (правой ногой через спину)
|
| Часовой пояс GMT +3, время: 22:12. |