Задать вопрос
  • Почему при постфиксном инкременте стейт не изменяется?

    0xD34F
    @0xD34F Куратор тега React
    Вам бы разобраться, как оператор ++ работает. Сначала вы изменяете значение state.counter напрямую (чего делать НЕ НАДО), затем setState устанавливает в качестве нового значения counter'а его предыдущее значение, возвращаемое постфиксным ++.
    Ответ написан
  • Как получить разницу между датами в typescript в миллисекундах для обратного отчета времени?

    0xD34F
    @0xD34F
    TS2362 The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum

    Ну да. Надо преобразовывть даты в числа при вычитании, т.е., вместо

    this.endDate - this.currentDate

    пусть будет

    +this.endDate - +this.currentDate

    , например. Ну а в целом, то что вы делаете - это просто бред сумасшедшего. Зачем вам пять разных интервалов? Что вы пытаетесь сделать в коллбеках этих интервалов? - результаты ваших вычислений улетают в никуда. Говорите, ваша цель - обратный отсчёт? Давайте я вам покажу, как он может выглядеть, а вы посмотрите, и подумаете, что к чему.
    Ответ написан
    Комментировать
  • Исключить повторяющиеся объекты?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const uniqueDocs = docs
      .filter((n, i, a) => n === a.find(m => m.date === n.date && m.type === n.type))
      .map(({ type, date }) => ({ type, date }));

    или

    const uniqueDocs = Object
      .entries(docs.reduce((acc, n) => ((acc[n.type] = acc[n.type] || new Set).add(n.date), acc), {}))
      .reduce((acc, n) => (acc.push(...Array.from(n[1], m => ({ type: n[0], date: m }))), acc), []);

    или

    const unique = (arr, keys) =>
      arr.filter((n, i, a) => i === a.findIndex(m => keys.every(k => n[k] === m[k])));
    
    const pick = (obj, keys) =>
      keys.reduce((acc, k) => (acc[k] = obj[k], acc), {});
    
    
    const keys = [ 'type', 'date' ];
    const uniqueDocs = unique(docs, keys).map(n => pick(n, keys));
    Ответ написан
  • Как динамически выводить элементы массива?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Сделаем объект, который следует выводить, вычисляемым свойством:

    obj() {
      return this.items[0];
    },

    Если он существует - выводим:

    <div v-if="obj">
      <div v-for="(val, key) in obj">
        ...

    Похоже на то, что вам надо?
    Ответ написан
    1 комментарий
  • Как кастомизировать тултип в ngx-charts?

    0xD34F
    @0xD34F
    Если я правильно понял что вам нужно, то вместо seriesTooltipTemplate надо было передавать tooltipTemplate, типа так.
    Ответ написан
    Комментировать
  • Выборка внутри блока на jQuery скрипта по добавлению класса?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Проверяйте, где был клик:

    $('.shop-ellement-sidebar').on('click', function(e) {
      if ($(e.target).closest('.element-sidebar_content').length) {
        return;
      }
      // дальше проверка наличия класса active и т.д. - без изменений

    Или останавливайте всплытие события при клике на .element-sidebar_content:

    $('.element-sidebar_content').click(function(e) {
      e.stopPropagation();
    });
    Ответ написан
    3 комментария
  • Динамичская загрузка и рендеринг компонента?

    0xD34F
    @0xD34F Куратор тега Vue.js
    new Vue({
      router,
      store,
      components: {
        AppModile: () => import('@/AppMobile.vue'),
        App: () => import('@/App.vue')
      },
      render: h => h(isMobile ? 'AppMobile' : 'App')
    }).$mount('#app')
    Ответ написан
    Комментировать
  • Vuex для каталога с корзиной - как лучше реализовать такое решение?

    0xD34F
    @0xD34F Куратор тега Vue.js
    получать данные для корзины - в actions, через Promise.all по id вытаскивая данные для каждого товара?

    В смысле - хранить в cartItems только id (ну ещё количество и цену), а при каждом заходе пользователя в корзину подтягивать остальные данные (название/производитель/гарантия/...)? Во-первых, что ещё за Promise.all - собираетесь ради каждого товара выполнять отдельный запрос? Так дела не делаются - передавать на сервер следует массив id, запрос должен быть один. Во-вторых - получится, что у вас есть в хранилище массив id, а в компоненте корзины локально лежат полные данные товаров. На мой взгляд - как-то сложновато, при манипуляции данными cartItems из компонента корзины последний придётся вручную поддерживать в актуальном состоянии - watch на cartItems, отфильтровывание из локального массива удалённых элементов, копирование количества существующих.

    Короче, я при добавлении товара в корзину просто полностью бы копировал в cartItems данные из products.
    Ответ написан
    2 комментария
  • Как еще можно оптимизировать js код?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Исправил синтаксические ошибки.

    Ага, на пять с плюсом.

    • Пропущен if или условие лишнее:

      } else (date.getDay() == 0) {

      } else (a < 1) {

    • Лишнее : после ?:

      this.updateTime.getMonth() > 9 ? : '0'

    • Перед методом renderItems стоит лишняя фигурная скобка, а после метода createPeriod такой скобки не хватает.


    И это только синтаксические. Есть ещё ворох иных.

    • Имена свойств, содержащих обработчики событий, состоят из букв только в нижнем регистре, тут должно было быть input.onchange:

      this.input.onChange = this.onChange;

    • Какое там первое слово в имени базового класса должно быть - date или data? Вы бы определились:

      class dateInput {

      class dateRange extends dataInput {

    • В конструкторе dateRange отсутствует вызов конструктора базового класса - не хватает super(); перед this.container = ...:

      constructor() {
       this.container = document.querySelector('.containerForLastUpdateRecordAndPeriodItems');

    • Это ещё что за на хрен:

      period = `${date.toLocaleDateString()} - {date.setHours(168).toLocaleDateString()}`;

      Во-первых - не указан индекс, и вместо собираемого массива используется объект, переданный в функцию, вместо period должно быть periods[i].
      Во-вторых- метод setHours возвращает число, а не объект даты, так вызвать toLocaleDateString не получится.
      В-третьих - отсутствует $ перед фигурной скобкой при подстановке второй даты.

    • Присваивание значений необъявленным переменным:

      b = false;

      element = document.createElement('div')

      Никогда так больше не делайте. Ну и бегом гуглить, почему это плохо.

    • Неправильно пытаетесь вызывать метод renderItems - не хватает this.:

      onChange() {
       renderItems(this.createItems(this.createPeriod(this.inputValue)));

      Кроме того, this тут будет вовсе не экземпляром класса - надо привязывать контекст при установке этого метода в качестве обработчика события (this.onChange.bind(this) - это в конструкторе dateInput). А ещё, поскольку метод переопределён, надо не забыть вызвать метод базового класса, иначе не будет установлено значение свойства inputValue:

      onChange(e) {
        super.onChange(e);
        this.renderItems(...

    • Можете хоть из кожи вон вылезти, но константа своего значения не изменит, а вот TypeError при попытке выполнить хотя бы одну итерацию подобного цикла получите обязательно:

      for (const i = 0; i < n-a; i++) {

    • Что принимает document.createElement в качестве параметров? Откройте документацию и разберитесь, чтобы такую чушь больше не сочинять:

      const element = document.createElement('div', {textContent: item});

    • Опять проблемы со значением this:

      this.container.appendChild(element);

      Поскольку данная строка находится внутри коллбека forEach, который представлен обычной функцией, то экземпляр класса оказывается недоступен. Или замените обычную функцию на стрелочную, или передайте this в forEach третьим параметром.

    • Это ещё что за на хрен №2:

      createPeriod(date) {
       var newDate = date;
        newDate.year = newDate.year + 1;

      Во-первых - в метод передаётся строка, а не дата.
      Во-вторых - будь там дата, скопировать с помощью оператора присваивания её бы не получилось, для объектов копируются ссылки, а не значения.
      В-третьих - год получается и устанавливается совсем не так, для этого есть методы:

      createPeriod(dateStr) {
        const start = new Date(dateStr);
        const end = new Date(dateStr);
        end.setFullYear(end.getFullYear() + 1);
        return { start, end };
      }

    • Это ещё что за на хрен №3:

      const range = Object.create(dateRange.prototype); 
      range.constructor = range.constructor.bind(range); 
      range.constructor();

      Во-первых, без new конструктор вызывать нельзя.
      Во-вторых - к чему такие сложности? - достаточно new dateRange;.


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

    Подскажите, как еще можно оптимизировать(зарефакторить) данный js код?

    А зачем? Лучшее, что тут можно сделать - выбросить всё на хрен и попробовать написать заново, предварительно подумав, на этот раз головой вместо задницы. Не стыдно подобный мусор показывать?

    Но окей, окей - метод createItems, например:

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

      const MS_IN_HOUR = 3600000;
      const HOURS = 168;

    • Вместо двух циклов сделайте один - промежуточный массив dates не нужен:

      for (let i = +period.start; i < +period.end; i += MS_IN_HOUR * HOURS) {
        const date = new Date(i);

    • "Оптимизируйте" if-else-if-... - складываем нижние значения часов в массив (тоже бы неплохо определить его отдельно, дав осмысленное имя), извлекаем их используя день недели как индекс, верхнее значение получаем добавляя сколько там надо (я так понял, разница везде одинаковая между нижним и верхним):

      const hours = [ -120, 0, -24, -48, -48, -72, -96 ][date.getDay()];
      periods.push([ hours, hours + HOURS ]
        .map(n => (date.setHours(n), date.toLocaleDateString()))
        .join(' - ')
      );

    • Для обмена значениями дополнительная переменная не нужна:

      [ periods[i + a], periods[i] ] = [ periods[i], periods[i + a] ];



    Или, renderItems:

    Четыре обращения к свойству updateTime - как-то многовато, достаточно одного, чтобы запомнить значение под коротким именем:

    const ut = this.updateTime;

    Вместо отдельных элементов можно вставлять разметку:

    this.container.insertAdjacentHTML('beforeend',
      `<div>Последнее изменение: ${ut.getDate()}.${`${ut.getMonth()}`.padStart(2, 0)}</div>` +
      items.map(n => `<div>${n}</div>`).join('')
    );
    Ответ написан
    3 комментария
  • Как составить компонент грамотно?

    0xD34F
    @0xD34F Куратор тега React
    Как Вы думаете, как бы написал опытный реакт-разработчик...
    Я конечно таковым ни разу не являюсь, но всё-таки скажу пару слов.

    проверки через тернарный оператор внутри render?
    Это окей - conditional rendering.

    render() {
        const paths = [
    Из метода render массив paths следует убрать. Может быть, его даже стоит сделать параметром компонента.

    onClick={ () => {this.setState({isOpen: !this.state.isOpen})} }
    Следует сделать метод. Создавать при каждом вызове render новый обработчик - само по себе не очень здорово, ну и ещё этот код повторяется дважды.

    this.props.history.listen(...
    Если предполагается, что во время работы приложения экземпляр компонента будет создаваться несколько раз, то при удалении экземпляра надо снимать обработчик, иначе вывод в консоль задвоится (затроится, зачетверится,...). Сделать это несложно - listen возвращает функцию, снимающую обработчик, так что:
    componentWillMount() {
      this.unlisten = this.props.history.listen(...
    
    componentWillUnmount() {
      this.unlisten();


    <Link className="next_btn"...
    <Link className="prev_btn"...
    Выглядят подозрительно похожими. Я бы рассмотрел вариант сделать под них отдельный компонент, который бы получал isOpen и свойства объектов paths[currPathIndex +/- 1] в качестве параметров.
    Ответ написан
    1 комментарий
  • Как получить значения data-атрибутов элементов с определённым классом?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каком классе и data-атрибуте идёт речь:

    const className = 'dropdown-trigger';
    const attr = 'target';

    Как получить элементы:

    const elems = document.querySelectorAll(`.${className}`);
    // или
    const elems = document.getElementsByClassName(className);

    Как извлечь значение атрибута из элемента:

    const getAttr = el => el.dataset[attr];
    // или
    const getAttr = el => el.getAttribute(`data-${attr}`);
    // или
    const getAttr = el => el.attributes['data-' + attr].value;

    Как собрать массив значений:

    const attrs = Array.from(elems, getAttr);
    
    // или
    
    const attrs = Array.prototype.map.call(elems, getAttr);
    
    // или
    
    const attrs = [];
    for (const n of elems) {
      attrs.push(getAttr(n));
    }
    
    // или
    
    const attrs = [];
    for (let i = 0; i < elems.length; i++) {
      attrs[i] = getAttr(elems[i]);
    }
    
    // или
    
    const attrs = (function get(i, n = elems.item(i)) {
      return n ? [ getAttr(n), ...get(i + 1) ] : [];
    })(0);
    Ответ написан
    Комментировать
  • Как найти индекс элемента массива, удовлетворяющего определённому условию?

    0xD34F
    @0xD34F Куратор тега React
    Это что-то вроде пагинации.

    Очень странно, но допустим:

    const currPathIndex = paths.findIndex(n => n.link === location.pathname);
    const isPrev = currPathIndex !== 0;
    const isNext = currPathIndex !== paths.length - 1;

    Дальше можно отключать кнопки:

    const onClick = e =>
      history.push(paths[currPathIndex + +e.target.dataset.step].link);

    <button disabled={!isPrev} data-step={-1} onClick={onClick}>PREV</button>
    <button disabled={!isNext} data-step={+1} onClick={onClick}>NEXT</button>

    Или не рендерить ссылки:

    {isPrev && <NavLink to={paths[currPathIndex - 1].link}>PREV</NavLink>}
    {isNext && <NavLink to={paths[currPathIndex + 1].link}>NEXT</NavLink>}

    https://jsfiddle.net/ev93d8fj/1/
    Ответ написан
    1 комментарий
  • Почему не перерисовывается компонент?

    0xD34F
    @0xD34F Куратор тега React
    почему он может не перерисовывается когда данные поступают?

    Ни почему.

    Компонент перерисовывается.

    С тем же результатом, что и без данных.

    Потому что забыли .length где-то здесь:

    Object.keys(this.props.landingState) > 0
    Ответ написан
    1 комментарий
  • Как получить 2й элемент из списка дивов с одинаковыми классами?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каком классе идёт речь, и элемент с каким индексом надо получить:

    const className = 'class';
    const index = 1;

    Если у элементов общий родитель, то можно сразу схватить нужный:

    const element = document.querySelector(`.${className}:nth-child(${index + 1})`);

    В противном случае сперва придётся получить все элементы, имеющие класс:

    const element = document.querySelectorAll('.' + className)[index];
    // или
    const element = document.getElementsByClassName(className).item(index);
    Ответ написан
    Комментировать
  • Как локализовать datepicker?

    0xD34F
    @0xD34F
    есть пример локализации, но он по структуре элементов не похож на мой пример поэтому у меня не получается им воспользоваться

    Даже и не знаю, что сказать. Использовал этот пример как он есть (ну, почти - добавил пару свойств, dayTemplate передаётся из родителя, а обратно эмитится выбранная дата) - всё получилось.
    Ответ написан
    Комментировать
  • Как подобрать координаты и зум так, чтобы все метки были видимы?

    0xD34F
    @0xD34F Куратор тега Яндекс.Карты
    map.setBounds(map.geoObjects.getBounds())

    jsfiddle.net/mw52nqrp

    Или, если кроме интересующих вас меток на карте есть и другие, загоняете нужные метки в GeoObjectCollection, и getBounds вызываете уже на этой коллекции:

    jsfiddle.net/8941pawj
    Ответ написан
    Комментировать
  • Как запретить брать данные из определенного поля при сериализации формы в JSON?

    0xD34F
    @0xD34F
    Добавьте атрибут disabled тем полям, значения которые получать не хотите.
    Ответ написан
    1 комментарий
  • Как передать в функцию первое и третье значение?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Если нужна возможность выборочной передачи параметров, объедините их в один - пусть это будут свойства объекта:

    function f({ a, b, c }) {
      console.log(a, b, c);
    }
    
    f({ b: 9, c: 5 }); // undefined 9 5

    Если надо, можно каждому задать значения по умолчанию:

    function f({ a = 1, b = 2, c = 3 } = {}) {
      console.log(a, b, c);
    }
    
    f({ a: 100, c: 300 }) // 100 2 300
    f({ b: -1 }) // 1 -1 3
    f() // 1 2 3
    f({ a: 0, b: 0, c: 0 }) // 0 0 0
    Ответ написан
    Комментировать
  • Как получить текущий роут из React Router?

    0xD34F
    @0xD34F Куратор тега React
    Используйте withRouter.
    Ответ написан
    Комментировать
  • Почему hover срабатывает только на последний блок?

    0xD34F
    @0xD34F
    Селектор неправильный, замените

    &:hover + .block .circle-1

    на

    &:hover ~ .block .circle-1

    Ну и для второго аналогично (да и для последнего тоже не помешает - ради единообразия).

    UPD. А вообще, прописывать вручную стили для каждого элемента необходимости нет. Можно сложить цвета в список, и сделать по нему цикл:

    .hover {
      ...
    
      .text {
        ...
    
        $hover-colors: red, green, blue;
        @for $i from 1 through length($hover-colors) {
          &:nth-child(#{$i}):hover ~ .block .circle:nth-child(#{$i}) {
            background: nth($hover-colors, $i);
          }
        }
    Ответ написан
    1 комментарий