Компоненты веб-страницы SVG для Интернета вещей и производителей (часть 1)

Опубликовано: 2022-03-10
Краткий обзор ↬ Интернет вещей расширяется и включает в себя множество устройств со многими владельцами. Веб-разработчики столкнутся с проблемой поиска способов, позволяющих владельцам взаимодействовать со своими устройствами. Но эта проблема порождает большой бизнес. Давайте рассмотрим некоторые аспекты разработки веб-страниц для Интернета вещей (IoT), которые уже пользуются спросом.

Рынок IoT все еще находится на ранней стадии, но набирает обороты. Мы находимся на пороге истории IoT. Рынки выросли в четыре раза за пять лет, с 2015 по 2020 год. Для веб-разработчиков этот рост IoT имеет большое значение. Уже существует большой спрос на веб-технологии IoT.

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

В этом обсуждении рассматриваются требования к интерфейсу с использованием Vue.js в качестве катализатора и иллюстрируется один из множества вариантов взаимодействия веб-страницы с устройством.

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

  1. Создайте одностраничное веб-приложение SPWA, в котором размещены группы человеко-машинных интерфейсов IoT (мы можем назвать эти группы «панелей»);
  2. Отображение списков идентификаторов групп панелей в результате запроса к серверу;
  3. Отображение панелей выбранной группы в результате запроса;
  4. Убедитесь, что дисплей панели загружается лениво и быстро анимируется;
  5. Убедитесь, что панели синхронизируются с устройствами IoT.
Еще после прыжка! Продолжить чтение ниже ↓

Интернет вещей и быстрый рост веб-страниц

Представление графики для визуализации и удаленного управления оборудованием, а также синхронизация веб-страниц с физическими процессами в реальном времени находятся в сфере решения проблем веб-страниц, присущих этому будущему IoT.

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

Востребованы дашборды и визуализация данных. Кроме того, высока потребность в том, чтобы выйти за рамки веб-страниц, которые предоставляют формы, списки отображения или текстовое содержимое. Панели для IoT должны быть пиктографическими, анимированными. Анимации должны быть синхронизированы с физическими процессами в реальном времени, чтобы предоставить пользователям достоверное представление о состоянии машины. Состояние машины, например, горит пламя или нет, превосходит состояние приложения и предоставляет операторам важную информацию, возможно, даже информацию о безопасности.

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

Ничего нового. Компьютерные интерфейсы для оборудования существуют уже давно, но быстрый рост использования веб-страниц для этих интерфейсов является частью нашего нынешнего опыта. WebRTC и Speech API находятся на пути развития, который начался в 2012 году. WebSockets разрабатывались в аналогичные сроки.

IoT уже давно в наших умах. IoT был частью человеческого диалога с 1832 года. Но IoT и беспроводная связь, как мы узнаем, были задуманы Теслой примерно в 1926 году. Forbes 2018 State of IoT рассказывает нам о текущем фокусе рынка для IoT. В статье, представляющей интерес для веб-разработчиков, называются информационные панели:

«Первые последователи или сторонники IoT отдают приоритет информационным панелям, отчетности, вариантам использования IoT, которые обеспечивают потоки данных, являющиеся неотъемлемой частью аналитики, расширенной визуализации и интеллектуального анализа данных».

Рынок IoT огромен. В этой статье о размере рынка дается прогноз количества устройств, которые появятся: 2018 год: 23,14 миллиарда ⇒ 2025 год: 75,44 миллиарда. И он пытается подсчитать финансовые показатели: 2014 год: 2,99 триллиона долларов ⇒ 2020 год: 8,90 триллиона долларов. Спрос на навыки IoT будет расти быстрее всего: IoT в спросе.

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

Современные интерфейсы, созданные для управления машинами, часто имеют четко определенную компоновку, характерную для конкретной машины или установки нескольких машин. Например, в умном доме система высокого класса будет иметь ЖК-дисплей с панелями для аккуратно размещенных устройств. Но по мере того, как мы будем расти с веб-версией IoT, будет любое количество панелей для динамического и даже мобильного потока устройств.

Управление панелями для устройств становится похожим на управление социальными связями на социальных веб-сайтах.

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

Панель инструментов представляет собой одностраничное веб-приложение SPWA. И мы можем представить себе базу данных панелей. Таким образом, если один пользователь собирается получить доступ к нескольким панелям и конфигурациям своих устройств, разбросанных по планете, SPWA необходимо получить доступ к компонентам панели по запросу. Панели и некоторые из поддерживающих их JavaScript должны загружаться лениво.

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

Давайте воспользуемся Vue.js, WebSockets, MQTT и SVG, чтобы сделать шаг на рынок IoT.

Рекомендуемая литература : Создание интерактивной инфографики с помощью Vue.js

Архитектура высокого уровня для веб-приложения IoT

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

Многие из нас знакомы с инструментами, которые позволяют записывать HTML-шаблоны со специальными маркерами, указывающими, куда помещать значения переменных. Увидев {{temperature}} в таком шаблоне, мы и механизм представления обратимся к температуре, запрошенной с устройства, и заменим ею символ {{temperature}} . Таким образом, дождавшись, пока сервер запросит устройство, устройство ответит, отобразит страницу и доставит страницу, пользователь, наконец, сможет увидеть температуру, сообщаемую устройством.

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

