Задать вопрос
  • Debounce и динамический input v-model как подружить?

    0xD34F
    @0xD34F Куратор тега Vue.js
    хочу сделать задержку ввода

    Ну так и следите тогда за вводом:

    methods: {
      onInput: debounce(function(val) {
        this.debouncedInput = val;
      }, 500),
      ...

    <v-text-field
      @input="onInput"
      ...

    Если же на самом деле нужно следить не только за тем, что вводит пользователь непосредственно в input, а за изменениями вообще, тогда делаете вычисляемое свойство, представляющее массив интересующих вас значений, вешаете на него наблюдателя, который ищет изменившееся значение:

    computed: {
      count() {
        return this.orders.map(n => n.count);
      },
    },
    watch: {
      count: debounce(function(newVal, oldVal) {
        this.debouncedInput = newVal.find((n, i) => n !== oldVal[i]);
      }, 500),
    },
    Ответ написан
    Комментировать
  • Возможно ли добавить .active к маркеру с помощью router-link?

    0xD34F
    @0xD34F Куратор тега Vue.js
    data: () => ({
      links: [ 'tasks', 'kanban', 'activity', 'calendar', 'files' ],
    }),

    ul
      li(v-for="n in links")
        router-link(:to="{ name: n }") {{ n }}
    .marker
      div(v-for="n in links" :class="[ `select${n}`, $route.name === n ? 'active' : '' ]")
        span

    https://jsfiddle.net/rmnLokj3/

    Непонятно только зачем оно надо - убрали бы эти "маркеры", и стилизовали сами ссылки, там вручную никаких классов добавлять не надо, уже всё есть.

    https://jsfiddle.net/rmnLokj3/1/
    Ответ написан
    Комментировать
  • Почему в параметр функции компонента Vue 3 прилетает undefined?

    0xD34F
    @0xD34F Куратор тега Vue.js
    const certificate = ref({});

    shortingTechItems(certificate.pto)

    прилетает undefined

    Вот это на хрен неожиданность - пытаемся прочитать из объекта значение несуществующего свойства и получаем... получаем... А-а-а-а-а-а!!!!!!111

    В чем проблема

    В нулевых знаниях js.

    как исправить?

    Вообще - освоить js.

    Ну а прямо сейчас можете задать для передаваемого в функцию свойства дефолтное значение в виде пустого массива. Или можете проверять внутри функции, что пришло, если не массив - не пытаться пользоваться этой штукой как массивом. Или можете не рендерить элемент, по данных нет.

    UPD. Обязательно тратить семь строк на то, что можно сделать в одну?

    - const shortingTechItems = (item) => {
    -   const arr = [];
    -   item.map((i) => {
    -     arr.push(Number(i.replace(/\D+/g, "")));
    -   });
    -   return arr;
    - };
    + const shortingTechItems = items => items.map(n => +n.replace(/\D/g, ''));
    Ответ написан
    Комментировать
  • Как сделать компонент радио-кнопок на Vue?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Vue 2, options API
    Компонент радиогруппы:

    props: [ 'value' ],
    provide() {
      return {
        radioGroup: this,
      };
    },

    Компонент радиокнопки:

    props: [ 'value' ],
    inject: [ 'radioGroup' ],

    <input
      type="radio"
      :value="value"
      :checked="radioGroup.value === value"
      @change="radioGroup.$emit('input', value)"
    >

    https://jsfiddle.net/d7aow8fq/

    Vue 3, composition API
    Компонент радиогруппы:

    props: [ 'modelValue' ],
    emits: [ 'update:modelValue' ],
    setup(props, { emit }) {
      provide('radioGroupValue', computed({
        get: () => props.modelValue,
        set: v => emit('update:modelValue', v),
      }));
    },

    Компонент радиокнопки:

    props: [ 'value' ],
    setup() {
      return {
        radioGroupValue: inject('radioGroupValue'),
      };
    },

    <input
      type="radio"
      :value="value"
      v-model="radioGroupValue"
    >

    https://jsfiddle.net/d7aow8fq/2/
    Ответ написан
    4 комментария
  • Как сделать object to HTML string?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const voidTags = [ 'input', 'img', 'br', 'hr', ещё какой-то тэг, и ещё, ... ];
    
    function createHTML(data) {
      const attrs = Object
        .entries(data.attrs ?? {})
        .map(n => `${n[0]}="${n[1]}"`)
        .join(' ');
    
      const startTag = `<${data.tagName}${attrs && (' ' + attrs)}>`;
    
      if (voidTags.includes(data.tagName)) {
        return startTag;
      }
    
      const children = (data.subTags ?? [])
        .map(createHTML)
        .join('');
    
      return `${startTag}${data.text ?? ''}${children}</${data.tagName}>`;
    }
    Ответ написан
    Комментировать
  • Как вернуть нужное значение?

    0xD34F
    @0xD34F
    def sq(n):
      return '\n'.join('x' * (i + 1) for i in range(n))
    Ответ написан
  • V-range-slider - почему не изменяется вид при изменении модели?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Кто-то невнимательно читал документацию:

    Vue cannot detect the following changes to an array <...> When you directly set an item with the index

    Вместо присваивания значений отдельным элементам перезаписывайте массив целиком:

    filterRS.filter_range_value = [ selected_start, selected_end ];


    А вообще, как-то стрёмно всё это выглядит. Может, лучше пусть выбранные значения всегда будут числами? - это позволит использовать в v-model один массив и для select'ов и для range'а, без необходимости заниматься ручной синхронизацией. А там, где значения надо представить в человекопонятном виде, это можно делать через вычисляемое свойство - например, так.
    Ответ написан
    1 комментарий
  • Как складывать числа, представленные в виде массивов цифр?

    0xD34F
    @0xD34F
    Массивы перебираются от конца к началу; цикл крутится до тех пор, пока какой-то из массивов не полностью обработан или имеет место быть переполнение разряда. Сумма разряда - сумма элементов массивов (если массив кончился, то 0) и переполнения предыдущего разряда. Цифра разряда нового числа - младший разряд суммы (т.е., остаток от деления на 10).

    function sum(a, b) {
      const result = [];
    
      for (
        let i = ~-a.length, j = ~-b.length, overflow = 0;
        i >= 0 || j >= 0 || overflow;
        i--, j--
      ) {
        const digit = (a[i] | 0) + (b[j] | 0) + overflow;
        overflow = +(digit > 9);
        result.push(digit % 10);
      }
    
      return result.reverse();
    }
    Ответ написан
    6 комментариев
  • Как вернуть строку в которой есть нужное мне слово?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Получаем одну подходящую строку:

    const search = ` ${str}.`;
    const item = arr.find(n => n.includes(search));

    Все:

    const test = RegExp.prototype.test.bind(RegExp(`\\b${str}\\b`));
    const items = arr.filter(test);
    Ответ написан
    1 комментарий
  • Как уточнить работу меток в Яндекс карте?

    0xD34F
    @0xD34F Куратор тега Яндекс.Карты
    Добавить ссылкам и меткам индексы - использовать для этого data-атрибуты и properties соответственно.

    Дальше при клике по ссылке просто открываете балун метки с тем же индексом, что и у ссылки:

    контейнерСсылок.addEventListener('click', e => {
      const index = e.target.dataset.index;
      if (index) {
        массивМеток[index].balloon.open();
      }
    });

    Меткам добавляете обработчики событий открытия и закрытия балуна, где добавляете/снимаете выделение ссылке с тем же индексом, что и у метки:

    массивМеток.forEach(n => {
      n.events.add('balloonopen', onBalloonOpen);
      n.events.add('balloonclose', onBalloonClose);
    });
    
    function onBalloonOpen(e) {
      const index = e.get('target').properties.get('index');
      const link = контейнерСсылок.children[index]; /* или, если структура списка ссылок более сложная,
                                                     * как в примере из документации, можно искать нужную
                                                     * через .querySelector(`[data-index="${index}"]`)
                                                     */
      link.scrollIntoView({
        behavior: 'smooth',
      });
      link.classList.add('active');
    }
    
    function onBalloonClose(e) {
      const index = e.get('target').properties.get('index');
      контейнерСсылок.children[index].classList.remove('active');
    }

    https://jsfiddle.net/19sbtk0d/1/
    Ответ написан
  • Как заменить имена пользователей на вёрстку при рендеринге элементов массива?

    0xD34F
    @0xD34F Куратор тега Vue.js
    .highlight {
      color: white;
      background: red;
    }

    methods: {
      highlightNames: str => str.replace(/(?<=^|\s)@\S+/g, '<span class="highlight">$&</span>'),
    },

    <div v-html="highlightNames(item.text)"></div>
    Ответ написан
    1 комментарий
  • Как с помощью рекурсии преобразовать массив?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Не надо никакой рекурсии:

    arr.map((n, i, a) => a.slice(0, i + 1).join(''))
    // или
    arr.reduce((acc, n) => (acc.push((acc.at(-1) ?? '') + n), acc), [])

    Но, конечно, если очень хочется, то

    (function xxx(arr, str = '') {
      if (str.length === arr.length) {
        return [];
      }
    
      const newStr = str.concat(arr[str.length]);
      return [ newStr, ...xxx(arr, newStr) ];
    })(arr)
    Ответ написан
    1 комментарий
  • Как отфильтровать массив объектов со вложенными массивами?

    0xD34F
    @0xD34F Куратор тега Vue.js
    отфильтровать массив по введенному значению в строке поиска в watch-ере

    Для таких вещей принято использовать computed:

    computed: {
      filteredProjects() {
        const search = this.searchString.toLowerCase();
    
        return this.journal.flatMap(n => {
          return n.savedProjects.filter(m => m.name.toLowerCase().includes(search));
        });
      },
      ...
    Ответ написан
    2 комментария
  • Как сделать слежение полукруга за мышью в круге на Vue js?

    0xD34F
    @0xD34F Куратор тега Vue.js
    const circles = reactive(Array.from({ length: 10 }, () => {
      const size = `${50 + Math.random() * 50 | 0}px`;
    
      return {
        left: `${Math.random() * window.innerWidth | 0}px`,
        top: `${Math.random() * window.innerHeight | 0}px`,
        width: size,
        height: size,
      };
    }));
    
    function onMouseMove({ pageX, pageY }) {
      circles.forEach(n => {
        const angle = Math.atan2(-pageX + parseInt(n.left), pageY - parseInt(n.top));
        n.transform = `translate(-50%, -50%) rotate(${angle}rad)`;
      });
    }
    
    onMounted(() => document.addEventListener('mousemove', onMouseMove));
    onBeforeUnmount(() => document.removeEventListener('mousemove', onMouseMove));

    <div v-for="n in circles" :style="n" class="circle"></div>

    .circle {
      position: absolute;
      display: inline-block;
      transform: translate(-50%, -50%);
      box-sizing: border-box;
      border: 10px solid silver;
      border-bottom-color: black;
      border-radius: 50%;
    }

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

    0xD34F
    @0xD34F
    dict(n.split('=') for n in string.split('?'))
    Ответ написан
    Комментировать
  • Как менять иконку при сортировке каждого столбца?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Заменить

    <div class="img">
      <img
        v-if="
          currentSort === tableHeader.name && currentSortDir === 'desc'
        "
        src="https://avatars.mds.yandex.net/i?id=2a00000179dddfd8448e981541c75114a166-4080640-images-thumbs&n=13"
        alt=""
      />
      <img v-else src="https://avatars.mds.yandex.net/i?id=f5c72675790756bfeb0dbe860b634778-5110698-images-thumbs&n=13" alt="" />
    </div>

    на

    <div class="img" v-if="currentSort === tableHeader.influencerSync">
      <img
        :src="currentSortDir === 'desc'
          ? 'https://avatars.mds.yandex.net/i?id=2a00000179dddfd8448e981541c75114a166-4080640-images-thumbs&n=13'
          : 'https://avatars.mds.yandex.net/i?id=f5c72675790756bfeb0dbe860b634778-5110698-images-thumbs&n=13'
        "
      />
    </div>
    Ответ написан
  • Можно ли сделать сортировку через computed, если сортировок несколько?

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

    Добавляем в компонент свойство - массив объектов, которые будут содержать в себе столбец, по которому надо сортировать, и направление сортировки.

    Когда пользователь кликает по заголовку столбца, проверяем, есть ли этот столбец в массиве. Если нет - добавляем с порядком сортировки по возрастанию. Если есть и порядок сортировки по возрастанию - делаем порядок сортировки по убыванию. Есть и порядок сортировки по убыванию - удаляем.

    Собственно сортировка (функция сравнения элементов): обходим массив и сравниваем значения соответствующих свойств у переданных элементов; как только попадаются неравные - возвращаем результат, не забыв его умножить на +/- 1, в зависимости от направления сортировки.

    https://jsfiddle.net/yp8nhLe5/1/
    Ответ написан
    Комментировать
  • Как в React создать два зависимые инпута типа range (slider) с неровным шагом?

    0xD34F
    @0xD34F Куратор тега React
    Сложить допустимые значения второго инпута в массив:

    const values = [ 2, 3, 5, 7, 11, 13, 17, 19, ... ];

    Сделать эффект, зависящий от обоих значений, где второе будет исправляться. Берёте ту половину допустимых значений второго инпута, которая соответствует текущему значению первого инпута, ищите в ней ближайшее к текущему второму:

    useEffect(() => {
      const index = values.indexOf(граничное_значение_второго_инпута);
    
      setVal2(values
        .slice(...(val1 > граничное_значение_первого_инпута ? [ index ] : [ 0, index ]))
        .reduce((val, n) => Math.abs(val - val2) < Math.abs(n - val2) ? val : n)
      );
    }, [ val1, val2 ]);

    https://jsfiddle.net/recx8j6w/
    Ответ написан
    1 комментарий
  • Почему параграфы съезжают Vue-transition?

    0xD34F
    @0xD34F Куратор тега Vue.js
    <transition-group name='slide-components' mode="out-in"

    Открываем документацию, читаем, что transition-group принимает

    те же атрибуты, что и у <transition> кроме mode

    Так что бессмысленно указывать mode, элементы всегда будут удаляться и добавляться одновременно. Ну а если элемента два, то одному из них придётся "съехать".

    Вместо transition-group тут следует использовать transition:

    <transition name="slide-components" mode="out-in">
      <p :key="window">{{ window }}</p>
    </transition>
    Ответ написан
    Комментировать