亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Inhaltsverzeichnis
Lernziele
Was bauen wir?
Fauna einrichten
Generieren Sie den Administratorschlüssel
Schreiben von GraphQL -Muster
Erstellen Sie ein neues Flutter -Projekt
Einrichten des GraphQL -Clients in Flutteranwendung
Anwendungsseite
Abfragen und Mutationen ausführen
Neue Daten hinzufügen
Daten l?schen
Daten bearbeiten
Heim Web-Frontend CSS-Tutorial So erstellen Sie eine mobile Full-Stack-Anwendung mit Flutter, Fauna und GraphQL

So erstellen Sie eine mobile Full-Stack-Anwendung mit Flutter, Fauna und GraphQL

Mar 21, 2025 am 10:34 AM

So erstellen Sie eine mobile Full-Stack-Anwendung mit Flutter, Fauna und GraphQL

Flutter ist das UI-Framework von Google zum Erstellen flexibler, ausdrucksstarker plattformübergreifender mobiler Anwendungen. Es ist eines der am schnellsten wachsenden Rahmen für die Entwicklung der mobilen Anwendungen. Fauna hingegen ist eine transaktionale, entwicklerfreundliche serverlose Datenbank, die native GraphQL unterstützt. Flutter Fauna ist ein perfektes Spiel vom Himmel. Wenn Sie Funktionen in der Aufzeichnungszeit erstellen und ver?ffentlicht m?chten, sind Flutter und Fauna die richtigen Werkzeuge. In diesem Artikel führen wir Sie durch den Bau Ihrer ersten Flutter -Anwendung mit Fauna und GraphQL -Backends.

Sie finden den vollst?ndigen Code für diesen Artikel auf GitHub.

Lernziele

Nach dem Lesen dieses Artikels sollten Sie wissen, wie Sie:

  1. Richten Sie die Fauna -Instanz ein,
  2. Schreiben Sie GraphQL -Muster für Fauna,
  3. Richten Sie den GraphQL -Client in der Flutter -Anwendung ein und ein
  4. Führen Sie Abfragen und Mutationen im Fauna GraphQL -Backend aus.

Fauna vs. AWS Amplify vs. Firebase : Welche Probleme l?sen Fauna? Wie unterscheidet es sich von anderen serverlosen L?sungen? Wenn Sie mit Fauna nicht vertraut sind und mehr über Faunas Vergleich mit anderen L?sungen erfahren m?chten, schlage ich vor, dass Sie diesen Artikel lesen.

Was bauen wir?

Wir werden eine einfache mobile App erstellen, mit der Benutzer ihre bevorzugten Film- und TV -Serienfiguren hinzufügen, l?schen und aktualisieren k?nnen.

Fauna einrichten

Gehen Sie zu Fauna.com und erstellen Sie ein neues Konto. Nach dem Anmelden sollten Sie in der Lage sein, eine neue Datenbank zu erstellen.

Nennen Sie Ihre Datenbank. Ich habe meinen Flutter_Demo genannt. Als n?chstes k?nnen wir eine Regionsgruppe ausw?hlen. Für diese Demo werden wir Classic ausw?hlen. Fauna ist eine global verteilte serverlose Datenbank. Es ist die einzige Datenbank, die von überall mit dem Lese- und Schreibzugriff mit geringer Latenz unterstützt wird. Stellen Sie sich es als CDN (Content Distribution Network) vor, aber es ist für Ihre Datenbank. Um mehr über die Region -Gruppe zu erfahren, folgen Sie diesem Leitfaden.

Generieren Sie den Administratorschlüssel

Sobald die Datenbank erstellt wurde, wechseln Sie zur Registerkarte Sicherheit. Klicken Sie auf die Schaltfl?che Neue Taste und erstellen Sie einen neuen Schlüssel für Ihre Datenbank. Bitte behalten Sie diesen Schlüssel ordnungsgem??, da wir ihn für GraphQL -Operationen ben?tigen.

Wir erstellen einen Administratorschlüssel für unsere Datenbank. Ein Schlüssel mit einer Administratorrolle wird verwendet, um die zugeh?rigen Datenbanken zu verwalten, einschlie?lich Datenbankzugriffsanbietern, Subdatabasen, Dokumenten, Funktionen, Indizes, Tasten, Token und benutzerdefinierten Rollen. Weitere Informationen zu den verschiedenen Sicherheitsschlüssel von Fauna und Zugriffsrollen finden Sie in den folgenden Links.

