Рубрики
Без рубрики

Создание сортировщика времени с реактивными js

Недавно я написал учебник о том, как построить сортировку даты с React JS, поэтому я подумал, что расширим это и подробному, как написать пикера времени.

Автор оригинала: Chris Harrington.

Я недавно написал учебник о том, как Создайте сортирую даты с React JS Поэтому я подумал, что расширим это и подробно, как писать время пикера. Первые вещи первыми: как раз в прошлый раз я поставил код на Github Если вы хотите увидеть полную монты. Я также сделал Пакет Bower На случай, если вы хотите использовать его на вашем сайте где-то.

Примечание: Код далеко от производства готов, поэтому используйте по своему страхому риску.

Если вы просто хотели бы взглянуть на соискание времени в действии, я также собрал (действительно простую) демонстрационную страницу. Взглянуть!

Классы

Я сломал код React в кучу отдельных классов. Вот что они есть и о чем они несут ответственность.

  • Timepicker – Это общий класс, который соединяет все вместе. Это то, что пользователь будет создан в собственном реагированном проекте. Он несет ответственность за оказание триггера (входное поле, показывающее текущее выбранное время) и Часы класс.
  • Часы – Класс, используемый для показать пользователю фактический соперник времени, который плавает выше или ниже триггера в зависимости от вертикального положения прокрутки пользователя в окне. Это обрабатывает, показывая и скрывая Часы и Минут классы, а также рендеринг Ampminfo класс.
  • Ampminfo – Класс, используемый для отображения двух вещей: в текущем отобранном времени и кнопки AM и PM, чтобы позволить пользователю переключаться между утренним и днем соответственно.
  • Часы – Отвечать за то, что показывает часы часы, из которого пользователь может выбрать час в течение своего времени. Строит список часов, затем выключен в Лицо класс.
  • Минут – То же, что и Часы класс, но в течение нескольких минут.
  • Лицо – Этот класс отвечает за нанесение рисунка часы, используемое Часы и Минут классы. Это включает в себя Клещи и Longhand Отказ
  • Longhand – Когда появляется часовое лицо, есть линию, которая тянутся из центра к выбранному значению, как длинная рука на часах. Этот класс отвечает за рисунок этой линии и обновлять свою позицию.
  • Клещи – Этот класс рисует линии тика, которые соответствуют минутам на лицевой стороне. Они сидят по краю.

Здесь здесь довольно много классов, но большинство из них маленькие и имеют действительно узкий набор обязанностей. Давайте начнем.

Тима

var TimePicker = React.createClass({
    getInitialState: function getInitialState() {
        return {
            visible: false,
            hour: 12,
            minute: 0,
            am: true,
            position: {
                top: 0,
                left: 0
            }
        };
    },

    componentWillMount: function componentWillMount() {
        document.addEventListener("click", this.hideOnDocumentClick);
    },

    componentWillUnmount: function componentWillUnmount() {
        document.removeEventListener("click", this.hideOnDocumentClick);
    },

    show: function show() {
        var trigger = this.refs.trigger.getDOMNode(),
            rect = trigger.getBoundingClientRect(),
            isTopHalf = rect.top > window.innerHeight / 2;

        this.setState({
            visible: true,
            position: {
                top: isTopHalf ? rect.top + window.scrollY - CLOCK_SIZE - 3 : rect.top + trigger.clientHeight + window.scrollY + 3,
                left: rect.left
            }
        });
    },

    hide: function hide() {
        this.setState({
            visible: false
        });
    },

    hideOnDocumentClick: function hideOnDocumentClick(e) {
        if (!_parentsHaveClassName(e.target, "time-picker")) this.hide();
    },

    onTimeChanged: function onTimeChanged(hour, minute, am) {
        this.setState({
            hour: hour,
            minute: minute,
            am: am
        });
    },

    formatTime: function formatTime() {
        return this.state.hour + ":" + _pad(this.state.minute) + " " + (this.state.am ? "AM" : "PM");
    },

    render: function render() {
        return 
; } });

Во-первых, мы устанавливаем основное состояние на весь сортировщик времени в Получающийся стадь функция. Изменения этих значений привод рендеринга обновлений в остальной части модуля. В ComponentWillmount и ComponentWillunmount Методы, мы устанавливаем обработчик событий, чтобы скрыть сортирую времени, в том случае, чтобы пользователь нажимал его, используя HideondocumentClick функция.

Показать Метод немного сложен. Он несет ответственность за не только сказывающуюся пикур, но и для позиционирования его правильно внутри окна. Мы установили Ref на входном элементе триггера, чтобы мы могли получить его положение. Ref In React JS запутывает элемент DOM, потому что большую часть времени нам не нужно связаться с ним. Чтобы попасть в основной элемент DOM, мы называем getdomnode функция. Затем мы называем GetBoundingClientRect Чтобы получить его позицию на странице, из которой мы можем определить, следует ли отображать время отбора времени выше или ниже триггера.

