Heim  >  Artikel  >  WeChat-Applet  >  Analyse und Beispiele der WeChat Mini-Programmarchitektur

Analyse und Beispiele der WeChat Mini-Programmarchitektur

伊谢尔伦
伊谢尔伦Original
2017-01-24 11:24:443984Durchsuche

Die öffentliche Beta des WeChat Mini-Programms hat eine Welle des Lernens über die Entwicklung des Mini-Programms ausgelöst. Es ist von Natur aus plattformübergreifend, gebrauchsfertig, mit nativer Erfahrung, vollständiger Dokumentation und einem effizienten Entwicklungs-Framework ausgestattet viele Überraschungen für Entwickler. In diesem Artikel werden wir die Struktur des Miniprogramms analysieren und Entwicklungserfahrungen mit allen teilen.

Funktionen des Miniprogramms:

Analyse und Beispiele der WeChat Mini-Programmarchitektur

Architektur des Miniprogramms

Das Framework des WeChat-Miniprogramms besteht aus zwei Teilen: Ansichtsebene und Die App Service-Logikschicht wird zum Rendern der Seitenstruktur verwendet und die AppService-Schicht wird für die logische Verarbeitung, Datenanforderungen und Schnittstellenaufrufe verwendet. Sie werden in zwei Threads ausgeführt.

Die Ansichtsebene wird mit WebView gerendert und die Logikebene wird mit JSCore ausgeführt.

Die Ansichtsschicht und die Logikschicht kommunizieren über die JSBridage der Systemschicht. Die Logikschicht benachrichtigt die Ansichtsschicht über Datenänderungen und löst die Seitenaktualisierung der Ansichtsschicht aus. Die Ansichtsschicht benachrichtigt die Logik über die ausgelösten Ereignisse Schicht für die Geschäftsabwicklung.

Analyse und Beispiele der WeChat Mini-Programmarchitektur

Wenn das Miniprogramm gestartet wird, wird das komplette Paket des Miniprogramms vom CDN heruntergeladen

Analyse und Beispiele der WeChat Mini-Programmarchitektur

Ansicht (Seitenansicht)

Die Ansichtsebene wird von WXML und WXSS geschrieben und nach Komponenten angezeigt.

Reflektieren Sie die Daten der logischen Ebene in der Ansicht und senden Sie gleichzeitig die Ereignisse der Ansichtsebene an die logische Ebene.

1. Ansicht - WXML

WXML (WeiXin Markup Language)

Unterstützt die Datenbindung

Unterstützt logische Arithmetik und Operationen

Unterstützt Vorlagen und Referenzen

Unterstützt das Hinzufügen von Ereignissen (bindtap)

wxml-Compiler: wcc Konvertieren der wxml-Datei in js Ausführungsmethode: wcc index.wxml

2. Ansicht – WXSS

WXSS (WeiXin Style Sheets)

Unterstützt die meisten CSS-Funktionen

Größeneinheit Rpx hinzufügen, die entsprechend der Bildschirmbreite angepasst werden kann

Verwenden Sie @import-Anweisungen kann in externe Stylesheets importiert werden

Unterstützt keine mehrstufigen Selektoren – um eine Zerstörung durch die interne Struktur der Komponente zu vermeiden

Analyse und Beispiele der WeChat Mini-Programmarchitektur

wxss-Compiler: wcsc WXSS-Dateien konvertieren Für js-Ausführungsmethode: wcsc index.wxss

3. Ansicht – WXSS-Selektoren

WXSS unterstützt derzeit die folgenden Selektoren:

Analyse und Beispiele der WeChat Mini-Programmarchitektur

4, Ansicht – Komponente

Das Applet stellt eine Reihe von Komponenten für die Entwicklung von Geschäftsfunktionen bereit. Der Vergleich mit HTML5-Tags entsprechend den Funktionen ist wie folgt:

Analyse und Beispiele der WeChat Mini-Programmarchitektur

Miniprogramm Die Komponente basiert auf dem Web Component-Standard

Verwenden Sie das Polymer-Framework, um die Webkomponente zu implementieren

Analyse und Beispiele der WeChat Mini-Programmarchitektur

5 Komponente

Die derzeit von Native implementierte Komponente ist

Native-Komponentenebene WebView-Schicht

Analyse und Beispiele der WeChat Mini-Programmarchitektur

App Service (Logikschicht)