Schreiben von GraphQL -Muster

Wir erstellen eine einfache App, mit der Benutzer ihre bevorzugten Fernsehfiguren hinzufügen, aktualisieren und l?schen k?nnen.

Erstellen Sie ein neues Flutter -Projekt

Erstellen wir ein neues Flutter -Projekt, indem wir den folgenden Befehl ausführen.

 <code>flutter create my_app</code>

Im Projektverzeichnis erstellen wir eine neue Datei namens GraphQL/Schema.Graphql.

In der Schema -Datei definieren wir die Struktur der Sammlung. Sammlungen in Fauna ?hneln den Tabellen in SQL. Wir brauchen jetzt nur einen Satz. Wir nennen es Charakter.

 <code>### schema.graphql type Character { name: String! description: String! picture: String } type Query { listAllCharacters: [Character] }</code>

Wie oben gezeigt, definieren wir einen Typ, der als Zeichen bezeichnet wird und mehrere Eigenschaften aufweist (d. H. Name, Beschreibung, Bild usw.). Eine Eigenschaft kann als Spalte einer SQL-Datenbank oder als Schlüsselwertpaar einer NoSQL-Datenbank behandelt werden. Wir definieren auch eine Frage. Diese Abfrage gibt die Rollenliste zurück.

Kehren wir jetzt zurück zum Fauna Dashboard. Klicken Sie auf GraphQL und klicken Sie auf den Modus importieren, um unseren Modus in Fauna hochzuladen.

Nach Abschluss des Imports sehen wir, dass Fauna GraphQL -Abfragen und Mutationen erzeugt.

M?gen Sie nicht die automatische Erzeugung von GraphQL? M?chten Sie eine bessere Kontrolle über Ihre Gesch?ftslogik haben? In diesem Fall k?nnen Sie mit Fauna einen benutzerdefinierten GraphQL -Parser definieren. Um mehr zu erfahren, klicken Sie auf diesen Link.

Einrichten des GraphQL -Clients in Flutteranwendung

?ffnen wir die Datei pubSpec.yaml und fügen Sie die erforderlichen Abh?ngigkeiten hinzu.

 <code>... dependencies: graphql_flutter: ^4.0.0-beta hive: ^1.3.0 flutter: sdk: flutter ...</code>

Wir haben hier zwei Abh?ngigkeiten hinzugefügt. GraphQL_FLTERTER ist die GraphQL Client -Bibliothek von Flutter. Es integriert alle modernen Funktionen des GraphQL -Clients in ein einfach zu bedienendes Paket. Wir haben das Hive -Paket auch als Abh?ngigkeit hinzugefügt. Hive ist eine leichte Schlüsselwertdatenbank, die in Pure Dart für den lokalen Speicher geschrieben wurde. Wir verwenden Hive, um unsere GraphQL -Abfragen zu speichern.

Als n?chstes erstellen wir eine neue Datei lib/client_provider.dart. Wir erstellen eine Anbieterklasse in dieser Datei, die unsere Fauna -Konfiguration enth?lt.

Um eine Verbindung zur GraphQL -API von Fauna herzustellen, müssen wir zun?chst einen GraphQLClient erstellen. GraphQLCLIENT ben?tigt einen Cache und einen Link, um initialisiert zu werden. Schauen wir uns den Code unten an.

 <code>// lib/client_provider.dart import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:flutter/material.dart'; ValueNotifier<graphqlclient> clientFor({ @required String uri, String subscriptionUri, }) { final HttpLink httpLink = HttpLink( uri, ); final AuthLink authLink = AuthLink( getToken: () async => 'Bearer fnAEPAjy8QACRJssawcwuywad2DbB6ssrsgZ2-2', ); Link link = authLink.concat(httpLink); return ValueNotifier<graphqlclient> ( GraphQLClient( cache: GraphQLCache(store: HiveStore()), link: link, ), ); }</graphqlclient></graphqlclient></code>