Архитектура веб-страницы для обработки Интернета вещей как сервера форм — поиск чего-то лучшего.
Архитектура веб-страницы для обращения с IoT как с сервером форм — поиск чего-то лучшего. (Большой превью)

Многие CMS работают таким образом для обновления записей в блогах и т.п. В этом нет ничего странного. Кажется, что HTML поверх HTTP всегда имел дизайн для получения обработанных страниц и для отправки данных формы для обработки веб-сервером. Более того, есть тысячи CMS на выбор. Итак, чтобы запустить нашу систему IoT, кажется разумным просмотреть эти тысячи CMS, чтобы увидеть, какая из них подходит для работы. Или мы можем применить один фильтр к CMS для начала.

Мы должны учитывать природу того, с чем имеем дело в реальном времени. Таким образом, хотя HTML в его первоначальном виде вполне хорош для многих корпоративных задач, ему требуется небольшая помощь, чтобы он стал механизмом доставки для управления IoT. Итак, нам нужна CMS или собственный веб-сервер, который помогает HTML выполнять эту работу IoT. Мы также можем просто думать о сервере, поскольку мы предполагаем, что CMS обеспечивает серверную функциональность. Нам просто нужно помнить, что сервер должен обеспечивать анимацию, управляемую событиями, поэтому страница не может быть на 100% завершена статической печатью.

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

  1. Получать данные датчиков и другие сообщения о состоянии устройства асинхронно ;
  2. Визуализировать данные датчика для страницы в клиенте (почти следствие 1);
  3. Публиковать команды на конкретное устройство или группу устройств асинхронно ;
  4. Опционально отправлять команды через сервер или обходить его.
  5. Надежно поддерживать отношения владения между устройством и пользователем;
  6. Управляйте критической работой устройства, не вмешиваясь и не переопределяя.

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

Что касается страницы, нам нужно запросить ее у веб-сервера только один раз. Мы ожидаем, что веб-сервер (или связанное с ним приложение) обеспечит безопасный путь связи. И путь не обязательно должен проходить через сервер, или, возможно, он должен вообще избегать сервера, поскольку у сервера могут быть задачи с более высоким приоритетом, кроме заботы об обмене данными одной страницы с данными, поступающими от датчиков.

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

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

Из-за физического мира с его требованиями к реальному времени и из-за дополнительных соображений безопасности наша диаграмма немного отличается от оригинала.

Одностраничное приложение, которое общается с одним MCU.
Одностраничное приложение, которое общается с одним MCU. Теперь он асинхронно взаимодействует с MCU независимо от сервера веб-страниц. (Большой превью)

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

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

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

Веб-сервер должен доставлять нужные панели нужному пользователю с учетом запросов к базе данных панелей и с учетом того, что устройства должны быть физически доступны. Более того, учитывая, что будет много разных типов устройств, панели для каждого устройства, скорее всего, будут разными. Таким образом, веб-сервер должен иметь возможность предоставлять пиктографическую информацию, необходимую для рендеринга панели. Тем не менее, HTML-страница панели мониторинга не должна загружаться со всеми возможными панелями. Неизвестно, сколько их будет.

Вот некоторые параметры, которые могут определять выбор нашей страницы панели инструментов, то, что она должна делать:

  1. Представить способ выбора групп связанных панелей устройств;
  2. Используйте механизмы одновременной связи устройств для некоторого количества устройств;
  3. Активировать панели устройств по запросу пользователя;
  4. Включите ленивую загрузку графики для создания уникальных дизайнов панелей;
  5. Используйте токены безопасности и параметры для каждой панели;
  6. Поддерживайте синхронность со всеми устройствами, находящимися под контролем пользователя.
Одностраничное приложение, которое взаимодействует с несколькими MCU асинхронно и независимо от сервера веб-страницы.
Одностраничное приложение, которое взаимодействует с несколькими MCU асинхронно и независимо от сервера веб-страницы. (Большой превью)

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

Давайте начнем с того, как мы можем визуализировать панели. Это уже кажется большой работой. Мы представляем множество различных видов панелей. Но если вы когда-либо пользовались музыкальной DAW, вы бы увидели, как они использовали графику, чтобы сделать панели похожими на аналоговые устройства, используемые группами в давние времена. Все панели в DAW рисуются плагинами, работающими со звуком. На самом деле, многие из этих плагинов DAW могут использовать SVG для рендеринга своих интерфейсов. Итак, мы ограничиваемся обработкой интерфейсов SVG, которые, в свою очередь, могут быть любой графикой, которую мы можем себе представить.

Выбор SVG для панелей

Конечно, мне нравятся DAW, и я бы использовал их в качестве примера, но SVG — это стандарт для веб-страниц. SVG — это стандарт W3C. Он предназначен для переноса штриховых рисунков на веб-страницы. Раньше SVG был гражданином второго сорта на веб-странице, который должен был жить в iFrames. Но, начиная с HTML5, он стал первоклассным гражданином. Возможно, когда выйдет SVG2, он сможет использовать элементы формы. На данный момент элементы формы являются внешними объектами в SVG. Но это не должно помешать нам сделать SVG основой для панелей.

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

Рисовать SVG несложно, потому что есть много программ для рисования линий, которые легко достать. Если вы потратите деньги, вы можете получить Adobe Illustrator, который экспортирует SVG. Inkscape уже некоторое время используется для создания SVG. Он имеет открытый исходный код и хорошо работает в Linux, но также может работать на Mac и Windows. Кроме того, есть несколько программ редактирования SVG веб-страниц с открытым исходным кодом, а также некоторые версии SaaS.