Die Logikschicht verarbeitet die Daten und sendet sie an die Ansichtsschicht und akzeptiert gleichzeitig Ereignisse Feedback von der Ansichtsebene

1. Zugang zum App-Applet ( ); Seite( )-Seiteneingang

3. Stellen Sie umfangreiche APIs bereit, z. B. WeChat-Benutzerdaten, Scan, Zahlung und andere WeChat -spezifische Fähigkeiten.

4. Jede Seite hat einen unabhängigen Umfang und bietet modulare Funktionen.

5. Datenbindung, Ereignisverteilung, Lebenszyklusverwaltung, Routing-Management

Laufumgebung

IOS – JSCore

Android – X5 JS-Parser

DevTool – nwjs Chrome Kernel

1

Die Datenbindung verwendet die Mustache-Syntax (doppelte geschweifte Klammern), um Variablen einzuschließen. Dynamische Daten stammen aus den Daten der entsprechenden Seite. Die Daten können über die setData-Methode geändert werden.


Ereignisbindung wird auf die gleiche Weise wie Komponentenattribute in Form von Schlüssel und Wert geschrieben. Der Schlüssel beginnt mit bind oder Catch, gefolgt von der Art des Ereignisses, z. B. bindtap, Catchtouchstart, und value eine Zeichenfolge ist, muss eine Funktion mit demselben Namen auf der entsprechenden Seite definiert werden.

Analyse und Beispiele der WeChat Mini-Programmarchitektur

Analyse und Beispiele der WeChat Mini-Programmarchitektur

2. App Service - Lebenszyklus

Analyse und Beispiele der WeChat Mini-Programmarchitektur

3 - API

API kommuniziert mit Native über JSBridge

Analyse und Beispiele der WeChat Mini-Programmarchitektur

4. App Service – Router

navigateTo(OBJECT)

Behalten Sie die aktuelle Seite bei, springen Sie zu einer Seite in der App und kehren Sie mit „navigationBack“ zur ursprünglichen Seite zurück. Der Seitenpfad kann nur fünf Ebenen umfassen

redirectTo(OBJECT)

Schließen Sie die aktuelle Seite und springen Sie zu einer Seite innerhalb der Anwendung.

navigateBack(OBJECT)

Schließen Sie die aktuelle Seite und kehren Sie zur vorherigen Seite oder mehrstufigen Seite zurück. Sie können den aktuellen Seitenstapel über getCurrentPages() abrufen und entscheiden, wie viele Ebenen zurückgegeben werden sollen.

5. Erfahrung in der Entwicklung von Miniprogrammen

1. Probleme mit Miniprogrammen

Miniprogramme verwenden immer noch WebView zum Rendern, nicht natives Rendern

Erfordert unabhängige Entwicklung , kann nicht in Nicht-WeChat-Umgebungen ausgeführt werden.

Entwickler können keine neuen Komponenten erweitern.

Der von der Serverschnittstelle zurückgegebene Header kann nicht ausgeführt werden, z. B.: Set-Cookie.

JS-Bibliotheken, die auf der Browserumgebung basieren, können nicht verwendet werden, da sie von JSCore ausgeführt werden und keine Fenster- oder Dokumentobjekte haben.

Lokal (Bilder, Schriftarten usw.) können in WXSS nicht verwendet werden.

WXSS wird aus Kompatibilitätsgründen mit rpx in js statt in css konvertiert.

WXSS unterstützt keine kaskadierenden Selektoren.

Das Applet kann die Seite nicht öffnen und die APP nicht starten.

Das Miniprogramm darf nicht denselben Namen wie das offizielle Konto haben, daher lautete der Name des Miniprogramms: Optional Stock+, Didi Chuxing DiDi.

2. Vorteile, von denen kleine Programme lernen können

Erstellen Sie im Voraus eine neue WebView und bereiten Sie sich auf das Rendern neuer Seiten vor.

Die Ansichtsschicht und die Logikschicht sind getrennt, datengesteuert und betreiben das DOM nicht direkt.

Verwenden Sie Virtual DOM für lokale Updates.

Alle verwenden https, um die Sicherheit bei der Übertragung zu gewährleisten.

Offline-Funktionen nutzen.

Entwicklung von Frontend-Komponenten.

Fügen Sie eine Rpx-Einheit hinzu, um die Gerätegröße zu isolieren und die Entwicklung zu erleichtern.

