Задать вопрос
  • Как сократить запись в v-bind?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Не надо indexOf, индексы доступны в v-for без каких-либо дополнительных телодвижений:

    <div v-for="(row, iRow) in rows" class="board__rows">
      <div
        v-for="(col, iCol) in columns"
        v-text="col + row"
        :class="[ [ 'white', 'black' ][(iRow ^ iCol) & 1], 'board__square' ]"
      ></div>
    </div>
    Ответ написан
    Комментировать
  • Почему state не обновляется корректно с использованием React.memo + useCallback?

    0xD34F
    @0xD34F Куратор тега React
    Всё обновляется корректно. Что написали, то и получили.

    Почему всегда рендерятся все экземпляры Child2 - потому что вместо обновления одного элемента data.list вы всегда обновляете все.

    Почему значения сбрасываются на дефолтные - потому что из-за useCallback data у вас всегда имеет начальное значение (ну, то, что было при первом рендеринге, то, которое initialData).

    Переделываем:

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

    React.useCallback((key, val) => {
      setData(data => ({
        ...data,
        [key]: val(data[key]),
      }));
    }, [])

    Ну и переписываем его вызовы внутри Child1:

    onChange('list', list => list.map((n, i) => i === index
      ? { ...n, [prop]: value }
      : n
    ))

    onChange('description', () => e.target.value)
    Ответ написан
  • Как создать фильтр для значения с массивом?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const filter = (arr, conditions) =>
      arr.filter(
        function(n) {
          return this.every(([ k, values ]) => values.some(v => v.includes(n[k])));
        },
        Object
          .entries(conditions)
          .map(n => [ n[0], [].concat(n[1]).map(String) ])
          .filter(n => n[1].length)
      );
    Ответ написан
    8 комментариев
  • Как грамотно использовать this в данном коде?

    0xD34F
    @0xD34F Куратор тега JavaScript
    А лучше всего просто объяснить что бы я в итоге допер сам!

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

    0xD34F
    @0xD34F Куратор тега JavaScript
    Кого будем подставлять вместо отсутствующих значений: const defaultValue = null;.

    Предполагаю что надо использовать reduce.

    Как скажете:

    const result = arr1.reduce((acc, n) => (
      acc.push(arr2.find(m => m.uniq === +n)?.sum ?? defaultValue),
      acc
    ), []);

    Или вот написание циклов руками - ничем не хуже:

    const result = [];
    
    for (const n of arr1) {
      let item = defaultValue;
    
      for (const m of arr2) {
        if (m.uniq == n) {
          item = m.sum;
          break;
        }
      }
    
      result[result.length] = item;
    }

    Ещё рекурсия отлично подойдёт:

    const sums = Object.fromEntries(arr2.map(n => [ n.uniq, n.sum ]));
    const result = (function get(i, n = arr1[i]) {
      return i < arr1.length
        ? [ Object.hasOwn(sums, n) ? sums[n] : defaultValue, ...get(-~i) ]
        : [];
    })(0);

    Главное, чтобы не map. Это ведь совсем не круто - идти наиболее простым и очевидным путём:

    const result = arr1.map(function(n) {
      return this.has(n) ? this.get(n) : defaultValue;
    }, new Map(arr2.map(n => [ `${n.uniq}`, n.sum ])));
    Ответ написан
    1 комментарий
  • Как правильно работать с контекстом в react?

    0xD34F
    @0xD34F Куратор тега React
    Вначале удаляем элемент из массива, затем выбираем новый. Но получается так, что, иногда, выбор случайного элемента массива, происходит до удаления элемента из массива и он выбирает только что удаленный элемент.

    Не "удаляем" - создаётся новый массив, в котором может оказаться (а может и нет) на один элемент меньше. Не "иногда" - всегда выбор нового случайного элемента осуществляется из старого массива.

    Как правильно реализовать такую логику?

    Надо выбирать новый случайный элемент из нового массива, а не из старого. Переносим соответствующий вызов dispatch из обработчика клика в эффект:

    useEffect(() => {
      dispatch({
        type: SET_RND_NUM,
        payload: state.arr[Math.random() * state.arr.length | 0],
      });
    }, [ state.arr ]);
    Ответ написан
  • Как добавить сотрудника в список (таблицу)?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Cannot read properties of undefined (reading 'lastname')

    Понятно, смотрим, где есть попытка чтения свойства lastname.

    async addNewEmployee({ commit }, employee) {
        await axios
            .post(`http://127.0.0.1:8000/api/v1/employees/`, {
                lastname: employee.lastname,

    Тоже понятно, смотрим, где вызывается addNewEmployee и что туда передаётся.

    @submit.prevent="addNewEmployee(employee)"

    А вот здесь непонятно - что такое employee? Такого свойства в компоненте нет. Надо добавить. Его содержимым будет то, что сейчас находится в хранилище - firstname, lastname, number - там, в хранилище, этим данным делать нечего.
    Ответ написан
    1 комментарий
  • Почему возникает TypeError: Illegal invocation при вызове drawImage у canvas'а?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const { drawImage } = canvas.getContext('2d') as CanvasRenderingContext2D;
    
    drawImage(
      ...

    Откуда вы взяли, что методы контекста можно вызывать в отрыве от, м-м-м, КОНТЕКСТА?

    Что у вас происходит, поясняю на пальцах:

    const obj = {
      fucking_value: 666,
      fucking_method() {
        if (!this.hasOwnProperty('fucking_value')) {
          throw 'FUCK OFF';
        }
    
        console.log(this.fucking_value);
      },
    };
    
    const { fucking_method } = obj;
    fucking_method();

    Если вдруг не поняли, то...
    ...вот бы узнать - а какого хрена вы взялись за react (кстати, а при чём он здесь? да не при чём, как и ts), обладая нулевыми знаниями js?

    Ключевое слово this - бегом гуглить, разбираться, что это, зачем, к каким значениям в каких случаях даёт доступ.
    Ответ написан
    4 комментария
  • Как подставить данные из динамического элемента в динамический элемент с помощью JQuery?

    0xD34F
    @0xD34F Куратор тега JavaScript
    document.querySelector('.form').addEventListener('input', e => {
      const data = Array.from(
        e.currentTarget.children,
        n => Array.from(n.querySelectorAll('input'), m => m.value)
      );
    
      document.querySelector('.total').innerText = Array
        .from(document.querySelectorAll('.row'))
        .reduce((acc, n, i) => {
          data[i].forEach((m, j) => n.children[j + 1].innerText = m);
          return acc + (+data[i].at(-1) || 0);
        }, 0);
    });

    или

    const total = document.querySelector('.total');
    const form = document.querySelector('.form');
    const formRows = form.getElementsByClassName('d-flex');
    const tableRows = document.getElementsByClassName('row');
    
    form.addEventListener('input', ({ target: t }) => {
      const inputBox = t.closest('.input-box');
      const formRow = inputBox.parentNode;
      const iRow = Array.prototype.indexOf.call(formRows, formRow);
      const iCol = -~Array.prototype.indexOf.call(formRow.children, inputBox);
    
      tableRows[iRow].cells[iCol].textContent = t.value;
    
      if (iCol === formRow.children.length) {
        total.textContent = Array.prototype.reduce.call(
          formRows,
          (acc, n) => acc + (n.lastElementChild.children[0].value | 0),
          0
        );
      }
    });
    Ответ написан
    4 комментария
  • Как преобразовать древовидный массив в плоский?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Рекурсия есть:

    const getFromTree = (tree, childrenKey, getter = n => n) =>
      Array.isArray(tree)
        ? tree.flatMap(n => [
            getter(n),
            ...getFromTree(n[childrenKey], childrenKey, getter),
          ])
        : [];
    
    // или
    
    function* flatTree(tree, childrenKey) {
      if (
        tree instanceof Object &&
        tree[Symbol.iterator] instanceof Function
      ) {
        for (const n of tree) {
          yield n;
          yield* getFromTree(n[childrenKey], childrenKey);
        }
      }
    }

    Рекурсии нет:

    const getFromTree = function(tree, childrenKey, getter = n => n) {
      const result = [];
    
      for (const stack = this(tree); stack.length;) {
        const n = stack.pop();
        result.push(getter(n));
        stack.push(...this(n[childrenKey]));
      }
    
      return result;
    }.bind(x => x instanceof Array ? [...x].reverse() : []);
    
    // или
    
    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, x?.constructor === Array ? x : [] ]);

    Получаем массив:

    // если использовать обычную функцию
    const result = getFromTree(tree, 'children', ({ children, ...n }) => n);
    // или, генератор
    const result = Array.from(flatTree(tree, 'children'), ({ children, ...n }) => n);
    Ответ написан
    1 комментарий
  • Как создать объект с регистронезависимыми ключами?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Если завернуть объект в Proxy, можно будет изменять ключи при обращениях к объекту:

    const obj = new Proxy({}, {
      get(target, key) {
        const lowerKey = key.toLowerCase();
        return target[Object.hasOwn(target, lowerKey) ? lowerKey : key];
      },
      set(target, key, val) {
        target[key.toLowerCase()] = val;
        return true;
      },
      has(target, key) {
        return key in target || key.toLowerCase() in target;
      },
      defineProperty(target, key, descriptor) {
        return Object.defineProperty(target, key.toLowerCase(), descriptor);
      },
      deleteProperty(target, key) {
        return delete target[key.toLowerCase()];
      },
      getOwnPropertyDescriptor(target, key) {
        return Object.getOwnPropertyDescriptor(target, key.toLowerCase());
      },
    });
    Ответ написан
    1 комментарий
  • Как объединить массивы объектов по значениям одного из свойств их элементов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const merge = (key, ...arrs) =>
      Object.values(arrs.flat().reduce((acc, n) => (
        Object.assign(acc[n[key]] ??= {}, n),
        acc
      ), {}));
    
    const result = merge('id', sum, arr1, arr2);

    или

    const merge = (key, ...arrs) =>
      Array.from(arrs.reduce((acc, arr) => arr.reduce((acc, n) => {
        const k = key(n);
        return acc.set(k, Object.assign(acc.get(k) ?? {}, n));
      }, acc), new Map).values());
    
    const result = merge(n => n.id, sum, arr1, arr2);
    Ответ написан
    4 комментария
  • Как правильно реализовывать прелоадеры?

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

    Смотрите, где какие куски кода есть похожие, оформляете их в отдельный компонент. А что у них разного - будет параметрами этого компонента.

    Или это считается нормальной практикой?

    Да, считается. У говнокодеров.
    Ответ написан
    3 комментария
  • Как из массива объектов получить данные по id в другом массиве?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const result = arr.map(function(n) {
      return this[n];
    }, Object.fromEntries(sum.map(n => [ n.id, n.name ])));
    
    // или
    
    const result = arr.map(Map.prototype.get.bind(new Map(sum.map(n => [ n.id, n.name ]))));
    
    // или
    
    const result = arr.map(n => sum.find(m => m.id === n)?.name);

    Но что если в массиве sum отсутствуют некоторые из нужных элементов, а получать undefined внутри массива с результатами не хочется?

    Можно подставлять вместо отсутствующих элементов какое-нибудь другое значение:

    const names = Object.fromEntries(sum.map(n => [ n.id, n.name ]));
    const result = arr.map(n => names[n] ?? `объекта с id=${n} нет`);

    Или, есть вариант получать только то, что существует:

    const names = new Map(sum.map(n => [ n.id, n.name ]));
    const result = arr.reduce((acc, n) => ((n = names.get(n)) && acc.push(n), acc), []);
    Ответ написан
    2 комментария
  • Почему не меняется класс при скролле?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Встречный вопрос - почему вы решили, что класс должен меняться? Может, всё-таки стоит почаще заглядывать в документацию, а?

    app.ifScroll =

    Меняйте эту чушь на ifScroll.value =.
    Ответ написан
    Комментировать
  • Как через скрипт добавить элемент?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Куда и что надо добавить:

    const containers = document.querySelectorAll('.parent');
    const tag = 'div';
    const className = 'child';

    Добавляем:

    containers.forEach((n, i) => {
      n.insertAdjacentHTML(
        'beforeend',
        `<${tag} class="${className}">${arr[i]}</${tag}>`
      );
    });
    
    // или
    
    for (const [ i, n ] of containers.entries()) {
      n.append(Object.assign(document.createElement(tag), {
        className,
        innerText: arr[i],
      }));
    }
    
    // или
    
    for (let i = 0; i < containers.length; i++) {
      const el = document.createElement(tag);
      el.classList.add(className);
      el.textContent = arr[i];
      containers[i].insertAdjacentElement('beforeend', el);
    }
    
    // или
    
    (function add(i, n = containers.item(i)) {
      if (n) {
        n.appendChild(document.createElement(tag));
        n.lastChild.setAttribute('class', className);
        n.lastChild.insertBefore(new Text(arr[i]), null);
        add(-~i);
      }
    })(0);
    Ответ написан
    2 комментария
  • Как написать такое регулярное выражение?

    0xD34F
    @0xD34F Куратор тега Регулярные выражения
    \.[a-z]+(-[a-z]+)*
    Ответ написан
    Комментировать
  • Как сделать активацию кнопки после нажатия на checkbox?

    0xD34F
    @0xD34F Куратор тега React
    const [ checked, setChecked ] = React.useState(false);

    <input
      type="checkbox"
      checked={checked}
      onChange={e => setChecked(e.target.checked)}
      ...

    <button
      disabled={!checked}
      ...
    Ответ написан
    3 комментария
  • Как применять в Quasar Select методы hidePopup и showPopup?

    0xD34F
    @0xD34F Куратор тега Vue.js
    нет примера их использования

    И не должно быть - всё более чем очевидно.

    Конечно, для тех, кто о vue хоть что-то знает - например, что у vue есть документация. Тогда можно её открыть и прочитать там про ref:

    <q-select
      ref="select"
      ...

    <q-btn
      @click="$refs.select.showPopup()"
      ...
    Ответ написан
    Комментировать