Im obigen Code erstellen wir einen Valuenotifier, um den GraphQLClient zu wickeln. Beachten Sie, dass wir Authlink in den Zeilen 13-15 konfiguriert haben (hervorgehoben). In Zeile 14 haben wir den Administratorschlüssel von Fauna als Teil des Tokens hinzugefügt. Hier habe ich den Administratorschlüssel fest codiert. In Produktionsanwendungen müssen wir jedoch fest codierte Sicherheitsschlüssel von Fauna vermeiden.

Es gibt verschiedene M?glichkeiten, Schlüssel in einer Flutteranwendung zu speichern. Bitte überprüfen Sie diesen Blog als Referenz.

Wir m?chten in der Lage sein, Abfragen und Mutation von jedem Widget in der Anwendung aufzurufen. Dazu müssen wir unser Widget mit dem GraphQLProvider -Widget einwickeln.

 <code>// lib/client_provider.dart .... /// 使用`graphql_flutter`客戶端包裝根應用程序。 /// 我們使用緩存進行所有狀態(tài)管理。 class ClientProvider extends StatelessWidget { ClientProvider({ @required this.child, @required String uri, }) : client = clientFor( uri: uri, ); final Widget child; final ValueNotifier<graphqlclient> client; @override Widget build(BuildContext context) { return GraphQLProvider( client: client, child: child, ); } }</graphqlclient></code>

Als n?chstes gehen wir zur Main.Dart -Datei und wickeln unser Haupt -Widget mit dem ClientProvider -Widget ein. Schauen wir uns den Code unten an.

 <code>// lib/main.dart ... void main() async { await initHiveForFlutter(); runApp(MyApp()); } final graphqlEndpoint = 'https://graphql.fauna.com/graphql'; class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ClientProvider( uri: graphqlEndpoint, child: MaterialApp( title: 'My Character App', debugShowCheckedModeBanner: false, initialRoute: '/', routes: { '/': (_) => AllCharacters(), '/new': (_) => NewCharacter(), } ), ); } }</code>

Zu diesem Zeitpunkt k?nnen alle unsere nachgeschalteten Widgets Abfragen und Mutationenfunktionen ausführen und mit der GraphQL -API interagieren.

Anwendungsseite

Die Demo -Anwendung sollte einfach und leicht zu verstehen sein. Lassen Sie uns ein einfaches Listen -Widget erstellen, das eine Liste aller Rollen anzeigt. Erstellen wir eine neue Datei lib/screens/charakterlist.dart. In dieser Datei werden wir ein neues Widget namens AllCharacters schreiben.

 <code>// lib/screens/character-list.dart.dart class AllCharacters extends StatelessWidget { const AllCharacters({Key key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: [ SliverAppBar( pinned: true, snap: false, floating: true, expandedHeight: 160.0, title: Text( 'Characters', style: TextStyle( fontWeight: FontWeight.w400, fontSize: 36, ), ), actions:<widget> [ IconButton( padding: EdgeInsets.all(5), icon: const Icon(Icons.add_circle), tooltip: 'Add new entry', onPressed: () { Navigator.pushNamed(context, '/new'); }, ), ], ), SliverList( delegate: SliverChildListDelegate([ Column( children: [ for (var i = 0; i _CharacterTileeState(); } class _CharacterTileState extends State<charactertile> { @override Widget build(BuildContext context) { return Container( child: Text("Character Tile"), ); } }</charactertile></widget></code>

Wie im obigen Code gezeigt, haben wir eine für Schleife, die die Liste mit einigen gef?lschten Daten füllt. Schlie?lich werden wir GraphQL -Abfragen im Fauna -Backend durchführen und alle Rollen aus der Datenbank erhalten. Bevor wir dies tun, versuchen wir, unsere Bewerbung auszuführen. Wir k?nnen unsere Anwendung über den folgenden Befehl ausführen

 <code>flutter run</code>

Zu diesem Zeitpunkt sollten wir in der Lage sein, den folgenden Bildschirm zu sehen.

Abfragen und Mutationen ausführen

Jetzt haben wir einige grundlegende Widgets, die wir weiterhin zu GraphQL -Abfragen herstellen k?nnen. Wir m?chten alle Rollen aus der Datenbank anstelle von festcodierten Zeichenfolgen erhalten und sie im AllCharacters -Widget anzeigen.