3. „Miniprogramm“, das sich von WeChat löst: PWA Progressive Applications

Der vollständige Name von PWA ist Progressive Web Apps, was ins Chinesische als Progressive Applications übersetzt wird Google hat am 15. Juni 2015 Konzept vorgestellt.

Progressive Web Apps sind ein Erlebnis, das die besten Funktionen des Webs und nativer Apps kombiniert. Dies ist für Erstanwender von großem Vorteil, da sie ohne die Installation einer Anwendung direkt im Browser darauf zugreifen können. Je mehr Benutzer mit der Zeit eine Verbindung zur Anwendung aufbauen, desto leistungsfähiger wird sie. Es wird schnell geladen, kann relevante Nachrichten auch in schwachen Netzwerkumgebungen übertragen und kann wie eine native Anwendung zum Startbildschirm hinzugefügt werden, sodass ein Surferlebnis im Vollbildmodus möglich ist.

Analyse und Beispiele der WeChat Mini-Programmarchitektur

PWA hat die folgenden Eigenschaften:

Progressive Verbesserung – Browser, die neue Funktionen unterstützen, erhalten ein besseres Erlebnis, und Browser, die diese nicht unterstützen, behalten das Original bei Erfahrung.

Offline-Zugriff – Servicemitarbeiter können offline oder in Umgebungen mit schlechter Netzwerkgeschwindigkeit arbeiten.

Native-ähnliche Anwendung – Verwenden Sie das App-Shell-Modell, um ein natives, anwendungsähnliches Erlebnis zu erzielen.

Installierbar – Ermöglicht Benutzern, für sie nützliche Apps auf ihrem Startbildschirm zu behalten, ohne den App Store zu durchlaufen.

Einfach zu teilen – Apps können einfach per URL geteilt werden.

Kontinuierliche Updates – Dank des Update-Prozesses des Servicemitarbeiters kann die Anwendung immer auf dem neuesten Stand bleiben.

Sicherheit – Stellen Sie Dienste über HTTPS bereit, um Netzwerkschnüffeln zu verhindern und sicherzustellen, dass Inhalte nicht manipuliert werden.

Durchsuchbar – Ermöglicht Suchmaschinen das Auffinden von Webanwendungen dank W3C-Manifest-Metadaten und Service-Worker-Registrierung.

Erneut besuchen – Erleichtern Sie Benutzern den erneuten Besuch durch Funktionen wie Nachrichten-Push.

Web App Manifest macht das Web nativer (Standardkonfiguration, Vollbildeinstellungen usw.).

Analyse und Beispiele der WeChat Mini-ProgrammarchitekturService Worker verbessern die Webfunktionen

Offline-Caching und Aktualisierung von Ressourcen durch Service Works

Analyse und Beispiele der WeChat Mini-Programmarchitektur

App Shell verbessert die Anzeigeeffizienz

App Shell (Anwendungsshell) ist das grundlegendste HTML, CSS und JavaScript, das für die Benutzeroberfläche der Anwendung erforderlich ist, unmittelbar nach dem Erster Ladevorgang Es wird zwischengespeichert und muss nicht bei jeder Verwendung heruntergeladen werden. Stattdessen werden nur die erforderlichen Daten asynchron geladen, um die Lokalisierung der Benutzeroberfläche zu gewährleisten.

Analyse und Beispiele der WeChat Mini-Programmarchitektur

Eine Todos-App, die auf der Grundlage des Miniprogramm-Frameworks entwickelt wurde

Im Folgenden finden Sie eine Einführung in die wichtigsten Punkte dieser App-Entwicklung :

1. Die Verzeichnisstruktur und Konfiguration dieser App werden nicht im Detail im Abschnitt „Dokument-Framework“ beschrieben. Auf dieser Plattform gibt es kein HTML und CSS, sie werden durch WXML und WXSS ersetzt. Es gibt fast keinen Unterschied zwischen WXSS und CSS. Der Nachteil besteht darin, dass es nicht so leistungsfähig ist wie CSS und nur begrenzte Selektoren unterstützt. Der Vorteil besteht jedoch darin, dass es aufgrund der Tatsache, dass es nur eine Plattform, WeChat, gibt, nahezu keine Kompatibilitätsprobleme gibt und Sie Standard- und aktualisierte CSS-Technologie verwenden können. Nur die von der Plattform bereitgestellten Tags können in wxml verwendet werden. Beispiele für die Verwendung der einzelnen Komponenten in wxml finden Sie im Abschnitt „Dokument – ​​Komponenten“. Tatsächlich gibt es also kein Problem beim Schreiben von wxml und wxss.