Я искал веб-редактор SVG с открытым исходным кодом. Немного осмотревшись, я наткнулся на SVG-Edit. Вы можете включить его в свои собственные веб-страницы, возможно, если вы делаете блог на основе SVG или что-то в этом роде.

Электрическая схема в SVG готова к анимации.
Электрическая схема довольно подробная, но мы можем легко получить ее в SVG и анимировать с помощью небольшого кода. (Большой превью)

Когда вы сохраняете свою работу в файл, SVG-Edit загружает ее в ваш браузер, и вы можете выбрать файл из каталога загрузки.

На рисунке, который я нарисовал, показан логический элемент И, управляющий интегратором. Это не то, что обычно можно ожидать увидеть в панели MCU. Возможно, на панели есть кнопка для подачи на один из входов логического элемента И. Затем он может иметь дисплей от АЦП, который считывает выходные данные интегратора. Возможно, это будет линейный график на оси времени. Большинство панелей будут иметь графику, которая позволит пользователю понять, что происходит внутри MCU. И, если наша схема будет где-то жить, она будет внутри микроконтроллера.

Тем не менее, нашу электронную схему можно использовать для обсуждения анимации. Что мы хотим сделать, так это взглянуть на SVG и посмотреть, где мы можем получить некоторые из тегов DOM, которые мы хотели бы каким-то образом изменить. Затем мы можем анимировать SVG, используя немного ванильного JavaScript и таймер. Давайте заставим вентиль И мигать разными цветами.

SVG, который мы ищем, находится в следующем кодовом поле. Для программиста это выглядит не очень дружелюбно, хотя пользователь будет вполне доволен. Тем не менее, есть еще некоторые подсказки, чтобы определить, с каким элементом DOM мы хотим работать. Во-первых, большинство инструментов рисования SVG имеют способ получения свойств объекта, в частности, атрибута id . У SVG-Edit тоже есть способ. В редакторе выберите вентиль И и посмотрите на панель инструментов. Вы также увидите поле для id и class CSS.

Один из инструментов рисования SVG со способом захвата идентификатора объекта с использованием предоставленного интерфейса.
Один из инструментов рисования SVG со способом захвата идентификатора объекта с использованием предоставленного интерфейса. (Большой превью)

Если вы по какой-то причине не можете получить доступ к инструменту редактирования, вы можете открыть SVG в браузере и проверить DOM. В любом случае мы обнаружили, что у наших ворот был id = «svg_1».

 <svg width="640" height="480" xmlns="https://www.w3.org/2000/svg" xmlns:svg="https://www.w3.org/2000/svg"> <g class="layer"> <title>Layer 1</title> <path d="m80.59881,87.020171l14.714795,0m-14.714793,-11.938687l14.714797,0.000004m-0.033867,-6.543869l0,24.758504c42.377882,2.221929 43.364812,-27.139117 0,-24.758504zm47.366321,12.333056l-15.303943,0m-48.188699,-6.489897l1.454753,0l0,1.454751l-1.454753,0l0,-1.454751zm-0.068425,11.869359l1.454753,0l0,1.454753l-1.454753,0l0,-1.454753zm63.545246,-6.089294l1.454751,0l0,1.454751l-1.454751,0l0,-1.454751z" fill="#FF0000" stroke="#000000"/> <path d="m48.58886,119.662231l18.234678,0l2.523043,-7.173309l4.128604,13.808613l4.587337,-13.987948l4.013933,13.808613l4.35797,-13.629278l4.35797,13.718944l2.408353,-6.72497l18.349357,0m-64.482612,-0.623112l1.515724,0l0,1.515728l-1.515724,0l0,-1.515728zm64.484275,-0.103111l1.515721,0l0,1.515728l-1.515721,0l0,-1.515728z" fill="#FF0000" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="rotate(90.3367 80.0675 119.304)"/> <polygon cx="108.5" cy="79.5" edge="0" fill="#ffffff" orient="x" shape="regularPoly" sides="3" strokeWidth="null" strokecolor="#000000"/> <polygon cx="215.5" cy="192.5" edge="0" fill="#ffffff" orient="x" shape="regularPoly" sides="3" strokeWidth="null" strokecolor="none"/> <polygon cx="165.5" cy="164.5" edge="0" fill="#ffffff" orient="x" shape="regularPoly" sides="3" strokeWidth="null" strokecolor="none"/> <polygon cx="161.5" cy="138.5" edge="0" fill="#ffffff" orient="x" shape="regularPoly" sides="3" strokeWidth="null" strokecolor="none"/> <polygon cx="160.5" cy="161.5" edge="0" fill="#ffffff" orient="x" shape="regularPoly" sides="3" strokeWidth="null" strokecolor="none"/> <g> <path d="m225.016923,53.008793l0,3.419331m-4.558966,-1.709666l9.11791,0m10.303228,4.235512l-25.770656,0m-34.429182,0l24.544724,0m0.220544,-4.058194l1.543807,0l0,8.164451l-1.543807,0l0,-8.164451zm7.939567,-4.473673l1.543805,0l0,16.999955l-1.543805,0l0,-16.999955zm-34.176663,8.126854l1.474036,0l0,0.747515l-1.474036,0l0,-0.747515zm61.677552,0.018809l1.474038,0l0,0.747515l-1.474038,0l0,-0.747515z" fill="#FF0000" sides="3" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null"/> <polygon cx="171.5" cy="159.5" edge="43.256342" fill="#ffffff" orient="x" points="223.47406005859375,91.5 186.01296997070312,113.128173828125 186.01296997070312,69.871826171875 223.47406005859375,91.5 " shape="regularPoly" sides="3" stroke="#000000" stroke-width="null" strokeWidth="null" strokecolor="#000000"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="171" x2="186" y1="103.5" y2="103.5"/> <path d="m130.801817,80.659041l15.333707,0l2.12165,-4.564833l3.47178,8.787299l3.857534,-8.901421l3.375353,8.787299l3.664657,-8.673176l3.664657,8.730237l2.025206,-4.279526l15.430142,0m-54.224016,-0.396526l1.274586,0l0,0.964554l-1.274586,0l0,-0.964554zm54.225414,-0.065616l1.274584,0l0,0.964554l-1.274584,0l0,-0.964554z" fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="171.5" x2="171.5" y1="103.75" y2="135.388167"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="177.75" x2="177.75" y1="58.75" y2="80.255951"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="223.75" x2="266.854524" y1="91.75" y2="91.75"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="241.75" x2="241.75" y1="59.75" y2="91.754167"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="168.25" x2="180.75" y1="135.75" y2="135.75"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="169.75" x2="179.25" y1="138.5" y2="138.5"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" x1="171" x2="179.75" y1="141.25" y2="141.25"/> </g> </g> </svg>

