IoT ve Yapıcılar için SVG Web Sayfası Bileşenleri (Bölüm 1)
Yayınlanan: 2022-03-10IoT pazarı hala erken aşamalarında, ancak hız kazanıyor. IoT tarihinde bir dönüm noktasındayız. 2015'ten 2020'ye kadar olan beş yıllık süreçte pazarlar dörde katlanıyor. Web geliştiricileri için bu IoT büyümesi önemli. IoT web tekniklerine şimdiden büyük bir talep var.
Birçok cihaz jeo-uzaysal olarak yayılacak ve sahipleri uzaktan kontrol ve yönetim isteyecektir. Teleoperasyon için kanallar oluşturmak için tam web yığınları yapılmalıdır. Ayrıca, etkileşim aynı anda bir veya daha fazla IoT cihazıyla olacaktır. Etkileşim, fiziksel dünyanın gerçek zamanında olmalıdır.
Bu tartışma, Vue.js'yi katalizör olarak kullanan arayüz gereksinimlerini araştırır ve birçok ikameden bir web sayfasından cihaza iletişim yöntemini gösterir.
İşte bu tartışma için planlanan hedeflerden bazıları:
- IoT insan-makine arabirimi gruplarını barındıran tek sayfalık bir web uygulaması SPWA oluşturun (bunlara “panel grupları” diyebiliriz);
- Bir sunucuyu sorgulamanın bir sonucu olarak panel grubu tanımlayıcılarının listelerini görüntüleyin;
- Bir sorgu sonucunda seçilen grubun panellerini görüntüleyin;
- Panel ekranının yavaş yüklendiğinden ve hızlı bir şekilde canlandırıldığından emin olun;
- Panellerin IoT cihazlarıyla senkronize olduğundan emin olun.
IoT ve Web Sayfalarının Hızlı Büyümesi
Web sayfalarının gerçek zamanlı fiziksel süreçlerle senkronizasyonu ile birlikte donanımın görselleştirilmesi ve uzaktan kontrolü için grafiklerin sunumu, bu IoT geleceğinde bulunan web sayfası problem çözme alanı içindedir.
Birçoğumuz IoT sunum teknikleri aramaya başlıyoruz, ancak şimdi kullanmaya başlayabileceğimiz birkaç sunum tekniğinin yanı sıra birkaç web standardı var. Bu standartları ve teknikleri birlikte keşfederken, bu IoT dalgasına katılabiliriz.
Gösterge tabloları ve veri görselleştirme talep görmektedir. Ayrıca, formlar veya görüntüleme listeleri veya metin içeriği sağlayan web sayfalarının ötesine geçme talebi yüksektir. IoT için panoların resimli ve hareketli olması gerekir. Kullanıcılara makine durumunun doğru bir görünümünü sağlamak için animasyonlar gerçek zamanlı fiziksel süreçlerle senkronize edilmelidir. Alevin yanması veya yanmaması gibi makine durumu, uygulama durumunu geride bırakır ve operatörlere kritik bilgiler, hatta belki de güvenlik bilgileri sağlar.
Panolar, verilerin görselleştirilmesinden daha fazlasını gerektirir. IoT'nin nesnelerinin bir parçasının yalnızca sensörleri değil, aynı zamanda kontrol arayüzlerini de içeren cihazlar olduğunu unutmamalıyız. Donanım uygulamalarında MCU'lar, anahtarlar, eşik anahtarları, parametre ayarları ve daha fazlasıyla genişletilir. Yine de, web sayfaları bu donanım kontrol bileşenlerinin yerini alabilir .
Herşey aynı. Donanım için bilgisayar arayüzleri uzun zamandan beri var, ancak bu arayüzler için web sayfası kullanımının hızlı büyümesi mevcut deneyimimizin bir parçası. WebRTC ve Speech API, 2012'de başlayan bir geliştirme yolundadır. WebSockets, benzer bir zaman diliminde gelişmektedir.
IoT uzun zamandır aklımızda. IoT, 1832'den beri insan diyaloğunun bir parçası olmuştur. Ancak, 1926 civarında Tesla tarafından tasavvur edilen IoT ve kablosuz iletişim. Forbes 2018 State of IoT, bize IoT için mevcut pazar odağını anlatıyor. Web geliştiricilerinin ilgisini çeken makale, gösterge tablolarını çağırıyor:
"IoT'yi erken benimseyenler veya savunucuları, analitiğe, gelişmiş görselleştirmeye ve veri madenciliğine entegre veri akışları sağlayan panolara, raporlamaya, IoT kullanım durumlarına öncelik veriyor."
IoT pazarı çok büyük. Bu Pazar Büyüklüğü makalesi, görünecek cihaz sayısı için bir tahmin sunar: 2018: 23,14 milyar ⇒ 2025: 75,44 milyar. Ve bunun üzerine finansal bir rakam koymaya çalışıyor: 2014: 2,99 trilyon dolar ⇒ 2020: 8,90 trilyon dolar. IoT becerilerine olan talep en hızlı büyüyen talep olacak: IoT In Demand.
Cihazları kontrol etmek ve izlemek için net arayüzler geliştirirken, arayüzlerimizi geliştirmek için yeni bir sorunla karşılaşıyoruz. Milyarlarca cihazın tamamı birçok kişiye (veya kuruluşa) ait olacaktır. Ayrıca, her kişi herhangi bir sayıda cihaza sahip olabilir. Belki bazı cihazlar bile paylaşılacaktır.
Makine kontrolleri için yapılmış modern arayüzler, genellikle belirli bir makineye veya birkaç makinenin kurulumuna özgü iyi tanımlanmış bir düzene sahiptir. Örneğin, akıllı bir evde, üst düzey bir sistem, dikkatlice yerleştirilmiş cihazlar için panelleri olan bir LCD'ye sahip olacaktır. Ancak, IoT'nin web sürümüyle birlikte büyüdükçe, dinamik ve hatta mobil cihaz akışı için herhangi bir sayıda panel olacak.
Cihazlar için panellerin yönetimi, sosyal web sitelerindeki sosyal bağlantıları yönetmeye benzer hale gelir.
"Kullanıcı arayüzlerimiz, her bir belirli kullanıcı için herhangi bir zamanda hangi son derece hareketli gerçek zamanlı panelin görüntülenmesi gerektiğini yönetmede dinamik olmalıdır."
Pano, tek sayfalık bir web uygulaması SPWA'dır. Ve bir panel veritabanı hayal edebiliriz. Dolayısıyla, tek bir kullanıcı gezegene yayılmış cihazları için bir dizi panele ve konfigürasyona erişecekse, SPWA'nın talep üzerine panel bileşenlerine erişmesi gerekir. Paneller ve destekleyici JavaScript'lerinden bazıları tembelce yüklenmek zorunda kalacak.
"Arayüzlerimiz, çerçevelerini yeniden başlatmadan eşzamansız bileşen bağlamalarını birleştirmeye izin verebilecek web sayfası çerçeveleriyle çalışmak zorunda kalacak."
IoT pazarına adım atmak için Vue.js, WebSockets, MQTT ve SVG'yi kullanalım.
Önerilen okuma : Vue.js ile Etkileşimli Bir İnfografik Oluşturma
Bir IoT Web Uygulaması İçin Üst Düzey Mimari
IoT web sayfası için arayüz tasarlarken, her zaman birçok seçeneğe sahiptir. Seçeneklerden biri, tek bir sayfayı tek bir aygıta ayırmak olabilir. Sayfa, sunucu tarafında bile oluşturulabilir. Sunucu, sensör değerlerini almak için cihazı sorgulama ve ardından değerleri HTML dizesinde uygun yerlere yerleştirme işine sahip olacaktır.
Birçoğumuz, HTML şablonlarının, değişken değerlerin nereye yerleştirileceğini gösteren özel işaretlerle yazılmasına izin veren araçlara aşinayız. Böyle bir şablonda {{temperature}}
görmek bize ve görünüm motoruna bir cihazdan sorgulanan sıcaklığı almamızı ve {{temperature}}
sembolünü onunla değiştirmemizi söyler. Böylece sunucunun cihazı sorgulamasını, cihazın yanıt vermesini, sayfayı oluşturmasını ve sayfayı teslim etmesini bekledikten sonra, kullanıcı nihayet cihazın bildirdiği sıcaklığı görebilecek.
Cihaz mimarisi başına bu sayfa için kullanıcı daha sonra cihaza bir komut göndermek isteyebilir. Sorun değil, bir HTML formu doldurup gönderebilir. Sunucunun yalnızca aygıt için bir rotası bile olabilir veya belki biraz daha akıllıca, aygıt türü ve aygıt kimliği için bir rota olabilir. Sunucu daha sonra form verilerini cihaza göndermek için bir mesaja çevirir, bazı cihaz işleyicilerine yazar ve bir onay bekler. Ardından, sunucu nihayet gönderi isteğine yanıt verebilir ve kullanıcıya cihazda her şeyin yolunda olduğunu söyleyebilir.
Birçok CMS, blog girişlerini ve benzerlerini güncellemek için bu şekilde çalışır. Bunda garip bir şey yok. Görünüşe göre HTTP üzerinden HTML, oluşturulmuş sayfaları almak ve web sunucusu tarafından işlenecek form verilerini göndermek için her zaman tasarıma sahip olmuştur. Dahası, aralarından seçim yapabileceğiniz binlerce CMS var. Bu nedenle, IoT sistemimizi yükseltmek için, hangisinin iş için doğru olduğunu görmek için bu binlerce CMS'yi gözden geçirmek mantıklı görünüyor. Veya başlangıç olarak CMS'lere bir filtre uygulayabiliriz.
Uğraştığımız şeyin gerçek zamanlı doğasını dikkate almalıyız. Bu nedenle, orijinal haliyle HTML birçok kurumsal görev için oldukça iyi olsa da, IoT yönetimi için dağıtım mekanizması haline gelmesi için biraz yardıma ihtiyacı var. Bu nedenle, HTML'nin bu IoT işini yapmasına yardımcı olan bir CMS'ye veya özel web sunucusuna ihtiyacımız var. CMS'nin sunucu işlevselliği sağladığını varsaydığımız için sunucuyu da düşünebiliriz. Yalnızca sunucunun olaya dayalı animasyon sağlaması gerektiğini unutmamalıyız, bu nedenle sayfa %100 nihai statik baskı olamaz.
Cihaz bağlantılı web sayfamız için seçimleri yönlendirebilecek bazı parametreler ve yapması gerekenler şunlardır:
- Sensör verilerini ve diğer cihaz durumu mesajlarını asenkron olarak alın;
- İstemcide sayfa için sensör verilerini işleyin (neredeyse 1'in sonucu);
- Komutları belirli bir cihaza veya cihaz grubuna eşzamansız olarak yayınlayın;
- İsteğe bağlı olarak komutları sunucu üzerinden gönderin veya atlayın.
- Cihaz ve kullanıcı arasındaki sahiplik ilişkisini güvenli bir şekilde sürdürmek;
- Müdahale etmeden veya geçersiz kılarak kritik cihaz çalışmasını yönetin.
Liste , seçilen bir cihaza arayüz görevi gören yalnızca bir sayfa düşünüldüğünde akla gelir. Komutlar ve veriler söz konusu olduğunda cihazla özgürce iletişim kurabilmek istiyoruz.
Sayfaya gelince, web sunucusundan sadece bir kez istememiz gerekiyor. Web sunucusunun (veya ilişkili uygulamanın) güvenli bir iletişim yolu sağlamasını beklerdik. Ve yolun sunucu üzerinden olması gerekmez veya sunucunun sensörlerden gelen veriler için bir sayfanın iletişimiyle ilgilenmekten başka daha yüksek öncelikli görevleri olabileceğinden, sunucudan tamamen kaçınması gerekir.
Aslında, bir sensörden saniyede bir veri geldiğini hayal edebiliyoruz ve web sunucusunun, binlerce izleyiciyle çarpılan binlerce ayrı sensör akışı için ikinci güncellemeyle sabit bir saniye sağlamasını beklemiyoruz. Elbette, bir web sunucusu bir yük dengeleme çerçevesinde bölümlenebilir veya kurulabilir, ancak sensör teslimi ve donanıma komutları sıralamak için özelleştirilmiş başka hizmetler de vardır.
Sayfanın cihazla güvenli iletişim kanalları kurabilmesi için web sunucusunun bir miktar paket teslim etmesi gerekecektir. Geçmekte olan mesaj türlerinin yönetimini sağlamayan kanallara mesaj gönderirken dikkatli olmalıyız. Bir cihazın kesintiye uğrayabilecek bir modda olup olmadığı veya bir cihaz kontrolden çıkarsa kullanıcı eylemi için bir talep olup olmadığı konusunda biraz bilgi sahibi olunmalıdır. Böylece, web sunucusu, istemcinin cihaz hakkında daha fazla bilgi sahibi olabilecek uygun kaynakları elde etmesine yardımcı olabilir. Mesajlaşma, MQTT sunucusu gibi bir şeyle yapılabilir. Ayrıca MQTT sunucusunun hazırlanması için kullanıcı web sunucusu üzerinden paneline erişim sağladığında başlatılabilecek bazı servisler olabilir.
Gerçek zamanlı gereksinimleri olan fiziksel dünya ve ek güvenlik hususları nedeniyle diyagramımız orijinalinden biraz farklı hale gelir.
Burada duramayız. Duyarlı olsa ve iletişimi iyi yönetse bile, cihaz başına tek bir sayfa ayarlamak istediğimiz şey değildi. Bir kullanıcının hesabına giriş yapacağını ve kontrol paneline erişeceğini varsaymalıyız. Oradan, içerik projelerinin bir listesini isteyecektir (büyük olasılıkla üzerinde çalıştığı projeler). Listedeki her öğe bir dizi kaynağa atıfta bulunacaktır. Tıklayarak veya dokunarak bir öğe seçtiğinde, her biri belirli bir kaynak veya IoT cihazı hakkında bazı bilgilere sahip olacak bir panel koleksiyonuna erişim kazanacaktır.
Kullanıcının arayüz eyleminin bir sonucu olarak oluşturulan sorguya yanıt olarak gönderilen panellerin herhangi bir sayısı, canlı cihazlarla etkileşime giren paneller olabilir. Yani bir panel gelir gelmez gerçek zamanlı aktivite göstermesi ve bir cihaza komut gönderebilmesi beklenecektir.
Panellerin sayfada nasıl göründüğü bir tasarım kararıdır. Kayan pencereler olabilirler veya kaydırılabilir bir arka plan üzerinde kutular olabilirler. Bununla birlikte, paneller zaman, sıcaklık, basınç, rüzgar hızı veya hayal edebileceğiniz başka herhangi bir şeyi işaretleyecektir. Panellerin çeşitli grafik ölçeklerine göre canlandırılmasını bekliyoruz. Sıcaklık bir termometre olarak, hız yarım daire biçimli bir hız göstergesi olarak, ses bir akış dalga formu olarak vb. olarak sunulabilir.
Web sunucusunun görevi, bir panel veritabanına yapılan sorgular ve cihazların fiziksel olarak kullanılabilir olması gerektiği göz önüne alındığında, doğru panelleri doğru kullanıcıya teslim etme işidir. Dahası, birçok farklı türde cihaz olacağı göz önüne alındığında, her cihazın panelleri büyük olasılıkla farklı olacaktır. Bu nedenle, web sunucusu, bir panel oluşturmak için gereken resimsel bilgileri sağlayabilmelidir. Ancak, kontrol panelinin HTML sayfasının tüm olası panellerle yüklenmesi gerekmemelidir. Kaç tane olacağına dair bir fikir yok.
Pano sayfamız için seçimlere rehberlik edebilecek bazı parametreler ve yapması gerekenler şunlardır:
- İlgili cihaz paneli gruplarını seçmenin bir yolunu sunun;
- Bazı cihazlar için eşzamanlı cihaz iletişim mekanizmalarından yararlanın;
- Kullanıcı talep ettiğinde cihaz panellerini etkinleştirin;
- Benzersiz panel tasarımları için tembelce yüklenmiş grafikler ekleyin;
- Her bir panele ilişkin güvenlik belirteçlerini ve parametrelerini kullanın;
- Kullanıcı denetimi altındaki tüm cihazlarla senkronizasyonu koruyun.
Oyunun nasıl değiştiğini görmeye başlayabiliriz, ancak gösterge paneli tasarımı dünyasında, oyun bir süredir burada ve orada biraz değişiyor. Kendimizi ayağa kaldırmak için kendimizi bazı güncel ve kullanışlı sayfa geliştirme araçlarıyla daraltmamız gerekiyor.
Panelleri nasıl oluşturacağımızla başlayalım. Bu zaten büyük bir iş gibi görünüyor. Birçok farklı türde panel hayal ediyoruz. Ancak, bir müzik DAW'ı kullandıysanız, panelleri uzun zaman önce gruplar tarafından kullanılan analog cihazlara benzetmek için grafikleri nasıl kullandıklarını görürdünüz. DAW'lardaki tüm paneller, sesle çalışan eklentiler tarafından çizilir. Aslında, bu DAW eklentilerinin çoğu, arayüzlerini oluşturmak için SVG kullanabilir. Bu nedenle, kendimizi SVG arayüzlerini işlemekle sınırlandırıyoruz, bu da hayal edebileceğimiz herhangi bir grafik olabilir.
Paneller için SVG Seçimi
Tabii ki, DAW'ları severim ve bunu örnek olarak kullanırdım, ancak SVG bir web sayfası standardıdır. SVG, bir W3C standardıdır. Çizgi çizimleri web sayfalarına taşımak içindir. SVG, web sayfasında iFrame'lerde yaşamak için gerekli olan ikinci sınıf bir vatandaştı. Ancak HTML5'ten beri birinci sınıf bir vatandaş olmuştur. Belki de SVG2 çıktığında form öğelerini kullanabilecektir. Şimdilik, form öğeleri SVG'deki Yabancı Nesnelerdir. Ancak bu, SVG'yi paneller için alt tabaka yapmaktan alıkoymamalı.
SVG çizilebilir, görüntülenmek üzere saklanabilir ve tembelce yüklenebilir. Aslında, bileşen sistemini incelerken, bileşen şablonları için SVG'nin kullanılabileceğini göreceğiz. Bu tartışmada, paneller için bileşenler yapmak için Vue.js'yi kullanacağız.
SVG çizmek zor değil çünkü elde edilmesi kolay birçok çizgi çizme programı var. Para harcarsanız, SVG'yi dışa aktaran Adobe Illustrator'ı alabilirsiniz. Inkscape, bir süredir SVG oluşturma için bir hedef olmuştur. Açık kaynak kodludur ve Linux'ta iyi çalışır, ancak Mac ve Windows'ta da çalıştırılabilir. Ardından, açık kaynak kodlu birkaç web sayfası SVG düzenleme programı ve ayrıca bazı SaaS sürümleri vardır.
Açık kaynaklı web tabanlı bir SVG düzenleyicisi arıyordum. Biraz etrafa baktıktan sonra SVG-Edit'e rastladım. Belki de SVG tabanlı bir blog veya başka bir şey yapıyorsanız, bunu kendi web sayfalarınıza dahil edebilirsiniz.
Çalışmanızı bir dosyaya kaydettiğinizde, SVG-Edit onu tarayıcınıza indirir ve dosyayı indirme dizininizden alabilirsiniz.
Çizdiğim resim bir entegratörü kontrol eden bir AND geçidini gösteriyor. Bir MCU panelinde genellikle görmeyi beklediğiniz şey bu değil. Panelde AND geçidi girişlerinden birini beslemek için bir düğme olabilir. Ardından, entegratörün çıktısını okuyan bir ADC'den bir ekrana sahip olabilir. Belki de bu bir zaman ekseninde bir çizgi grafik olacaktır. Çoğu panel, kullanıcının MCU'nun içinde neler olup bittiğiyle ilişki kurmasını sağlayan grafiklere sahip olacaktır. Ve devremiz herhangi bir yerde yaşayacaksa, MCU'nun içinde olacaktır.
Yine de, elektronik diyagramımız animasyonu tartışmak için kullanılabilir. Yapmak istediğimiz şey, SVG'ye bir göz atmak ve bir şekilde değiştirmek istediğimiz bazı DOM etiketlerine nereden ulaşabileceğimizi görmek. Daha sonra biraz vanilya JavaScript ve bir zamanlayıcı kullanarak SVG'yi canlandırabiliriz. AND geçidinin farklı renklerde yanıp sönmesini sağlayalım.
Aradığımız SVG aşağıdaki kod kutusundadır. Kullanıcı oldukça mutlu olmasına rağmen, programcı için pek kolay görünmüyor. Yine de, hangi DOM öğesi üzerinde çalışmak istediğimizi bulmak için devam edilecek bazı ipuçları var. İlk olarak, çoğu SVG çizim aracının nesne özelliklerine, özellikle de id
niteliğine erişmenin bir yolu vardır. SVG-Edit'in de bir yolu var. Editörde AND geçidini seçin ve araç çubuğunu gözlemleyin. id
ve CSS class
için de bir alan göreceksiniz.
Herhangi bir nedenle düzenleme aracına ulaşamıyorsanız, SVG'yi bir tarayıcıda açıp DOM'yi inceleyebilirsiniz. Her durumda, kapımızın id
= “svg_1” olduğunu bulduk.
<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>
Şimdi tek ihtiyacımız olan biraz JavaScript. İlk önce, "doldur" öğe özniteliğinin mevcut olduğunu not ediyoruz. Sonra sadece aşağıdaki basit program var:
<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>
Sahip olduğumuz şeyin minimal bir HTML sayfası olduğuna dikkat edin. Kodu kesip favori düzenleyicinize yapıştırabilirsiniz. Ardından, yorumu değiştirmek için SVG'yi kesip yapıştırmayı unutmayın. Chrome sürümüm, JavaScript bölümüne sahip olmak için sayfanın HTML olmasını gerektiriyor. Bu, SVG'ye hala ayrı bir şey gibi davranan bir tarayıcıdır. Ancak, <iframe>
günlerinden çok uzakta.
Doğru kesip yapıştırırsanız, sayfayı açabilir ve AND geçidinin tekrar tekrar kırmızıdan yeşile döndüğünü görebilirsiniz.
Önerilen okuma : Yollara SVG Daire Ayrıştırma
VUE Bileşenlerinden Bina Panelleri
Zaten herhangi bir paneli hayata geçirme yolundayız, ancak büyük panel koleksiyonlarını mantıklı yollarla yönetmek istiyorsak, işimizi bizim için bitirirdik. Bu, özellikle ilk örneğimizi basitçe inşa edersek böyle olur.
İlk örnek bize bir nesne görünümünü eşzamansız olarak nasıl değiştirebileceğimizi gösterirken, bize bırakın bir makineyi yöneten herhangi bir veri nesnesinin durumuna görünümü nasıl bağlayacağımızı göstermez. setInterval
gösteriminin bir fetch
işleyicisi ile nasıl değiştirilebileceğini kesinlikle anlayabiliriz, ancak SVG içeren sayfaya hizmet eden web sunucusundan bir makinenin durumunu bile alamayabiliriz. Ayrıca, verileri aldığımızda, programlarımızın verilen sayfanın DOM yapısını bilmesi gerekiyor.
Neyse ki, Vue gibi çerçeveler popüler hale geldi ve bizi çok fazla iş kurtarabilirler.
Vue hakkında bilgi edinmek kolaydır. Vue belgelerine çok erişilebilir. Dolayısıyla, bu tartışma çok ileri giderse, kendi web sitesinde Vue hakkında bilgi edinmek için biraz zaman harcayabilirsiniz. Ama Smashing sayfalarında çok güzel tartışmalar var. Krutie Patel, bir infografik yapmakla ilgili çarpıcı bir makale yazdı. Souvik Sarkar bize Vue ile nasıl bir hava durumu panosu oluşturacağımızı anlatıyor.
İlgili Panoların Grup Seçimi
İlk adım olarak, panel gruplarını aramayı ele almalıyız. Bunu ilk olarak yapmamızın bir nedeni, insan etkileşimlerimizin çerçeve düzeyinde olmasıdır.
Kullanıcı ilgi duyduğu bir şeyi arar. Belki bir şehirdeki tüm cihazlarla ilgileniyordur. Belki de birçok sıvı ürün partisine sahiptir ve her partide küçük bir IoT cihazı koleksiyonu tarafından yönetilen tek bir ürün türüne daraltmak istiyor. Bu nedenle, kullanıcı önce küçük bir liste almak için arama yapacaktır.
İşte süreç:
- Özellikler/parametrelere göre panel gruplarını arayın.
- Grupları temsil eden simgelerin listesini görüntüleyin.
- Bir simge seçin (tıklayın/dokunun).
- Simge ile tanımlanan paneller çıktıklarında kullanmaya başlayın.
Bunun iyi bir ilk adım olmasının bir başka nedeni de Vue'yu en basit haliyle kullanabilmemizdir. Oluşturma araçları gerekmez. Sadece HTML'de bir script etiketi ile vue.js
. Aslında indirmemize bile gerek yok. vue.js
çalışan bir kopyasının sunulduğu bir site var.
Tek ihtiyacımız olan aşağıdaki etiket:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
Komut dosyası etiketini doğrudan kurulumla ilgili Vue belgelerinden kopyaladım.
Şimdi, simgeleri yükleyebilecek ve onları tıklayan bir şeye dönüştürebilecek bir web sayfasına ihtiyacımız var. Vue bunu çok kolaylaştırıyor. Aslında, Vue kullanarak bir Twitter listesini yönetmek için küçük bir uygulama yazdım. Sadece metin alanlarını yönetir. Simgeleri kullanan bir SPWA'dan biraz daha basit olduğu için, ona bir göz atabilir ve ardından onu istediğimiz tek sayfalık uygulama çerçevesi olarak değiştirebiliriz.
İşte sayfanın nasıl göründüğünün bir kısmı:
Bu oldukça basit bir sayfaya benziyor. Her dış sayısal giriş, içinde bir veya iki tweet bulunan bir zaman dilimidir. İkinci tweet isteğe bağlıdır. Bir tweet'i düzenlerseniz, Vue mekanizmaları bir JavaScript nesnesini günceller. Bu sayfa, sunucuya düğme işleyici işlevi aracılığıyla bir şeylerin değiştiğini söylemek için “girişleri güncelle” düğmesini tıklatmayı kullanıcıya bırakır.
Düğme işleyicinin verileri sunucuya iletebilmesi için Vue veri nesnesini bir JSON dizesine değiştirmesi gerekir. Şimdi, bir Vue nesnesini JSON'a çevirmenin ne kadar zor olacağını merak edebilirsiniz. Bir kod satırı olduğu ortaya çıkıyor. Satırı aşağıdaki kaynak kodda bulabilirsiniz fakat daha hızlı bulmak isterseniz kaynak kodundan sonraki paragrafta vurgulanmıştır.
Sayfa basit görünüyor. Görünüş aldatıcı olabilir. Elbette sayfa basit görünüyor ama kod basit mi? Evet, gerçekten öyle! Sayfa, Vue kullanarak alanların içeriğini neredeyse sihirli bir şekilde yönetir. İşte kod:
<!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>
Yani, çerçevenin gücünden bahseden harika satırları vurgulamak için burada tekrar edelim:
A. Bu, verileri dışarı çekiyor.
postOptionsObject.body = JSON.stringify(twtApp.tweets);
B. Bu, verileri Vue'ya yerleştiriyor ve ekran güncellemesini görüyor:
twtApp.tweets = JSON.parse(text) // text is the server response
Bu ne kadar iş?
Verilerin IoT için panelleri nasıl güncelleyeceğini ifade etmenin güzel bir yolu olacak gibi görünüyor.
Şimdi, tweet'leri web sunucusundan bileşenleri almak için tasarlanmış tıklanabilir simgelere dönüştürelim.
Tweetlerden Panel Getirme Simgelerine
İnsanlar simgeler için SVG kullanmayı sever. Söyleyebildiğim kadarıyla, SVG için bu kullanımı diğer şeylerden daha çok seviyorlar. Sadece SVG'de yapılmış ikonları satan veya dağıtan web sitelerinin sayısına gidiyorum. Satış noktası, çizgi grafiklerin resimlerden daha az bayta sahip olmasıdır. Ayrıca, düğme benzeri davranışa sahip resimlerin listelerini isteyecek olsaydım, SVG'nin iframe'lerde olduğu günlerde PNG'leri veya JPEG'leri yakalayabilirdim. 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.
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>
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:
The data being sent is an array with the following kind of structure:
{ "style" : { "color" : "red", "backgroundColor" : "yellow" }, "icon" : svg1, "name" : "thermos" },
Burada svg1
, bir dosyadan alınan SVG'dir. Elbette doğru bir sunucu, yapıyı SVG'nin yapıda depolanacağı bir veritabanından alırdı.
İşte yukarıdaki koddan bir pasaj. Bu, JSON'u getiren ve yapı dizisini Vue uygulamasına yerleştiren koddur. fetch
söz yapısını kullanımda görebilirsiniz. Metin ayrıştırılır ve sonraki satırda kodlanmış SVG'nin kodu çözülür. Bir satır daha ve Vue sayfayı günceller. Düğme çubuğundaki düğmelerin sayısı, JSON dizisinin uzunluğuna eşit olacaktır.
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; }); });
Şimdi, sadece iki parça daha. Vue uygulaması. Okuyucu, @click
yönergesinin butonlara dahil edildiğini fark edecektir. iconEntry.name
adlı veri öğesi, tırnak işaretleri içinde bir yönteme iletilir.
Yöntem, Vue uygulamasında tanımlanır:
<div class="entryart"> <button v-for="iconEntry in iconList" @click="goGetPanel(iconEntry.name)" > <div v-html="iconEntry.icon"> </div> </button> </div> </div>
İşte yöntemlerin tanımı için snippet. methods
nesnesi, uygulama parametresi nesnesindeki data
nesnesinden hemen sonra eklenir:
, methods: { goGetPanel: (pname) => { // `this` inside methods points to the Vue instance alert('Hello ' + pname + '!') } }
Okuyucu goGetPanel
tanımını bulmalıdır ve @click
işleyicisi için bunun kullanımı belirtilmiştir. Son uygulamamızda, alert
çağrısı, sunucudan panelleri getiren bir işlevle değiştirilebilir.
IoT Panelleri İçin Bir Bileşen Kitaplığı
Sunucudan alacağımız panellerin HMTL veya sadece SVG çizimleri olabileceğine karar verebilirdik, ancak çok sayıda panel olacaksa, panel oluşturma işinin bileşen kitaplıkları ile basitleştirilebileceğini umarız. içinden seçmek. SVG editörlerinin, kitaplık bileşenlerinin düzenlemenin bir parçası olarak resimlerin üzerine bırakılmasına izin verecek şekilde geliştirilebileceğini hayal edebiliyoruz. Ardından, SVG düzenleyicisi, bileşen etiketleriyle birlikte resmin bir sürümünü çıkarabiliyorsa, Vue kullanımı, JavaScript otomasyonu ve animasyonunun düzgün bir şekilde bir araya getirilmesini sağlarken resmin oluşturulmasına izin verir. Tartışmamız için, bazı el düzenlemeleri oraya ulaşmamıza yardımcı olabilir.
Vue bileşenlerinden paneller oluşturmak istiyorsak, bileşenleri nasıl oluşturacağımızı bulmamız ve sonra bunları bir araya getirerek yararlı bir şey haline getirmemiz daha iyi olur. Vue tarafından sağlanan komut satırı araçlarını kullanmaya geçmemiz ve iş akışımızı düzenlememiz gerekecek.
Bileşenler
Vue belgeleri, bileşen tanımının bileşen data
bölümünün (alt nesne) veri döndüren bir işlev olması gerektiğine işaret eder. Bunun nedeni, Vue'nin verileri örnekler arasında ayrı tutması gerektiğidir. Bu nedenle, bir Vue uygulamasının başlatılmasından bir bileşen tanımına geçerken başka bir küçük kod değişikliği vardır.
Bu ilk kod parçacığında bir Vue uygulaması başlatılıyor:
var iconApp = new Vue({ el: '#iconApp', data: { // this is the data field that can be easily updated }, methods : { ... } });
Bu yeni kod parçacığında, bir bileşen tanımlanıyor ve kaydediliyor. İlk olarak, new Vue
örneği oluşturmak yerine, iconic
adlı bir bileşenin kaydedildiğine dikkat edin. Ardından, data
alanı, Vue uygulamasının yaptığı herhangi bir iconic
örnek için özel veriler döndürür. Son olarak, bileşen kaydının sonunda template
alanı bulunur. Bileşeni görüntülemek için web sayfasında yazılmış olabilecek herhangi bir HTML, template
bir parçası olabilir.
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>' });
Yani termometreli bir panel düşünebiliriz. Bu nedenle, birisi bir thermometer
bileşeni sağladıysa, kodumuzda bir yerde bir bileşen tanımı bekleriz. Haddi zatında:
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>' });
Şuna benzeyen bir şey yaratmaya çalışıyoruz:
Termometre bileşeni, Vue eğitimlerinde karşılaşacağınız ilk bileşenlere çok benzer. Ancak, nasıl güncelleneceğini anlamak biraz zor. Özellikleri kullanarak bileşeni reaktivite için tanımlamanın daha iyi bir yolu vardır. Ve bu, aşağıdakilerde:
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' })
Bu nedenle, sıcaklığı bir veri öğesi olarak temsil etmek yerine. props
altında bir özellik olarak temsil edilir. Ardından, özelliğin işlevleri olan değişkenleri sağlayan hesaplanan yeni bir bölüm vardır. this.temperature
hem y
hem de height
için kullanıldığını görüyoruz. Bu hesaplanmış değişkenler, SVG'de bir dikdörtgenin öznitelikleri olarak kullanılmaktadır.
SVG'de y
yukarıdan aşağıya doğru büyür. Bu nedenle, termometrenin altındaki dikdörtgenin küçük olmasını istediğimizde, kırmızı kutunun y'si daha düşük olmalı ve yüksekliği ( y
y + height
) termometre sıfırda kalacak şekilde azaltılmalıdır.
Bileşenlerin tanımındaki template
alanına dikkat edin. Aslında, bir belge öğesi kimliğidir. Başvurulan öğe, özel türü olan bir komut dosyası bölümüdür: type="text/x-template"
. Komut dosyası öğesi, termometreler için SVG'nin olduğu yerdir. Ve SVG, reaktivitenin tanımlanabilmesi için Vue değişkenlerini ve kontrol terimlerini kullanır.
İşte SVG'den bazıları:
<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"
Okuyucu en üstte id="thermometer-template"
bulabilir ve rect
elemanlara daha yakından bakarak hesaplanan değişkenleri bulabilir.
Burada değişken kullanımları ayrılmıştır. v-bind
için Vue kısayol sözdizimi :height="height"
ile kullanımda ve y
için aynı:
x="111.90748" :height="height" :y="y"
SVG öğelerinin ebeveyni, termometre özelliği temperature
girdi olarak işlev gören değişkenleri ayarladığında, Vue height
ve y
yeniden hesaplar. Sonuç olarak, kırmızı kutunun konumu ve yüksekliği değişir.
Termometreyi kullanan Vue uygulamasının bir listesinin bulunmasına yardımcı olur.
<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>
Bütün mesele bu. thermoApp
Vue uygulamasının updateTemp
yöntemini çağıran üç düğme vardır. Veri bölümünde iki sıcaklık değişkeni vardır. Ve her thermometer
, değerler değiştiğinde sıcaklığını günceller.
Aşağıda belirtilen iki termometrenin kodu, Vue uygulamasına atanan HTML'de bulunabilir.
<thermometer :temperature="temp1" ></thermometer> <thermometer :temperature="temp2" ></thermometer>
Uygulamanın yöntem tanımı için function
biçimciliğini kullandığına dikkat edin. updateTemp
bu şekilde tanımlamak updateTemp: function (tval1,tval2)
örnek değişkenine this
erişilmesine izin verir.
Ayrıca updateTemp
bu şekilde tanımlamak updateTemp: (tval1,tval2) =>
bunu, tepki vermeyen ve görünümü this
bir dahili veri yapısına atar.
Panel Montajı
Her IoT paneli bir bileşen olabilir. Vue, bileşenleri alt bileşenlerle tanımlamanın bir yolunu sağlar. Alternatif olarak, herhangi bir HTML içeriğini sarabilen bir bileşen elde etmek için kullanılabilecek bir yuva mekanizması vardır.
Aşağıdaki birkaç paragrafta, alt bileşenlerden bir panel oluşturmaya bakalım. Örneklerimizden hızlı bir şekilde takip eden iki form var. Bir durumda, termometreler JavaScript'te çağrılan alt bileşenler olabilir. Başka bir durumda, bileşenler bağımsız olarak tanımlanır ancak HTML'de belirtilir.
Her iki durumda da şablon için aynı HTML kullanılabilir. Şablon olarak panelimiz:
<script type="text/x-template"> <div> <thermometer :temperature="temp1" ></thermometer> <thermometer :temperature="temp2" ></thermometer> </div> </script>
Uygulamanın ilk detayı arasındaki tek fark, iki termometreyi çevreleyen bir div
elemanının olmasıdır. Şablonda bir üst düzey DOM öğesi eksikse Vue bir hata verir. div
, Vue gereksinimini geçer ve birden çok öğe bunun içine dahil edilebilir.
Şimdi iki termometreyi yan yana görebiliriz. Sıcaklıkları tepeden son termometreye geçirmek, basamaklı değerlere sahiptir. En üst düzeyde, uygulama DOM'sine tek bir satır eklendiğinde panel uygulamaya katılır.
<themo-panel :temp1="temp1" :temp2="temp2" ></themo-panel>
Panelin şablonu basit olmasına rağmen, bileşenler açısından panellerin kolayca tasarlanabileceğini gösteriyor gibi görünüyor. Sanki sadece IoT bileşenleri için bir dil mümkünmüş gibi.
Şimdi, panelin şablon tanımı yeterince basit. Burada bağımsız olarak tanımlanan alt bileşenlerle birlikte:
Vue.component('thermo-panel', { props: ['temp1','temp2'], template: '#thermo-panel-template' });
Bu, paneli işlevsel hale getirmek için gerekli olan kadardır. Bu sürümün, mesajlar sayfaya geldikçe güncellenecek değerleri tanımlamak için uzun bir özellik listesine dayandığı doğrudur. Ancak bu iyi bir başlangıç. data
nesnesini en üst düzeyde güncellemek, termometreleri canlandırma işini yapar. Ancak, paneller karmaşıklaştıkça, değişikliği göstermek için başka bir yönteme ihtiyaç duyulabilir.
Panel için alt bileşenleri belirlemenin diğer yollarından bahsettikten sonra, ona bir göz atmalıyız. İşte burada:
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) } } } } });
Kesinlikle daha fazla kod var, ancak bunun nedeni, thermometer
bileşeni için JavaScript'in thermo-panel
bileşen listesinde yer almasıdır. İki yaklaşım aynı işi yapar, ancak farklı paketleme bileşeni tanımları sunarlar.
Şu anda tercihim ilk yol. Yalnızca şablon ve özelliklerin değiştirilmesi gerekiyorsa, panelleri revize etmek ve dinamik olarak alınmasını sağlamak çok daha kolay olmalıdır. Bu amaçla, bağımsız olarak tanımlanan bileşenler bir bileşen kitaplığı oluşturur. Ancak, bu daha iyi görünse de, aşağıda ikinci, görünüşte daha ayrıntılı yolu kullanmak daha uygun hale geliyor.
Bileşenlerden açıkça tanımlanmış şekillerde responsive paneller yapabildiğimize göre, bunları basit sorgular yapabilen bir veritabanı olarak nasıl yönetebileceğimizi makalemin bir sonraki bölümünde anlatacağım.