תגי עיצוב, עיצוב, סקריפטים ועדכון של מיני אפליקציות

Markup languages

כפי שצוין קודם, אפליקציות מיני נכתבות בפייברטיבים של HTML ולא ב-HTML רגיל. אם עסקתם אי פעם בהנחיות ובאינטרפולציה של טקסט ב-Vue.js, תוכלו להבין את הנושא הזה בקלות. עם זאת, מושגים דומים היו קיימים הרבה לפני כן בטרנספורמציות XML‏ (XSLT). למטה מוצגות דוגמאות קוד מ-WXML של WeChat, אבל הקונספט זהה בכל פלטפורמות האפליקציות מיני, כלומר AXML של Alipay, Swan Element של Baidu, TTML של ByteDance (TTML (למרות ה-DevTools שקוראים לו Bxml) ו-HTML של אפליקציית Quick App. בדומה ל-Vue.js, העיקרון הבסיסי של תכנות אפליקציות המיני הוא מודל-תצוגה-תצוגת מודל (MVVM).

קישור נתונים

קישור הנתונים תואם לאינטרפולציה של טקסט ב-Vue.js.

<!-- wxml -->
<view>{{message}}</view>
// page.js
Page({
  data: {
    message: "Hello World!",
  },
});

רינדור רשימות

עיבוד רשימות פועל כמו ההוראה v-for ב-Vue.js.

<!-- wxml -->
<view wx:for="{{array}}">{{item}}</view>
// page.js
Page({
  data: {
    array: [1, 2, 3, 4, 5],
  },
});

רינדור מותנה

עיבוד תמונה מותנה פועל כמו ההוראה v-if ב-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",
  },
});

תבניות

במקום לדרוש העתקה של content של תבנית HTML, אפשר להשתמש בתבניות WXML באופן דקלרטיבי באמצעות המאפיין is שמקשר להגדרת תבנית.

<!-- 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" },
  },
});

עיצוב

הוספת סגנון מתבצעת באמצעות דיאלקטים של CSS. שם החבילה של WeChat הוא WXSS. ב-Alipay הוא נקרא ACSS, ב-Baidu הוא נקרא פשוט CSS וב-ByteDance הוא נקרא TTSS. הדבר המשותף להם הוא שהם מרחיבים את CSS באמצעות פיקסלים רספונסיביים. כשכותבים CSS רגיל, המפתחים צריכים להמיר את כל יחידות הפיקסלים כדי להתאים למסכים שונים של מכשירים ניידים עם רוחב ויחסי פיקסלים שונים. TTSS תומך ביחידת rpx כשכבה הבסיסית שלו, כלומר האפליקציה המיני מקבלת את התפקיד מהמפתח וממירה את היחידות בשבילו, על סמך רוחב המסך שצוין של 750rpx. לדוגמה, בטלפון Pixel 3a עם רוחב מסך של 393px (ושיעור פיקסלים במכשיר של 2.75), רכיבים עם תגובה דינמית מסוג 200rpx הופכים לרכיבים מסוג 104px במכשיר האמיתי כשבודקים אותם באמצעות כלי הפיתוח ל-Chrome (393px / 750rpx * 200rpx ≈ 104px). ב-Android, אותו עיקרון נקרא פיקסל בלתי תלוי בדחיסות.

