Ответы пользователя по тегу Vue.js
  • Глобальная шина событий Vue.js это норм?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Эта штука уже несколько лет как не рекомендуется к использованию.
    Но, конечно, решение за вами, надо - используйте.
    Ответ написан
    Комментировать
  • Как добавить фильтрацию по select к существующему поиску?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Добавляете в компонент свойство, которое будет содержать текущее значение выпадающего списка:

    data: () => ({
      status: '',
      ...

    Получаете массив возможных (не считая дефолтного) значений выпадающего списка:

    computed: {
      statuses() {
        return [...new Set(this.characters.map(n => n.status))];
      },
      ...

    Сам список пусть создаётся так, например:

    <select v-model="status">
      <option value="">&lt; ALL &gt;</option>
      <option v-for="n in statuses">{{ n }}</option>
    </select>

    Ну и фильтруете, наконец:

    computed: {
      filteredCharacters() {
        const search = this.search.toLowerCase();
        const status = this.status;
    
        return this.characters.filter(n => (
          (!search || n.name.toLowerCase().includes(search)) &&
          (!status || status === n.status)
        ));
      },
      ...
    Ответ написан
    1 комментарий
  • Как получить yandex marker в vue-yandex-maps?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Не надо манипулировать маркерами напрямую. Храните в данных компонента индекс активного маркера, по событиям enter/leave устанавливайте его значение, в зависимости от которого передавайте в экземпляры компонента маркера картинки иконок:

    data: () => ({
      map: {
        activeMarkerIndex: null,
        markerIconImages: [ MAP_MARKER_DEFAULT, MAP_MARKER_ACTIVE ],
        ...

    <ymap-marker
      v-for="(n, i) in markers"
      :icon="{
        ...map.markerIcon,
        imageHref: map.markerIconImages[+(map.activeMarkerIndex === i)],
      }"
      @mouseenter="map.activeMarkerIndex = i"
      @mouseleave="map.activeMarkerIndex = null"
      ...

    <li
      v-for="(n, i) in objects"
      @mouseenter="map.activeMarkerIndex = i"
      @mouseleave="map.activeMarkerIndex = null"
      ...

    https://jsfiddle.net/bw5eym2n/
    Ответ написан
    Комментировать
  • Почему хук мешает повторному появлению компонента?

    0xD34F
    @0xD34F Куратор тега Vue.js
    updated() {
      this.$refs.scroll.addEventListener('wheel', this.fadeOut);
    },

    Это ещё что за убожество?
    Откройте документацию vue, и разберитесь, как правильно подключать обработчики событий к элементам.

    Когда условие в v-if ложно, элемента нет. Соответственно, в $refs.scroll вместо ссылки на несуществующий элемент пишется null, и вы пытаетесь обратиться к свойству этого null, чего делать не следует - у null никаких свойств нет и быть не может, подобные обращения заканчиваются ошибками вот как та, что получили вы.
    Ответ написан
  • Реактивность не совсем работает vue 3?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Открываем раздел документации, посвящённый реактивности, и читаем там, что

    Отследить переназначение локальных переменных <...> не получится, такого механизма просто нет в JavaScript. Можно лишь отслеживать изменения свойств объектов.

    Так что менять надо внутреннее содержимое, а не заменять объект на полностью новый. Вместо reactive следует использовать ref (соответственно, вместо copyDB = будет copyDB.value =), или же удалять существующие элементы массива, и добавлять новые:

    copyDB.splice(0, copyDB.length, ...addFlags(props.items));
    Ответ написан
    Комментировать
  • Как передать данные через vuex в router?

    0xD34F
    @0xD34F Куратор тега Vue.js
    не передаются данные в router-link

    А что за данные? Почему не показали (да и не только данные - ни строчки кода не вижу)? Случайно не объект запихнуть пытаетесь? - если так, то скорее всего всё передаётся, но данные превращаются в мусор. Дело в том, что роутер приводит значения параметров к строкам (кроме массивов - они-то останутся массивами, в строки будут превращены их элементы). Соответственно, если дальше вы из полученной строки или строк попытаетесь извлечь какие-то свойства (конечно из тех, что у строк нет), то получите undefined.

    Если же сделать корзину на одной странице с каталогом, то все прекрасно записывается в массив корзины.

    Что-то не понял, что конкретно вы пытаетесь сделать. Вижу два варианта, и оба бредовые.

    1. Вы пытаетесь добавлять товар в корзину при переходе по ссылке. Если так - не надо никуда переходить, вместо router-link сделайте кнопку, по клику на которую сразу будет вызываться соответствующее действие или мутация.

    2. Вы пытаетесь через router-link передать в компонент корзины массив добавленных в неё товаров. Если так - не надо ничего передавать, пусть компонент корзины забирает данные сразу из vuex.
    Ответ написан
  • Как сделать доп фильтр?

    0xD34F
    @0xD34F Куратор тега Vue.js
    <option v-for="item in info">
      {{ item.fieldTypes.geo }}
    </option>

    Это неправильно. Если значения в fieldTypes.geo не уникальны, option'ы тоже будут повторяться. Зачем это? Не надо. Делаем вычисляемое свойство, представляющее уникальные значение, и используем при создании option'ов его:

    computed: {
      uniqueGeo() {
        return [...new Set(this.info.map(n => n.fieldTypes.geo))];
      },
      ...

    <option v-for="n in uniqueGeo">{{ n }}</option>

    В вычисляемом свойстве, которое представляет отфильтрованные данные, добавляем проверку второго значения, переписываем его следующим образом:

    computed: {
      filteredOffers() {
        const vacancy = this.searchVacancyName.toUpperCase();
        const geo = this.searchGeo;
    
        return this.info.filter(n => (
          (!vacancy || n.fieldTypes.vacancyName.toUpperCase().includes(vacancy)) &&
          (!geo || n.fieldTypes.geo === geo)
        ));
      },
      ...
    Ответ написан
    1 комментарий
  • Как во Vue подождать загрузки чего-то и только после успешной загрузки позволить навесить обработчик click?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Вот не надо этой ерунды с жонглированием обработчиками.

    Пусть кнопка будет неактивной, пока данных нет:

    <button :disabled="!данные" @click="onClick">

    Заодно и пользователь, вместо того, чтобы испытывать недоумение по поводу отсутствия какой-либо реакции на свои действия, будет ясно видеть, что кликать по кнопке не то, что не надо - бессмысленно.
    Ответ написан
    Комментировать
  • Как изменить вложенное свойство через сцепление во vue?

    0xD34F
    @0xD34F Куратор тега Vue.js
    computed: {
      model() {
        return new Proxy(Object.fromEntries(this.obj2.map(n => [ n.model, null ])), {
          get: (target, prop) => typeof prop === 'string'
            ? prop.split('.').reduce((p, c) => p?.[c], this.obj)
            : target[prop],
          set: (target, prop, value) => {
            const keys = prop.split('.');
            const key = keys.pop();
            const obj = keys.reduce((p, c) => (!p.hasOwnProperty(c) && this.$set(p, c, {}), p[c]), this.obj);
            this.$set(obj, key, value);
            return true;
          },
        });
      },
    },

    <div v-for="(v, k) in model">
      <input v-model="model[k]">
    </div>

    https://jsfiddle.net/34brtvok/

    Или, если несуществующие пути не должны обрабатываться, можно сделать попроще:

    computed: {
      model() {
        return this.obj2.map(n => {
          const keys = n.model.split('.');
          const key = keys.pop();
          const obj = keys.reduce((p, c) => p?.[c], this.obj);
    
          return obj && { obj, key };
        }).filter(Boolean);
      },
    },

    <div v-for="n in model">
      <input v-model="n.obj[n.key]">
    </div>

    https://jsfiddle.net/34brtvok/1/
    Ответ написан
    Комментировать
  • Как из объекта Proxy извлечь данные?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Точно так же, как если бы вместо Proxy у вас был оригинальный объект (кстати, а почему вы этого не попробовали сделать - что, увидели этот непонятный Proxy и испугались?).

    Vue заворачивает данные в Proxy для отслеживания изменений. Если вдруг очень надо, можно получить оригинальные данные с помощью toRaw.

    получить массив

    А где у вас там массив? Никакого массива нет. Или исправляйте код на сервере, чтобы присылались верные данные, или используйте Object.values.
    Ответ написан
    Комментировать
  • Как убрать реактивность?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Вам это не нужно.

    Компонент, который занимается редактированием - пусть он создаёт внутри себя копию редактируемых данных, и работает с копией. А по нажатию кнопки сохранения эта копия передаётся в мутацию, где значения её свойств будут записаны в оригинальный объект. Как-то так.
    Ответ написан
    Комментировать
  • Почему пропадает реактивность при слиянии объектов?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Потому что вы заменяете реактивный объект обычным.

    Вместо присваивания нового объекта добавляйте свойства одного другому:

    Object.assign(object1, object2);

    Ну или оборачивайте новый объект в reactive, так же, как и старый.
    Ответ написан
    Комментировать
  • Почему не изменяется значение в Vuex?

    0xD34F
    @0xD34F Куратор тега Vue.js
    По клику на кнопку вызывается мутация, в которою передаётся id.

    Эти слова следовало проиллюстрировать кодом. Потому что сама по себе показанная вами мутация... дичь дикая конечно, но рабочая, проблема где-то в другом месте - может, неправильно вызываете мутацию, или не ту, или при вызове передаёте несуществующий id.

    Я так понимаю, потому что метод возвращает только false/true, а не измененный item.

    Не понимаете. Какая разница, что вы там из мутации возвращаете? Да никакой.

    Как примерно должен был выглядеть ваш код. Смотрите, сравнивайте с тем, что у вас реально есть.

    UPD. Вынесено из комментариев:

    id передается, проверял через консоль

    ...mapMutations(['chekedItem', 'deleteItem']),
    itemSucces(id) {
      this.chekedItem({id});
    },

    Правда проверяли? И как же вы ухитрились при этом не заметить, что передаёте объект вместо числа? Кстати, в данной ситуации можно и объект передавать - сам item, тогда его не придётся искать в мутации:

    chekedItem: (state, item) => item.checked = !item.checked,

    Зачем метод дополнительный создавать? - вызывайте сразу chekedItem, а itemSucces удалите.
    Ответ написан
  • Почему не работает функция в Vue?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Нет никакой функции, нечему работать. Вы выполняете статическую привязку значения параметра, так что передаёте в компонент строку, а не функцию:

    succesItem='succesItem'

    А вообще, вам не мешало бы почитать документацию, чтобы узнать, как правильно в родительских компонентах обрабатывать события дочерних.
    Ответ написан
    Комментировать
  • Как использовать глобальный фильтр в методах?

    0xD34F
    @0xD34F Куратор тега Vue.js
    А оно вам действительно надо? Может, это тогда не фильтр должен быть? Подумайте об этом.

    Глобальные фильтры лежат в Vue.options.filters. Соответственно:

    const filteredValue = Vue.options.filters.someFilter(value);
    
    // или, если вспомнить, что компоненты являются экземплярами Vue
    const filteredValue = this.constructor.options.filters.someFilter(value);
    Ответ написан
    Комментировать
  • Как добавить data-атрибут в компонент vue-slick-carousel?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Поскольку ваш data-атрибут очевидно не является параметром, он конечно должен был быть назначен корневому элементу компонента, но автор компонента наследование атрибутов решил отключить. Так что придётся закостылить. Добавляем ссылку на экземпляр компонента, после монтирования вручную назначаем корневому элементу атрибут:

    <vue-slick-carousel
      ref="slick"
      @hook:mounted="$refs.slick.$el.dataset.id = 666"
      ...

    UPD. Раз у вас там v-for, значит вместо одной ссылки на экземпляр, будет массив. Надо индекс указывать. Ну и не забывать о том, что соответствие порядка элементов в массиве ссылок на экземпляры порядку элементов в массиве с данными не гарантируется.

    https://jsfiddle.net/v6pot7nr/
    Ответ написан
  • Как выполнить только один раз?

    0xD34F
    @0xD34F Куратор тега Vue.js
    throttle:

    const emitRedit = throttle(emit.bind(null, 'redit'), 60000, { leading: false });
    
    watch(() => {
      emit('input', text.value);
      emitRedit(text.value);
    }, [ text ]);
    Ответ написан
    Комментировать
  • Почему возникает ошибка "Property 'toLowerCase' does not exist on type 'Ref'"?

    0xD34F
    @0xD34F Куратор тега Vue.js
    seachCityName - обычная строка

    Да ну? Судя по тексту ошибки - это ref. А значит, вашей строкой будет seachCityName.value.
    Ответ написан
    1 комментарий
  • Как по клику в li добавить букву/символы?

    0xD34F
    @0xD34F Куратор тега Vue.js
    data: () => ({
      items: [
        'hello, world!!',
        'fuck the world',
        'fuck everything',
      ],
    }),

    <ul>
      <li
        v-for="(n, i) in items"
        v-text="n"
        @click="$set(items, i, `${n}!`)"
      ></li>
    </ul>
    Ответ написан
    1 комментарий
  • Как с помощью vue изменить background-color каждому второму элементу списка?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Лучше никак. Такие вещи принято делать через css:

    .item:nth-child(2n) {
      background-color: red;
    }

    <div v-for="n in items" class="item">

    Но, конечно, можно назначать или не назначать стили в зависимости от индекса:

    <div v-for="(n, i) in items" :style="i & 1 && { backgroundColor: 'red' }">

    https://jsfiddle.net/qcu93h2w/
    Ответ написан