Скрыть Метод просто скрывает Picker Time, установив свойство видимости состояния в false.

OntimeChanged Метод – это обработчик событий, который уволен, когда пользователь обновляет время. Это включает в себя изменения в час, минуту или значение AM/PM. Эти государственные свойства – это то, что Часы , Минут и Ampminfo Классы используют для рендеринга их соответствующих выбранных значений.

оказывать Метод требуется в классе React. Для Timepicker Класс, он используется для того, чтобы сделать две вещи: триггер и Часы модуль.

Часы

var Clock = React.createClass({
    getInitialState: function getInitialState() {
        return {
            hoursVisible: true,
            minutesVisible: false,
            position: "below"
        };
    },

    componentWillReceiveProps: function componentWillReceiveProps(props) {
        if (this.props.visible && !props.visible)
            this.setState({
                hoursVisible: true,
                minutesVisible: false,
                amPmVisible: false
            });
    },

    getTime: function getTime() {
        return {
            hour: this.props.hour,
            minute: this.props.minute,
            am: this.props.am
        };
    },

    onHourChanged: function onHourChanged(hour) {
        this._hour = hour;
        this.setState({
            hoursVisible: false,
            minutesVisible: true
        });
    },

    onHoursHidden: function onHoursHidden() {
        this.props.onTimeChanged(this._hour, this.props.minute, this.props.am);
    },

    onMinuteChanged: function onMinuteChanged(minute) {
        this.props.onDone();
        this._minute = minute;

        this.setState({
            minutesVisible: false,
            amPmVisible: true
        });
    },

    onMinutesHidden: function onMinutesHidden() {
        this.props.onTimeChanged(this.props.hour, this._minute, this.props.am);
    },

    onAmPmChanged: function onAmPmChanged(am) {
        this.props.onTimeChanged(this.props.hour, this.props.minute, am);
    },

    render: function render() {
        return 
; } });

Состояние для Часы Класс довольно прост.

ComponentWilreceiveProps Метод не часто используется в классах RACT (или, скорее, я не использовал его очень), но это мощный метод. Это позволяет классу реагировать на изменения в опоре перед тем, как метод рендеринга. В нашем случае здесь я сбрасываю начальное состояние модуля, когда текущая видимость (которая сохраняется в методе ComponentWillReceiveProps ), и новая видимость ложная, указывая на то, что родитель хочет Часы прятаться.

получить время Метод – это удобная функция для инкапсулирования выбранного часа, минуты и значение AM/PM, чтобы отдать до детских классов.

OnhourChanged и Onhourshidden Обработчики событий связаны. Бывшие пожары, когда пользователь нажал на час, а последние пожали, когда Часы Часы исчезли. Это не происходит одновременно из-за возникновения исчезновения. OnhourChanged Функция устанавливает переменную классу ( не в состоянии модуля, так как мы не хотим, чтобы он еще не вызывал Rerender), который содержит выбранный час. Тогда примерно полна вторая позже, когда срабатывает событие переходного дня, Onhourshidden Обработчик событий огонь и обновляет значение часа в Часы состояние через OntimeChanged опоры, который в свою очередь запускает рендер по модулю. OnminuteChanged и OnMinuteshidden Функция точно такой же, но в минуту вместо часов. OnampmChanged Обработчик событий не вызывает никаких анимаций, поэтому он просто указывает на родитель, что время изменилось.

Во время оказывать Метод, Часы класс строит Часы , Минут и Ampminfo Классы, наряду с несколькими позиционирования и стиль Divs.

Ampminfo.

var AmPmInfo = React.createClass({
    render: function render() {
        var time = this.props.time;
        return 
AM
{_getTimeString(time.hour, time.minute, time.am)}
PM
; } });

Ampminfo Класс отвечает за две вещи: предоставление кнопок для AM и PM, чтобы позволить пользователю переключаться между двумя и отображать текущее выбранное время. Время Класс несет ответственность за последнее и сидит между утренним и дневным кнопками.

Часы

var Hours = React.createClass({
    buildHours: function buildHours() {
        var hours = [];
        for (var i = 1; i <= 12; i++) hours.push(i);
        return hours;
    },

    render: function() {
        var { time, ...props } = this.props;
        return ;
    }
});

Часы в основном просто Passthroough к Лицо класс. Buildhours Функция просто создает массив, заполненный номерами 1-12 включительно, который передается в Лицо экземпляр в качестве значений для отображения.

Остальная часть реквизита, прошедших, передаются по очереди прямо в Лицо класс. Если вы не знакомы с ES6, я использую Разрушение задания Оператор для тяги время вне опоры, затем используя Распространение оператора пройти эти реквизиты прямо в Лицо класс. Нижняя линия вот что реквизит для Часы Класс в основном так же, как то, что требуется для Лицо класс, так что я принимаю все, кроме время опоры и передача их прямо к Лицо пример.

Минут

