• CSS-переход свойства height от 0px до auto
    +2
    Спасибо, интересное решение. Но весь смысл статьи теряется из-за, того что вы не объясняете зачем тут вообще нужна строка:
    window.getComputedStyle(elBlock, null).getPropertyValue("height");

    Было бы очень полезно если бы вы это описали. Кстати эту строку можно заменить на эту:
    elBlock.clientHeight;
  • 12 концепций JavaScript, о которых нужно знать
    0
    Методы find(), findIndexOf() и indexOf()

    В JS нет метода findIndexOf().

  • Vuex — чрезмерное использование геттеров в приложении. Разбор ошибки
    0

    Насчет увеличения связности...


    При использовании mapState, вам надо знать о структуре данных в модуле ровно столько же, сколько и при использовании mapGetters. Если я не прав — приведите пример в котором это не так.

  • Vuex — чрезмерное использование геттеров в приложении. Разбор ошибки
    0

    Насчет увеличения объема кода...


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


    Но в ваших примерах вы приводите также код из компонента. Давайте рассмотрим несколько вариантов:


    Вариант 1:
    Допустим я не использую mapState и mapGetters. Тогда объем кода в компоненте для меня не меняется так как я в любом случае создаю вычисляемое свойство и в нем одной строкой возвращаю состояние хоть из стейта, хоть из геттера:


    // Без геттера users()
    users() {
      return this.$store.state.users;
    },
    
    // С геттером users()
    users() {
      return this.$store.getters.users;
    },

    Тут объем кода одинаков (на самом деле нет — не используя геттер мы сэкономим 2 символа, но это мелочи).


    Вариант 2:
    Допустим я использую mapState и mapGetters.


    // Без геттера users()
    ...mapState([
      'users'
    ]),
    
    // С геттером users()
    ...mapGetters([
      'users'
    ]),

    Снова не вижу разницы.


    Тут вы наверное заметите что я вас обманул, так как не использую и mapState, и mapGetters одновременно. Что ж — вы правы, если использовать их вместе, то код в компоненте увеличится:


    // Без геттера users()
    ...mapState([
      'users'
    ]),
    ...mapGetters([
      'articles',
      'comments'
    ]),
    
    // С геттером users()
    ...mapGetters([
      'users',
      'articles',
      'comments'
    ]),

    Но должен сказать что эти 2 лишние строчки скорее всего окупятся теми строками, которые вы не напишите в хранилище. И еще по своему опыту могу сказать следующее: так как я не пишу геттеры для каждого свойства в состоянии, то мне очень (очень очень) редко приходится использовать в компоненте mapState и mapGetters одновременно. А значит и в последнем случае — я не получу выгоды от вашего подхода.

  • Vuex — чрезмерное использование геттеров в приложении. Разбор ошибки
    0

    Если я неправильно понял и имелось ввиду, то о чем вы говорите то дополню:


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


    На самом деле все просто. Эта и множество других, похожих как две капли воды, статей про геттеры Vuex пытаются донести одно простое правило:


    Не надо делать такие геттеры:


    getProp(state) {
      return state.prop;
    }
  • Vuex — чрезмерное использование геттеров в приложении. Разбор ошибки
    0

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


    getUser(state) {
      return state.user;
    }

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

  • Vuex — чрезмерное использование геттеров в приложении. Разбор ошибки
    0

    Вы не правы.
    Если формат данных меняется, то надо приводить данные к нужному формату еще на входе.
    Например API возвращал объект в одном формате:


    let user = {
      "name": "Вася",
      "sex": "male",
      "image": "https://site.ru/img/vasya.png"
    };

    А потом стал возвращать в другом:


    let rawUser = {
      "login": "Вася",
      "male": true,
      "avatar": "/img/vasya.png"
    };

    То не надо пихать его в хранилище в таком виде в каком он пришел. Надо сразу же в обработчике результата запроса или в экшене или, на худой конец, в мутации привести объект к такому формату с которым ваше приложение привыкло работать:


    let user = {
      "name": rawUser.login,
      "sex": rawUser.male ? "male" : "female",
      "image": "https://site.ru" + rawUser.avatar
    };

    И только после этого сохранять его в состоянии.
    А откладывать преобразование формата на самый последний момент (в геттер) — это по прежнему не правильно. Геттеры нужны только для того чтобы вычислять производное состояние на основе состояния хранилища. Т. е. это практически то же самое, что computed в компонентах.

  • Анонимный Дед Мороз 2018-2019: пост хвастовства новогодними подарками
    +10
    Мне повезло с Дедом Морозом, он быстро отправил подарок и поделился трек-номером, чтобы я его не пропустил. )

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

    Но пусть мой Дед не переживает — я обещаю не переусердствовать с экспериментами и даже буду использовать подарок по прямому назначению так как портативной колонки у меня до этого не было, а вещь действительно нужная.

    А еще в комплекте идут прикольные наклейки и душевное письмо. )))

    Дед Мороз, спасибо тебе ОГРОМНОЕ!!!

    Собственно сам подарок
    image
  • Введение в SOLID: новый редецентрализованный интернет Тима Бернерса-Ли
    0
    Turtle is a compact way of representing RDF data, using URLs to represent subject, predicate and object.

    Чуть чуть недоперевели.
  • Советы по CSS, которые вы вряд ли найдете в самоучителях
    0
    Спасибо. content-box это в моем понимании и есть «доступное пространство», просто не знал как его правильно обозвать.
  • Советы по CSS, которые вы вряд ли найдете в самоучителях
    0
    И если уж быть совсем точным, то padding-top считается не от ширины родителя, а от ширины доступного пространства. Т. е. если у родительского блока стоит box-sizing: border-box; и есть padding или border, то их размеры вычитаются из той ширины от которой считается padding-top и т. п.
  • Советы по CSS, которые вы вряд ли найдете в самоучителях
    +4
    Оно устанавливает параметры относительно родительской высоты. Вам нужна демонстрация?

    Не высоты, а ширины.

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

    Результат будет выглядеть так:
    image

    Не совсем так. За отступ берется не сумма а максимальное значение из Margin 1, Margin 2 и Margin 3.

    Если вы работали с CSS много лет и никогда не встречались с этой проблемой, то это потому, что отступы объединяются только когда:
    • ...
    • свойство overflow отличается от «initial»;
    • ...


    Наоборот. Не отличается от initial, а равно initial. Или visible.
  • Личный опыт: от идеи и чистого листа до черновой версии сайта
    0

    Спасибо, за статью. Местами я даже понимал что иногда чувствую то же самое что и вы, хоть я и работаю программистом уже очень давно. Старайтесь довести свой проект до конца, потому что я считаю это самой трудной задачей. Особенно трудно заставить себя что-то доделать, когда осталось совсем немного. Если нужна будет помощь — обращайтесь. С питоном я знаком мало, но с фронтендом помогу по возможности.

  • Освоение Vuex — с нуля до героя
    +1
    Ну во первых изменение состояние Vuex автоматически вызывает изменения в DOM, а в LocalStorage отследить состояние можно только отследив событие «storage», причем это событие не сработает если оно вызвано кодом исполняемым в той же вкладке.

    Во вторых в LocalStorage можно хранить только строки, а чтобы поместить туда хотябы простейший объект — его надо сериализовать.

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

    Ну и еще много причин. Если в кратце — то это разные механизмы, предназначенные для разных задач и заменить одно другим нельзя.
  • Освоение Vuex — с нуля до героя
    0
    Геттеры используются для доступа к значениям, находящимся в хранилище.
    Даже в официальной документации Vuex сказано что геттеры следует использовать только для производных данных, основанных на состоянии.
  • Освоение Vuex — с нуля до героя
    0
    В коде из раздела «Но почему?» ошибка в действии «SET_NAME»:

    context.dispatch('SET_NAME', name);

    Тут должно быть не dispatch, a commit — иначе получается какая-то рекурсия.

  • Странные операторы в PHP
    +3
    Ну, например, вы понимаете смысл следующих строк?
    Просто добавьте b перед любой строкой, но это ничего сделает, словно строка обычным образом.
    Он работает так, вы ожидаете, то есть добавляя элемент с правой части в левую частью массива.
    И просто прочтите остальной текст — сами все увидите.

    Насчет снятия с публикации — решайте сами. Я бы постарался довести перевод до нормального состояния.
  • Странные операторы в PHP
    +1
    Очень крутой стеб. ))) Не сразу понял в чем подвох.
    Жаль только качество перевода оставляет желать лучшего. Исправьте хотя бы явные орфографические ошибки.
  • Типографика и современный CSS
    0
    Точно. ) Что-то у меня переклинило.
  • Типографика и современный CSS
    +1
    А в чем проблема? Есть псевдоселектор :lang для этого:

    p:lang(ru) {
      quotes: "«" "»" "„" "“";
    }
    p:lang(en) {
      quotes: "“" "”" "‘" "’";
    }

    Живой пример
  • Типографика и современный CSS
    0
    Не обязательно. Свойство quotes может принимать сколько угодно пар кавычек в качестве значения и они будут использоваться для вложенных кавычек:

    p {
      quotes: "«" "»" "„" "“" "“" "”" "‘" "’";
    }
  • Типографика и современный CSS
    +2
    Поддерживается font-variant пока что только в Firefox и Safari, поэтому использовать его как основную фишку дизайна не стоит.
    Ошибаетесь. Именно small-caps давно поддерживается всеми современными браузерами.
    Да и не современными тоже.
  • Размещение иконок на странице сайта. Делать проще, поддерживать легче
    –1
    Насчет того что надо использовать button — согласен. А насчет остального нет.
    Посмотрите как сделаны кнопки «Fork», «Settings», «Change view» на том же CodePen, где вы писали примеры. Для меня этот вариант наиболее верный.
  • Делаем GraphQL API на PHP и MySQL. Часть 2: Мутации, переменные, валидация и безопасность
    0
    Сейчас мне проще это сделать ибо у меня множество URI (точек входа — «дверей») которым я могу сопоставить роли.

    В случае GraphQL у меня будет фактически одно URI — «одно окно» — и возникает вопрос — где мне прописывать ограничения?

    Да ведь можно же ограничить сам список полей в схеме. Например, если роль «Авторизованный пользователь», то он может запрашивать поле «messages», а если «Гость», то нет (возвращать null или выводить ошибку).

    И в конце концов, если вам хочется, можно сделать несколько endpoint`ов (URI/точек входа/дверей/окон) с разными схемами данных и сопоставлять им соответствующие роли.
  • Делаем GraphQL API на PHP и MySQL. Часть 3: Решение проблемы N+1 запросов
    0
    Спасибо. Поправил и даже дополнил немного.
  • Делаем GraphQL API на PHP и MySQL. Часть 2: Мутации, переменные, валидация и безопасность
    0
    Начиная от доступа к URI по ролям, использование ролей при выводе результатов (уже после основного запроса/запросов) и заканчивая — ставим роль на конкретный метод сервиса (чтоб уж наверняка не «пробило»).

    Вот точно так же и с GraphQL. )

    Но дело в том, что мы сейчас знаем — что выдать клиенту — ибо фактически не он, а мы управляем запросом.
    А вот GraphQL — тут первую скрипку ведёт клиент. И в этом то и отличие.

    Клиент может выбирать какие данные запросить из тех, которые ему доступны и задавать их структуру. Вам же остается только ограничить те данные, которые доступны клиенту (как вы это и делаете сейчас) и пусть балуется.
  • Делаем GraphQL API на PHP и MySQL. Часть 3: Решение проблемы N+1 запросов
    0
    В качестве основы для статьи я взял код написанный в предыдущих частях статьи. И там все делалось примерно так как вы написали. В этой же статье я постарался изменить код, чтобы уменьшить количество запросов (количество выполнений execute). В цикле для запроса данных о 30 пользователях вы бы отправили 30 запросов, а после описанных мною манипуляций вы бы сделали это за 1 запрос.
    А нужно это для того чтобы снизить нагрузку на сервер БД и уменьшить время выполнения. Так как выполнить 1 запрос быстрее чем 30.
  • Делаем GraphQL API на PHP и MySQL. Часть 2: Мутации, переменные, валидация и безопасность
    0
    Совершенно верно. )
  • Делаем GraphQL API на PHP и MySQL. Часть 2: Мутации, переменные, валидация и безопасность
    0
    Вот о какой безопасно идёт речь, в случае GraphQL. Имхо.

    Просто «в комментариях к предыдущей статье» в основном спрашивали про тяжелые запросы и nested attacks.

    Что касается вашего вопроса:
    Вот как разграничить это удобно?

    Я пожалуй отвечу так: А как вы это делаете сейчас (без GraphQL)?
  • Делаем GraphQL API на PHP и MySQL. Часть 2: Мутации, переменные, валидация и безопасность
    0
    Также, как если бы в ответе вернулось null.
    Если тип поля NonNull, то выдает ошибку: Cannot return null for non-nullable field
    Если нет, то просто возвращает значение как null.
  • Делаем GraphQL API на PHP и MySQL. Часть 3: Решение проблемы N+1 запросов
    0
    Спасибо.
    Я смотрю у вас любопытная библиотека готовится. Буду следить. )
  • Vue.js для сомневающихся. Все, что нужно знать
    0
    Отличная статья. Я уже начинал погружение во Vue и мне он очень понравился. Но из-за недостатка свободного времени пришлось пока отложить его. Поэтому читать статью и снова вспоминать как это красиво реализовано было приятно.
    Хотелось бы еще более подробное описание про Vuex, так как без него врядли можно сделать серьезное приложение.
  • Делаем GraphQL API на PHP и MySQL. Часть 3: Решение проблемы N+1 запросов
    +1
    Я же надеюсь Вы с SQL Injection боретесь при помощи плейсхолдеров...

    В двух предыдущих статьях я делал оговорку, что для простоты примера я не заморачиваюсь с безопасностью, в этой же решил не повторять ее в третий раз. И видимо зря. ) Разумеется на живом проекте так делать ни в коем случае нельзя.

    А самый правильный — это JOIN двух таблиц

    Разумеется вы можете написать более сложный запрос в ресолвере поля «allUsers», добавив в него JOIN. И тогда вам даже не надо будет писать ресолвер для поля «countFriends».
    Я же намеренно усложнил себе задачу, чтобы «искусственно» создать себе проблему, в которой можно будет рассказать про Deferred. Главное вы знаете что делать если в один запрос уложиться не получается, а все остальное в ваших руках.
  • Делаем GraphQL API на PHP и MySQL. Часть 3: Решение проблемы N+1 запросов
    0
    Идея интересная, но к сожалению реализация мне не совсем понятна. Наверное мой уровень знания PHP недостаточно велик. ) Не могли бы вы привести пример использования данного класса? Или еще лучше было бы посмотреть код какого-либо проекта с использованием вашего подхода целиком, если такой есть в открытом доступе разумеется.
  • Делаем GraphQL API на PHP и MySQL. Часть 3: Решение проблемы N+1 запросов
    0
    В данной статье я решил не использовать какой-либо конкретный фреймворк, поэтому то, что похоже на Eloquent скорее является псевдокодом и сделано так, чтобы на мой взгляд было проще понять проблему.
    А вот уже на реальных проектах ваш совет будет очень полезен, про ResolveInfo я знаю, но таким образом его не использовал. Спасибо, возьму на вооружение. )
  • Делаем GraphQL API на PHP и MySQL. Часть 1: Установка, схема и запросы
    0
    Ответ на ваш вопрос в следующей статье.
  • Делаем GraphQL API на PHP и MySQL. Часть 1: Установка, схема и запросы
    +1
    Конкретно про решение проблемы n+1 можете почитать здесь:
    http://webonyx.github.io/graphql-php/data-fetching/#solving-n1-problem

    Это документация к библиотеке graphql-php и в ней этот случай описан. Если все равно возникнут вопросы — задавайте.
  • Делаем GraphQL API на PHP и MySQL. Часть 1: Установка, схема и запросы
    0
    В данном примере — да. Для каждого пользователя будет ещё отдельный запрос друзей, но как я уже писал ранее — это я сделал чтобы максимально упростить пример. Вы же можете написать любой запрос к базе данных и потом полученные результаты обработать в ресолвере как вам надо.
  • Делаем GraphQL API на PHP и MySQL. Часть 1: Установка, схема и запросы
    0
    Насколько я знаю в реализациях GraphQL на PHP пока нет готового решения этой проблемы, но думаю в будущем она появится. А пока можно просто накладывать определённые ограничения на вложенности или время выполнения запроса. Или же создать что-то вроде реестра доступных запросов и тогда, если запроса полученного сервером не будет в реестре, то он не будет выполняться. Хороший ответ на подобный вопрос есть тут: http://stackoverflow.com/questions/37337466/how-do-you-prevent-nested-attack-on-graphql-apollo-server
  • Делаем GraphQL API на PHP и MySQL. Часть 1: Установка, схема и запросы
    +2
    Вот я удивляюсь. Под каждой статьёй про GraphQL обязательно кто нибудь спросит про безопасность. Но ещё сильнее меня удивляет то, что после комментариев, в которых говорится: «безопасность вашего приложения зависит от вас, а не от GraphQL» — вы делаете вывод, что безопасности в GraphQL нет.