目次
学習目標
私たちは何を作っていますか?
動物相をセットアップします
管理者キーを生成します
GraphQLパターンの書き込み
新しいフラッタープロジェクトを作成します
フラッターアプリケーションでGraphQLクライアントのセットアップ
アプリケーションページ
クエリと突然変異を実行します
新しいデータを追加します
データを削除します
データを編集します
ホームページ ウェブフロントエンド CSSチュートリアル Flutter、Fauna、およびGraphQLを使用してフルスタックモバイルアプリケーションを構築する方法

Flutter、Fauna、およびGraphQLを使用してフルスタックモバイルアプリケーションを構築する方法

Mar 21, 2025 am 10:34 AM

Flutter、Fauna、およびGraphQLを使用してフルスタックモバイルアプリケーションを構築する方法

Flutterは、柔軟で表現力のあるクロスプラットフォームモバイルアプリケーションを作成するためのGoogleのUIフレームワークです。これは、モバイルアプリケーション開発のための最も急速に成長しているフレームワークの1つです。一方、動物相は、ネイティブGraphQLをサポートするトランザクションの開発者に優しいサーバーレスデータベースです。フラッターファウナは天国によって作られた完璧なマッチです。レコードタイムで機能が豊富なフルスタックアプリケーションを構築およびリリースする場合は、FlutterとFaunaが適切なツールです。この記事では、動物相とGraphQLバックエンドを使用して、最初のフラッターアプリケーションの構築について説明します。

この記事の完全なコードはGithubで見つけることができます。

学習目標

この記事を読んだ後、あなたは次の方法を知っている必要があります

  1. ファウナインスタンスを設定し、
  2. 動物相のgraphqlパターンを書く、
  3. FlutterアプリケーションでGraphQLクライアントを設定し、
  4. FAUNA GraphQLバックエンドでクエリと突然変異を実行します。

Fauna vs. AWS Amplify vs. Firebase :Faunaはどのような問題を解決しますか?他のサーバーレスソリューションとどう違うのですか?動物相に精通しておらず、ファウナと他のソリューションとの比較についてもっと知りたい場合は、この記事を読むことをお勧めします。

私たちは何を作っていますか?

ユーザーがお気に入りの映画やテレビシリーズのキャラクターを追加、削除、更新できるシンプルなモバイルアプリを構築します。

動物相をセットアップします

fauna.comにアクセスして、新しいアカウントを作成します。ログインした後、新しいデータベースを作成できるはずです。

データベースに名前を付けます。私は私のflutter_demoという名前を付けました。次に、地域グループを選択できます。このデモでは、クラシックを選択します。 Faunaは、グローバルに分散されたサーバーレスデータベースです。これは、どこからでも低遅延の読み取りおよび書き込みアクセスをサポートする唯一のデータベースです。それはCDN(コンテンツ配信ネットワーク)と考えてください。しかし、それはあなたのデータベース用です。地域グループの詳細については、このガイドをフォローしてください。

管理者キーを生成します

データベースが作成されたら、[セキュリティ]タブに移動します。 [新しいキー]ボタンをクリックして、データベースの新しいキーを作成します。 GraphQL操作に必要なため、このキーを適切に保持してください。

データベースの管理者キーを作成します。管理者の役割を備えたキーは、データベースアクセスプロバイダー、亜データベース、ドキュメント、関数、インデックス、キー、トークン、ユーザー定義の役割など、関連するデータベースを管理するために使用されます。 Faunaのさまざまなセキュリティキーの詳細と、以下のリンクでアクセスロールをご覧ください。

GraphQLパターンの書き込み

ユーザーがお気に入りのテレビキャラクターを追加、更新、削除できるシンプルなアプリを構築します。

新しいフラッタープロジェクトを作成します

次のコマンドを実行して、新しいフラッタープロジェクトを作成しましょう。

 <code>flutter create my_app</code>
ログイン後にコピー

プロジェクトディレクトリでは、graphql/schema.graphqlという名前の新しいファイルを作成します。

スキーマファイルでは、コレクションの構造を定義します。動物相のコレクションは、SQLの表に似ています。今は1セットしか必要ありません。私たちはそれをキャラクターと名付けます。

 <code>### schema.graphql type Character { name: String! description: String! picture: String } type Query { listAllCharacters: [Character] }</code>
ログイン後にコピー

上記のように、複数のプロパティ(つまり、名前、説明、画像など)を持つ文字と呼ばれるタイプを定義します。プロパティは、SQLデータベースの列またはNOSQLデータベースのキー価値ペアとして扱うことができます。また、クエリを定義します。このクエリはロールリストを返します。

それでは、ファウナダッシュボードに戻りましょう。 [GraphQL]をクリックし、[インポートモード]をクリックして、モードを動物相にアップロードします。

インポートが完了した後、FaunaがGraphQLクエリと突然変異を生成することがわかります。

