IoT 및 제조업체를 위한 SVG 웹 페이지 구성 요소(1부)

게시 됨: 2022-03-10
빠른 요약 ↬ IoT는 소유자가 많은 많은 장치를 포함하도록 성장하고 있습니다. 웹 개발자는 소유자가 장치와 상호 작용할 수 있는 방법을 찾는 문제에 직면하게 됩니다. 그러나 이 문제로 인해 많은 비즈니스가 발생합니다. 이미 수요가 있는 IoT(사물 인터넷)용 웹 페이지 개발의 몇 가지 측면을 살펴보겠습니다.

IoT 시장은 아직 초기 단계이지만 활기를 띠고 있습니다. 우리는 IoT 역사의 정점에 서 있습니다. 시장은 2015년에서 2020년까지 5년 동안 4배 성장했습니다. 웹 개발자에게 이러한 IoT 성장은 중요합니다. IoT 웹 기술에 대한 수요는 이미 많습니다.

많은 장치가 지리 공간적으로 분산될 것이며 소유자는 원격 제어 및 관리를 원할 것입니다. 원격 조작을 위한 채널을 생성하려면 전체 웹 스택을 만들어야 합니다. 또한 상호 작용은 한 번에 하나 이상의 IoT 장치와 이루어집니다. 상호 작용은 물리적 세계의 실시간이어야 합니다.

이 토론에서는 Vue.js를 촉매로 사용하는 인터페이스 요구 사항을 자세히 설명하고 많은 대체 중에서 장치 통신에 대한 웹 페이지의 한 방법을 보여줍니다.

다음은 이 토론을 위해 계획된 몇 가지 목표입니다.

  1. IoT 인간-기계 인터페이스 그룹을 호스팅하는 단일 페이지 웹 앱 SPWA를 만듭니다(이를 "패널 그룹"이라고 부를 수 있음).
  2. 서버 쿼리 결과로 패널 그룹 식별자 목록을 표시합니다.
  3. 쿼리 결과로 선택한 그룹의 패널을 표시합니다.
  4. 패널 디스플레이가 느리게 로드되고 빠르게 애니메이션되는지 확인합니다.
  5. 패널이 IoT 장치와 동기화되는지 확인합니다.
점프 후 더! 아래에서 계속 읽기 ↓

IoT와 웹 페이지의 급속한 성장

웹 페이지와 실시간 물리적 프로세스의 동기화와 함께 하드웨어의 시각화 및 원격 제어를 위한 그래픽 프레젠테이션은 이 IoT 미래에 내재된 웹 페이지 문제 해결의 영역에 속합니다.

우리 중 많은 사람들이 IoT 프레젠테이션 기술에 대한 검색을 시작하고 있지만 지금 사용할 수 있는 몇 가지 프레젠테이션 기술과 함께 몇 가지 웹 표준이 있습니다. 이러한 표준과 기술을 함께 탐색하면 이 IoT 물결에 합류할 수 있습니다.

대시보드 및 데이터 시각화가 필요합니다. 또한, 양식이나 표시 목록 또는 텍스트 콘텐츠를 제공하는 웹 페이지를 넘어서려는 요구가 높습니다. IoT용 대시보드는 그림과 같은 애니메이션이어야 합니다. 애니메이션은 사용자에게 기계 상태의 실제 보기를 제공하기 위해 실시간 물리적 프로세스와 동기화되어야 합니다. 화염 연소 여부와 같은 기계 상태는 응용 프로그램 상태보다 우선하며 작업자에게 중요한 정보, 심지어 안전 정보까지 제공합니다.

대시보드에는 데이터 시각화 이상의 것이 필요합니다. IoT 의 일부는 센서뿐만 아니라 제어 인터페이스도 포함하는 장치라는 점을 명심해야 합니다. 하드웨어 구현에서 MCU는 스위치, 임계값 스위치, 매개변수 설정 등으로 확장됩니다. 그러나 웹 페이지가 이러한 하드웨어 제어 구성 요소를 대신할 수 있습니다 .

