Как в quasar vue повесить click на иконку компонента expansion?
Столкнулся с проблемой.
Во фреймворке quasar есть прекрасный компонент меню q-expansion-item

Вот так он выглядит.
У него есть режим expand-icon-toggle, который позволяет открывать меню только по клику на стрелочку. Мне это и надо, но я не имею изначально список меню, а подгружаю его с back. Следовательно мне надо повесить обработчик на эту иконку. Но т.к. она идет не слотом, я не знаю как это сделать.
Ответы (1 шт):
У компонента QExpansionItem есть методы:
show- показать (развернуть)hide- скрыть (свернуть)toggle- переключить на противоположное состояние
, и он эмитит события:
inputshowbefore-showhidebefore-hideafter-showafter-hide
То есть, присутствуют все возможности и для программного открытия/закрытия, и для добавления обработчиков соответствующих событий.
Для доступа к экземплярам компонентов, обычно используются рефы (референсы, ссылки) на них.
Добавив атрибут ref="имяРефа" одиночному элементу в шаблоне, доступ к нему можно получить через свойство экземпляра $refs.имяРефа (или $refs['имяРефа'], если имя не соответствует правилам именования свойств в JS). А добавив такой атрибут элементу в итерации v-for, доступ к рефу потребует указания еще и индекса: $refs['имяРефа'][индекс].
Вызов метода компонента полученного по рефу, ничем не отличается от вызова метода js-объекта.
Добавление и удаление обработчиков событий - либо директивой v-on в шаблоне, либо по рефу через методы $on и $off.
Ниже простой пример, где раз в 2 секунды переключается (через toggle) элемент списка, выбранный по рефу случайным образом; и выполняется вывод в консоль из обработчика события input (на переключение курсором, обработчик конечно тоже реагирует).
Правда, увидеть эту забавность тут можно только открыв пример на всю страницу после его запуска, т.к. ифрейм слишком уж мелкий.
new Vue({
el: '#q-app',
data() { return {
loading: false,
icons: [],
users: [],
}},
computed: {
iconsCount() { return this.icons.length; },
},
methods: {
printToggledItem(itmData, itmIdx, itmVal) {
console.clear();
console.log(`Элемент №${itmIdx + 1} (${itmData.name}) ${itmVal ? 'от' : 'за'}крыт`);
},
rndTo(to) { return Math.floor(Math.random() * to); },
},
async mounted() {
this.loading = true;
const usersUrl = 'https://jsonplaceholder.typicode.com/users',
iconsUrl = 'https://raw.githubusercontent.com/google/material-design-icons/master/font/MaterialIconsOutlined-Regular.codepoints';
this.users = await fetch(usersUrl).then(r => r.json());
this.icons = (await fetch(iconsUrl).then(r => r.text()))
.split(/\r?\n/).map(l => l.split(' ')[0]).filter(n => n.length);
await (new Promise(yay => setTimeout(yay, 2e3)));
this.loading = false;
setInterval(() => {
const itm = this.$refs['qexp-item'][this.rndTo(this.users.length)];
itm.toggle();
}, 2e3);
},
});
* { font-family: sans-serif; }
<div id="q-app">
<div class="q-pa-md" style="max-width: 350px">
<q-card v-if="loading" flat bordered class="row items-center q-pa-lg">
<q-circular-progress indeterminate size="50px" color="lime" class="col"></q-circular-progress>
<div class="col">Загрузка...</div>
</q-card>
<q-list v-else bordered class="rounded-borders">
<q-expansion-item v-for="(user, idx) in users" :key="user.id" ref="qexp-item"
expand-separator expand-icon-toggle :icon="icons[rndTo(iconsCount)]"
:label="user.name" :caption="user.email"
@input="val => printToggledItem(user, idx, val)"
>
<q-card>
<q-card-section>
<div><b>From:</b> {{ user.address.city }}</div>
<div><b>Phone:</b> {{ user.phone }}</div>
<q-separator class="q-my-md"></q-separator>
<div><b>Company:</b> {{ user.company.name }}</div>
<div class="text-teal-9"><i>"{{ user.company.catchPhrase }}"<i></div>
</q-card-section>
</q-card>
</q-expansion-item>
</div>
<link href="https://fonts.googleapis.com/css?family=Material+Icons" rel="stylesheet" type="text/css">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/quasar.min.css" rel="stylesheet" type="text/css">
<script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/quasar.umd.min.js"></script>