Kehren wir zu Faunas GraphQL -Spielplatz zurück. Beachten Sie, dass wir die folgende Abfrage ausführen k?nnen, um alle Rollen aufzulisten.

 <code>query ListAllCharacters { listAllCharacters(_size: 100) { data { _id name description picture } after } }</code>

Um diese Abfrage aus unserem Widget auszuführen, müssen wir einige ?nderungen daran vornehmen.

 <code>import 'package:flutter/material.dart'; import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:todo_app/screens/Character-tile.dart'; String readCharacters = ";";"; query ListAllCharacters { listAllCharacters(_size: 100) { data { _id name description picture } after } } ";";";; class AllCharacters extends StatelessWidget { const AllCharacters({Key key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: [ SliverAppBar( pinned: true, snap: false, floating: true, expandedHeight: 160.0, title: Text( 'Characters', style: TextStyle( fontWeight: FontWeight.w400, fontSize: 36, ), ), actions:<widget> [ IconButton( padding: EdgeInsets.all(5), icon: const Icon(Icons.add_circle), tooltip: 'Add new entry', onPressed: () { Navigator.pushNamed(context, '/new'); }, ), ], ), SliverList( delegate: SliverChildListDelegate([ Query(options: QueryOptions( document: gql(readCharacters), // 我們要執(zhí)行的graphql查詢pollInterval: Duration(seconds: 120), // 重新獲取間隔), builder: (QueryResult result, { VoidCallback refetch, FetchMore fetchMore }) { if (result.isLoading) { return Text('Loading'); } return Column( children: [ for (var item in result.data\['listAllCharacters'\]['data']) CharacterTile(Character: item, refetch: refetch), ], ); }) ]) ) ], ), ); } }</widget></code>

Zun?chst definieren wir die Abfragezeichenfolge, um alle Rollen aus der Datenbank zu erhalten [Zeilen 5 bis 17]. Wir wickeln das List -Widget mit dem Abfrage -Widget in flutter_graphql ein.

Sehen Sie sich die offizielle Dokumentation der Flutter_Graphql -Bibliothek an.

Im Parameter der Abfragem?glichkeiten stellen wir die GraphQL -Abfrage -Zeichenfolge selbst an. Wir k?nnen jede schwimmende Punktzahl für den Pollinterval -Parameter übergeben. Das Umfrageintervall definiert, wie lange wir Daten aus dem Backend neutieren m?chten. Das Widget hat auch eine Standard -Builder -Funktion. Wir k?nnen die Builder-Funktion verwenden, um Abfragergebnisse zu übergeben, Rückruffunktionen wiederzugeben und mehr Rückruffunktionen in den Widget-Baum zu erhalten.

Als n?chstes werde ich das Charakter -Widget aktualisieren, um die Zeichendaten auf dem Bildschirm anzuzeigen.

 <code>// lib/screens/character-tile.dart ... class CharacterTile extends StatelessWidget { final Character; final VoidCallback refetch; final VoidCallback updateParent; const CharacterTile({ Key key, @required this.Character, @required this.refetch, this.updateParent, }) : super(key: key); @override Widget build(BuildContext context) { return InkWell( onTap: () { }, child: Padding( padding: const EdgeInsets.all(10), child: Row( children: [ Container( height: 90, width: 90, decoration: BoxDecoration( color: Colors.amber, borderRadius: BorderRadius.circular(15), image: DecorationImage( fit: BoxFit.cover, image: NetworkImage(Character['picture']) ) ), ), SizedBox(width: 10), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( Character['name'], style: TextStyle( color: Colors.black87, fontWeight: FontWeight.bold, ), ), SizedBox(height: 5), Text( Character['description'], style: TextStyle( color: Colors.black87, ), maxLines: 2, ), ], ) ) ], ), ), ); } }</code>

Neue Daten hinzufügen

Wir k?nnen unserer Datenbank neue Rollen hinzufügen, indem wir die folgende Mutation ausführen.

 <code>mutation CreateNewCharacter($data: CharacterInput!) { createCharacter(data: $data) { _id name description picture } }</code>