새로운 것은 없다. 하드웨어용 컴퓨터 인터페이스는 오랫동안 사용되어 왔지만 이러한 인터페이스에 대한 웹 페이지 사용의 급속한 성장은 현재 경험의 일부입니다. WebRTC와 Speech API는 2012년에 시작된 개발 경로에 있습니다. WebSockets도 비슷한 시기에 개발되었습니다.

IoT는 오랫동안 우리 마음 속에 있었습니다. IoT는 1832년부터 인간 대화의 일부였습니다. 그러나 우리가 알게 된 IoT와 무선은 1926년경 Tesla에 의해 구상되었습니다. Forbes 2018 IoT 현황은 IoT의 현재 시장 초점을 알려줍니다. 웹 개발자에게 흥미로운 기사는 대시보드를 호출합니다.

"IoT 얼리 어답터 또는 옹호자는 분석, 고급 시각화 및 데이터 마이닝에 필수적인 데이터 스트림을 제공하는 대시보드, 보고, IoT 사용 사례를 우선시합니다."

IoT 시장은 거대합니다. 이 시장 규모 기사에서는 2018년: 231억 4000만 ⇒ 2025년: 754억 4000만 대에 나타날 장치의 수를 예측합니다. 그리고 재정적 수치를 2014년: 2조 9900억 달러 ⇒ 2020년: 8조 9000억 달러로 계산하려고 합니다. IoT 기술에 대한 수요는 가장 빠르게 성장할 것입니다. 바로 IoT in Demand입니다.

장치를 제어하고 모니터링하기 위한 명확한 인터페이스를 개발함에 따라 인터페이스를 개발하는 데 새로운 문제가 발생합니다. 수십억 개의 모든 장치는 많은 사람(또는 조직)이 소유할 것입니다. 또한 각 사람은 원하는 수의 장치를 소유할 수 있습니다. 아마도 일부 장치도 공유될 것입니다.

기계 제어용으로 만들어진 최신 인터페이스에는 특정 기계 또는 몇 대의 기계 설치에 특정한 레이아웃이 잘 정의되어 있는 경우가 많습니다. 예를 들어, 스마트 하우스에서 고급 시스템에는 신중하게 배치된 장치용 패널이 있는 LCD가 있습니다. 그러나 웹 버전의 IoT와 함께 성장함에 따라 동적이고 균일한 모바일 장치 스트림을 위한 패널이 얼마든지 있을 것입니다.

장치용 패널 관리는 소셜 웹사이트에서 소셜 연결을 관리하는 것과 유사합니다.

"우리의 사용자 인터페이스는 각 특정 사용자에 대해 한 번에 표시되어야 하는 고도로 애니메이션된 실시간 패널을 관리하는 데 있어 동적이어야 합니다."

대시보드는 단일 페이지 웹 앱 SPWA입니다. 그리고 패널 데이터베이스를 상상할 수 있습니다. 따라서 단일 사용자가 지구 곳곳에 흩어져 있는 자신의 장치에 대한 여러 패널 및 구성에 액세스하려는 경우 SPWA는 요청 시 패널 구성 요소에 액세스해야 합니다. 패널과 일부 지원 JavaScript는 느리게 로드해야 합니다.

"우리 인터페이스는 프레임워크를 다시 초기화하지 않고도 비동기 구성 요소 바인딩을 통합할 수 있는 웹 페이지 프레임워크와 함께 작동해야 합니다."

Vue.js, WebSockets, MQTT 및 SVG를 사용하여 IoT 시장으로 한 발 더 나아갑시다.

추천 자료 : Vue.js로 인터랙티브 인포그래픽 만들기

IoT 웹 앱을 위한 고수준 아키텍처

IoT 웹 페이지에 대한 인터페이스를 디자인할 때 항상 많은 옵션이 있습니다. 하나의 옵션은 하나의 단일 장치에 하나의 단일 페이지를 지정하는 것일 수 있습니다. 페이지는 서버 측에서 렌더링될 수도 있습니다. 서버는 센서 값을 얻기 위해 장치를 쿼리한 다음 값을 HTML 문자열의 적절한 위치에 넣는 작업을 합니다.