Все, что нам сейчас нужно, это немного JavaScript. Сначала мы обращаем внимание на то, что атрибут элемента «заливка» присутствует. Далее следует простая программа:

 <html> <head> </head> <body> <!-- ALL THE SVG FROM ABOVE GOES HERE --> </body> <html> </svg> <script> // Set up a timer interval flash the color. var gateElement = document.getElementById("svg_1"); if ( gateElement ) { setInterval( () => { var fillC = gateElement.getAttribute("fill"); gateElement.setAttribute("fill", (fillC == "#00FF00") ? "#FF0000" : "#00FF00" ); }, 2000 ) } </script>

Обратите внимание, что у нас есть минимальная HTML-страница. Вы можете вырезать и вставить код в свой любимый редактор. И затем не забудьте вырезать и вставить SVG, чтобы заменить комментарий. Моя версия Chrome требует, чтобы страница была HTML, чтобы иметь раздел JavaScript. Итак, один браузер все еще рассматривает SVG как нечто отдельное. Но это далеко от дней <iframe> .

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

Рекомендуемая литература : Разложение круга SVG на пути

Строительные панели из компонентов VUE

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

Хотя первый пример показывает нам, как мы можем асинхронно изменить представление объекта, он не показывает нам, как связать представление с состоянием любого объекта данных, не говоря уже о том, который управляет машиной. Мы, конечно, можем понять, как демонстрацию setInterval можно заменить обработчиком fetch , но мы можем даже не получить состояние машины с веб-сервера, который обслуживает страницу, содержащую SVG. Кроме того, когда мы получаем данные, наши программы теперь должны знать о структуре DOM данной страницы.

К счастью, такие фреймворки, как Vue, стали популярными и могут сэкономить нам много работы.

Легко узнать о Vue. Документация Vue очень доступна. Итак, если это обсуждение зайдет слишком далеко, вы можете потратить некоторое время на изучение Vue на его собственном веб-сайте. Но на Smashing pages есть очень хорошие обсуждения. Крути Патель написала потрясающую статью о создании инфографики. Соувик Саркар рассказывает нам, как создать панель мониторинга погоды с помощью Vue.

Групповой выбор связанных панелей

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

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

Вот процесс:

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

Еще одна причина, по которой это хороший первый шаг, заключается в том, что мы можем использовать Vue в его простейшей форме. Инструменты для сборки не нужны. Мы просто включим vue.js с тегом script в HTML. На самом деле, нам даже не нужно его скачивать. Есть сайт, на котором обслуживается рабочая копия vue.js

Все, что нам нужно, это следующий тег:

 <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>

Я скопировал тег script непосредственно из документации Vue об установке.

Теперь нам нужна веб-страница, которая может загружать значки и превращать их во что-то, что щелкает. Vue делает это очень легко. На самом деле, я только что написал небольшое приложение для управления списком Twitter с помощью Vue. Он просто управляет текстовыми полями. Поскольку это немного проще, чем SPWA с использованием значков, мы можем взглянуть на него, а затем изменить его, чтобы он стал нашей желаемой структурой одностраничного приложения.

Вот часть того, как выглядит страница:

Текстовая страница, используемая в качестве отправной точки для создания графического приложения.
Текстовая страница, используемая в качестве отправной точки для создания графического приложения. (Большой превью)

Это выглядит как довольно простая страница. Каждая внешняя числовая запись представляет собой временной интервал с одним или двумя твитами в нем. Второй твит необязателен. Если вы редактируете твит, механизмы Vue обновляют объект JavaScript. На этой странице пользователь может нажать кнопку «обновить записи», чтобы сообщить серверу, что что-то изменилось, с помощью функции обработчика кнопок.

