Ускоренный курс по компонентам кода с новым Framer X API.

Вступление

Добро пожаловать в третью и последнюю часть Проектирования коммутатора во Framer, короткую серию руководств, в которой мы будем создавать и использовать компонент кода во Framer X.

В части I мы:

  • Настройте рабочее пространство Framer X.
  • Создал компонент кода для нашего Switch
  • Определили логику состояния нашего компонента
  • Представлено состояние нашего компонента с помощью анимации

В части II мы:

  • К нашему коммутатору добавлены свойства, чтобы мы могли устанавливать его состояние извне компонента.
  • Добавлены элементы управления свойствами для нашего коммутатора, чтобы мы могли настраивать свойства нашего компонента через пользовательский интерфейс Framer.

В части III мы:

  • Дайте нашему Switch свойство event handler, чтобы мы могли поделиться его состоянием с остальной частью нашего проекта.
  • Используйте переопределения, чтобы изменить второй компонент, когда наш переключатель Switch переключается

Если вы новичок во Framer X (или в React), это руководство станет отличным введением в работу с кодом. Я бы рекомендовал заполнить Часть I и Часть II, прежде чем работать над этой.

Начиная

Мы будем делать этот проект с Framer X. Если у вас его еще нет, скачайте копию и наслаждайтесь 14-дневной пробной версией.

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

Совместное использование состояния с обработчиком событий

В прошлой статье мы узнали о том, как получать информацию в наш компонент из внешнего мира через свойства. Однако, хотя теперь наш коммутатор может получать информацию, он по-прежнему не может передавать информацию другим компонентам. Другими словами, наш переключатель можно переключить, но он не может переключить что-либо еще!

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

Обработчики событий - это функции обратного вызова, которые компонент будет вызывать при возникновении события. Компоненты обычно вызывают обработчики событий с аргументами, содержащими информацию о произошедшем событии. Во Framer X Frames и другие компоненты используют события как способ реагирования на действия пользователя.

Добавление нашего обработчика событий

Мы вызовем наш обработчик событий onValueChange. Начнем с добавления onValueChange к свойствам по умолчанию нашего компонента.

  1. Когда наш проект открыт во Framer X, откройте вкладку кода, выбрав значок кода на панели вкладок или нажав Command + 4.
  2. В списке файлов выберите файл нашего компонента Switch.tsx.
  3. В файле нашего компонента найдите определениеdefaultProps компонента. Он будет ниже нашего компонента.
  4. В defaultProps нашего компонента добавьте новое свойство с именем onValueChange. Задайте для него функцию, которая принимает логический аргумент isOn и возвращает null.
import * as React from "react"
import { Frame } from "framer"
export function Switch(props) {
    ...
}
Switch.defaultProps = {
    isOn: false
    onValueChange: (isOn: boolean) => null
}

Обработчики событий обычно называют, помещая on перед именем события. Например, обработчик события «щелчок» обычно будет называться onClick, обработчик события «сбой» обычно будет называться onCrash и так далее. Однако, помимо упрощения использования наших компонентов, имена, которые мы используем, не влияют на работу функции.

Вызов обработчика событий

Затем давайте звонить props.onValueChange каждый раз, когда наш переключатель переключается.

  1. Вернувшись в наш компонент, найдите функцию flipSwitch.
  2. Над нашим вызовом setState вставьте строку, которая вызывает props.onValueChange с новым значением state.isOn.
const flipSwitch = () => {
    props.onValueChange(!state.isOn)
    setState({
        isOn: !state.isOn,
    })
}

Взгляните еще раз на эту функцию. Обратите внимание, что мы пишем !state.isOn дважды? Повторение обычно является признаком того, что наш код становится беспорядочным. Очистка запутанного кода (или рефакторинг) - это часть обучения программированию!

  • Можете ли вы реорганизовать нашу flipSwitch функцию, чтобы мы писали !state.isOn только один раз?

Тестирование нашего обработчика событий

Теперь, когда мы добавили обработчик событий, давайте убедимся, что он делает то, что мы хотим.

  1. Вернувшись в нашу defaultProps, измените функцию по умолчанию onValueChange, чтобы записывать сообщение в консоль, как показано ниже.
  2. Затем откройте предварительный просмотр.
  3. Откройте консоль, выбрав Показать консоль в меню предварительного просмотра или нажав Command + I.
Switch.defaultProps = {
    isOn: false
    onValueChange: (isOn: boolean) => console.log(isOn)
}

Консоль - отличный способ проверить, выполняет ли ваш проект то, что вы от него ожидаете. Вы можете console.log что угодно, оставив достаточно отзывов, чтобы исправить ваши ошибки.

Если все пойдет хорошо, мы увидим значение аргумента (!state.isOn), которое мы используем, когда вызываем props.onValueChange из нашей flipSwitch функции.