우리 중 많은 사람들이 변수 값을 넣을 위치를 나타내는 특수 마커로 HTML 템플릿을 작성할 수 있는 도구에 익숙합니다. 이러한 템플릿에서 {{temperature}} 를 보면 우리와 보기 엔진이 기기에서 쿼리한 온도를 가져와서 {{temperature}} 기호를 교체하도록 지시합니다. 따라서 서버가 장치를 쿼리하고 장치가 응답하고 페이지를 렌더링하고 페이지를 전달하기를 기다린 후 사용자는 마침내 장치에서 보고한 온도를 볼 수 있습니다.

장치 아키텍처당 이 페이지의 경우 사용자는 장치에 명령을 보낼 수 있습니다. 문제 없습니다. 그는 HTML 양식을 작성하고 제출할 수 있습니다. 서버에는 장치에 대한 경로만 있을 수도 있고, 조금 더 영리하게는 장치 유형 및 장치 ID에 대한 경로가 있을 수도 있습니다. 그런 다음 서버는 양식 데이터를 장치에 보낼 메시지로 변환하고 이를 일부 장치 핸들러에 쓰고 승인을 기다립니다. 그런 다음 서버는 최종적으로 게시 요청에 응답하고 사용자에게 모든 것이 장치에 문제가 없음을 알릴 수 있습니다.

IoT를 양식 서버로 취급하기 위한 웹 페이지 아키텍처 - 더 나은 것을 찾고 있습니다.
IoT를 양식 서버로 취급하기 위한 웹 페이지 아키텍처 — 더 나은 것을 찾고 있습니다. (큰 미리보기)

많은 CMS는 블로그 항목 등을 업데이트하기 위해 이러한 방식으로 작동합니다. 그것에 대해 이상한 것은 없어 보입니다. HTTP를 통한 HTML은 항상 렌더링된 페이지를 가져오고 웹 서버에서 처리할 양식 데이터를 보내는 디자인을 가지고 있는 것 같습니다. 게다가 수천 개의 CMS 중에서 선택할 수 있습니다. 따라서 IoT 시스템을 가동하려면 수천 개의 CMS를 살펴보고 어떤 것이 작업에 적합한지 확인하는 것이 합리적입니다. 또는 CMS에 하나의 필터를 적용하여 시작할 수 있습니다.

우리는 우리가 다루고 있는 것의 실시간 특성을 고려해야 합니다. 따라서 HTML의 원래 형식은 많은 엔터프라이즈 작업에 매우 적합하지만 IoT 관리를 위한 전달 메커니즘이 되기 위해서는 약간의 도움이 필요합니다. 따라서 HTML이 이 IoT 작업을 수행하는 데 도움이 되는 CMS 또는 사용자 지정 웹 서버가 필요합니다. 또한 CMS가 서버 기능을 제공한다고 가정할 때 서버를 생각할 수도 있습니다. 서버는 이벤트 기반 애니메이션을 제공해야 하므로 페이지가 100% 확정된 정적 인쇄가 될 수 없다는 점을 명심해야 합니다.

다음은 장치 연결 웹 페이지의 선택을 안내할 수 있는 몇 가지 매개변수입니다.

  1. 센서 데이터 및 기타 장치 상태 메시지를 비동기적 으로 수신합니다.
  2. 클라이언트의 페이지에 대한 센서 데이터를 렌더링합니다(거의 1에 가까운 결과).
  3. 특정 장치 또는 장치 그룹에 비동기식 으로 명령을 게시합니다.
  4. 선택적으로 서버를 통해 명령을 보내거나 무시합니다.
  5. 장치와 사용자 간의 소유권 관계를 안전하게 유지합니다.
  6. 방해하거나 무시하지 않음으로써 중요한 장치 작동을 관리합니다.

선택한 장치에 대한 인터페이스 역할을 하는 단 하나의 페이지 에 대해 생각할 때 목록이 떠오릅니다. 우리는 명령과 데이터에 관해서는 장치와 자유롭게 통신할 수 있기를 원합니다.