var Minutes = React.createClass({
    buildMinutes: function buildMinutes() {
        var minutes = [];
        for (var i = 1; i <= 12; i++) minutes.push(_pad((i === 12 ? 0 : i) * 5));
        return minutes;
    },

    render: function() {
        var { time, ...props } = this.props;
        return ;
    }
});

Минут Класс действительно похож на Часы класс в том, что он рушится к Лицо Класс с несколькими пользовательскими параметрами данных. Массив значений теперь заполняется незначительными значениями вместо часов. Вот и все.

Лицо

var Face = React.createClass({
    componentDidMount: function componentDidMount() {
        this.refs.face.getDOMNode().addEventListener("transitionend", this.onTransitionEnd);
    },

    componentWillUnmount: function componentWillUnmount() {
        this.refs.face.getDOMNode().removeEventListener("transitionend", this.onTransitionEnd);
    },

    onTransitionEnd: function onTransitionEnd(e) {
        if (e.propertyName === "opacity" && e.target.className.indexOf("face-hide") > -1) this.props.onHidden();
    },

    render: function render() {
        return 
{this.props.values.map(function(value, i) { return
{_pad(value)}
}.bind(this))}
; } });

Лицо Класс несет ответственность за рисование часов и минуты, которые позволяют пользователю выбирать час и минуту соответственно. Это включает в себя нанесение клещей вокруг края часовой поверхности (через Ticks класс), рисуя длинную руку, которая указывает на выбранное значение (через longhand класс) и обрабатывать щелчки каждого отдельного значения Отказ

ComponentDidmount и ComponentWillunmount Методы используются для прослушивания, когда произошла анимация Fade Clace Face. Когда это происходит, Ontransitionend Метод проверяет, если событие соответствует тому, что мы ищем (огненные события нескольких переходов), а затем выполняет Onhidden опоры, крючком к Onhourshidden или OnMinuteshidden Методы Часы класс.

Примечание: Я не огромный поклонник того, как этот код оказался, так как мои CSS протекает в мой JavaScript. Я действительно не хочу, чтобы проверить, что переход для стиля непрозрачности, и я действительно, действительно не хочу, чтобы проверить имя класса. Если у кого-то есть лучший способ достичь этого, я все уши – дайте мне знать в комментариях!

оказывать Способ, итерат над Значения опоры и выплевывает div для каждого, используя карта метод. Затем это создает экземпляры Longhand и Клещи Классы, а также заставить все выглядеть немного больше похоже на часы.

Лонгганда

var LongHand = React.createClass({
    render: function render() {
        var deg = (this.props.selected / (this.props.type === "hours" ? 12 : 60) * 360);
        return 
; } });

Longhand Класс используется исключительно, чтобы все выглядели немного приятнее. Он рисует линию из центра часов лица к выбранному значению, смутно выглядит как длинная рука аналоговых часов. Я делаю это, рисуя линию, которая входит в один пиксель из верхнего центра до среднего центра часовой части лица, а затем вращающуюся соответствующее количество градусов с использованием преобразований CSS. Обратите внимание, что мы должны использовать имя свойства свойства CSS WebKittransform », а также нормальное« преобразование », поскольку Safari еще не поддерживает не предварительно префиксную версию.

Галочка

var Ticks = React.createClass({
    buildTick: function buildTick(index) {
        return React.createElement(
            "div",
            { key: index, className: "tick " + (index % 5 === 0 ? "big " : ""), style: { transform: "rotate(" + index * 6 + "deg)", WebkitTransform: "rotate(" + index * 6 + "deg)" } },
            React.createElement("div", null)
        );
    },

    render: function render() {
        var ticks = [];
        for (var i = 0; i < 60; i++)
            ticks.push(this.buildTick(i));

        return 
{ticks}
; } });

Похож на Longhand класс, Клещи Класс в основном используется в качестве макияжа, чтобы позволить часовым лицом выглядеть немного ближе к фактическим часовым лицом. Большая часть волшебства здесь происходит в CSS (что вы можете увидеть в исходном коде ). По сути, я рисую линию от центра от центра до центра в середине, как в Longhand Класс, но на этот раз я делаю это шестьдесят раз. Каждый из линий вращается вокруг его нижней точки, чтобы дать иллюзию спиц на колесе. Эти линии нарисованы в белом, а вторая Div является положением выше и слоившись сверху в сером цвете, чтобы привести к появлению трассы в лицо. Каждая пятая галочка немного больше, чем остальное, поскольку они соответствуют выбору.

Заключение

Как я уже сказал в начале поста, если вы заинтересованы в использовании Picker Time в вашем приложении, я опубликовал его на Bower Отказ Пока код не полностью полон ошибок, это, вероятно, не готово не добыча, и нет никаких модульных тестов, чтобы поддержать его, поэтому пользователь остерегается!

Если вы заинтересованы в том, чтобы увидеть соперник времени в действии, я собрал Демо-страница для вас взглянуть. Исходный код Также доступен на Github.

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