GraphQLの自動生成が好きではありませんか?あなたのビジネスロジックをよりよく制御したいですか?この場合、FAUNAでは、カスタムGraphQLパーサーを定義できます。詳細については、このリンクをクリックしてください。

フラッターアプリケーションでGraphQLクライアントのセットアップ

pubspec.yamlファイルを開き、必要な依存関係を追加しましょう。

 <code>... dependencies: graphql_flutter: ^4.0.0-beta hive: ^1.3.0 flutter: sdk: flutter ...</code>
ログイン後にコピー

ここに2つの依存関係を追加しました。 GraphQL_FlutterはFlutterのGraphQLクライアントライブラリです。 GraphQLクライアントのすべての最新機能を、使いやすいパッケージに統合します。また、Hiveパッケージを依存関係として追加しました。 Hiveは、ローカルストレージのために純粋なDARTで記述された軽量のキー価値データベースです。 Hiveを使用して、GraphQLクエリをキャッシュします。

次に、新しいファイルlib/client_provider.dartを作成します。ファウナ構成を含むプロバイダークラスをそのファイルに作成します。

FaunaのGraphQL APIに接続するには、最初にGraphQlClientを作成する必要があります。 GraphQlClientには、キャッシュとリンクを初期化する必要があります。以下のコードを見てみましょう。

 <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>
ログイン後にコピー

上記のコードでは、graphqlclientをラップするvalueNotifierを作成します。 13〜15行目(強調表示)でAuthLinkを構成したことに注意してください。 14行目で、トークンの一部として動物相の管理者キーを追加しました。ここでは、管理キーをハードコードしました。ただし、生産アプリケーションでは、動物相のセキュリティキーをハードコードしないようにする必要があります。

Flutterアプリケーションにキーを保存する方法はいくつかあります。参照については、このブログを確認してください。

アプリケーション内の任意のウィジェットからクエリと突然変異を呼び出すことができます。これを行うには、GraphQLProviderウィジェットを使用してウィジェットをラップする必要があります。

 <code>// lib/client_provider.dart .... /// 使用`graphql_flutter`客户端包装根应用程序。 /// 我们使用缓存进行所有状态管理。 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>
ログイン後にコピー

次に、main.dartファイルに移動し、メインウィジェットをClientProviderウィジェットでラップします。以下のコードを見てみましょう。

 <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>
ログイン後にコピー

この時点で、すべてのダウンストリームウィジェットはクエリと変異関数を実行でき、GraphQL APIと対話できます。

アプリケーションページ

デモアプリケーションは、シンプルで理解しやすいものでなければなりません。先に進み、すべての役割のリストを表示するシンプルなリストウィジェットを作成しましょう。新しいファイルlib/screens/character-list.dartを作成しましょう。このファイルでは、AllCharactersという新しいウィジェットを書き込みます。

 <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>
ログイン後にコピー

上記のコードに示されているように、[37行目]は、リストにいくつかの偽のデータを埋めるループ用です。最後に、FaunaバックエンドでGraphQLクエリを実行し、データベースからすべての役割を取得します。これを行う前に、アプリケーションを実行してみましょう。次のコマンドを使用してアプリケーションを実行できます

<code>flutter run</code>
ログイン後にコピー

この時点で、次の画面を確認できるはずです。

クエリと突然変異を実行します

これで、GraphQLクエリに接続し続けることができる基本的なウィジェットがいくつかあります。ハードコーディングされた文字列の代わりに、データベースからすべての役割を取得し、AllCharactersウィジェットで表示したいと考えています。

動物相のGraphQL遊び場に戻りましょう。次のクエリを実行して、すべての役割をリストできることに注意してください。

 <code>query ListAllCharacters { listAllCharacters(_size: 100) { data { _id name description picture } after } }</code>
ログイン後にコピー

ウィジェットからこのクエリを実行するには、いくつかの変更を加える必要があります。

 <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), // 我们要执行的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>
ログイン後にコピー

最初に、データベースからすべての役割を取得するためにクエリ文字列を定義します[行5から17]。 Flutter_graphqlのクエリウィジェットを使用して、リストウィジェットをラップします。

Flutter_graphqlライブラリの公式ドキュメントをお気軽にご覧ください。

クエリオプションパラメーターでは、GraphQLクエリ文字列自体を提供します。 Pollinterintervalパラメーターのフローティングポイント番号を渡すことができます。世論調査の間隔は、バックエンドからデータを返したい時間を定義します。ウィジェットには標準のビルダー機能もあります。ビルダー関数を使用して、クエリの結果を渡し、コールバック関数を再ゲットし、ウィジェットツリーにより多くのコールバック関数を取得できます。

次に、キャラクターのウィジェットを更新して、画面に文字データを表示します。

 <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>
ログイン後にコピー

新しいデータを追加します