Um diese Mutation aus unserem Widget auszuführen, müssen wir das Mutations -Widget aus der Flutter_Graphql -Bibliothek verwenden. Erstellen wir ein neues Widget mit einem einfachen Formular, in dem Benutzer interagieren und Daten eingeben k?nnen. Nach der Einreichung des Formulars wird die Createcharacter -Mutation aufgerufen.

 <code>// lib/screens/new.dart ... String addCharacter = ";";"; mutation CreateNewCharacter(\$data: CharacterInput!) { createCharacter(data: \$data) { _id name description picture } } ";";";; class NewCharacter extends StatelessWidget { const NewCharacter({Key key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Add New Character'), ), body: AddCharacterForm() ); } } class AddCharacterForm extends StatefulWidget { AddCharacterForm({Key key}) : super(key: key); @override _AddCharacterFormState createState() => _AddCharacterFormState(); } class _AddCharacterFormState extends State<addcharacterform> { String name; String description; String imgUrl; @override Widget build(BuildContext context) { return Form( child: Padding( padding: EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TextField( decoration: const InputDecoration( icon: Icon(Icons.person), labelText: 'Name *', ), onChanged: (text) { name = text; }, ), TextField( decoration: const InputDecoration( icon: Icon(Icons.post_add), labelText: 'Description', ), minLines: 4, maxLines: 4, onChanged: (text) { description = text; }, ), TextField( decoration: const InputDecoration( icon: Icon(Icons.image), labelText: 'Image Url', ), onChanged: (text) { imgUrl = text; }, ), SizedBox(height: 20), Mutation( options: MutationOptions( document: gql(addCharacter), onCompleted: (dynamic resultData) { print(resultData); name = ''; description = ''; imgUrl = ''; Navigator.of(context).push( MaterialPageRoute(builder: (context) => AllCharacters()) ); }, ), builder: ( RunMutation runMutation, QueryResult result, ) { return Center( child: ElevatedButton( child: const Text('Submit'), onPressed: () { runMutation({ 'data': { ";picture";: imgUrl, ";name";: name, ";description";: description, } }); }, ), ); } ) ], ), ), ); } }</addcharacterform></code>

Wie aus dem obigen Code ersichtlich ist, funktioniert das Mutations -Widget sehr ?hnlich wie das Abfrage -Widget. Darüber hinaus bietet uns das Mutations -Widget eine OnComplete -Funktion. Diese Funktion gibt das Update -Ergebnis in der Datenbank zurück, nachdem die Mutation abgeschlossen ist.

Daten l?schen

Wir k?nnen Rollen aus der Datenbank l?schen, indem wir die Deletecharacter -Mutation ausführen. Wir k?nnen diese Mutante zu unserem Charakter hinzufügen und sie ausl?sen, wenn die Taste gedrückt wird.

 <code>// lib/screens/character-tile.dart ... String deleteCharacter = ";";"; mutation DeleteCharacter(\$id: ID!) { deleteCharacter(id: \$id) { _id name } } ";";";; class CharacterTile extends StatelessWidget { final Character; final VoidCallback refetch; final VoidCallback updateParent; const CharacterTile({ Key key, @required this.Character, @required this.refetch, this.updateParent, }) : super(key: key); @override Widget build(BuildContext context) { return InkWell( onTap: () { showModalBottomSheet( context: context, builder: (BuildContext context) { print(Character['picture']); return Mutation( options: MutationOptions( document: gql(deleteCharacter), onCompleted: (dynamic resultData) { print(resultData); this.refetch(); }, ), builder: ( RunMutation runMutation, QueryResult result, ) { return Container( height: 400, padding: EdgeInsets.all(30), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children:<widget> [ Text(Character['description']), ElevatedButton( child: Text('Delete Character'), onPressed: () { runMutation({ 'id': Character['_id'], }); Navigator.pop(context); }, ), ], ), ), ); } ); } ); }, child: Padding( padding: const EdgeInsets.all(10), child: Row( children: [ Container( height: 90, width: 90, decoration: BoxDecoration( color: Colors.amber, borderRadius: BorderRadius.circular(15), image: DecorationImage( fit: BoxFit.cover, image: NetworkImage(Character['picture']) ) ), ), SizedBox(width: 10), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( Character['name'], style: TextStyle( color: Colors.black87, fontWeight: FontWeight.bold, ), ), SizedBox(height: 5), Text( Character['description'], style: TextStyle( color: Colors.black87, ), maxLines: 2, ), ], ) ) ], ), ), ); } }</widget></code>