Чтобы обработчик кнопки передал данные на сервер, он должен преобразовать объект данных Vue в строку JSON. Теперь вы можете задаться вопросом, насколько сложным будет перевод объекта Vue в JSON. Получается одна строчка кода. Вы можете найти строку в следующем исходном коде, но если вы хотите найти ее быстрее, она выделена в абзаце после исходного кода.

Страница выглядит просто. Внешность может быть обманчива. Конечно, страница выглядит просто, но прост ли код? Да, действительно! Используя Vue, страница управляет содержимым полей почти волшебным образом. Вот код:

 <!DOCTYPE html> <html lang="en" prefix="og: https://ogp.me/ns#"> <!-- define microdata scope and type --> <head itemscope itemtype="https://schema.org/Article"> <title>Tweet Keeper</title> <style> body { margin: 2em; } .entryart { border: solid 1px navy; width: 80%; padding: 2px; padding-left: 6px; margin-bottom: 3px; background-color: #EEF4EE; } </style> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> </head> <body onload="GetTweets()"> <!-- some old fashioned handling --> <!-- The Vue app starts here. This is the HTML part of the Vue object --> <div> <!-- Recognize the name from the Vue doc --> <div itemscope itemtype="https://schema.org/Article"> <h1 itemprop="name">mangage tweets</h1> <p itemprop="description">My personal Tweet engine. This page accesses a personal tweet page that belongs to {{tweetOwner}}.</p> <!-- {{tweetOwner}} is in the data model. --> <button>Update Entries</button> </div> <!-- Here is a Vue loop for generating a lit --> <ol> <li v-for="tweet in tweets"> <!-- here is the first tweet represented as an object with a lable and tweet text --> <div class="entryart"> <input v-model="tweet.def[0].label" /> <input v-model="tweet.def[0].tweet" /> </div> <!-- here is the second tweet in the slot. But, notice that it is optional. --> <div class="entryart" v-if="tweet.def.length > 1"> <input v-model="tweet.def[1].label"/> <input v-model="tweet.def[1].tweet"/> </div> </li> </ol> </div> <script> var twtApp = new Vue({ el: '#tweetAppDiv', data: { tweets: [ // Where is the data? Still on the server.s ], tweetOwner : "Lucky Dude" // picked a name for demo } }); </script> </body> </html> <script> // Notice that you don't have to do everything in the Vue framework. // Here we are using some native API calls var gDefaultPostInfo = { // there server is beyond simple - an example from node.js docs method: 'POST', // or 'PUT' mode: "cors", // no-cors, cors, *same-origin cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached credentials: "same-origin", // include, *same-origin, omit redirect: "follow", // manual, *follow, error referrer: "no-referrer", // no-referrer, *client body: "", headers:{ 'Content-Type': 'application/json' } } // // // recall the "onload" function GetTweets(event) { var url = "https://localhost:8080/twitlist1.json" // We have a fixed file name. fetch(url).then((response) => { // this is now browser native response.text().then((text) => { var newData = JSON.parse(text); // DATA UPDATE! This is it. twtApp.tweets = newData // the page update right away with new data. }); }); } function sendTweets() { // recall the button up above. This is not a Vue style button, but still in the Vue app. var url = "https://localhost:8080/" var data = twtApp.tweets; // GET THE DATA OUT OF VUE. That's all folks. // // so happens that Vue pulls out the right data and stringifies it. var jdata = JSON.stringify(data); // data can be `string` or {object}! // gDefaultPostInfo.body = jdata; // that's for fetch - not Vue related // fetch(url,gDefaultPostInfo).then(res => { // We use fetch to POST as well as GET res.json() }).then(response => { console.log('Success:', JSON.stringify(response)) // promises }).catch(error => { console.error('Error:', error) }); } // // // </script>

Итак, просто чтобы выделить удивительные строки, которые говорят о силе фреймворка, давайте повторим здесь:

A. Это извлечение данных.

 postOptionsObject.body = JSON.stringify(twtApp.tweets);

Б. Это помещение данных в Vue и просмотр обновления экрана:

 twtApp.tweets = JSON.parse(text) // text is the server response

Сколько это работы?

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

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

От твитов к иконкам для получения панели

Людям нравится использовать SVG для иконок. Насколько я могу судить, им нравится это использование для SVG больше, чем для других вещей. Я привожу только количество веб-сайтов, которые продают или раздают иконки, сделанные в SVG. Преимущество заключается в том, что линейная графика имеет меньше байтов, чем изображения. И, если бы я собирался запросить списки изображений с поведением кнопки, я, возможно, ухватился бы за PNG или JPEG в те дни, когда SVG был в iframes. But, we can even find libraries in the Vue contributor lists that help us to a serving of icons.

We can turn the tweets page into an icon list returned as a search result. Just a little code has to be changed. Of course, there are a few things to be careful about if we want SVG icons to be loaded as buttons. Vue provides mechanisms for putting HTML into the application. These mechanisms have to be used or DOM elements fetched from the server don't get interpreted.

Here is the kind of rendering you can get from view if you follow your first impulse in creating a handlebars style variable location in the application DOM.

Vue will quote the HTML an insert it as text.
Vue will quote the HTML an insert it as text. (Большой превью)

Here is the code that produces the result in the picture:

 <div> <div class="entryart"> <span class="oneItem" v-for="icon in iconList"> {{icon}} </span> </div> </div> <script> var iconApp = new Vue({ el: '#iconAppTry', data: { iconList: [ // Where is the data? Still on the server. ], queryToken : "Thermo Batches" // picked a name for demo } }); </script>

Notice that we have gone from looping over tweets to looping over icons. tweet in tweets changed into icon in iconList . Our twtApp hooks into the DOM element #tweetAppDiv , while our iconApp hooks into the DOM element #iconAppTry . Within the Vue option object, the data subobject has a tweets in the first app, and iconList in the second. The fields are both empty arrays that receive data when the fetch routine does its job.

But, we have imitated our tweet app too closely. In the code above, the iconList is an array, and the server is expected to send an array of strings. So, let's say the server has sent us HTML, and we have it properly decoded with the array assigned to data.iconList . Then, the picture above can be seen.

Now, let's change the code just a little. In this revised code, we can see the following:

 v-html="icon">

Vue responds to the v-html syntax by putting in the DOM of the icon element. Notice that the syntax is included after the loop directive as another attribute to the span tag.

By removing the handlebars syntax and using v-html , our picture changes to something more comprehensible:

 <div> <div class="entryart"> <span class="oneItem" v-for="icon in iconList" v-html="icon"> </span> </div> </div> <script> var iconApp = new Vue({ el: '#iconAppTry2', data: { iconList: [ // Where is the data? Still on the server. ], queryToken : "Thermo Batches" // picked a name for demo } }); </script> 
Using the right directive, Vue inserts DOM, resulting in the rendering of desired graphics.
Using the right directive, Vue inserts DOM, resulting in the rendering of desired graphics. (Большой превью)

While v-html is a quick way to do things, the Vue team recommends using components to get the desired HTML into the page. That seems like a good idea, and we shall soon set about doing that.

But, let's use the v-html syntax for our next example.

It's time to set up our working example for fetching SVG icons. Let's have those icons be responsive to a button click. Once those are working, we can get the panels associated with an icon.

Let's suppose that the SVG required for icons is stored in a database. For our example, we can just fetch a JSON file from the server. The grown-up version of the icon server would store many such files in a database, and deliver them to the page with the same mechanisms.

Also, it's best if the SVG arrives on the page URL encoded since we will be using JSON parse. The SVG can be decoded by calling JavaScript's decodeURIComponent function.

In order to simulate the response to searching, we can make use of several JSON files. The page can have one button for each file. Here is the code for the page:

 <!DOCTYPE html> <html lang="en" prefix="og: https://ogp.me/ns#"> <!-- define microdata scope and type --> <head itemscope itemtype="https://schema.org/Article"> <title>Search Bar</title> <style> body { margin: 2em; } div { margin: 6px; } .entryart { border: solid 1px navy; width: 80%; padding: 2px; padding-left: 6px; margin: 2px; margin-bottom: 3px; background-color: #EEF4EE; } .oneItem { background-color: #EEFFFF; margin: 2px; padding: 4px; border: solid 1px purple; } </style> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> </head> <body> <!-- some old fashioned handling --> <!-- The Vue app starts here. This is the HTML part of the Vue object --> <div> <!-- Recognize the name from the Vue doc --> <div> <h2 itemprop="name">Request MCU Groups</h2> <p itemprop="description">These are groups satistfying this query: {{queryToken}}.</p> <!-- {{tweetOwner}} is in the data model. --> <button>Find All</button> <button>Find 5 Point</button> <button>Find 6 Point</button> </div> <!-- Here is a Vue loop for generating a lit --> <div class="entryart"> <button v-for="iconEntry in iconList" @click="goGetPanel(iconEntry.name)" > <div v-html="iconEntry.icon"> </div> </button> </div> </div> <script> var iconApp = new Vue({ el: '#iconAppTry', data: { iconList: [ // Where is the data? Still on the server. ], queryToken : "Thermo Batches" // picked a name for demo }, methods : { goGetPanel: (pname) => { // `this` inside methods points to the Vue instance alert('Hello ' + pname + '!') } } }); </script> </body> </html> <script> // // recall the "onclick" on the <buttons> function GetIcons(points) { // special file names instead of search parameters // var url = (points == 11) ? "https://localhost:8080/batchQuery-all.json" : ((points == 5) ? "https://localhost:8080/batchQuery-five.json" : "https://localhost:8080/batchQuery-six.json") fetch(url).then((response) => { // this is now browser native response.text().then((text) => { var newData = JSON.parse(text); // DATA UPDATE! This is it. newData = newData.map(obj => { obj.icon = decodeURIComponent(obj.icon); return(obj) }); iconApp.iconList = newData; // the page update right away with new data. }); }); } </script>

Here is one display of icons that have been fetched from the server:

Icons that might be returned from a search for MCU groups.
An artistic idea suggesting how search could return icons indicating certain groups of MCU's to interact with. (Большой превью)

The data being sent is an array with the following kind of structure:

{ "style" : { "color" : "red", "backgroundColor" : "yellow" }, "icon" : svg1, "name" : "thermos" },

Здесь svg1 — это SVG, взятый из файла. Конечно, праведный сервер взял бы структуру из базы данных, где в структуре хранился бы SVG.

Вот фрагмент кода выше. Это код, который извлекает JSON и помещает массив структур в приложение Vue. Вы можете увидеть структуру fetch в использовании. Текст анализируется, и в следующей строке декодируется закодированный SVG. Еще одна строка, и Vue обновит страницу. Количество кнопок на панели кнопок будет равно длине массива JSON.

 fetch(url).then((response) => { // this is now browser native response.text().then((text) => { var newData = JSON.parse(text); // DATA UPDATE! This is it. newData = newData.map(obj => { obj.icon = decodeURIComponent(obj.icon); return(obj) }); // the page update right away with new data. iconApp.iconList = newData; }); });

Теперь еще два фрагмента. Приложение Vue. Читатель заметит, что к кнопкам добавлена ​​директива @click . Элемент данных iconEntry.name передается методу в кавычках.

Метод определен в приложении Vue:

 <div class="entryart"> <button v-for="iconEntry in iconList" @click="goGetPanel(iconEntry.name)" > <div v-html="iconEntry.icon"> </div> </button> </div> </div>

Вот фрагмент определения методов. Объект methods добавляется сразу после объекта data в объекте параметра приложения:

 , methods: { goGetPanel: (pname) => { // `this` inside methods points to the Vue instance alert('Hello ' + pname + '!') } }

Читатель должен найти определение goGetPanel , и его использование было указано для обработчика @click . В нашем финальном приложении вызов alert можно заменить функцией, которая извлекает панели с сервера.

Библиотека компонентов для панелей IoT

Мы могли бы просто решить, что панели, которые мы получаем с сервера, могут быть рисунками HMTL или просто SVG, но если будет много видов панелей, мы надеемся, что работа по созданию панелей может быть упрощена за счет наличия библиотек компонентов для выберите из. Мы можем представить, что редакторы SVG можно было бы улучшить, чтобы компоненты библиотеки можно было перетаскивать на изображения как часть редактирования. Затем, если редактор SVG мог выводить версию изображения с тегами компонентов, то использование Vue позволило бы создать изображение, гарантируя, что автоматизация JavaScript и анимация аккуратно сплетены вместе. Для нашего обсуждения немного редактирования вручную может помочь нам добраться туда.

Если мы хотим создавать панели из компонентов Vue, то нам лучше понять, как сделать компоненты, а затем собрать их во что-то полезное. Нам придется переключиться на использование инструментов командной строки, предоставляемых Vue, и организовать наш рабочий процесс.

Компоненты

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

В этом первом фрагменте кода инициализируется приложение Vue:

 var iconApp = new Vue({ el: '#iconApp', data: { // this is the data field that can be easily updated }, methods : { ... } });

В этом новом фрагменте кода определяется и регистрируется компонент. Во-первых, обратите внимание, что вместо создания new Vue регистрируется компонент с именем iconic . Затем поле data возвращает пользовательские данные для любого экземпляра iconic , созданного приложением Vue. Наконец, поле template присутствует в конце регистрации компонента. Любой HTML-код, который мог быть написан на веб-странице для отображения компонента, может быть частью template .

 Vue.component('iconic', data: () => { var instanceData = { // data fields named for the // variables appearing in the template onevar : "test" } return(instanceData); }, methods : { ... }, template: '<div>This appears in every instance {{onevar}}</div>' });

Итак, мы можем представить панель с термометрами. Итак, если бы кто-то предоставил компонент thermometer , мы бы ожидали определения компонента где-то в нашем коде. В качестве таких:

 Vue.component('thermometer', data: () => { var instanceData = { // data fields named for the // variables appearing in the template temperature : 0 } return(instanceData); }, methods : { ... }, template: '<div>Some SVG will go here</div>' });

Мы пытаемся создать что-то похожее на это:

Анимированное приложение термометра в Vue перед изучением компонентов.
Анимированное приложение термометра в Vue перед изучением компонентов. (Большой превью)

Компонент термометра очень похож на первые компоненты, с которыми вы столкнетесь в руководствах по Vue. Но немного сложно понять, как его обновить. Существует лучший способ определения реактивности компонента с помощью свойств. А именно в следующем:

 Vue.component('thermometer', { props: ['temperature'], computed : { y: function() { var t = this.temperature/100; var h = 54.724472; var y_bar = 41.176476 // starts near the top // pretend the scale is 1 to 100, so that the temperature is a precentage return((1 - t)*h + y_bar) }, height : function() { var t = this.temperature/100; var h = 54.724472; // as high as the whole range var y_bar = 41.176476 // pretend the scale is 1 to 100, so that the temperature is a precentage return(t*h) } }, template: '#thermometer-template' })

Итак, вместо того, чтобы представлять температуру как элемент данных. Он представлен как свойство под props . Затем есть новый раздел, вычисленный , который предоставляет переменные, которые являются функциями свойства. Мы видим, что this.temperature используется как для y , так и для height . Эти вычисляемые переменные используются в SVG как атрибуты для прямоугольника.

В SVG y растет сверху вниз. Итак, когда мы хотим, чтобы прямоугольник внизу термометра был маленьким, y красного прямоугольника должен быть ниже, а высота должна быть уменьшена так, чтобы ( y + height ) оставалось на нуле термометра.

Обратите внимание на поле template в определении компонентов. Фактически это идентификатор элемента документа. Упомянутый элемент представляет собой раздел сценария со специальным типом: type="text/x-template" . Элемент сценария находится там, где находится SVG для термометров. Кроме того, SVG использует переменные Vue и элементы управления, чтобы можно было определить реактивность.

Вот некоторые из SVG:

 <script type="text/x-template"> <svg xmlns:svg="https://www.w3.org/2000/svg" xmlns="https://www.w3.org/2000/svg" width="20" height="70" version="1.1" > <g transform="translate(0,-180)"> <g transform="matrix(2.0111869,0,0,1.0489665,-215.11053,144.5592)"> <rect stroke-linecap="null" stroke-linejoin="null" width="2.9665921" height="54.724472" x="111.90748" y="41.176476" /> <rect stroke-linecap="null" stroke-linejoin="null" width="2.9665921" x="111.90748" :height="height" :y="y" /> <g transform="matrix(0.76503813,0,0,1,26.586929,0)"> <line y2="57.306953" y1="57.306953" x2="113.15423" x1="107.22105" stroke-linejoin="null" stroke-linecap="null" /> <line y2="74.408356" y1="74.408356" x2="113.15423" x1="107.22105" stroke-linejoin="null" stroke-linecap="null"

Читатель может найти id="thermometer-template" вверху, а посмотрев ниже на rect элементы, можно найти вычисляемые переменные.

Здесь переменные используются отдельно. Используется сокращенный синтаксис Vue для v-bind с :height="height" и таким же для y :

 x="111.90748" :height="height" :y="y"

Когда родитель элементов SVG устанавливает переменные, которые действуют как входные данные для свойства термометра temperature , Vue пересчитывает height и y . В результате положение и высота красного прямоугольника меняются.

Полезно иметь список приложений Vue, использующих термометр.

 <body> <!-- The Vue app starts here. This is the HTML part of the Vue object --> <div> <!-- Recognize the name from the Vue doc --> <div> <h2 itemprop="name">Set Temperature</h2> <p itemprop="description">These are groups satistfying this query: {{queryToken}}.</p> <!-- {{tweetOwner}} is in the data model. --> <button @click="updateTemp(50,50)">mid</button> <button @click="updateTemp(20,80)">low</button> <button @click="updateTemp(80,20)">high</button> </div> <thermometer :temperature="temp1" ></thermometer> <thermometer :temperature="temp2" ></thermometer> </div> <script> var thermoApp = new Vue({ el: '#thermoApp', data: { temp1 : 30, temp2 : 60, queryToken : "HEAT" }, methods : { updateTemp: function (tval1,tval2) { this.temp1 = tval1; this.temp2 = tval2; } } }); </script> </body>

В этом все дело. Есть три кнопки, которые вызывают метод updateTemp приложения thermoApp Vue. Раздел данных имеет две температурные переменные. И каждый thermometer обновляет свою температуру при изменении значений.

Код двух показанных ниже термометров можно найти в HTML-коде, назначенном приложению Vue.

 <thermometer :temperature="temp1" ></thermometer> <thermometer :temperature="temp2" ></thermometer>

Обратите внимание, что приложение использует формализм function для определения метода. Определение updateTemp таким образом updateTemp: function (tval1,tval2) позволяет получить доступ к переменной экземпляра this .

Кроме того, определение updateTemp таким образом updateTemp: (tval1,tval2) => присваивает this внутренней структуре данных, которая не реагирует и не обновляет представление.

Сборка панели

Каждая панель IoT может быть компонентом. Vue предоставляет способ определения компонентов с помощью подкомпонентов. В качестве альтернативы существует механизм слотов, который можно использовать для получения компонента, который может обернуть любой HTML-контент.

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

В обоих случаях для шаблона можно использовать один и тот же HTML. Вот наша панель в качестве шаблона:

 <script type="text/x-template"> <div> <thermometer :temperature="temp1" ></thermometer> <thermometer :temperature="temp2" ></thermometer> </div> </script>

Единственная разница между первой детализацией приложения заключается в том, что элемент div окружает два термометра. Vue выдаст ошибку, если в шаблоне отсутствует элемент DOM верхнего уровня. Элемент div соответствует требованиям Vue, и в него могут быть включены несколько элементов.

Теперь мы можем видеть два термометра рядом. При передаче температур от верхнего к конечному термометру значения каскадируются вниз. На верхнем уровне панель присоединяется к приложению, когда в DOM приложения включается одна строка.

 <themo-panel :temp1="temp1" :temp2="temp2" ></themo-panel>

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

Теперь определение шаблона для панели достаточно простое. Вот он с подкомпонентами, определенными независимо:

 Vue.component('thermo-panel', { props: ['temp1','temp2'], template: '#thermo-panel-template' });

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

Упомянув другие способы указания подкомпонентов, для панели мы должны взглянуть на него. Вот:

 Vue.component('thermo-panel', { props: ['temp1','temp2'], template: '#thermo-panel-template', components: { // a sub component for the labels 'thermometer': { props: { temperature: Number, }, template: '#thermometer-template', computed : { y: function() { var t = this.temperature/100; var h = 54.724472; var y_bar = 41.176476 // starts near the top // pretend the scale is 1 to 100, so that the temperature is a precentage return((1 - t)*h + y_bar) }, height : function() { var t = this.temperature/100; var h = 54.724472; // as high as the whole range var y_bar = 41.176476 // pretend the scale is 1 to 100, so that the temperature is a precentage return(t*h) } } } } });

Кода, безусловно, больше, но это потому, что JavaScript для компонента thermometer включен в список компонентов thermo-panel . Оба подхода выполняют одну и ту же работу, но предлагают разные способы упаковки определений компонентов.

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

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