페이지의 경우 웹 서버에 한 번만 요청하면 됩니다. 웹 서버(또는 관련 응용 프로그램)가 보안 통신 경로를 제공할 것으로 예상합니다. 그리고 경로가 서버를 통할 필요는 없으며 센서에서 오는 데이터에 대한 한 페이지의 통신을 처리하는 것 외에 서버가 더 높은 우선 순위 작업을 수행할 수 있으므로 서버를 완전히 피해야 합니다.

사실, 우리는 1초에 한 번씩 센서에서 들어오는 데이터를 상상할 수 있으며, 웹 서버 자체가 수천 명의 뷰어를 곱한 수천 개의 개별 센서 스트림에 대한 두 번째 업데이트로 일정한 초를 제공할 것이라고 기대하지 않습니다. 물론 로드 밸런싱 프레임워크에서 웹 서버를 분할하거나 설정할 수 있지만 센서 전달 및 하드웨어에 대한 명령 마샬링을 위해 사용자 정의된 다른 서비스가 있습니다.

웹 서버는 페이지가 장치와 보안 통신 채널을 설정할 수 있도록 일부 패킷을 전달해야 합니다. 우리는 통과하는 메시지 종류에 대한 관리를 제공하지 않는 채널에서 메시지를 보낼 때 주의해야 합니다. 장치가 중단될 수 있는 모드에 있는지 또는 장치가 제어되지 않는 경우 사용자 작업에 대한 요구가 있을 수 있는지에 대한 지식이 있어야 합니다. 따라서 웹 서버는 클라이언트가 장치에 대해 더 많이 알 수 있는 적절한 리소스를 얻도록 도울 수 있습니다. 메시징은 MQTT 서버와 같은 것으로 수행될 수 있습니다. 그리고 사용자가 웹 서버를 통해 자신의 패널에 액세스할 때 시작할 수 있는 MQTT 서버를 준비하기 위한 몇 가지 서비스가 있을 수 있습니다.

실시간 요구 사항이 있는 실제 세계와 추가 보안 고려 사항으로 인해 다이어그램이 원본과 약간 달라집니다.

하나의 MCU와 통신하는 단일 페이지 앱.
하나의 MCU와 통신하는 단일 페이지 앱. 이제 웹 페이지 서버와 독립적으로 MCU와 비동기식으로 상호 작용합니다. (큰 미리보기)

여기서 멈출 수 없습니다. 반응이 좋고 통신을 잘 처리하더라도 장치당 단일 페이지를 설정하는 것은 우리가 요구한 것이 아닙니다. 사용자가 자신의 계정에 로그인하여 대시보드에 액세스한다고 가정해야 합니다. 거기에서 그는 콘텐츠 프로젝트(그가 작업 중인 프로젝트일 가능성이 높음)의 일부 목록을 요청할 것입니다. 목록의 각 항목은 여러 리소스를 참조합니다. 클릭하거나 탭하여 항목을 선택하면 패널 컬렉션에 액세스할 수 있으며 각 패널에는 특정 리소스 또는 IoT 장치에 대한 정보가 있습니다.

사용자 인터페이스 작업의 결과로 생성된 쿼리에 대한 응답으로 전달되는 패널은 라이브 장치와 상호 작용하는 패널일 수 있습니다. 따라서 패널이 나오자 마자 실시간 활동을 표시하고 장치에 명령을 보낼 수 있을 것으로 예상됩니다.

페이지에서 패널이 어떻게 보이는지는 디자인 결정입니다. 떠 있는 창일 수도 있고 스크롤 가능한 배경의 상자일 수도 있습니다. 그것이 제시되더라도 패널은 시간, 온도, 압력, 풍속 또는 기타 상상할 수 있는 모든 것을 똑딱거리게 될 것입니다. 우리는 패널이 다양한 그래픽 스케일과 관련하여 애니메이션될 것으로 기대합니다. 온도는 온도계로, 속도는 반원형 속도 게이지로, 소리는 스트리밍 파형으로 표시할 수 있습니다.