На следующих этапах мы снова будем использовать консоль, поэтому давайте очистим ее, удалив вызов console.log.

  1. Вернитесь к defaultProps нашего компонента.
  2. Верните нашу onValueChange функцию обратно на (isOn: boolean) => null.

Последние штрихи

Вы не поверите, но мы закончили с нашим компонентом! По крайней мере, в этом руководстве мы больше не будем вносить в него никаких изменений. Если вы хотите продолжить работу над коммутатором, вот некоторые проблемы:

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

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

Отменяет

Во Framer X переопределения - это способ соединить части нашего дизайна вместе.

На самом базовом уровне переопределения позволяют нам объединять новые свойства с существующими свойствами компонентов нашего дизайна. Они дают нам возможность изменять (или переопределять) свойства, которые мы установили на холсте, например height и width фрейма, но они также позволяют нам устанавливать реквизиты, которые не могут быть установлены из холст, например onTap. Переопределения действуют только в режиме предварительного просмотра.

Чтобы действительно сделать переопределения полезными, нам нужно использовать их вместе с объектом Data. Объект Data похож на state нашего компонента, но предназначен для работы с переопределениями: всякий раз, когда мы изменяем его значения, каждое переопределение запускается снова, каждое слияние новых свойств с их подключенными компонентами.

Не волнуйтесь, если вы еще не поняли! Как обычно во Framer X, мы будем учиться на практике.

Создание файла переопределений

Давайте создадим новый файл, в котором мы запишем наши переопределения.

  1. Вернитесь на холст.
  2. Нажмите на наш экземпляр Switch, чтобы выбрать его.
  3. На панели свойств щелкните раздел Переопределить.
  4. В раскрывающемся списке Файлы выберите Новый файл.
  5. Теперь нажмите кнопку Изменить код.

Это откроет новый файл переопределений с именем App.tsx.

Как и файл нашего компонента (Switch.tsx), файл переопределений - это .tsx файл, который экспортирует различные функции в остальную часть нашего проекта.

Создание нашего состояния данных

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

  1. Вверху нашего App.tsx файла добавьте Data в список импорта из библиотеки "framer".
  2. Удалите остальной код в файле.
  3. Создайте новый объект данных, как показано ниже.
import { Override, Data } from "framer"
const data = Data({
    theme: "day"
})

Переопределение нашего фрейма устройства

Затем давайте создадим переопределение для нашего устройства Frame. Наш фрейм устройства - это самый первый фрейм, который мы создали в этом уроке: он находится на нашем холсте и содержит наш экземпляр Switch.

  1. В нашем файле переопределений удалите переопределение по умолчанию.
  2. Вместо него создайте новое переопределение с именем DeviceFrame, как показано ниже.

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

import { Override, Data } from "framer"
const data = Data({
    theme: "day"
})
export function DeviceFrame(props): Override  {
    return {
        backgroundColor: "#222222"
    }
}

Это наиболее «простое» переопределение: function, который вызывается с props подключенного фрейма, и который возвращает объект новых свойств. При предварительном просмотре компонента, подключенного к переопределению, Framer вызовет функцию переопределения, вернет новые свойства, а затем объединит эти свойства с исходными свойствами подключенного компонента. Затем Framer передаст результат обратно компоненту в качестве свойств.

Чтобы увидеть, как это работает, давайте подключим переопределение к нашему устройству Frame.

  1. Вернувшись на холст, выберите фрейм устройства.
  2. На панели свойств выберите новое переопределение в раскрывающемся списке Переопределение.
  3. Откройте предварительный просмотр, чтобы увидеть результаты.

Интересно! Фон кадра нашего устройства белый на холсте, но - благодаря нашему переопределению - элегантный черный в нашем предварительном просмотре.

Как бы красиво это ни было, оно не соответствует нашей теме! В соответствии с нашим data состоянием, наша тема в настоящее время "day". Мы хотим, чтобы рамка нашего устройства была черной, только если наша тема “night”.

Делаем наше переопределение условным

Давайте вернемся и изменим наше переопределение так, чтобы свойство background, которое оно возвращает, было либо черным, либо белым, в зависимости от значения data.theme.

  1. Вернитесь на вкладку код.
  2. Если он еще не выбран, выберите наш файл переопределений (App.tsx) в списке файлов кода нашего проекта.
  3. В нашем DeviceFrame переопределении удалите свойство background из набора возвращаемых свойств переопределения.
  4. Вместо этого добавьте набор variants для day и night, как показано ниже.
  5. Добавьте свойство initial и animate и укажите для обоих свойств значение data.theme.
import { Override, Data } from "framer"
const data = Data({
    theme: "day",
})
export function DeviceFrame(props): Override {
    return {
        variants: {
            day: {
                backgroundColor: "#FFFFFF"
            },
            night: {
                backgroundColor: "#222222"
            }
        },
        initial: data.theme,
        animate: data.theme,
    }
}

