• Как разбить файл?

    devellopah
    @devellopah
    этот генератор выдаёт неплохой галпфайл
    Ответ написан
    Комментировать
  • Применения generator и promise?

    devellopah
    @devellopah
    прочитай секцию ES6 Generators In Brief
    Ответ написан
    Комментировать
  • Очередной вопрос касаемо БЭМ?

    devellopah
    @devellopah
    я насчитал пять компонентов: c-searchbar, c-searchbar-menu, c-searchbar-dropdown, c-searchbar-megamenu, c-searchbar-megamenu-tags(бем с префиксами)

    соответсвенно выглядеть должно так

    <div class="c-searchbar">
        ...
        <ul class="c-searchbar__menu c-searchbar-menu">
    			
          <li class="dropdown [ c-searchbar__dropdown c-searchbar-dropdown ]">
            <a href="#" class="dropdown-toggle [ c-searchbar-menu__link ]" data-toggle="dropdown">Country <b class="caret"></b></a>
            <div class="dropdown-menu [ c-searchbar__megamenu c-searchbar-megamenu ]">
              <div class="container">
                <div class="c-searchbar-megamenu__header">
                  <div class="c-searchbar-megamenu__tags c-searchbar-megamenu-tags">
                    <div class="c-searchbar-megamenu-tags__item">CZECH REPUBLIC <button type="button" class="remove-tag"></button></div>
                    <div class="c-searchbar-megamenu-tag__item">CONSUMERS ELECTRONICS</div>									
                  </div>
                </div>
              </div>
            </div>
          </li>
    			
    			<li class="c-searchbar-menu__item"></li>
    			
        </ul>
      ...
    </div>


    Есть тонкий момент, стилистика компонента не должна содержать правил позиционирования. То есть ты не должен задавать margin, padding, position(и что-то ещё) в классе c-searchbar-dropdown, а должен для этих целей использовать c-searchbar__dropdown. Если же компонент c-searchbar-dropdown не будет иметь правил позиционирования ,то можно(наверное) убрать класс c-searchbar__dropdown
    Ответ написан
    Комментировать
  • Как очистить массив не трогая свойства и методы?

    devellopah
    @devellopah
    1) зачем нужно очищать массив? Почему-бы просто не создать новый?
    2) оффтоп:
    не делай так:
    ar.sum = function() {
        this.reduce(function(a, b) {
            return a + b;
        });
    }


    Просто напишу функцию, типа
    const sum = arr => arr.reduce((a, b) => a + b)
    sum(ar); // 6
    Ответ написан
    Комментировать
  • Лучшая библиотека для asynchronous data fetching?

    devellopah
    @devellopah Автор вопроса
    Прошу прощения, не совсем верно сформулировал влпрос. Я имел ввиду библиотеку, которая сохраняет полученные ассинхронным запросом данные в редуксе и затем снабжаете этими данными компоненты.
    Ответ написан
    Комментировать
  • Что именно рендерит на сервере Next.js?

    devellopah
    @devellopah
    у них, видимо, code-splitting "из коробки", но ты и сам можешь настроить, если с вебпаком "в ладах"

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

    Затем на клиенте react проверяет совпадают ли значения аттрибутов data-react-checksum клиетского приложения и серверного. Если совпадают, это означает, что если мы "поднимем" клиентское приложение(дорогая операция), то что мы получим будет совпадать с тем, что отправил сервер. Выходит, что этого можно избежать. Именно это и делает реакт, просто копирует полученный на сервер DOM в клиентское приложение.

    Next.js делает всё это за тебя. С одной стороны это хорошо, не надо возиться с настройкой серверного рендеринга, с другой стороны - плохо, потому что всё-таки стоит знать как всё происходит в деталях на сервере.
    Ответ написан
    Комментировать
  • Как выполнить синхронную итерацию массива?

    devellopah
    @devellopah
    попробуй так
    let array = Array.from({ length: 10 }, (v, k) => k);
    
    const fn = (el) => {
      setTimeout(() => { console.log(el) }, 100 * el);
      return el * 2;
    };
    
    console.log(array.map(fn));
    Ответ написан
  • React. Полезные библиотеки на подобие Redux?

    devellopah
    @devellopah
    на самом деле, таких библиотек пишется очень много. Поэтому лучше подпишись на рассылки по реакту, пусть новинки приходят на почту
    Ответ написан
    Комментировать
  • Как работать с булевыми методами?

    devellopah
    @devellopah
    d - это NodeList (список узлов), не имеющий метода hasAttribute()

    попробуй так (es5 версия)
    var tags = ['div', 'span', 'ul', 'li', 'p', 'script', 'h1', 'h2'];
    var forEach = Array.prototype.forEach
    
    tags.map(function(tag) {
      var list = document.querySelectorAll(tag);
    
      forEach.call(list, function(el) {
        el.className && console.log(el.className)
      })
    })
    Ответ написан
    2 комментария
  • Как сделать, чтобы меню появлялось только после прокрутки?

    devellopah
    @devellopah
    1. даёшь изначально display: none, затем когда при прокрутке добавляешь класс .top-nav-collapse элементу nav возвращаешь гамбургер через display: block

    2. элементу с классами nav navbar-nav navbar-right navbar-border добавляешь айдишку mobileNav

    добавляешь джаваскрипт код

    var mobileNav  = document.getElementById('mobileNav')
    var navbarToggler = document.querySelector('.navbar-toggle')
    
    mobileNav.addEventListener('click', onMobileNavLink)
    
    function onMobileNavClick(e) {
      if (e.target && e.target.nodeName === 'A') { // если нажал на ссылку в пределах меню
      navbarToggler.click() // закрываешь меню
    }
    Ответ написан
  • Настройка окружения для front end?

    devellopah
    @devellopah
    установи yeoman командой npm install -g yo
    установи webapp-generator (сгенерирует дефолтный шаблон для будущего сайта) командой npm install -g webapp-generator
    установи gulp-cli и bower командой npm install -g gulp-cli bower

    и наконец командаyo webapp чтобы поднять каркас

    Вообщем всё это объясняется на самом сайте yeoman.io

    UPDATE: поскольку этот вопрос очень многих заинтересовал, я написал простой стартер для вёрстки с pug.
    вкратце: под капотом проект, который скаффолдит webapp-generator, только приспособленный для работы с pug, убрана папка тестов, добавлен gulp-uncss(чтобы отрезать неиспользумемые стили фреймворка) и почищен gulpfile.js
    Вобщем форкайте, лайкайте, пулл-реквестите(если хотите)
    Ответ написан
    1 комментарий
  • Почему в работе так категорично требуют реакт или ангуляр?

    devellopah
    @devellopah
    V1 - производительность приложения написанного на ваниле
    V2 - производительность приложения, написанного с помощью реакт(или альтернативы)
    T1 - время, потраченное на написание ванильного приложения
    T2- время, потраченное на написание реактовского варианта аналогичного приложения

    V1 - V2 < T1 - T2

    Даже если ты напишешь сложное приложение на ваниле, которое будет читабельно и будет поддерживаемо и масштабируемо так же хорошо как и вариант на реакте, ты же не идиот, чтобы каждый раз так сложно писать. Ты захочешь упростить написание кода, что-то абстрагировать и в итоге сам напишешь ui library типа vuejs.
    Ответ написан
    9 комментариев
  • Коллекцию элементов преобразовать в массив?

    devellopah
    @devellopah
    если ты не используешь транспайлера(babel, к примеру), то лучше
    var items = Array.prototype.slice.call( document.querySelectorAll('div') )

    в противном случае ie и opera будут плакать
    Ответ написан
    2 комментария
  • Почему из переменной не вычитается значение?

    devellopah
    @devellopah
    возможно ты хотел что-то такое

    var snake = document.querySelector('#snake');
        var snakeHP = 3;
        
        snake.addEventListener('click', onSnakeClick);
        
        function onSnakeClick(ev) { // ev - event object
        	snakeHP = snakeHP - 1;
        	
        	if(!snakeHP) {
        		// что-то делаешь 
        		
        		return;
        	}
        	
        	snakeHP--;
        	
        }
    Ответ написан
    Комментировать
  • Почему для возвращенного выражения недоступны свойства объекта?

    devellopah
    @devellopah
    всё же так лучше

    var products = [
      {name:"Grapefruit", calories: 170, color: "red", sold: 8200},
      {name:"Orange", calories: 160, color: "orange", sold: 12101},
      {name:"Cola", calories: 210, color: "caramel", sold: 25412},
      {name:"Diet cola", calories: 0, color: "caramel", sold: 43922},
      {name:"Lemon", calories: 200, color: "clear", sold: 14983},
      {name:"Rapsberry", calories: 180, color: "pink", sold: 9427},
      {name:"Root Beer", calories: 200, color: "caramel", sold: 9909},
      {name:"Water", calories: 0, color: "clear", sold: 62123}
    ];
      
      
    var mapper = {
     	'sold': function (product) {
        console.log('Продукт: ' + product.name + ' был продан ' + product.sold + ' раз.');
      },
      'name': function (product) {
      	console.log('Название продукта: ' + product.name);
      },
      'calories': function (product) {
      	console.log('Продукт: ' + product.name + ' имеет ' + product.calories + ' калорий.');
      },
      'color': function (product) {
      	console.log('Продукт: ' + product.name + ' имеет ' + product.color + ' цвет.');
      }
    };
     
     printBy(products, 'calories');
     
     function printBy(collection, prop) {
       collection.map(mapper[prop]);
     }
    Ответ написан
    Комментировать
  • Верстка сайта, возможно ли так организовать структуру и переходы(в описании) ??

    devellopah
    @devellopah
    тебе нужно смотреть в сторону библиотек, делающих page transition, типа barba.js
    и уж вряд ли стоит изобретать колесо
    Ответ написан
    Комментировать
  • Прокомментируете приложение на React/Redux?

    devellopah
    @devellopah
    1) ты можешь использовать spread operator из-под коробки

    вместо

    case 'SWITCH_EDIT_MODE':
          return Object.assign({}, state, {
            editMode: action.value
          })


    так

    case 'SWITCH_EDIT_MODE':
          return { ...state, editMode: action.value}


    2) weatherApiId спрятать в .env, а .env кинуть в .gitignore (dotenv-webpack to the rescue)

    3)MainContainer на мой взгляд
    import React from 'react';
    import { connect } from 'react-redux';
    import { bindActionCreators } from 'redux';
    import * as actionCreators from './../../actions/actionCreators';
    import Main from './../Main/Main';
    
    class MainContainer extends React.Component {
    
    	componentDidMount() {
        this.props.actions.detectLocation();
      }
    
      render() {
      	return <Main {...this.props.store}  {...this.props.actions} />
      }
    }
    
    const mapStateToProps = state => ({ store: state })
    const mapDispatchToProps = dispatch => ({ actions: bindActionCreators(actionCreators, dispatch) })
    
    export default connect(mapStateToProps, mapDispatchToProps)(MainContainer)


    и Main соответсвенно
    import React from 'react';
    import PropTypes from 'prop-types';
    
    import styles from './Main.css';
    
    import PageBackground from './../PageBackground/PageBackground';
    import WeatherIcon from './../WeatherIcon/WeatherIcon';
    import Temperature from './../Temperature/Temperature';
    import Location from './../Location/Location';
    import Loader from './../Loader/Loader';
    import Error from './../Error/Error';
    
    const propTypes = {
      pageBackground: PropTypes.string,
      location: PropTypes.object,
      editMode: PropTypes.bool,
      changeLocation: PropTypes.func,
      switchEditMode: PropTypes.func,
      weatherIcon: PropTypes.string,
      temperature: PropTypes.number,
      weatherDescription: PropTypes.string
    };
    
    export default function Main (props) {
      return (
        <div className={styles.container}>
          {props.loading && <Loader />}
          {props.loadingError && <Error>Sorry, an error occurred. Try to reload page</Error>}
          <PageBackground background={props.pageBackground} />
          <Location city={props.location.city}
            editMode={props.editMode}
            onLocationSelect={props.changeLocation}
            onChangeLocationClick={() => props.switchEditMode(true)}
            onInputBlur={() => props.switchEditMode(false)} />
          <div className={styles.split}>
           <WeatherIcon code={props.weatherIcon} class={styles.icon}/>
          	<span className={styles.date}>Today</span>
          </div>
          <Temperature value={props.temperature}/>
          <div className={styles.description}>props.weatherDescription}</div>
        </div>
      )
    }
    
    Main.propTypes = propTypes;


    4) в идеале все компоненты кромеMainContainer должны (в этом проекте) быть functional components.

    5) можно было бы написать больше редьюсеров(отдельный для получения location, для weather, для pagebackground) это позволило бы тебе "выдавить" логику из дочерних компонентов(PageBackground, Temperature, WeatherIcon) в MainContainer, чтобы представить в функуиональном виде

    6) нужно ограничить кол-во запросов за определённый промужуток времени(например, 15минут), ибо погода не меняется так часто (express-rate-limit).
    Ответ написан
    3 комментария
  • Объясните простым языком Higher Order Component в React?

    devellopah
    @devellopah
    замени слово component на слово function и всё поймёшь
    Ответ написан
    Комментировать
  • Почему элемент в консоле неопределён?

    devellopah
    @devellopah
    введи в консоли $('.logo')
    Ответ написан
    Комментировать
  • Таймер на JS работает не корректно при обновлении дива почему?

    devellopah
    @devellopah
    думаю так будет чуток лучше
    const timer = document.getElementById("my_timer");
    
    
    // выбери "время в секундах" или число вызовов функции startTimer() 
    let total = 60;
    
    // сохраним в переменную, чтобы потом очистить
    let timerInterval = setInterval(tick, 1000);
    
    // достаём число, минуты, секунды в числовом формате
    const getHours = x => Math.floor( total / 3600 )
    const getMinutes = x => Math.floor( total % 3600 / 60)
    const getSeconds = x => Math.floor( total % 3600 % 60 )
    
    // приводим вышеуказанные значения в нужный для отображения вид
    const prepair = val => val < 10 ? '0' + val : val
    
    // эта функция принимает фукцию и вызывает её, передав в качестве аргумента total
    const passTotal = fn => fn(total);
    
    
    function tick() {
    	// типа делаем [a, b] = [10, 20] и получаем a = 10 и b = 20 (деструктивное присваивание)
    	const [hour, minutes, seconds] = [getHours, getMinutes, getSeconds].map(passTotal)
    	
    	if (total <= 0) {
    		clearInterval(timerInterval)
    		// return fetchAnotherQuestion()
    	}
    		// отображаем строку
       timer.textContent = prepair(hour)+ ':' + prepair(minutes) + ':' + prepair(seconds)
       
    	 // уменьшаем "время в секундах" на "одну секунду"
    	 total--;
    }
    Ответ написан
    Комментировать