웹 서버는 패널 데이터베이스에 대한 쿼리와 장치가 물리적으로 사용 가능해야 하는 경우 올바른 사용자에게 올바른 패널을 제공하는 작업을 수행합니다. 더욱이 다양한 종류의 장치가 있다는 점을 감안할 때 각 장치의 패널은 다를 수 있습니다. 따라서 웹 서버는 패널을 렌더링하는 데 필요한 그림 정보를 전달할 수 있어야 합니다. 그러나 대시보드의 HTML 페이지는 가능한 모든 패널과 함께 로드될 필요가 없습니다. 몇 개가 될지는 알 수 없습니다.

다음은 대시보드 페이지에 대한 선택을 안내할 수 있는 몇 가지 매개변수입니다.

  1. 관련 장치 패널 그룹을 선택하는 방법을 제시합니다.
  2. 일부 장치에 대해 동시 장치 통신 메커니즘을 사용합니다.
  3. 사용자가 요청할 때 장치 패널을 활성화합니다.
  4. 고유한 패널 디자인을 위해 느리게 로드된 그래픽을 통합합니다.
  5. 각 패널에 대한 보안 토큰 및 매개변수를 사용합니다.
  6. 사용자가 검사하는 모든 장치와 동기화를 유지합니다.
웹 페이지 서버와 비동기적으로 독립적으로 여러 MCU와 통신하는 단일 페이지 앱입니다.
웹 페이지 서버와 비동기적으로 독립적으로 여러 MCU와 통신하는 단일 페이지 앱입니다. (큰 미리보기)

게임이 어떻게 변하는지 알 수 있겠지만 대시보드 디자인의 세계에서는 한동안 게임이 여기 저기 조금씩 바뀌고 있습니다. 우리는 스스로를 발전시키기 위해 최신의 유용한 페이지 개발 도구로 범위를 좁혀야 합니다.

패널을 렌더링하는 방법부터 시작하겠습니다. 이것은 이미 큰 일처럼 보입니다. 우리는 다양한 종류의 패널을 상상하고 있습니다. 그러나 음악 DAW를 사용해 본 사람이라면 패널이 옛날부터 밴드에서 사용하던 아날로그 장치처럼 보이도록 그래픽을 사용했다는 것을 알 수 있을 것입니다. DAW의 모든 패널은 사운드에서 작동하는 플러그인에 의해 그려집니다. 사실, 많은 DAW 플러그인이 SVG를 사용하여 인터페이스를 렌더링할 수 있습니다. 그래서 우리는 SVG 인터페이스를 처리하는 것으로 우리 자신을 제한합니다. SVG 인터페이스는 우리가 상상할 수 있는 모든 그래픽이 될 수 있습니다.

패널용 SVG 선택

물론 나는 DAW를 좋아하고 그것을 예로 사용하지만 SVG는 웹 페이지 표준입니다. SVG는 W3C 표준입니다. 웹 페이지에 라인 드로잉을 전달하기 위한 것입니다. SVG는 iFrame에서 살기 위해 필요한 웹 페이지의 2급 시민이었습니다. 그러나 HTML5 이후로 그것은 일류 시민이었습니다. 아마도 SVG2가 나오면 양식 요소를 사용할 수 있게 될 것입니다. 현재 양식 요소는 SVG의 외부 개체입니다. 하지만 그렇다고 해서 SVG를 패널용 기판으로 만드는 것을 막을 수는 없습니다.

SVG를 그려서 표시할 수 있으며 느리게 로드할 수 있습니다. 사실, 컴포넌트 시스템을 탐색하면서 SVG가 컴포넌트 템플릿에 사용될 수 있다는 것을 알게 될 것입니다. 이 토론에서는 Vue.js를 사용하여 패널의 구성 요소를 만들 것입니다.

SVG 그리기는 어렵지 않습니다. 쉽게 구할 수 있는 선 그리기 프로그램이 많기 때문입니다. 돈을 쓰면 SVG를 내보내는 Adobe Illustrator를 얻을 수 있습니다. Inkscape는 한동안 SVG 제작을 위한 goto였습니다. 오픈 소스이며 Linux에서 잘 작동하지만 Mac 및 Windows에서도 실행할 수 있습니다. 그런 다음 오픈 소스인 웹 페이지 SVG 편집 프로그램과 일부 SaaS 버전이 있습니다.

