この記事では、主に WeChat ミニ プログラム フレームワークの詳細な説明とサンプル アプリケーションの関連情報を紹介します。必要な友人は参考にしてください。
ミニ プログラム フレームワークに基づいて開発された Todos アプリである WeChat ミニ プログラムの使い方をすぐに理解できます。
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
このプロジェクトをローカルで実行したい場合は、最初に開発者ツールをインストールする必要があり、ドキュメント内の簡単なチュートリアルでは、まずプロジェクトをビルドします。
構築が完了したら、開発者ツールがプロジェクトを開きます。
次に、ディスク上でビルドされたプロジェクトのフォルダーを見つけて、その中のすべてのコンテンツを削除し、すべてを貼り付けます。
次に、開発者ツールを再度開き、最初に編集タブに入り、次にコンパイルボタンをクリックすると、アプリの機能を表示するために直接デバッグインターフェイスに入ります:
これの開発を紹介しましょう。 app の要点:
1. このアプリのディレクトリ構造と構成については、「ドキュメント フレームワーク」セクションで詳しく説明しません。このプラットフォームには html と css はなく、wxml と wxss に置き換えられます。 wxss と css にはほとんど違いがありません。欠点は、css ほど強力ではなく、サポートされるセレクターが限られていることです。ただし、プラットフォームが WeChat 1 つだけであるため、互換性の問題がほとんどなく、標準および最新の CSS テクノロジーを使用できるという利点があります。 wxml では、プラットフォームによって提供されるコンポーネントのタグのみを使用できます。HTML タグを直接使用することはできません。wxml での各コンポーネントの使用方法の例は、「ドキュメント - コンポーネント」セクションにあります。したがって、実際には、wxml と wxss を記述することに問題はありません。
2. wxml は次の機能をサポートします:
テンプレートと参照を除き、その他すべての機能は todo アプリで使用されます。ただし、各機能の詳細はアプリの適切な機能に基づいてのみ使用されます。選ばれる。数日前、WeChat アプレットは vue フレームワークに基づいて実装される可能性があるという記事を見たので、vue のドキュメントを調べてみました。データ バインディング、条件付きレンダリング、リスト レンダリング、およびイベントについて、vue の使用法を詳しく説明しました。それに比べて、wxml が提供する機能は vue の関連機能によく似ていますが、機能がそれほど多くないため、vue フレームワークの機能を小さなプログラムに直接使用するのは簡単ではありません。ベストプラクティスはやはり公式ドキュメントに記載されている手順に基づいています。公式ドキュメントに記載されていない機能を推測で使用すると、間違いなく動作しません。いくつかのオブジェクトのプロトタイプを印刷して確認しましたが、公式ドキュメントよりも多くのインスタンス メソッドは見つかりませんでした。これは、ミニ プログラムのフレームワーク機能が実際に制限されていることを示しています。
3. セレクターがフレームワークの要件を満たしている限り、Wxss は実際にはless または sass で書くことができます。時間の都合上、このアプリでは試しませんでした。
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(); },
以上代码中,通过e.detail.value[0]拿到单个todo项里面checkbox的值,通过该值来判断todo的complete状态。最后在updateData的内部,还会通过setData方法,刷新model的内容。只有这样,在toggle操作之后,app底部的统计信息才会更新。
5. 事件绑定的时候,无法传递参数,只能传递一个event。比如上面那个toggle的操作,我其实很想在回调里面把当前todo的id传到这个回调里面,但是想尽办法都做不到,最后只能通过id的方式来处理:就是在wxml中绑定事件的组件上面,加一个id,这个id全page也不能重复,所以id得加前缀,然后在id最后加上todo的id值;当事件触发的时候,通过e.currentTarget.id就能拿到该组件的id,去掉相应的id前缀,就得到todo的id值了。这是目前用到的一个方法,我认为不是很优雅,希望后面能发现更好的办法来实现。
6. app中考虑到了loading的效果,要利用button组件的loading属性来实现。但是loading仅仅是一个样式的控制,它不会控制这个按钮是否能重复点击。所以还要利用buttong的disabled属性,防止重复点击。
剩下的实现细节,都在下面两个文件的源码中,欢迎大家指出其中的问题。
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: '' }); } });
最后需要补充的是,这个app在有限的时间内依据微信的官方文档进行开发,所以这里面的实现方式到底是不是合理的,我也不清楚。我也仅仅是通过这个app来了解小程序这个平台的用法。希望微信官方能够推出一些更全面、最好是项目性的demo,在代码层面,给我们这些开发者提供一个最佳实践规范。欢迎有其它的开发思路的朋友,帮我指出我以上实现中的问题。
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
以上がWeChat ミニプログラムのフレームワークの分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。