בדיקה של תצוגה באמצעות כלי הפיתוח ל-Chrome, שבה הרווח האדפטיבי לפיקסלים צוין כ-200rpx, מראה שהוא למעשה 104px במכשיר Pixel 3a.
בדיקת המילוי בפועל במכשיר Pixel 3a באמצעות כלי הפיתוח ל-Chrome.
/* 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;
}

מכיוון שרכיבים (מידע נוסף מופיע בהמשך) לא משתמשים ב-Shadow DOM, סגנונות שהוגדרו בדף מגיעים לכל הרכיבים. הארגון הנפוץ של קובצי גיליונות סגנונות הוא שימוש בגיליונות סגנונות ברמה הבסיסית (root) לסגנונות גלובליים, ובגיליונות סגנונות נפרדים לכל דף ספציפי באפליקציית המיני. אפשר לייבא סגנונות באמצעות כלל @import שמתנהג כמו כלל at-rule של CSS‏ @import. כמו ב-HTML, אפשר להצהיר על סגנונות גם בתוך שורות הטקסט, כולל אינטרפולציה דינמית של טקסט (ראו לפני).

<view style="color:{{color}};" />

כתיבת סקריפטים

אפליקציות מיני תומכות ב'קבוצת משנה בטוחה' של JavaScript, שכוללת תמיכה במודולים באמצעות תחבירים שונים שדומים ל-CommonJS או ל-RequireJS. לא ניתן להריץ קוד JavaScript דרך eval(), ואי אפשר ליצור פונקציות באמצעות new Function(). הקשר לביצוע הסקריפט הוא V8 או JavaScriptCore במכשירים, ו-V8 או NW.js בסימולטור. בדרך כלל אפשר לכתוב קוד עם תחביר של ES6 ואילך, כי כלי DevTools הספציפיים מבצעים תרגום אוטומטי של הקוד ל-ES5 אם יעד ה-build הוא מערכת הפעלה עם הטמעה ישנה יותר של WebView (מידע נוסף זמין בהמשך). במסמכי העזרה של ספקי האפליקציות הגדולות מצוין במפורש ששפות הסקריפט שלהן שונות מ-JavaScript ואין להתבלבל ביניהן. עם זאת, ההצהרה הזו מתייחסת בעיקר לאופן הפעולה של המודולים, כלומר שהם עדיין לא תומכים במודולים רגילים של ES.

כפי שצוין לפני כן, מושג התכנות של אפליקציות המיני הוא מודל-תצוגה-תצוגת מודל (MVVM). שכבת הלוגיקה ושכבת התצוגה פועלות בשרשוריים שונים, כך שממשק המשתמש לא נחסם על ידי פעולות ממושכות. במונחים של אינטרנט, אפשר לחשוב על סקריפטים שפועלים בWeb Worker.

שפת הסקריפטים של WeChat נקראת WXS, של Alipay נקראת SJS ושל ByteDance נקראת SJS. ב-Baidu מתייחסים ל-JS כשמתייחסים ל-JS שלהם. צריך לכלול את הסקריפטים האלה באמצעות סוג מיוחד של תג, לדוגמה, <wxs> ב-WeChat. לעומת זאת, באפליקציה המהירה נעשה שימוש בתגים רגילים מסוג <script> ובתחביר JS של ES6.

<wxs module="m1">
  var msg = "hello world";
  module.exports.message = msg;
</wxs>

<view>{{m1.message}}</view>

אפשר גם לטעון מודולים באמצעות מאפיין src או לייבא אותם באמצעות 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);

JavaScript bridge API

גשר JavaScript שמחבר אפליקציות מיני למערכת ההפעלה מאפשר להשתמש ביכולות של מערכת ההפעלה (ראו גישה לתכונות מתקדמות). בנוסף, יש בו כמה שיטות נוחות. תוכלו לקרוא סקירה כללית על ממשקי ה-API השונים של WeChat, Alipay, Baidu, ByteDance ו-Quick App.

זיהוי התכונות פשוט, כי כל הפלטפורמות מספקות שיטה בשם canIUse() (שנקראת כך ממש). נראה שהשם שלה מושפע מהאתר caniuse.com. לדוגמה, tt.canIUse() של ByteDance מאפשרת לבדוק את התמיכה בממשקי API, בשיטות, בפרמטרים, באפשרויות, ברכיבים ובמאפיינים.

// Testing if the `<swiper>` component is supported.
tt.canIUse("swiper");
// Testing if a particular field is supported.
tt.canIUse("request.success.data");

עדכונים

לאפליקציות המיני אין מנגנון עדכון סטנדרטי (דיון בנושא סטנדרטיזציה פוטנציאלית). לכל פלטפורמות מיני של האפליקציות יש מערכת קצה עורפי שמאפשרת למפתחי אפליקציות קטנים להעלות גרסאות חדשות של האפליקציות שלהם. לאחר מכן, אפליקציית-על משתמשת במערכת הקצה העורפי הזו כדי לבדוק אם יש עדכונים ולהוריד אותם. אפליקציות-על מסוימות מבצעות עדכונים לגמרי ברקע, בלי שאפליקציית המיני-אפליקציה עצמה תשפיע על תהליך העדכון. אפליקציות-על אחרות נותנות יותר שליטה במיני אפליקציות עצמן.

דוגמה לתהליך מתוחכם שמתארת את מנגנון העדכון של WeChat למיני אפליקציות בפירוט רב יותר. אפליקציית WeChat בודקת אם יש עדכונים זמינים בשני התרחישים הבאים:

  1. אפליקציית WeChat תבדוק באופן קבוע אם יש עדכונים לאפליקציות המיני שבהן השתמשתם לאחרונה, כל עוד אפליקציית WeChat פועלת. אם יימצא עדכון, הוא יוריד וייושם באופן סינכרוני בפעם הבאה שהמשתמש יפעיל מחדש את האפליקציה המיניאטורית. הפעלה מחדש של אפליקציה מיניאטורית מתרחשת כשהאפליקציה המיניאטורית לא הייתה פועלת בזמן שהמשתמש פתח אותה (אפליקציות מיניאטוריות נסגרות בכוח ב-WeChat אחרי שהן נמצאות ברקע במשך 5 דקות).
  2. אפליקציית WeChat בודקת אם יש עדכונים גם כשמפעילים אפליקציית מיני בפעם הראשונה. במקרה של מיני אפליקציות שהמשתמש לא פתח במשך זמן רב, העדכון נבדק ומוריד באופן סינכרוני. בזמן הורדת העדכון, המשתמש צריך להמתין. כשההורדה תסתיים, העדכון יוחל ואפליקציית המיני תיפתח. אם ההורדה נכשלת, למשל בגלל חיבור לקוי לרשת, האפליקציה המיני תפתח בכל מקרה. לגבי אפליקציות מיני שהמשתמש פתח לאחרונה, כל עדכון פוטנציאלי מוריד באופן אסינכררוני ברקע וייושם בפעם הבאה שהמשתמש יפעיל את האפליקציה המיני מחדש.

אפשר להשתמש ב-API של UpdateManager כדי להביע הסכמה לעדכונים קודמים באפליקציות המיני. היא מספקת את הפונקציונליות הבאה:

  • מודיע לאפליקציית המיני כשמתבצעת בדיקה של עדכונים. (onCheckForUpdate)
  • מודיע לאפליקציית המיני כשהעדכון הורדה וזמין. (onUpdateReady)
  • מודיע לאפליקציית המיני כשלא ניתן להוריד עדכון. (onUpdateFailed)
  • מאפשרת לאפליקציית המיני להתקין בכפייה עדכון זמין, שיגרום להפעלה מחדש של האפליקציה. (applyUpdate)

בנוסף, במערכת הקצה העורפי של WeChat יש אפשרויות נוספות להתאמה אישית של עדכונים למפתחי אפליקציות מיני: 1. אחת מהאפשרויות מאפשרת למפתחים לבטל את ההסכמה לעדכונים סינכרוניים למשתמשים שכבר מותקנת אצלם גרסה מינימלית מסוימת של האפליקציה המיני, ובמקום זאת לאלץ את העדכונים להיות אסינכרונים. 2. אפשרות נוספת מאפשרת למפתחים להגדיר גרסת מיני מינימלית נדרשת של אפליקציית המיני של האפליקציה. בעקבות העדכון, עדכונים אסינכרוניים מגרסה נמוכה יותר מהגרסה המינימלית הנדרשת יאלצו לטעון מחדש את גרסת המיני של האפליקציה אחרי החלת העדכון. הוא גם יחסום את פתיחת הגרסה הישנה יותר של האפליקציה המיני אם ההורדה של העדכון תיכשל.

תודות

הבדיקה של המאמר בוצעה על ידי Joe Medley,‏ Kayce Basques,‏ Milica Mihajlija,‏ Alan Kent ו-Keith Gu.