저는 오픈 소스 웹 기반 SVG 편집기를 찾고 있었습니다. 주위를 둘러본 후 SVG-Edit를 찾았습니다. SVG 기반 블로그 등을 만드는 경우 자신의 웹 페이지에 포함할 수 있습니다.

애니메이션에 사용할 준비가 된 SVG의 전기 다이어그램.
전기 다이어그램은 매우 상세하지만 SVG에서 쉽게 얻을 수 있으며 약간의 코드로 애니메이션을 적용할 수 있습니다. (큰 미리보기)

작업을 파일에 저장하면 SVG-Edit가 브라우저에 파일을 다운로드하고 다운로드 디렉토리에서 파일을 선택할 수 있습니다.

내가 그린 그림은 적분기를 제어하는 ​​AND 게이트를 보여줍니다. 이것은 일반적으로 MCU용 패널에서 볼 것으로 예상되는 것이 아닙니다. 패널에는 AND 게이트 입력 중 하나를 공급하는 버튼이 있을 수 있습니다. 그런 다음 적분기의 출력을 읽는 ADC의 디스플레이가 있을 수 있습니다. 아마도 그것은 시간 축의 꺾은 선형 차트가 될 것입니다. 대부분의 패널에는 사용자가 MCU 내부에서 일어나는 일과 관련될 수 있는 그래픽이 있습니다. 그리고 우리의 회로가 어디에든 존재한다면 MCU 내부에 있을 것입니다.

마찬가지로 전자 다이어그램을 사용하여 애니메이션을 논의할 수 있습니다. 우리가 하고자 하는 것은 SVG를 살펴보고 어떤 식으로든 변경하고자 하는 일부 DOM 태그를 어디에서 얻을 수 있는지 확인하는 것입니다. 그런 다음 약간의 바닐라 JavaScript와 타이머를 사용하여 SVG에 애니메이션을 적용할 수 있습니다. AND 게이트를 다른 색으로 깜박이게 해 봅시다.

우리가 찾고 있는 SVG는 다음 코드 상자에 있습니다. 프로그래머에게는 그다지 친숙하지 않아 보이지만 사용자는 매우 만족할 것입니다. 그럼에도 불구하고 작업하려는 DOM 요소를 찾기 위해 계속해야 할 몇 가지 단서가 있습니다. 첫째, 대부분의 SVG 그리기 도구에는 개체 속성, 특히 id 속성을 가져오는 방법이 있습니다. SVG-Edit에도 방법이 있습니다. 편집기에서 AND 게이트를 선택하고 도구 모음을 관찰하십시오. id 및 CSS class 에 대한 필드도 표시됩니다.

제공된 인터페이스를 사용하여 개체 ID를 캡처하는 방법이 있는 SVG 그리기 도구 중 하나입니다.
제공된 인터페이스를 사용하여 개체 ID를 캡처하는 방법이 있는 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에서 JavaScript 섹션을 사용하려면 페이지가 HTML이어야 합니다. 그래서 그것은 여전히 ​​SVG를 별도의 것으로 취급하는 하나의 브라우저입니다. 하지만 <iframe> 시절과는 거리가 멉니다.

자르고 붙여넣기만 하면 페이지를 불러올 수 있고 AND 게이트가 빨간색에서 녹색으로 계속 바뀌는 것을 볼 수 있습니다.

추천 자료 : 경로로의 SVG 원 분해

VUE 구성 요소에서 패널 만들기

우리는 이미 단일 패널을 생생하게 만드는 과정에 있지만 많은 패널 컬렉션을 합리적인 방식으로 관리하려면 작업을 중단해야 합니다. 우리가 단순히 첫 번째 예제를 기반으로 구축한 경우 특히 그렇습니다.