2. wxml unterstützt die folgenden Funktionen:

Mit Ausnahme von Vorlagen und Referenzen werden alle anderen in der Todo-App verwendet, die Details der einzelnen Funktionen werden jedoch nicht verwendet, sondern nur die entsprechenden Funktionen entsprechend den Bedürfnissen der App. Ich habe vor ein paar Tagen einen Artikel gesehen, in dem stand, dass das WeChat-Applet möglicherweise auf Basis des Vue-Frameworks implementiert werden könnte, also habe ich einen Blick auf die Vue-Dokumentation geworfen. Für Datenbindung, bedingtes Rendern, Listenrendering und Ereignisse haben wir uns die Verwendung von Vue im Detail angesehen. Im Vergleich dazu sind die von wxml bereitgestellten Funktionen den verwandten Funktionen von Vue ziemlich ähnlich, es gibt jedoch nicht so viele Funktionen, sodass es nicht einfach ist, die Funktionen des Vue-Frameworks direkt in kleinen Programmen zu verwenden. Die beste Vorgehensweise basiert immer noch auf den Anweisungen in den offiziellen Dokumenten. Wenn die Funktionen nicht in den offiziellen Dokumenten erwähnt werden, wird es definitiv nicht funktionieren, wenn Sie sie nur erraten. Ich habe die Prototypen einiger Objekte durch Drucken überprüft und nicht mehr Instanzmethoden als in den offiziellen Dokumenten gefunden, was zeigt, dass die Rahmenfunktion des Miniprogramms tatsächlich begrenzt ist.

3. Wxss kann tatsächlich in Less oder Sass geschrieben werden, solange der Selektor die Anforderungen des Frameworks erfüllt. Aus Zeitgründen habe ich es nicht in dieser App ausprobiert.

4. Keine Zwei-Wege-Bindung. In Vue ist eine Vue-Instanz ein Ansichtsmodell. Aktualisierungen der Daten in der Ansichtsebene werden in Echtzeit an das Modell zurückgegeben. Im Miniprogramm gibt es keine bidirektionale Bindung und die Aktualisierung der Ansicht wird nicht direkt mit dem Modell synchronisiert. Sie müssen die Daten direkt aus der Ansichtsebene im entsprechenden Ereignisrückruf abrufen und dann das Modell aktualisieren über setData. Das Miniprogramm verwendet dann intern setData. Für ein einzelnes Aufgabenelement lautet die Umschaltoperation beispielsweise:

toggleTodo: function( e ) {
 
 var id = this.getTodoId( e, 'todo-item-chk-' );
 var value = e.detail.value[ 0 ];
 var complete = !!value;
 var todo = this.getTodo( id );
 
 todo.complete = complete;
 this.updateData( true );
 this.updateStorage();
},

Im obigen Code wird der Wert des Kontrollkästchens in einem einzelnen Aufgabenelement über e.detail.value[0] abgerufen. und der vollständige Status der Aufgabe wird anhand dieses Werts beurteilt. Schließlich wird innerhalb von updateData der Inhalt des Modells über die setData-Methode aktualisiert. Nur so werden die Statistiken am unteren Rand der App nach dem Umschaltvorgang aktualisiert.

5. Bei der Ereignisbindung können keine Parameter übergeben werden, sondern nur ein Ereignis. Im obigen Umschaltvorgang wollte ich beispielsweise eigentlich die ID der aktuellen Aufgabe an den Rückruf übergeben, konnte dies jedoch nicht auf jede erdenkliche Weise tun. Am Ende konnte ich es nur über die ID-Methode handhaben: Bindung Fügen Sie in der Komponente des Ereignisses eine ID hinzu. Diese ID kann nicht auf der gesamten Seite wiederholt werden. Daher muss der ID ein Präfix vorangestellt werden. Fügen Sie dann den Todo-ID-Wert am Ende der ID hinzu , kann über e.currentTarget.id abgerufen werden. Entfernen Sie für die ID der Komponente das entsprechende ID-Präfix, um den ID-Wert der Aufgabe zu erhalten. Dies ist eine derzeit verwendete Methode, die meiner Meinung nach nicht sehr elegant ist. Ich hoffe, dass ich später einen besseren Weg finden kann, sie umzusetzen.

