皆さんがミニプログラムをどのように書いているかは分かりませんが、数ヶ月前にWeChatミニプログラムを書いていた時、自分で考えたアーキテクチャ、あるいはフレームワークと呼べるものがあります。 WeChatネイティブのアーキテクチャは次のようになっています。
├── app.js ├── app.json ├── app.wxss ├── pages │ │── index │ │ ├── index.wxml │ │ ├── index.js │ │ ├── index.json │ │ └── index.wxss │ └── logs │ ├── logs.wxml │ └── logs.js └── utils
なぜWeChatネイティブの書き方を使わないのか? ミニプログラムはスマホアプリに似ていて、tabBarがありますよね。WeChat公式のtabBarはapp.jsonでグローバルに設定されます。一般的な開発では何の問題もありませんが、複雑なtabBarを実装する場合、公式のネイティブな方法では実現できず、動的に読み込むこともできません。例えば、ある動画アプリの中央にある撮影・録画機能のようなものです。 これは、公式が提供するtabBarを使えず、自作する必要があることを意味します。 最初の私のアプローチは、ネイティブの構造を維持しつつ、tabBarだけを自作するというものでした。そのため、ページのコードはすべて1つのファイルに書き、デフォルトで最初の画面を表示し、他は非表示にします。ページを切り替える際に、対応するページを表示し、他を非表示にして、データを動的にレンダリングします。しかし、これには問題がありました。小規模なプロジェクトなら大した問題はありませんが、大規模なプロジェクトでコード量が膨大になると、すべてを1つのファイルに書くのは後のメンテナンスが困難になります。そのため、この方法は最終的に却下されました。
その後、ページの切り替え方法を(wx.switchTabなどを使った)画面遷移に変更し、異なるページのコードを別々のファイルに分けました。しかし、まだ問題がありました。切り替え時に画面がちらつくのです。ページを切り替えるたびに、まるで新しいウェブページを開くかのように、tabBarが再レンダリングされるため、ちらつきが発生します。これも却下です。
そこで、現在の全く新しいアーキテクチャ方式が生まれました:
/pages/index/以下のファイルをすべてエントリーファイル(JSエントリー、CSSエントリー、ビューエントリー)として定義します。異なるページのファイルは、管理しやすいように、やはり別の場所に置きます。新しくtemplateというフォルダを作成し、異なるページ間のコードを格納します。その構造は公式の単一ページの構造と同じです。
ルートディレクトリのapp.jsはグローバル関数を格納するために使用し、他のページからはgetApp()で呼び出すだけです。
JSのエントリーファイル
const app = getApp();
var index_js = require("../../template/index/index.js");
var types_js = require("../../template/types/types.js");
var Global_Data = [];
Page({
data: {
active: 0,
show: {
index: true,
types: false,
course: false,
user: false
}
},
onLoad(options) {
this.setData({
Global_Data: index_js.getData()
})
},
// 下部ナビゲーションの切り替え
tabbar_onChange(event) {
var key = '';
this.data.show = {
index: false,
types: false,
course: false,
user: false
};
console.log(event)
switch (event.detail) {
case 0:
key = 'index';
Global_Data = index_js.getData();
break;
case 1:
key = 'types';
Global_Data = types_js.getData()
break;
case 2:
key = 'course';
Global_Data = index_js.getData();
break;
case 3:
key = 'user';
Global_Data = index_js.getData();
break;
}
this.data.show[key] = true;
console.log(Global_Data)
this.setData({
show: this.data.show,
Global_Data: Global_Data
})
},
});wxmlエントリーファイル
<!-- エントリーファイル -->
<import src="/template/nav" />
<block wx:if="{{show.index }}">
<import src="/template/index/index" />
<template is="index" data="{{Global_Data}}" />
</block>
<block wx:elif="{{show.types}}">
<import src="/template/types/types" />
<template is="types" data="{{Global_Data}}" />
</block>
<block wx:elif="{{show.course}}">
<import src="/template/course/course" />
<template is="course" data="{{Global_Data}}" />
</block>
<block wx:elif="{{show.user}}">
<import src="/template/user/user" />
<template is="user" data="{{Global_Data}}" />
</block>
<template is="nav" data="{{active}}" />
<view style='height:50px;'></view>cssエントリー
@import "/template/user/user.wxss";
.container {
height: 100vh;
background-color: #fff;
}
.tag,
.button {
margin-right: 5px;
}
.van-card__footer {
margin-top: 5px;
}そして、サブページのコード構造 js
const app = getApp();
var index_data = {
banner: [
'//img4.mukewang.com/szimg/5c4a74c009dea3b500000000.jpg', '//img2.mukewang.com/szimg/5c734d880939299918000600.jpg', '//img4.mukewang.com/szimg/5c63e89209f9f17d00000000.jpg'
],
imageUrl: 'http://img1.sycdn.imooc.com/szimg/5c6bdb3e08e4674a06000338-360-202.jpg',
tabs_active: 0
};
// app.alert('aa');
// 外部にインターフェースを公開しないと呼び出せない
module.exports = { //グローバルデータを返すために使用
getData: function() {
return index_data;
},
myfunction: function (){
app.alert('aa');
}
};cssとwxmlは通常通り書けばOKです。wxmlで再利用したい部分があれば、現在のディレクトリ内で共通部分を分け、<template>タグでインポートすればよいです。
この方法なら、ページを高速に切り替えてもちらつかず、ファイルの分割も管理しやすくなります。
この方法は、前の2つの失敗経験を組み合わせて、一つにしたものです。
最終的にプロジェクトをすべて書き上げる前に、別のプロジェクトの開発に呼ばれてしまいました。そのため、詳細に不備があるかもしれません。今後、何か進展があれば、また更新します。