첫 번째 예는 객체 보기를 비동기적으로 변경하는 방법을 보여주지만 시스템을 관리하는 것은 물론이고 모든 데이터 객체의 상태에 보기를 연결하는 방법을 보여주지는 않습니다. setInterval 데모를 fetch 처리기로 대체하는 방법을 확실히 이해할 수 있지만 SVG 포함 페이지를 제공하는 웹 서버에서 시스템 상태를 얻지 못할 수도 있습니다. 또한 데이터를 얻을 때 프로그램은 이제 주어진 페이지의 DOM 구조에 대해 알아야 합니다.

다행스럽게도 Vue와 같은 프레임워크가 대중화되어 많은 작업을 절약할 수 있습니다.

Vue에 대해 알아보는 것은 쉽습니다. Vue 문서는 매우 쉽게 접근할 수 있습니다. 따라서 이 논의가 너무 앞서 간다면 자체 웹 사이트에서 Vue에 대해 배우는 데 시간을 할애할 수 있습니다. 그러나 Smashing 페이지에는 매우 좋은 토론이 있습니다. Krutie Patel은 인포그래픽 제작에 관한 놀라운 기사를 썼습니다. Souvik Sarkar는 Vue로 날씨 대시보드를 구축하는 방법을 알려줍니다.

관련 패널의 그룹 선택

첫 번째 단계에서는 패널 그룹 검색을 해결해야 합니다. 이 작업을 먼저 수행하는 한 가지 이유는 이것이 인간 상호 작용의 프레임워크 수준에 있기 때문입니다.

사용자는 관심 있는 것을 검색합니다. 아마도 그는 한 마을에 있는 모든 장치에 관심이 있을 것입니다. 아마도 그는 많은 액체 제품 배치를 가지고 있고 IoT 장치의 작은 컬렉션에 의해 관리되는 각 배치와 함께 한 가지 유형의 제품으로 좁히기를 원할 것입니다. 따라서 사용자는 먼저 작은 목록을 얻기 위해 검색합니다.

다음은 프로세스입니다.

  1. 기능/매개변수별로 패널 그룹을 검색합니다.
  2. 그룹을 나타내는 아이콘 목록을 봅니다.
  3. 아이콘을 선택합니다(클릭/탭).
  4. 아이콘이 표시되면 패널을 사용하여 시작합니다.

이것이 좋은 첫 번째 단계인 또 다른 이유는 Vue를 가장 간단한 형태로 사용할 수 있기 때문입니다. 빌드 도구가 필요하지 않습니다. HTML에 스크립트 태그와 함께 vue.js 를 포함할 것입니다. 사실, 우리는 그것을 다운로드할 필요조차 없습니다. vue.js 의 작업 복사본이 제공되는 사이트가 있습니다.

다음 태그만 있으면 됩니다.

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

설치에 대한 Vue 설명서에서 직접 스크립트 태그를 복사했습니다.

이제 아이콘을 로드하고 클릭하는 것으로 만들 수 있는 웹 페이지가 필요합니다. Vue는 이를 매우 쉽게 만듭니다. 사실 Vue를 사용하여 Twitter 목록을 관리하는 작은 앱을 작성했습니다. 그것은 단지 텍스트 필드를 관리합니다. 아이콘을 사용하는 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);

B. 이것은 데이터를 Vue에 넣고 화면 업데이트를 보는 것입니다.

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

얼마나 많은 작업입니까?

데이터가 IoT용 패널을 업데이트하는 방법을 표현하는 좋은 방법이 있을 것 같습니다.

이제 트윗을 웹 서버에서 구성 요소를 가져오도록 설계된 클릭 가능한 아이콘으로 바꿔보겠습니다.

트윗에서 패널 가져오기 아이콘까지