Daten bearbeiten

Das Bearbeiten von Daten entspricht dem Hinzufügen und L?schen. Es ist nur eine weitere Mutation in der GraphQL -API. Wir k?nnen ein Widget für das Rollenformular für Bearbeitungsformular erstellen, das dem neuen Rollenform -Widget ?hnelt. Der einzige Unterschied besteht darin, dass die Bearbeitung des Formulars die UpdateCharacter -Mutation ausführt. Zur Bearbeitung habe ich ein neues Widget Lib/Screens/edit.dart erstellt. Hier ist der Code für dieses Widget.

 <code>// lib/screens/edit.dart String editCharacter = """ mutation EditCharacter(\$name: String!, \$id: ID!, \$description: String!, \$picture: String!) { updateCharacter(data: { name: \$name description: \$description picture: \$picture }, id: \$id) { _id name description picture } } """; class EditCharacter extends StatelessWidget { final Character; const EditCharacter({Key key, this.Character}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Edit Character'), ), body: EditFormBody(Character: this.Character), ); } } class EditFormBody extends StatefulWidget { final Character; EditFormBody({Key key, this.Character}) : super(key: key); @override _EditFormBodyState createState() => _EditFormBodyState(); } class _EditFormBodyState extends State<editformbody> { String name; String description; String picture; @override Widget build(BuildContext context) { return Container( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TextFormField( initialValue: widget.Character['name'], decoration: const InputDecoration( icon: Icon(Icons.person), labelText: 'Name *', ), onChanged: (text) { name = text; } ), TextFormField( initialValue: widget.Character['description'], decoration: const InputDecoration( icon: Icon(Icons.person), labelText: 'Description', ), minLines: 4, maxLines: 4, onChanged: (text) { description = text; } ), TextFormField( initialValue: widget.Character['picture'], decoration: const InputDecoration( icon: Icon(Icons.image), labelText: 'Image Url', ), onChanged: (text) { picture = text; }, ), SizedBox(height: 20), Mutation( options: MutationOptions( document: gql(editCharacter), onCompleted: (dynamic resultData) { print(resultData); Navigator.of(context).push( MaterialPageRoute(builder: (context) => AllCharacters()) ); }, ), builder: ( RunMutation runMutation, QueryResult result, ) { print(result); return Center( child: ElevatedButton( child: const Text('Submit'), onPressed: () { runMutation({ 'id': widget.Character['_id'], 'name': name != null ? name : widget.Character['name'], 'description': description != null ? description : widget.Character['description'], 'picture': picture != null ? picture : widget.Character['picture'], }); }, ), ); } ), ] ) ), ); } }</editformbody></code>

Sie k?nnen den vollst?ndigen Code dieses Artikels wie folgt anzeigen.

Fragen zu Fauna oder Flattern haben? Sie k?nnen mich auf Twitter @Haqueshadid kontaktieren

Github ### N?chste Schritte

Der Hauptzweck dieses Artikels ist es, Sie mit Flutter und Fauna zu beginnen. Wir berühren hier nur die Oberfl?che. Das Fauna-?kosystem bietet Ihrer mobilen Anwendung ein komplettes, automatisches, Entwickler-freundlicher Backend als Service. Wenn Ihr Ziel darin besteht, eine plattformübergreifende mobile App zu ver?ffentlichen, die für die Produktion in Rekordzeit verwendet werden kann, probieren Sie Fauna und Flattern .

Ich empfehle Ihnen dringend, die offizielle Dokumentations -Website von Fauna zu lesen. Wenn Sie mehr über den GraphQL -Client von Dart/Flutter erfahren m?chten, lesen Sie das offizielle Github -Repository von GraphQL_FLTERT.

Ich wünsche Ihnen ein glückliches Programmieren, wir sehen uns beim n?chsten Mal.

Das obige ist der detaillierte Inhalt vonSo erstellen Sie eine mobile Full-Stack-Anwendung mit Flutter, Fauna und GraphQL. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erkl?rung dieser Website
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

Hei?e KI -Werkzeuge

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem v?llig kostenlosen KI-Gesichtstausch-Tool aus!

Hei?e Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Hei?e Themen