次の突然変異を実行することにより、データベースに新しい役割を追加できます。

 <code>mutation CreateNewCharacter($data: CharacterInput!) { createCharacter(data: $data) { _id name description picture } }</code>
ログイン後にコピー

ウィジェットからこの突然変異を実行するには、Flutter_graphqlライブラリのMutation Widgetを使用する必要があります。ユーザーが対話してデータを入力できるように、シンプルなフォームを備えた新しいウィジェットを作成しましょう。フォームを送信した後、CreateCharacter変異が呼び出されます。

 <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>
ログイン後にコピー

上記のコードからわかるように、Mutationウィジェットはクエリウィジェットと非常に同様に機能します。さらに、Mutationウィジェットは、oncomplete機能を提供します。この関数は、変異が完了した後、データベースの更新結果を返します。

データを削除します

DeleteCharacter変異を実行することにより、データベースから役割を削除できます。このミュータントをキャラクターに追加し、ボタンが押されたときにトリガーできます。

 <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>
ログイン後にコピー

データを編集します

データの編集は、追加と削除と同じです。 GraphQL APIの別の突然変異です。新しいロールフォームウィジェットと同様の編集ロールフォームウィジェットを作成できます。唯一の違いは、フォームの編集がUpdateCharacter変異を実行することです。編集用に、新しいウィジェットLIB/SCREENS/EDIT.DARTを作成しました。これがこのウィジェットのコードです。

 <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>
ログイン後にコピー

この記事の完全なコードを次のように表示できます。

動物相やフラッターについて質問がありますか? Twitter @Haqueshadidで私に連絡できます

github ###次のステップ

この記事の主な目的は、FlutterとFaunaを始めることです。ここでのみ表面に触れます。 Fauna Ecosystemは、モバイルアプリケーションにサービスとして完全な自動スケーリング、開発者に優しいバックエンドを提供します。あなたの目標が、記録的な時期に生産に使用できるクロスプラットフォームモバイルアプリをリリースすることである場合は、 FaunaとFlutterを試してください。

Faunaの公式ドキュメントWebサイトをチェックすることを強くお勧めします。 DART/FlutterのGraphQLクライアントについて詳しく知りたい場合は、GraphQL_Flutterの公式GitHubリポジトリをご覧ください。

私はあなたに幸せなプログラミングを願っています、次回もまた会いましょう。

以上がFlutter、Fauna、およびGraphQLを使用してフルスタックモバイルアプリケーションを構築する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

GraphQLキャッシングの使用 GraphQLキャッシングの使用 Mar 19, 2025 am 09:36 AM

最近GraphQLの作業を開始した場合、またはその長所と短所をレビューした場合、「GraphQLがキャッシュをサポートしていない」または

Redwood.jsと動物相を使用してイーサリアムアプリを構築します Redwood.jsと動物相を使用してイーサリアムアプリを構築します Mar 28, 2025 am 09:18 AM

最近のビットコインの価格が20k $ $ USDを超えており、最近30Kを破ったので、イーサリアムを作成するために深く掘り下げる価値があると思いました

Eleventyで独自のBragdocを作成します Eleventyで独自のBragdocを作成します Mar 18, 2025 am 11:23 AM

開発者としての段階に関係なく、私たちが完了したタスクは、大小を問わず、個人的および専門的な成長に大きな影響を与えます。

Vue 3 Vue 3 Apr 02, 2025 pm 06:32 PM

それは&#039; Vueチームにそれを成し遂げてくれておめでとうございます。それは大規模な努力であり、長い時間がかかったことを知っています。すべての新しいドキュメントも同様です。

ブラウザから有効なCSSプロパティ値を取得できますか? ブラウザから有効なCSSプロパティ値を取得できますか? Apr 02, 2025 pm 06:17 PM

私はこの非常に正当な質問で誰かに書いてもらいました。 Leaは、ブラウザから有効なCSSプロパティ自体を取得する方法についてブログを書いています。それはこのようなものです。

CI/CDで少し CI/CDで少し Apr 02, 2025 pm 06:21 PM

「ウェブサイト」は「モバイルアプリ」よりも適していると言いますが、Max Lynchからのこのフレーミングが好きです。

粘着性のあるポジショニングとサスのダッシュを備えた積み重ねられたカード 粘着性のあるポジショニングとサスのダッシュを備えた積み重ねられたカード Apr 03, 2025 am 10:30 AM

先日、Corey Ginnivanのウェブサイトから、この特に素敵なビットを見つけました。そこでは、スクロール中にカードのコレクションが互いに積み重ねられていました。

レスポンシブデザインのブラウザを比較します レスポンシブデザインのブラウザを比較します Apr 02, 2025 pm 06:25 PM

これらのデスクトップアプリがいくつかあり、目標があなたのサイトをさまざまな次元ですべて同時に表示しています。たとえば、書くことができます

See all articles