Język znaczników
Jak już wspomnieliśmy, miniaplikacje są tworzone za pomocą dialektów HTML, a nie zwykłego HTML. Jeśli miałeś/miałaś do czynienia z interpolacją tekstu i direktiwami Vue.js, od razu poczujesz się jak w domu. Jednak podobne koncepcje istniały już wcześniej w ramach transformacji XML (XSLT). Poniżej znajdziesz przykłady kodu z WXML WeChat, ale koncepcja jest taka sama w przypadku wszystkich platform miniaplikacji, czyli AXML Alipay, Swan Element ByteDance (pomimo że w narzędziu DevTools jest on nazywany Bxml) oraz HTML Quick App. Podobnie jak w przypadku Vue.js, podstawową koncepcją programowania miniaplikacji jest model-view-viewmodel (MVVM).
Wiązanie danych
Wiązanie danych odpowiada interpolacji tekstu w Vue.js.
<!-- wxml -->
<view>{{message}}</view>
// page.js
Page({
data: {
message: "Hello World!",
},
});
Renderowanie listy
Renderowanie list działa podobnie do dyrektywy v-for
w Vue.js.
<!-- wxml -->
<view wx:for="{{array}}">{{item}}</view>
// page.js
Page({
data: {
array: [1, 2, 3, 4, 5],
},
});
Renderowanie warunkowe
Rendering warunkowy działa jak dyrektywa v-if
w Vue.js.
<!-- wxml -->
<view wx:if="{{view == 'one'}}">One</view>
<view wx:elif="{{view == 'two'}}">Two</view>
<view wx:else="{{view == 'three'}}">Three</view>
// page.js
Page({
data: {
view: "three",
},
});
Szablony
Zamiast wymagać imperatywnego klonowania content
szablonu HTML, szablony WXML można używać deklaratywnie za pomocą atrybutu is
, który łączy się z definicją szablonu.
<!-- wxml -->
<template name="person">
<view>
First Name: {{firstName}}, Last Name: {{lastName}}
</view>
</template>
<template is="person" data="{{...personA}}"></template>
<template is="person" data="{{...personB}}"></template>
<template is="person" data="{{...personC}}"></template>
// page.js
Page({
data: {
personA: { firstName: "Alice", lastName: "Foo" },
personB: { firstName: "Bob", lastName: "Bar" },
personC: { firstName: "Charly", lastName: "Baz" },
},
});
Styl
Stylizacja odbywa się za pomocą dialektów CSS. WeChat ma nazwę WXSS.
W przypadku Alipay jest to ACSS, w przypadku Baidu – CSS, a w przypadku ByteDance – TTSS.
Mają one wspólną cechę: rozszerzają CSS o elastyczną rozdzielczość pikseli. Podczas pisania zwykłego kodu CSS deweloperzy muszą przekształcać wszystkie jednostki pikseli, aby dostosować je do ekranów różnych urządzeń mobilnych o różnej szerokości i proporcjach pikseli. TTSS obsługuje jednostkę rpx
jako warstwę podstawową, co oznacza, że miniaplikacja przejmuje zadanie od dewelopera i konwertuje jednostki w jego imieniu na podstawie określonej szerokości ekranu 750rpx
. Na przykład na telefonie Pixel 3a o szerokości ekranu 393px
(i współczynniku pikseli urządzenia 2.75
) responsywne 200rpx
na urządzeniu staje się 104px
, gdy sprawdzisz je za pomocą zestawu narzędzi Chrome DevTools (393 piksele / 750 rpx * 200 rpx ≈ 104 piksele). W Androidzie ta sama koncepcja nosi nazwę piksel niezależny od gęstości.
/* app.wxss */
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 200rpx 0; /* ← responsive pixels */
box-sizing: border-box;
}
Ponieważ komponenty (patrz poniżej) nie używają modelu Shadow DOM, style zadeklarowane na stronie są dostępne we wszystkich komponentach. Typowa organizacja pliku czcionki to jedna czcionka główna dla stylów globalnych oraz czcionki dla poszczególnych stron w miniaplikacji. Stylów można używać za pomocą reguły @import
, która działa jak reguła at-rule w CSS (@import
). Podobnie jak w HTML, style można też deklarować w kodze inline, w tym w przypadku interpolacji tekstu dynamicznego (patrz przed).
<view style="color:{{color}};" />
Tworzenie scenariusza
Miniaplikacje obsługują „bezpieczny podzbiór” kodu JavaScript, który obejmuje obsługę modułów używających różnych składni, przypominających CommonJS lub RequireJS.
Kod JavaScript nie może być wykonywany za pomocą elementu eval()
, a funkcje nie mogą być tworzone za pomocą elementu new Function()
. Kontekst wykonywania skryptu to V8 lub JavaScriptCore na urządzeniach oraz V8 lub NW.js w symulatorze. Kodowanie z użyciem składni ES6 lub nowszej jest zwykle możliwe, ponieważ konkretne Narzędzia deweloperskie automatycznie transpilują kod do ES5, jeśli celem kompilacji jest system operacyjny ze starszą implementacją WebView (patrz później). Dokumentacja dostawców super aplikacji wyraźnie informuje, że ich języki skryptowe nie są powiązane z JavaScriptem i nie należy ich mylić z tym językiem. To stwierdzenie dotyczy jednak głównie sposobu działania modułów, czyli tego, że nie obsługują one jeszcze standardowych modułów ES.
Jak już wspomnieliśmy wcześniej, koncepcja programowania miniaplikacji to model-view-viewmodel (MVVM). Warstwa logiki i warstwa widoku działają na różnych wątkach, co oznacza, że interfejs użytkownika nie jest blokowany przez długotrwałe operacje. Mówiąc ogólnie o skryptach działających w narzędziu Web Worker,
Język skryptowy WeChat nosi nazwę WXS, a Alipay używa języka SJS, a ByteDance – SJS.
Baidu używa terminu JS, gdy odnosi się do swoich usług. Te skrypty trzeba dodać za pomocą specjalnego tagu, np. <wxs>
w WeChat. Z kolei aplikacja szybka używa zwykłych tagów <script>
i składni JS ES6.
<wxs module="m1">
var msg = "hello world";
module.exports.message = msg;
</wxs>
<view>{{m1.message}}</view>
Moduły można też wczytywać za pomocą atrybutu src
lub importować za pomocą require()
.
// /pages/tools.wxs
var foo = "'hello world' from tools.wxs";
var bar = function (d) {
return d;
};
module.exports = {
FOO: foo,
bar: bar,
};
module.exports.msg = "some msg";
<!-- page/index/index.wxml -->
<wxs src="./../tools.wxs" module="tools" />
<view>{{tools.msg}}</view>
<view>{{tools.bar(tools.FOO)}}</view>
// /pages/logic.wxs
var tools = require("./tools.wxs");
console.log(tools.FOO);
console.log(tools.bar("logic.wxs"));
console.log(tools.msg);
Interfejs JavaScript Bridge API
Mostek JavaScript łączący miniaplikacje z systemem operacyjnym umożliwia korzystanie z funkcji systemu (patrz Dostęp do zaawansowanych funkcji). Oferuje też kilka wygodnych metod. Aby uzyskać ogólny przegląd, możesz sprawdzić różne interfejsy API WeChat, Alipay, Baidu, ByteDance i Quick App.
Wykrywanie funkcji jest proste, ponieważ wszystkie platformy udostępniają metodę canIUse()
, której nazwa została zaczerpnięta z witryny caniuse.com. Na przykład firma ByteDance udostępnia funkcję tt.canIUse()
, która umożliwia sprawdzanie obsługi interfejsów API, metod, parametrów, opcji, komponentów i atrybutów.
// Testing if the `<swiper>` component is supported.
tt.canIUse("swiper");
// Testing if a particular field is supported.
tt.canIUse("request.success.data");
Aktualizacje
Miniaplikacje nie mają ustandaryzowanego mechanizmu aktualizacji (dyskusja na temat potencjalnej standaryzacji). Wszystkie platformy miniaplikacji mają system backendu, który umożliwia deweloperom miniaplikacji przesyłanie nowych wersji miniaplikacji. Następnie superaplikacja korzysta z tego systemu do sprawdzania i pobierania aktualizacji. Niektóre superaplikacje przeprowadzają aktualizacje całkowicie w tle, bez możliwości wpływania na proces aktualizacji przez miniaplikację. Inne superaplikacje dają większą kontrolę nad miniaplikacjami.
Jako przykład zaawansowanego procesu w następnych akapitach opisujemy szczegółowo mechanizm aktualizacji miniaplikacji w WeChat. WeChat sprawdza dostępność aktualizacji w tych 2 sytuacjach:
- WeChat będzie regularnie sprawdzać dostępność aktualizacji ostatnio używanych miniaplikacji, dopóki działa. Jeśli zostanie znaleziona aktualizacja, zostanie ona pobrana i zaaplikowana synchronicznie przy następnym uruchomieniu miniaplikacji przez użytkownika. Uruchomienie „na zimno” miniaplikacji ma miejsce, gdy miniaplikacja nie była uruchomiona w momencie jej otwarcia przez użytkownika (WeChat wymusza zamknięcie miniaplikacji po 5 minutach działania w tle).
- WeChat sprawdza też dostępność aktualizacji, gdy miniaplikacja jest uruchamiana po raz pierwszy. W przypadku miniaplikacji, których użytkownik nie otwierał od dłuższego czasu, aktualizacja jest sprawdzana i pobierana synchronicznie. Podczas pobierania aktualizacji użytkownik musi czekać. Po zakończeniu pobierania aktualizacja zostanie zastosowana, a miniaplikacja otworzy się. Jeśli pobieranie nie powiedzie się, np. z powodu słabego połączenia z internetem, miniaplikacja otworzy się mimo wszystko. W przypadku miniaplikacji, które użytkownik otworzył niedawno, wszelkie potencjalne aktualizacje są pobierane asynchronicznie w tle i są stosowane przy następnym uruchomieniu miniaplikacji.
Miniaplikacje mogą korzystać z wcześniejszych aktualizacji za pomocą interfejsu API UpdateManager
. Oferuje ona te funkcje:
- Powiadamia miniaplikację o sprawdzeniu dostępności aktualizacji.
(
onCheckForUpdate
) - Powiadamia miniaplikację o pobraniu i udostępnieniu aktualizacji.
(
onUpdateReady
) - Informuje miniaplikację, gdy nie udało się pobrać aktualizacji.
(
onUpdateFailed
) - Umożliwia miniaplikacji wymuszenie zainstalowania dostępnej aktualizacji, co spowoduje ponowne uruchomienie aplikacji. (
applyUpdate
)
WeChat udostępnia też deweloperom miniaplikacji dodatkowe opcje dostosowywania aktualizacji w systemie backend:1. Jedna z opcji umożliwia deweloperom rezygnację z aktualizacji synchronicznych w przypadku użytkowników, którzy mają już zainstalowaną minimalną wersję miniaplikacji, i zamiast tego wymuszanie asynchroniczności aktualizacji. 2. Inna opcja umożliwia deweloperom ustawienie minimalnej wymaganej wersji miniaplikacji. W takim przypadku aktualizacje asynchroniczne z wersji starszych niż minimalna wymagana wersja spowoduje przymusowe ponowne załadowanie miniaplikacji po zastosowaniu aktualizacji. W przypadku niepowodzenia pobierania aktualizacji zablokuje też otwieranie starszej wersji miniaplikacji.
Podziękowania
Ten artykuł został sprawdzony przez Joe Medley, Kayce Basques, Milica Mihajlija, Alan Kent i Keitha Gu.