PHP-Tutorial
1488
72
CSS -Tutorial zum Erstellen von Ladespinner und Animationen CSS -Tutorial zum Erstellen von Ladespinner und Animationen Jul 07, 2025 am 12:07 AM

Es gibt drei M?glichkeiten, einen CSS -Laderotator zu erstellen: 1. Verwenden Sie den Basisrotator der Grenzen, um eine einfache Animation durch HTML und CSS zu erreichen. 2. Verwenden Sie einen benutzerdefinierten Rotator mit mehreren Punkten, um den Sprungeffekt durch verschiedene Verz?gerungszeiten zu erreichen. 3. Fügen Sie einen Rotator in die Taste hinzu und wechseln Sie den Klassen über JavaScript, um den Ladestatus anzuzeigen. Jeder Ansatz betont die Bedeutung von Entwurfsdetails wie Farbe, Gr??e, Zug?nglichkeit und Leistungsoptimierung, um die Benutzererfahrung zu verbessern.

Behandeln Sie Probleme und Pr?fixe von CSS -Browser -Kompatibilit?t und Pr?fixe Behandeln Sie Probleme und Pr?fixe von CSS -Browser -Kompatibilit?t und Pr?fixe Jul 07, 2025 am 01:44 AM

Um mit CSS -Browser -Kompatibilit?t und Pr?fixproblemen umzugehen, müssen Sie die Unterschiede im Browser -Support verstehen und Anbieterpr?fixe vernünftigerweise verwenden. 1. Verstehen Sie gemeinsame Probleme wie Flexbox und Grid -Unterstützung, Position: Sticky Invaly und Animationsleistung ist unterschiedlich. 2. überprüfen Sie den Best?tigungsunterstützungsstatus von Caniuse. 3. Verwenden Sie korrekt -webkit-, -moz-, -ms-, -o- und andere Herstellerpr?fixe; 4. Es wird empfohlen, Autoprefixer zu verwenden, um automatisch Pr?fixe hinzuzufügen. 5. Postcss installieren und Browserlist konfigurieren, um den Zielbrowser anzugeben. 6. automatisch die Kompatibilit?t w?hrend des Baus bew?ltigen; 7. Modernizr -Erkennungsmerkmale k?nnen für alte Projekte verwendet werden; 8. Keine Notwendigkeit, die Konsistenz aller Browser zu verfolgen,

Erstellen von benutzerdefinierten Formen mit CSS-Clip-Pfad Erstellen von benutzerdefinierten Formen mit CSS-Clip-Pfad Jul 09, 2025 am 01:29 AM

Verwenden Sie das Clip-Pfad-Attribut von CSS, um Elemente in benutzerdefinierte Formen wie Dreiecke, kreisf?rmige Kerben, Polygone usw. zu erregen, ohne sich auf Bilder oder SVGs zu verlassen. Zu den Vorteilen geh?ren: 1.. Unterstützt eine Vielzahl von Grundformen wie Circle, Ellipse, Polygon usw.; 2. reagierende Anpassung und anpassbar an mobile Terminals; 3. Einfach zu animation und kann mit Hover oder JavaScript kombiniert werden, um dynamische Effekte zu erzielen. 4. Es wirkt sich nicht auf den Layoutfluss aus und erfüllt nur den Anzeigebereich. H?ufige Verwendungen sind z. B. kreisf?rmiger Clip-Pfad: Kreis (50pxatcenter) und Dreieck-Clip-Pfad: Polygon (50%0%, 100 0%, 0 0%). Beachten

Was ist der Unterschied zwischen Anzeige: Inline, Anzeige: Block und Anzeige: Inline-Block? Was ist der Unterschied zwischen Anzeige: Inline, Anzeige: Block und Anzeige: Inline-Block? Jul 11, 2025 am 03:25 AM

ThemaNDiffercesbetweenplay: Inline, Block, Andinline-Blockinhtml/CsSarelayoutBehavior, Spaceusage und Stylingcontrol.1.inlineelementsflowwithtext, Don'tstartonNewlines, Ignorewidth/HeighthThorchingstyhorching-/idelthorchorching/ardaldhordhortaliTalding/ardaldhordelthortex

Das Styling besuchte Links unterschiedlich mit CSS Das Styling besuchte Links unterschiedlich mit CSS Jul 11, 2025 am 03:26 AM

