Задать вопрос
  • Как заставить отдельные блоки прокручиваться независимо?

    johnymkp
    @johnymkp Автор вопроса
    Сергей delphinpro, Решение интересное, попробовал - получилось. Но есть несколько вопросов:
    1) Использовать гриды для создания сетки - это нормально? Просто помню, что когда-то давно считалось, что использовать таблицы для верстки - это моветон. А гриды вроде как преемник таблицы. Удобен для отображения товаров в виде колонок-строк, а вот именно для верстки самой сетки страницы я пока не встречал гриды.
    2) Как поступать в случае адаптивности? Например, если в моем примере с флексами мне надо скрыть боковое меню, я просто ставлю `display: none` и оно исчезает, а блок контента безо всяких дополнений просто растягивается по всей ширине. В случае с гридом же блок контента становится урезанным по горизонтали.
    Написано
  • Почему при переносе элементов столбцы получаются разной ширины?

    johnymkp
    @johnymkp Автор вопроса
    Ankhena, а при чем здесь они? Это свойства не контейнера, а элементов. Элементы имеют такую ширину, какую имеют, я не хочу на них влиять через basis. Параметры расширения и сжатия я тоже не трогаю. Другое дело, что если ширина столбцов рассчитывается пропорционально самому широкому элементу, как сказал Ivan Ustûžanin выше, тогда понятно почему такая ширина у них неравномерная.
    Написано
  • Почему при переносе элементов столбцы получаются разной ширины?

    johnymkp
    @johnymkp Автор вопроса
    Увеличил шрифт одному из элементов в строке, она стала выше второй строки.
    Написано
  • Почему код внутри промиса работает, хотя this там undefined?

    johnymkp
    @johnymkp Автор вопроса
    Разобрался. Оказалось две ошибки:
    1) Концептуальная - сохранять объект indexeddb в событии onupgradeneeded это неправильно, потому что БД будет находиться в состоянии незавершенной транзакции обновления и не позволит сохранять в хранилище данные.
    2) Техническая - я не дождался окончания промиса из метода init, из-за чего метод save по сути вызывался до того как в this.database реально попал объект открытой indexeddb.

    Вот
    исправленный код
    const idbConfig = {
      version: 1,
      dbname: 'stats123',
      storages: [
        {
          name: "constants123",
          settings: { }
        }
      ]
    };
    
    class Database {
      // config
      // database  <-- Это поля класса
    
      constructor(config) {
        this.config = config;
      }
    
      init() {
        return new Promise((resolve, reject) => {
          const openRequest = indexedDB.open(this.config.dbname, this.config.version);
    
          openRequest.onupgradeneeded = (event) => {
            // Здесь нельзя перезаписывать this.database, потому что БД будет находиться в режиме незавершенной
            // upgrage-транзакции и все равно не позволит ничего в себя сохранить.
            const database = openRequest.result;
            this.createStorages(database);
          }
    
          openRequest.onsuccess = (event) => {
            // Перезаписывать this.database надо именно в этом событии, потому что зедсь транзакция обновления уже завершена
            // и БД готова к дальнейшей работе.
            // Это событие всегда вызывается после onupgradeneeded/
            this.database = openRequest.result;
            resolve(true);
          }
        })
      }
    
      createStorages(database) {
        this.config.storages.forEach(s => {
          if (!database.objectStoreNames.contains(s.name)) {
            database.createObjectStore(s.name, s.settings);
          }
        });
      }
    
      save(storage, data, key = null) {
        return new Promise((resolve, reject) => {
          const tx = this.database.transaction(storage, "readwrite");
          const st = tx.objectStore(storage);
          if (key) {
            st.add(data, key);
          } else {
            st.add(data);
          }
          resolve(data);
        })
      }
    }
    
    class ConstantsService {
      storage = "constants123";
      database;
      requestConfig;
    
      constructor(database) {
        this.database = database;
      }
    
      async loadConstants() {
        const gameVersion = await this.loadGameVersion();
        await this.saveOrUpdateGameVersion(gameVersion);
      }
    
      async loadGameVersion() {
        return {
          id: 132, 
          name: "pathched", 
          releaseDate: 1722470400
        };
      }
    
      async saveOrUpdateGameVersion(gameVersion) {
        await this.database.save(this.storage, gameVersion, "gameVersion");
      }
    }
    
    
    async function demo() {
      const database = new Database(idbConfig);
      // Тут надо было дождаться окончания промиса, иначе save вызывалось до того, как this.database успеет перезаписаться
      await database.init();
      const cs = new ConstantsService(database);
      cs.loadConstants();
    }
    
    demo();
    Написано
  • Почему код внутри промиса работает, хотя this там undefined?

    johnymkp
    @johnymkp Автор вопроса
    Вообще конечная проблема у меня с indexeddb связана. То, что описано у меня в посте, очень странно, но наверное это и правда чудит мишура, потому что в конечном итоге БД создается и хранилище тоже.

    Я не нашел песочницу, где мог бы опубликовать пример с indexeddb, но вот я попытался вырезать кусок из программы и минимизировать его, чтобы он при этом самостоятельно запускался и не отвлекал лишними деталями:
    Кусок кода
    const idbConfig = {
      version: 1,
      dbname: 'stats123',
      storages: [
        {
          name: "constants123",
          settings: { }
        }
      ]
    };
    
    class Database {
      // config  <-- Это поля класса
      // database  <-- Тут должен храниться объект открытой БД.
    
      constructor(config) {
        this.config = config;
        this.database = "ololo";  // Просто для наглядности, что поле не перезапишется.
      }
    
      init() {
        return new Promise((resolve, reject) => {
          const openRequest = indexedDB.open(this.config.dbname, this.config.version);
    
          openRequest.onupgradeneeded = (event) => {
            this.database = openRequest.result; // a) Здесь предполагалось сохранить объект открытой БД, чтобы не переоткрывать каждый раз.
            this.createStorages();
            resolve(true);
          }
        })
      }
    
      createStorages() {
        this.config.storages.forEach(s => {
          if (!this.database.objectStoreNames.contains(s.name)) {
            this.database.createObjectStore(s.name, s.settings);
          }
        });
      }
    
      save(storage, data, key = null) {
        return new Promise((resolve, reject) => {
          const tx = this.database.transaction(storage, "readwrite");  // b) Ошибка вываливается тут, из-за this.database = "ololo", т.е. как будто не перезаписалось.
          const st = tx.objectStore(storage);
          if (key) {
            st.add(data, key);
          } else {
            st.add(data);
          }
          resolve(data);
        })
      }
    }
    
    class ConstantsService {
      storage = "constants";
      database;  // <-- Это поле не под саму БД indexeddb, а под экземпляр класса Database.
      requestConfig;
    
      constructor(database) {
        this.database = database;
      }
    
      async loadConstants() {
        const gameVersion = await this.loadGameVersion();
        await this.saveOrUpdateGameVersion(gameVersion);
      }
    
      async loadGameVersion() {
        return {
          id: 132, 
          name: "pathched", 
          releaseDate: 1722470400
        };
      }
    
      async saveOrUpdateGameVersion(gameVersion) {
        await this.database.save(this.storage, gameVersion, "gameVersion");
      }
    }
    
    const database = new Database(idbConfig);
    database.init();
    const cs = new ConstantsService(database);
    cs.loadConstants();

    Идея такая была: делаем класс под работу с БД, создаем его экземпляр (пуcть Foo). Запускаем инициализацию, которая заключается в создании \ открытии БД. При этом объект открытой БД сохраняем в поле экземпляра, чтобы не приходилось каждый раз открывать БД заново.
    Всем другим объектам, которым в работе нужна БД, передаем Foo. В данном примере это работа с игровыми константами. Нужно сохранить константу - вызываем на Foo метод сохранения. Внутри Foo у нас уже открытая БД сохранена в поле database - так с ней и работаем, через это поле. Однако почему-то при заходе в метод save выясняется, что в this.database лежит "ololo", а не объект с открытой БД.
    Написано
  • Почему код внутри промиса работает, хотя this там undefined?

    johnymkp
    @johnymkp Автор вопроса
    Да вот в том-то и дело, что я тоже себе верю и знаю что не может там быть undefined, но браузер жестко газлайтит, что я уж и сомневаться начал. Вот ссылка со скрином браузера.
    Написано
  • Использует ли вебпак какие-нибудь плагины по умолчанию?

    johnymkp
    @johnymkp Автор вопроса
    Опытным путем удалось выяснить, что подключать плагин DefinePlugin вручную не обязательно. process.env.NODE_ENV ставится автоматически в такое же знаение как флаг --mode.

    Остальные части вопроса актуальны.
    Написано
  • Почему возникает ошибка при использовании переменной окружения в конфиге webpack?

    johnymkp
    @johnymkp Автор вопроса
    Спасибо, в самом деле с -- начало работать.
    Написано
  • Почему возникает ошибка при использовании переменной окружения в конфиге webpack?

    johnymkp
    @johnymkp Автор вопроса
    Aetae,
    webpack.config.js

    const path = require('path');
    
    module.exports = (settings) => {
      console.log("Hello, world!");
      сonsole.log(settings.mode);
    
      return {
        mode: settings.mode,
        entry: './src/index.js',
        output: {
          filename: 'main.js',
          path: path.resolve(__dirname, 'dist'),
          clean: true
        }
      }
    };


    package.json

    {
      "name": "mywebpack",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "build": "webpack"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "webpack": "^5.93.0",
        "webpack-cli": "^5.1.4"
      }
    }


    Команда запуска npm run build --env mode=production
    Ошибка:
    [webpack-cli] Unknown command or entry 'mode=production'
    [webpack-cli] 
    Run 'webpack --help' to see available commands and options


    P.S. Есть подозрение, что если в package.json в скрипте не указать хотя бы одну переменную, например `"build": "webpack --env ololo=nomatter"`, то при запуске скрипта, например `npm run build --env some=thing" объект env вообще не создается, даже если передавать переменные. А если в скрипте хотя бы одна переменная описана, тогда env создается, и в него накидывается все, что мы передаем при запуске.
    Написано
  • Чем технически отличаются dev-, prod- и peer-зависимости в Node JS?

    johnymkp
    @johnymkp Автор вопроса
    Lynn «Кофеман», а можете написать, что такое сплющивание дерева, о котором вы упоминали?
    ну с npm всё возможно. Он же попробует сплющить дерево и Foobar попадёт в область видимости приложения. Это прямо-таки стандартная ошибка новичков и не только.


    И еще вы в комментариях писали, что
    но поскольку в реальности Plug2 явно не вызывает Foobar, то в итоге он будет работать с Foobar@1 из верхнего уровня и привет два часа счастливого дебага.
    . Как в итоге такую проблему обычно решают?
    Написано
  • Чем технически отличаются dev-, prod- и peer-зависимости в Node JS?

    johnymkp
    @johnymkp Автор вопроса
    Дмитрий Беляев, вроде стало понятнее. Если перевести на какую-нибудь житейскую аналогию, то получается примерно так: есть Садовник и Охранник (ПакетА и ПакетВ). Садовник в своей работе использует Ножницы и Инсектицид (это его prod-зависимости, он держит их у себя в кармане (в своей личной папке node_modules)), а Охранник - Рацию и Пистолет (тоже prod-зависимости). А в целом Садовник и Охранник работают на Усадьбе (это их peer-зависимость). При этом каждый из них может пользоваться функциональностью усадьбы, например, ЗакрытьВорота или ВключитьВодуДляПоливаГазона. Соответственно, если Садовник вручную поливать не намерен, он указывает в своей пир-зависимости Усадьба 1.5.3 (в которой есть автополив), и если Садовника пытаются нанять на Усадьбу 1.2.0 (пытаются установить пакет в проект, где peer-зависимость неподходящей версии), он предупреждает, что не сможет работать на ней. То же и с Охранником - если Усадьба не огорожена по периметру забором, он патрулировать не намерен. Так что и у него есть свои требования к версии.

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

    В целом получается, что если у какой-то библиотеки есть peer-зависимость, то это в 99% случаев означает, что библиотека не является чем-то самодостаточным, а предназначена для работы в паре со своей peer-зависимостью.
    Написано
  • Чем технически отличаются dev-, prod- и peer-зависимости в Node JS?

    johnymkp
    @johnymkp Автор вопроса
    Алексей Уколов,
    Я крепко запутался. Давайте определимся, что вы подразумеваете под плагином? Я например два вида могу представить:
    1) На примере джавы: нечто вроде драйвера-реализации JDBC. Есть интерфейс работы с БД, зафиксированный стандартом. Есть провайдеры, которые этот интерфейс реализуют. Вы берете реализацию, кидаете в определенную папочку, пишете нечто вроде Provider.createConnection(параметры), у вас происходит автоматический поиск подсунутых реализаций и как только она найдена, вам возвращается объект, через который вы работаете с БД. В этом случае явно прослеживается связь между "библиотекой" и "плагином". В роли библиотеки тут, грубо говоря, "джава", а в роли плагина - конкретная реализация интерфейса.
    2) Плагины вроде html-webpack-plugin, которые реально никак не связаны ни с какой библиотекой и делают какую-то свою мелочь, типа чистит папку при каждом билде или подключает скрипт в html-страницу.

    Второй вариант как будто бы не о нашем разговоре, потому что там зависимостями не пахнет, все как раз независимо. А как при первом варианте возможно, как вы говорите
    Библиотека плагином тоже не пользуется, ей от его существования ни горячо, ни холодно. Соответственно, у Foobar никаких зависимостей нет, у Plug зависимостей тоже нет, но в peer-зависимостях указано, что те, кто хочет Plug установить к себе в качестве зависимости, должны установить рядом с ним и Foobar тоже.
    , я представить не могу.

    Lynn «Кофеман», что значит сплющивание? Перенос зависимостей из собственной node_modules пакета в папку node_modules проекта?
    И что значит
    но поскольку в реальности Plug2 явно не вызывает Foobar, то в итоге он будет работать с Foobar@1 из верхнего уровня и привет два часа счастливого дебага.

    "явно не вызывает Foobar"? Хотя тут тоже надо уточнить, что именно вы под плагином имеете ввиду.
    Написано
  • Чем технически отличаются dev-, prod- и peer-зависимости в Node JS?

    johnymkp
    @johnymkp Автор вопроса
    Вопрос у меня в том, правильные ли я выводы сделал. Потому что если бы я просто спросил, "что такое peer-зависимость" например, меня бы просто отослали на один из десятков существующих ответов, а я их прочитал (и не только их) и все равно не понял, потому что в моем видении они не полные. Так что я расписал свое текущее понимание и через уточнения хочу-таки разобраться.
    Написано
  • Чем технически отличаются dev-, prod- и peer-зависимости в Node JS?

    johnymkp
    @johnymkp Автор вопроса
    Не очень понял.

    Например есть библиотека Foobar версии 1.4.5
    И есть плагин Plug к ней.

    По идее, это именно библиотека пользуется плагином, а плагин значит является независимой единицей и не пользуется кодом библиотеки. Значит, Plug является пир-зависимостью для Foobar, т.е. у Foobar в секции peerDeps находится Plug?
    Написано
  • Есть ли в IndexedDb возможность сохранить данные в инвертированном порядке?

    johnymkp
    @johnymkp Автор вопроса
    Получается, что курсор с выбором с конца - единственный выход?
    Написано
  • Есть ли смысл учить абсолютно все элементы HTML?

    johnymkp
    @johnymkp
    Ratenti,
    Давно хотелось написать какую-нибудь прогу для себя, с графическим интерфейсом, а gui-технологии для языков, использующихся на беке (C#, Java) очень неудобные по сравнению со связкой html+css. Плюс поднадоела духота конкретно Spring. Занялся фронтом просто чтобы посмотреть что тут и как, в итоге вот думаю докачать необходимый минимум и искать работу именно как фронт.
    Написано
  • Есть ли смысл учить абсолютно все элементы HTML?

    johnymkp
    @johnymkp
    Алексей Уколов, а раз вы не заморачиваетесь над запоминанием, то как тогда находите нужную инфу? Каждый раз [гугл | лазание по проектам в поисках нужного места] или ведете личные заметки, что-то вроде собственной википедии?
    Написано
  • Есть ли смысл учить абсолютно все элементы HTML?

    johnymkp
    @johnymkp
    Зубрежка зубрежке рознь. Вот из личного примера: я постоянно забываю всякие мелочи, типа есть ли для ввода текста отдельный тег или это input с каким-то атрибутом. Или например, я помню, что список это select со вложенными option, но совершенно не помню как выставить дефолтное значение или как его получить. Или как подключить стили на страницу. Я конечно пока еще не полноценный фронтендер, только перекатываюсь с бека во фронт, но чувствую, что ситуация не изменится, т.к. подобная канитель у меня всегда была. От того, что не используется пару дней, начинает оставаться только общее воспоминание.

    Многие такие базовые вещи не требуют понимания, они именно на "помнишь\не помнишь". Это не промисы например, где и вправду зубрежкой не отделаешься (хотя после наступления понимания почему бы и не зазубрить синтаксис). И лично мне не комфортно от того, что я постоянно что-то такое базированное забываю. Поэтому я делаю карточки и периодически их просматриваю с целью, чтобы эта самая база всегда была, так сказать, "в оперативке". Что в принципе можно назвать подвидом зубрежки. Аналогично со стандартными методами, например, массивов. Удобнее помнить, что метод называется includes, а не contains например, нежели каждый раз гуглить. Про существование некоторых вещей вообще можно забыть даже, если долго их не трогать.

    Есть расхожее мнение, мол, "программист должен уметь думать, а не все методы помнить". Но если методов\тегов не помнишь, то получается как "читаю\перевожу со словарем", если через каждые три слова надо в словарь лезть, много не начитаешь. То же самое и тут. Так что имхо зубрежка некоторых вещей может быть полезна. Опять же, если на лайвкодинге постоянно говорить что-то вроде "ой, тут вот так должно быть, но я забыл как там пишется", вряд ли хорошее впечатление оставишь. Имхо, как боксер должен уметь отправлять в нокаут, а не только знать как это делается, так и программист должен по максимум уметь писать без гуглежа. Ну кроме совсем конечно отбитых случаев, вроде того как например в RTK слайс создавать, такое я конечно зубрить никогда не буду.
    Написано
  • Как правильно сформировать объект-результат в перегруженной функции в TypeScript?

    johnymkp
    @johnymkp Автор вопроса
    Alexandroppolus Решение определенно интересное, но выглядит слишком технически привязанным к таким вещам как последовательность параметров, их количество. В общем несколько хрупковато как будто. Перемещение параметра было бы удобно, но в целях обучения хотелось бы оставить его на месте пока что.
    P.S. Я конечно понимаю, что если что-то изменится, то на то она и строгая типизация, чтобы все сразу ломалось как можно быстрее, но есть ли еще какие-нибудь варианты решения? Просто для сравнения хотя бы.
    Написано
  • Как в react работать с большим количеством данных?

    johnymkp
    @johnymkp Автор вопроса
    Пагинацию в итоге нашел в документации.
    Чтобы свой бэк сделать, надо где-то его поднимать, а бесплатно такие сервисы вряд ли есть. К тому же хотелось бы самодостаточное приложение.
    Вот за indexedDB спасибо, не знал что такое существует. Погуглю про него и про локалстор.
    Написано