사람들은 아이콘에 SVG를 사용하는 것을 좋아합니다. 그들은 내가 말할 수 있는 한 다른 것들보다 SVG에 대한 사용을 더 좋아합니다. 나는 SVG로 만든 아이콘을 판매하거나 제공하는 웹 사이트의 수에 대해서만 갈 것입니다. 판매 포인트는 라인 그래픽이 이미지보다 바이트 수가 적다는 것입니다. 그리고 버튼과 같은 동작이 있는 사진 목록을 요청하려면 SVG가 iframe에 있던 시절에 PNG 또는 JPEG를 선택했을 것입니다. 그러나 Vue 기여자 목록에서 아이콘 제공에 도움이 되는 라이브러리를 찾을 수도 있습니다.

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 의 promise 구조를 볼 수 있습니다. 텍스트가 구문 분석되고 다음 줄에서 인코딩된 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; }); });

이제 두 개의 스니펫만 더 있으면 됩니다. 뷰 앱. 독자는 @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 필드는 Vue 앱이 만드는 모든 iconic 인스턴스에 대한 사용자 지정 데이터를 반환합니다. 마지막으로 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 아래에 속성으로 표시됩니다. 그런 다음 속성의 기능인 변수를 제공하는 새 섹션인 computed 가 있습니다. this.temperatureyheight 모두에 사용되는 것을 볼 수 있습니다. 이러한 계산된 변수는 SVG에서 사각형의 속성으로 사용됩니다.

SVG에서 y 는 위에서 아래로 커집니다. 따라서 직사각형이 온도계 하단에서 작아지기를 원할 때 빨간색 상자의 y 는 더 낮아야 하고 높이는 ( y + height )가 온도계 0에 머물도록 줄여야 합니다.

구성 요소 정의의 template 필드를 확인하십시오. 사실 이것은 문서 요소 ID입니다. 참조되는 요소는 특수 유형이 있는 스크립트 섹션입니다: 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 요소를 더 아래로 보면 계산된 변수를 찾을 수 있습니다.

여기서 변수 용도가 분리됩니다. v-bind 에 대한 Vue 속기 구문이 사용 중이며, :height="height"y 에 대해서도 동일합니다.

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

SVG 요소의 부모가 온도계 속성 temperature 에 대한 입력 역할을 하는 변수를 설정하면 Vue는 heighty 를 다시 계산합니다. 결과적으로 빨간색 상자의 위치와 높이가 변경됩니다.

온도계를 사용하는 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>

그게 전부입니다. thermoApp Vue 애플리케이션의 updateTemp 메소드를 호출하는 세 개의 버튼이 있습니다. 데이터 섹션에는 두 개의 온도 변수가 있습니다. 그리고 각 thermometer 는 값이 변경되면 온도를 업데이트합니다.

아래에 있는 두 개의 온도계 코드는 Vue 앱에 할당된 HTML에서 찾을 수 있습니다.

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

응용 프로그램은 메서드 정의에 대해 function 형식을 사용합니다. updateTemp: function (tval1,tval2) updateTemp 방식으로 updateTemp를 정의하면 인스턴스 변수 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 요소가 두 온도계를 둘러싸고 있다는 것입니다. 템플릿에 최상위 DOM 요소가 없으면 Vue에서 오류가 발생합니다. 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) } } } } });

확실히 더 많은 코드가 있지만 그것은 thermometer 구성 요소에 대한 JavaScript가 thermo-panel 의 구성 요소 목록에 포함되어 있기 때문입니다. 두 가지 접근 방식은 동일한 작업을 수행하지만 구성 요소 정의를 패키징하는 다른 방법을 제공합니다.

현재로서는 첫 번째 방법을 선호합니다. 템플릿 및 속성 변경만 필요한 경우 패널을 수정하고 동적으로 검색하도록 하는 것이 훨씬 더 쉬워야 합니다. 이를 위해 독립적으로 정의된 구성 요소는 구성 요소 라이브러리를 구성합니다. 그러나 그것이 더 나은 것처럼 보이지만 다음에서는 더 장황해 보이는 두 번째 방법을 사용하는 것이 더 편리해집니다.

우리가 명확하게 정의된 방식으로 구성 요소에서 반응형 패널을 만들 수 있다는 점을 감안할 때 내 기사의 다음 부분에서 간단한 쿼리를 만들 수 있는 데이터베이스로 관리하는 방법을 설명하겠습니다.