Durch das Festlegen des von Ihnen besuchten Links k?nnen Sie die Benutzererfahrung verbessern, insbesondere in inhaltsintensiven Websites, um den Benutzern dabei zu helfen, sich besser zu navigieren. 1. Verwenden Sie CSS: Besuchte Pseudoklasse, um den Stil des besuchten Links wie Farb?nderungen zu definieren. 2. Beachten Sie, dass der Browser nur eine ?nderung einiger Attribute aufgrund von Datenschutzbeschr?nkungen erm?glicht. 3. Die Farbauswahl sollte mit dem Gesamtstil koordiniert werden, um abrupte abrupt zu werden. 4. Das mobile Terminal zeigt diesen Effekt m?glicherweise nicht an. Es wird empfohlen, ihn mit anderen visuellen Eingabeaufforderungen wie Icon -Auxiliary -Logos zu kombinieren.

Wie erstelle ich reaktionsschnelle Bilder mit CSS? Wie erstelle ich reaktionsschnelle Bilder mit CSS? Jul 15, 2025 am 01:10 AM

Um reaktionsschnelle Bilder mit CSS zu erstellen, kann es haupts?chlich durch die folgenden Methoden erreicht werden: 1. Verwenden Sie maximale Breite: 100% und H?he: Auto, damit das Bild an die Containerbreite anpasst und gleichzeitig den Anteil beibeh?lt. 2. Verwenden Sie die SRCSet- und Gr??enattribute von HTML, um die an verschiedenen Bildschirme angepassten Bildquellen intelligent zu laden. 3.. Verwenden Sie Objektfit und Objektposition, um die Bildaufbindung und Fokusanzeige zu steuern. Gemeinsam stellen diese Methoden sicher, dass die Bilder auf verschiedenen Ger?ten klar und wundersch?n pr?sentiert werden.

Entmystifizierende CSS -Einheiten: PX, EM, REM, VW, VH -Vergleiche Entmystifizierende CSS -Einheiten: PX, EM, REM, VW, VH -Vergleiche Jul 08, 2025 am 02:16 AM

Die Auswahl der CSS -Einheiten h?ngt von den Entwurfsanforderungen und den reaktionsschnellen Anforderungen ab. 1.PX wird für die feste Gr??e verwendet, geeignet für eine pr?zise Kontrolle, aber mangelnde Elastizit?t; 2.Em ist eine relative Einheit, die leicht durch den Einfluss des übergeordneten Elements verursacht wird, w?hrend REM basierend auf dem Wurzelelement stabiler ist und für die globale Skalierung geeignet ist. 3.VW/VH basiert auf der Ansichtsfenstergr??e, die für das reaktionsschnelle Design geeignet ist. Die Leistung unter extremen Bildschirmen sollte jedoch Aufmerksamkeit geschenkt werden. 4. Bei der Auswahl sollte es ermittelt werden, ob reaktionsschnelle Anpassungen, Elementhierarchiebeziehungen und Ansichtsfensterabh?ngigkeit festgelegt werden. Angemessener Gebrauch kann die Layoutflexibilit?t und -wartung verbessern.

Was sind gemeinsame Inkonsistenzen von CSS -Browser? Was sind gemeinsame Inkonsistenzen von CSS -Browser? Jul 26, 2025 am 07:04 AM

Verschiedene Browser weisen Unterschiede in der CSS -Analyse auf, was zu inkonsistenten Anzeigeeffekten führt, haupts?chlich die Differenzentscheidung, die Berechnung des Boxmodells, die Flexbox- und Raster -Layout -Unterstützung und das inkonsistente Verhalten bestimmter CSS -Attribute. 1. Die Standardstilverarbeitung ist inkonsistent. Die L?sung besteht darin, CSSReset oder Normalize.css zu verwenden, um den anf?nglichen Stil zu vereinen. 2. Die Box -Modellberechnung der alten Version von IE ist unterschiedlich. Es wird empfohlen, eine einheitliche Boxgr??e: Border-Box zu verwenden. 3. Flexbox und Grid führen in Kantenf?llen oder in alten Versionen unterschiedlich ab. Weitere Tests und verwenden Sie Autoprefixer; 4. Einige CSS -Attributverhalten sind inkonsistent. Caniuse muss konsultiert und herabgestuft werden.

See all articles