Analyse und Beispiele der WeChat Mini-Programmarchitektur

6. Der Ladeeffekt wird in der App berücksichtigt, was durch die Verwendung des Ladeattributs der Schaltflächenkomponente erreicht werden muss. Beim Laden handelt es sich jedoch nur um ein Stilsteuerelement. Es steuert nicht, ob die Schaltfläche wiederholt angeklickt werden kann. Daher müssen wir auch das Attribut „disabled“ der Schaltfläche verwenden, um wiederholte Klicks zu verhindern.

Die restlichen Implementierungsdetails finden Sie im Quellcode der folgenden beiden Dateien. Gerne können Sie auf die Probleme hinweisen.

Quellcode von index.wxml:

<!--list.wxml-->
<view class="container">
 <view class="app-hd">
  <view class="fx1">
   <input class="new-todo-input" value="{{newTodoText}}" auto-focus bindinput="newTodoTextInput"/>
  </view>
  <button type="primary" size="mini" bindtap="addOne" loading="{{addOneLoading}}" disabled="{{addOneLoading}}">
  + Add
  </button>
 </view>
 <view class="todos-list" >
  <view class="todo-item {{index == 0 ? &#39;&#39; : &#39;todo-item-not-first&#39;}} {{todo.complete ? &#39;todo-item-complete&#39; : &#39;&#39;}}" wx:for="{{todos}}" wx:for-item="todo">
   <view wx-if="{{!todo.editing}}">
    <checkbox-group id="todo-item-chk-{{todo.id}}" bindchange="toggleTodo">
     <label class="checkbox">
      <checkbox value="1" checked="{{todo.complete}}"/>
     </label>
    </checkbox-group>
   </view>
   <view id="todo-item-txt-{{todo.id}}" class="todo-text" wx-if="{{!todo.editing}}" bindlongtap="startEdit">
    <text>{{todo.text}}</text>
   </view>
   <view wx-if="{{!todo.editing}}">
    <button id="btn-del-item-{{todo.id}}" bindtap="clearSingle" type="warn" size="mini" loading="{{todo.loading}}" disabled="{{todo.loading}}">
     Clear
    </button>
   </view>
   <input id="todo-item-edit-{{todo.id}}" class="todo-text-input" value="{{todo.text}}" auto-focus bindblur="endEditTodo" wx-if="{{todo.editing}}"/>
  </view>
 </view>
 <view class="app-ft" wx:if="{{todos.length > 0}}">
  <view class="fx1">
   <checkbox-group bindchange="toggleAll">
    <label class="checkbox">
     <checkbox value="1" checked="{{todosOfUncomplted.length == 0}}"/>
    </label>
   </checkbox-group>
   <text>{{todosOfUncomplted.length}} left.</text>
  </view>
  <view wx:if="{{todosOfComplted.length > 0}}">
   <button type="warn" size="mini" bindtap="clearAll" loading="{{clearAllLoading}}" disabled="{{clearAllLoading}}">
    Clear {{todosOfComplted.length}} of done.
   </button>
  </view>
 </view>
 <loading hidden="{{loadingHidden}}" bindchange="loadingChange">
  {{loadingText}}
 </loading>
 <toast hidden="{{toastHidden}}" bindchange="toastChange">
  {{toastText}}
 </toast>
</view>

Quellcode von index.js:

var app = getApp();
 