Этот код должен выглядеть знакомо: он почти идентичен коду, который мы использовали для определения вариантов нашего компонента в Части I этого руководства.

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

Чтобы проверить, все ли работает, попробуйте изменить значение data.theme с "day" на "night". Ваше устройство также изменило цвет фона с белого на черный?

Переопределение нашего коммутатора

Теперь, когда цвет фона Frame нашего устройства связан с нашим состоянием данных, давайте перейдем к нашему экземпляру Switch. Мы хотим, чтобы наш переключатель был включен, когда theme.mode равен "night", и выключен, когда theme.mode равен “day”.

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

  1. В нашем файле переопределений создайте новое переопределение и назовите его ThemeSwitch. Если этого имени нет, вы можете использовать другое - имена наших переопределений не имеют значения, если они уникальны.
  2. В реквизитах, которые возвращает наше переопределение, задайте для свойства isOn выражение, которое будет оценивать значение true, если data.theme равно "night", или false.
  3. Вернувшись на холст, подключите наш экземпляр Switch к новому переопределению.
export function ThemeSwitch(props): Override {
    return {
        isOn: data.theme === "night",
    }
}

Теперь снова откройте предварительный просмотр и посмотрим, что изменилось.

Изменение состояния наших данных

Мы почти закончили! Все, что осталось, это переключить наш переключатель между on и off, а также переключить нашу тему между днем ​​ и ночью. Для этого воспользуемся обработчиком событий onValueChange нашего компонента.

  1. В нашем ThemeSwitch переопределении добавьте свойство onValueChange к реквизитам, возвращаемым этим переопределением.
  2. Задайте для этого свойства функцию обратного вызова, которая принимает isOn в качестве аргумента.
  3. Внутри этой функции используйте значение аргумента isOn, чтобы установить data.theme на "day" или “night”.
export function ThemeSwitch(props): Override {
    return {
        isOn: data.theme === "night",
        onValueChange: isOn => {
            data.theme = isOn ? "night" : "day"
        },
    }
}

А при предварительном просмотре…

Наш маленький коммутатор наконец-то приступил к работе!

Наш готовый компонент

Давайте еще раз посмотрим на наш компонент.

Как и раньше, мы рассмотрим каждую добавленную часть. Все, что не описано ниже, - это код, который мы уже рассмотрели в Части I или Части II.

Line 18: в нашей функции flipSwitch мы добавили строку, которая вызывает props.onValueChange. Мы вызываем эту функцию со значением state.isOn.

Line 63: Мы также onValueChange применили defaultProps к нашему компоненту. Значение по умолчанию - это функция, которая ничего не делает.

Наши готовые переопределения

Давайте также рассмотрим наш файл переопределений.

Line 1: В первой строке нашего файла переопределений мы импортировали псевдоним типа Override и функцию Data из библиотеки "framer".

Lines 3 - 5: Здесь мы создаем объект Данные и назначаем его переменной data. Наш объект данных отслеживает единственное свойство theme, имеющее начальное значение "day".

Lines 7 - 20: Это наше переопределение для нашего устройства Frame. Он возвращает набор variants, day и night и использует data.theme, чтобы определить, какой вариант использовать при первом монтировании подключенного компонента (его вариант initial) и к какому варианту компонент должен animate при повторном рендеринге компонента.

Lines 22 - 29: Наконец, мы создали переопределение для нашего коммутатора. Он заменяет isOn подключенного компонента значением, которое является условным для data.theme, возвращая true, когда data.theme равно “night”, и false, когда data.theme равно “day”. Он также заменяет опору onValueChange функцией обратного вызова, которая устанавливает значение data.theme на “night”, если переключатель был включен, или “day”, если он был выключен.

И в заключение давайте рассмотрим, как работает наш прототип:

  • Перемещение переключателя изменит значение data.theme.
  • Поскольку data - это особый объект данных, это изменение заставит снова выполнить каждое из наших переопределений.
  • При их запуске любые выражения, указывающие на data.theme, будут решены с использованием текущего значения этого свойства, возвращая разные реквизиты в зависимости от того, является ли это значение “day” или “night”.

Чтобы скачать готовый проект, нажмите здесь.

Эй, ты добрался до конца. Поздравляем! Если вы новичок в программировании или только что знакомы с Framer X, я надеюсь, что вам понравилось делать первые шаги в разработке интерактивных компонентов и прототипов.

Если вам понравился этот урок, пожалуйста, помогите распространить информацию, нажав кнопку хлопка! Если у вас есть вопросы, задавайте их ниже или пишите мне в Твиттере на @steveruizok. Мы также можем подключиться к сообществам Framer Slack и Spectrum.

Следите за появлением новых руководств и пошаговых руководств в ближайшее время!