WeChat は、WeChat ミニ プログラムの公式ドキュメントと開発者ツールを正式にオープンしました。過去 2 日間、私は小さなプログラムの開発方法を理解するために関連ニュースを読んでいました。公式ドキュメントが公開された後、すぐにそれらに目を通し、ドキュメントの 2 つの部分 (フレームワークとフレームワーク) を理解することに集中しました。コンポーネントを作成し、通常の ToDo アプリを作成するための簡単なチュートリアルに基づいています。このアプリは WeChat アプレット プラットフォームに基づいており、todo アプリの通常の機能を実装すると同時に、実際の作業シナリオに近づけるために、読み込みコンポーネントとトースト コンポーネントを使用して対話とフィードバックを完了します。いくつかの操作の。このプラットフォームについての私の直観的な印象は、技術レベルでは Vue に似ていますが、Vue よりもはるかに強力ではなく、開発アイデアは Vue とは異なり、バックボーンに似ているということです。したがって、backbone や vue などの mvc、mvvm フレームワークを使用したことがある人は、このプラットフォームを簡単に始めることができます。この記事では、このtodoアプリの実装のポイントを中心に紹介します。
まず、この記事に関連する情報を追加します:
公式ドキュメント: https://mp.weixin.qq.com/debug/wxadoc/dev/index.html
公式開発者ツールのダウンロード: https://mp. weixin.qq.com/debug/wxadoc/dev/devtools/download.html
この記事の todo アプリの機能デモ:
注: todo テキストを直接編集するには、todo テキストを長押しする必要があります。携帯電話なのでダブルクリックイベントが編集に使えず、長押しイベントに変更しました。ミニ プログラム プラットフォームは、ダブルクリック イベントのバインドも提供しません。
関連ソースコード: https://github.com/liuyunzhuge/blog/tree/master/todos/wx
このプロジェクトをローカルで実行したい場合は、最初に開発者ツールをインストールする必要があり、ドキュメント内の簡単なチュートリアルでは、まずプロジェクトをビルドします。
構築が完了したら、開発者ツールがプロジェクトを開きます。次に、ディスク上でビルドされたプロジェクトのフォルダーを見つけ、その中のすべてのコンテンツを削除し、[すべて貼り付け]を削除します。
次に開発者ツールを再度開き、最初に編集タブに入り、次にコンパイルボタンをクリックすると、直接デバッグインターフェイスに入り、アプリの機能を表示します:
4. 双方向の拘束はありません。 Vue では、Vue インスタンスはビューモデルです。ビューレイヤー内のデータの更新はリアルタイムでモデルにフィードバックされ、モデルの更新もリアルタイムでビューにフィードバックされます。ミニ プログラムでは双方向のバインディングはなく、ビューの更新はモデルに直接同期されません。関連するイベント コールバックでビュー レイヤーからデータを直接取得して、モデルを更新する必要があります。ミニ プログラムは、ミニ プログラム内で setData を使用して、ページを再レンダリングします。たとえば、単一の Todo 項目の場合、切り替え操作は次のようになります。
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(); },
上記のコードでは、単一の Todo 項目のチェックボックスの値は e.detail.value[0] を通じて取得され、完全なステータスはこの値によってtodoの内容が判断されます。最後に、updateData 内で、setData メソッドを通じてモデルのコンテンツが更新されます。この方法でのみ、切り替え操作後にアプリの下部にある統計が更新されます。
5. イベントをバインドする場合、パラメーターを渡すことはできません。渡せるのは 1 つのイベントのみです。たとえば、上記のトグル操作では、実際には現在の Todo の ID をコールバックに渡したいと思っていましたが、あらゆる方法でそれを行うことはできず、最終的には ID メソッド、つまりバインドすることでしか処理できませんでした。 wxml で、イベントのコンポーネントに ID を追加します。この ID はページ全体で繰り返すことができないため、イベントがトリガーされるときに ID の最後に todo ID 値を追加する必要があります。 、e.currentTarget.id を通じて取得できます。コンポーネントの ID については、対応する ID プレフィックスを削除して、todo の ID 値を取得します。これは現在使用されている方法であり、あまりエレガントではないと思います。後で実装するより良い方法を見つけたいと思います。
6. アプリではローディング効果が考慮されており、ボタンコンポーネントのloading属性を使用して実現する必要があります。ただし、読み込みは単なるスタイル コントロールであり、ボタンを繰り返しクリックできるかどうかは制御しません。したがって、ボタンの disabled 属性も使用して、繰り返しクリックされないようにする必要があります。
残りの実装の詳細は、次の 2 つのファイルのソース コードにあります。問題点を指摘してください。
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 ? '' : 'todo-item-not-first'}} {{todo.complete ? 'todo-item-complete' : ''}}" 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>
index.js ソース コード:
var app = getApp(); Page( { data: { todos: [], todosOfUncomplted: [], todosOfComplted: [], newTodoText: '', addOneLoading: false, loadingHidden: true, loadingText: '', toastHidden: true, toastText: '', 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( 'todos', storage ); }, onLoad: function() { this.setData( { todos: wx.getStorageSync( 'todos' ) || [] }); 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, '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(); }, 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, 'btn-del-item-' ); 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: 'Success' }); }, 500 ); }, startEdit: function( e ) { var id = this.getTodoId( e, 'todo-item-txt-' ); 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, 'todo-item-edit-' ); 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: 'Waiting...' }); var that = this; setTimeout( function() { //close loading and toggle button loading status that.setData( { loadingHidden: true, addOneLoading: false, loadingText: '' }); that.data.todos.push( { id: app.getId(), text: that.data.newTodoText, compelte: false }); that.setData( { newTodoText: '' }); that.updateData( true ); that.updateStorage(); }, 500 ); }, loadingChange: function() { this.setData( { loadingHidden: true, loadingText: '' }); }, toastChange: function() { this.setData( { toastHidden: true, toastText: '' }); } });
最後に追加する必要があるのは、このアプリは限られた時間内で WeChat の公式ドキュメントに従って開発されたということです。ここでの実装が合理的かどうかはわかりません。このアプリは、ミニ プログラム プラットフォームの使用法を理解するためにのみ使用します。 WeChat関係者がより包括的な、できればプロジェクトベースのデモを立ち上げて、私たち開発者にコードレベルでのベストプラクティス仕様を提供できることを願っています。他の開発アイデアを持つ友人は、上記の実装の問題点を指摘するのを手伝ってくれるでしょう。
WeChat ミニ プログラムの使用法について詳しく知りたい場合は、PHP 中国語 Web サイトにあるミニ プログラム フレームワークに基づいて開発された Todos アプリに関する関連記事に注目してください。