Page( {
 data: {
  todos: [],
  todosOfUncomplted: [],
  todosOfComplted: [],
  newTodoText: &#39;&#39;,
  addOneLoading: false,
  loadingHidden: true,
  loadingText: &#39;&#39;,
  toastHidden: true,
  toastText: &#39;&#39;,
  clearAllLoading: false
 },
 updateData: function( resetTodos ) {
  var data = {};
  if( resetTodos ) {
   data.todos = this.data.todos;
  }
 
  data.todosOfUncomplted = this.data.todos.filter( function( t ) {
   return !t.complete;
  });
 
  data.todosOfComplted = this.data.todos.filter( function( t ) {
   return t.complete;
  });
 
  this.setData( data );
 },
 updateStorage: function() {
  var storage = [];
  this.data.todos.forEach( function( t ) {
   storage.push( {
    id: t.id,
    text: t.text,
    complete: t.complete
   })
  });
 
  wx.setStorageSync( &#39;todos&#39;, storage );
 },
 onLoad: function() {
  this.setData( {
   todos: wx.getStorageSync( &#39;todos&#39; ) || []
  });
  this.updateData( false );
 },
 getTodo: function( id ) {
  return this.data.todos.filter( function( t ) {
   return id == t.id;
  })[ 0 ];
 },
 getTodoId: function( e, prefix ) {
  return e.currentTarget.id.substring( prefix.length );
 },
 toggleTodo: function( e ) {
 
  var id = this.getTodoId( e, &#39;todo-item-chk-&#39; );
  var value = e.detail.value[ 0 ];
  var complete = !!value;
  var todo = this.getTodo( id );
 
  todo.complete = complete;
  this.updateData( true );
  this.updateStorage();
 },
 toggleAll: function( e ) {
  var value = e.detail.value[ 0 ];
  var complete = !!value;
 
  this.data.todos.forEach( function( t ) {
   t.complete = complete;
  });
 
  this.updateData( true );
  this.updateStorage();
 
 },
 clearTodo: function( id ) {
  var targetIndex;
  this.data.todos.forEach( function( t, i ) {
   if( targetIndex !== undefined ) return;
 
   if( t.id == id ) {
    targetIndex = i;
   }
  });
 
  this.data.todos.splice( targetIndex, 1 );
 },
 clearSingle: function( e ) {
  var id = this.getTodoId( e, &#39;btn-del-item-&#39; );
  var todo = this.getTodo( id );
 
  todo.loading = true;
  this.updateData( true );
 
  var that = this;
  setTimeout( function() {
   that.clearTodo( id );
   that.updateData( true );
   that.updateStorage();
  }, 500 );
 },
 clearAll: function() {
  this.setData( {
   clearAllLoading: true
  });
 
  var that = this;
  setTimeout( function() {
   that.data.todosOfComplted.forEach( function( t ) {
    that.clearTodo( t.id );
   });
   that.setData( {
    clearAllLoading: false
   });
   that.updateData( true );
   that.updateStorage();
 
   that.setData( {
    toastHidden: false,
    toastText: &#39;Success&#39;
   });
  }, 500 );
 
 },
 startEdit: function( e ) {
  var id = this.getTodoId( e, &#39;todo-item-txt-&#39; );
  var todo = this.getTodo( id );
  todo.editing = true;
 
  this.updateData( true );
  this.updateStorage();
 },
 newTodoTextInput: function( e ) {
  this.setData( {
   newTodoText: e.detail.value
  });
 },
 endEditTodo: function( e ) {
  var id = this.getTodoId( e, &#39;todo-item-edit-&#39; );
  var todo = this.getTodo( id );
 
  todo.editing = false;
  todo.text = e.detail.value;
 
  this.updateData( true );
  this.updateStorage();
 },
 addOne: function( e ) {
  if( !this.data.newTodoText ) return;
 
  this.setData( {
   addOneLoading: true
  });
 
  //open loading
  this.setData( {
   loadingHidden: false,
   loadingText: &#39;Waiting...&#39;
  });
 
  var that = this;
  setTimeout( function() {
   //close loading and toggle button loading status
   that.setData( {
    loadingHidden: true,
    addOneLoading: false,
    loadingText: &#39;&#39;
   });
 
   that.data.todos.push( {
    id: app.getId(),
    text: that.data.newTodoText,
    compelte: false
   });
 
   that.setData( {
    newTodoText: &#39;&#39;
   });
 
   that.updateData( true );
   that.updateStorage();
  }, 500 );
 },
 loadingChange: function() {
  this.setData( {
   loadingHidden: true,
   loadingText: &#39;&#39;
  });
 },
 toastChange: function() {
  this.setData( {
   toastHidden: true,
   toastText: &#39;&#39;
  });
 }
});

最后需要补充的是,这个app在有限的时间内依据微信的官方文档进行开发,所以这里面的实现方式到底是不是合理的,我也不清楚。我也仅仅是通过这个app来了解小程序这个平台的用法。希望微信官方能够推出一些更全面、最好是项目性的demo,在代码层面,给我们这些开发者提供一个最佳实践规范。欢迎有其它的开发思路的朋友,帮我指出我以上实现中的问题。

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn