小程式目錄結構
關於小程式的目錄結構,可以說一開始大家都有各自的開發習慣和命名規則,但一旦專案變得複雜龐大的時候,你就發現管理起來和後期維護變得很麻煩,如果是 協同開發 的話,更容易出現 “互坑” 的情況。
智庫君在一年多的小程式開發中也跳過不少的坑,總結了一套還算好維護的目錄結構跟大家分享(僅供參考,覺得好拿去,覺得不好歡迎提出意見),以下是實戰專案中的結構示例:
├─ app.js --- 小程式載入時優先載入的入口JS
├─ app.json ---入口檔案和公共配置
├─ app.wxss ---公共樣式表
├─ project.config.json ---小程式全域性配置檔案
├─ sitemap.json ---允許微信索引檔案
│
├─cloud-functions ---雲函式
│ └─setCrypto ---資料加密模組,使用者加密一些資料
│ index.js
│ package.json
│ ...
│ ...
│
├─components ---小程式自定義元件
│ ├─plugins --- (重點)可獨立執行的大型模組,可以打包成plugins
│ │ ├─comment ---評論模組
│ │ │ │ index.js
│ │ │ │ index.json
│ │ │ │ index.wxml
│ │ │ │ index.wxss
│ │ │ │ services.js ---(重點)用來處理和清洗資料的service.js,配套模板和外掛
│ │ │ │
│ │ │ └─submit ---評論模組子模組:提交評論
│ │ │ index.js
│ │ │ index.json
│ │ │ index.wxml
│ │ │ index.wxss
│ │ │
│ │ └─canvasPoster ---canvas海報生成模組
│ │ index.js
│ │ index.json
│ │ index.wxml
│ │ index.wxss
│ │ services.js ---(重點)用來處理和清洗資料的service.js,配套模板和外掛
│ │ ...
│ │ ...
│ │
│ └─templates ---(重點)模板,通過外部傳參的容器,不做過多的資料處理
│ │
│ ├─slideshow ---滾屏切換模板
│ │ index.js
│ │ index.json
│ │ index.wxml
│ │ index.wxss
│ │ service.js ---(重點)用來處理和清洗資料的service.js,配套模板和外掛
│ │
│ └─works ---作品模板
│ │ index.js
│ │ index.json
│ │ index.wxml
│ │ index.wxss
│ │ service.js
│ │
│ ├─articlePlugin ---作品模板中的文章型別
│ │ index.js
│ │ index.json
│ │ index.wxml
│ │ index.wxss
│ │
│ ├─galleryPlugin ---作品模板中的九宮格型別
│ │ index.js
│ │ index.json
│ │ index.wxml
│ │ index.wxss
│ │
│ └─videoPlugin ---作品模板中的視訊型別
│ index.js
│ index.json
│ index.wxml
│ index.wxss
│ ...
│ ...
│
├─config ---自定義配置檔案
│ config.js ---存放基礎配置
│ constants.js ---儲存常量
│ weui.wxss ---第三方檔案wxss,js等
│ ...
│ ...
│
├─pages ---小程式頁面
│ ├─user ---使用者頁面
│ │ index.js
│ │ index.json
│ │ index.wxml
│ │ index.wxss
│ ├─news ---新聞頁面
│ │ index.js
│ │ index.json
│ │ index.wxml
│ │ index.wxss
│ │
│ └─home ---首頁
│ index.js
│ index.json
│ index.wxml
│ index.wxss
│ ...
│ ...
│
├─request ---https請求管理(根據switch tab分類會比較好)
│ common.js ---一些公共請求獲取,如兌換openId,unionId 等
│ news.js
│ uri.js --- (重點)總的URI請求管理,方便切換和配置DEV,QA,PROD環境
│ user.js
│ ...
│ ...
│
└─utils ---功能元件
logger.js ---日誌管理
util.js ---公共小元件庫
...
...
複製程式碼
為什麼一定要寫這個目錄結構呢?例如微信自己的wepy的官方文件,現在也新增了目錄結構說明:
不知道大家有沒有發現,在以往的老專案交接和多人協同開發中,容易遇到別人寫的模組,變數命名不準確,或者資料缺損,一次十來個方法/元件間的互相呼叫,直接把接(盤)手的人整懵逼了,所以智庫君覺得,無論是獨立開發,還是協同開發,留一份完整的目錄說明文件是很有必要的,勿坑 他人 OR 未來的自己~~~
component使用心得
大家在開發過程中肯定會去看官方文件,但不可能全看完才開始寫程式碼,大多數情況都是用到了再看,本人也是,所以下面抽一些開發中遇到的重點來講:
一、引用元件模板頁面的自定義
元件模板的寫法與頁面模板相同。元件模板與元件資料結合後生成的節點樹,將被插入到元件的引用位置上。 在元件模板中可以提供一個 節點,用於承載元件引用時提供的子節點。
<!-- 元件模板 -->
<view class="wrapper">
<view>這裡是元件的內部節點</view>
<slot></slot>
</view>
複製程式碼
<!-- page頁/父頁面引用元件的頁面模板 -->
<view>
<component-tag-name>
<!-- 這部分內容將被放置在元件 <slot> 的位置上 -->
<view>這裡是插入到元件slot中的內容</view>
<view>在載入元件的頁面裡自定義內容,將沒有複用性的內容寫在這裡</view>
</component-tag-name>
</view>
複製程式碼
頁面自定義部分預設是載入在元件上方。
為什麼要在引用元件的頁面新增這些內容呢?
因為元件其中一個重要的特點是複用性,但是有的時候可能要根據不同場景做一些自定義,如果在元件中寫大量的場景/邏輯判斷,會增加元件的冗餘,而且這些方法只是被複用一次的話,完全可以不寫到元件裡。
二、“一鍵換膚”根據不同場景給元件引入外部樣式
<!-- 外部引用元件的頁面傳入樣式 -->
<WorkComponent extra-class="style1" j-data="{{workData}}"></WorkComponent>
複製程式碼
//元件中js
Component({
/**
* 引入外部樣式,可傳多個class
*/
externalClasses: ['extra-class','extra-class2'],
})
複製程式碼
extra-class 從外部引入父級css,可用根據不同場景配置不同的樣式方案,這樣使得元件自定義能力更強。
三、資料清洗與容錯
//service.js 思路示例
module.exports = {
/**
* 功能:處理作者列表
* @param list
* @returns {Array}
*/
authorList: function (list = []) {
let result = [];
list.forEach(item => {
result.push({
guid: item.recommend_obj_id || '',
type: item.recommend_type || '',
logo: (item.theme_pic || '').trim() || '',
title: item.title || ''
});
});
return result;
}
};
複製程式碼
如果外部傳入的資料要分別匯入多個元件中,可以在元件中建立一個對應的service.js,有2個作用:
- 清洗資料,避免setData()的時有過多的髒資料
- 錯誤資料的相容,新增資料預設值,增加程式碼健壯性
四、canvas在component元件中無法選中的問題
//這裡只需要在後面 新增this物件
let ctx = wx.createCanvasContext('myCanvas', this);
複製程式碼
其他一些預設元件,遇到類似的問題,一般只要引用時傳入this物件即可解決。
五、元件之間的通訊
在實際生產環境中,我們常常需要控制各個元件之間的互相通訊/傳參,下面介紹下具體的用法:
- WXML 資料繫結:用於父元件向子元件的指定屬性設定資料,僅能設定 JSON 相容資料(自基礎庫版本 2.0.9 開始,還可以在資料中包含函式)。具體在 元件模板和樣式 章節中介紹。
- 事件:用於子元件向父元件傳遞資料,可以傳遞任意資料。
- 如果以上兩種方式不足以滿足需要,父元件還可以通過 this.selectComponent 方法獲取子元件例項物件,這樣就可以直接訪問元件的任意資料和方法。
設定監聽事件:
<!-- wxml 中 當自定義元件觸發“myevent”事件時,呼叫“onMyEvent”方法 -->
<component-tag-name bindmyevent="setMyEvent" />
<!-- 或者可以寫成 -->
<component-tag-name bind:myevent="setMyEvent" />
複製程式碼
// index.js 父頁面中
Page({
setMyEvent: function(e){
let self = this;
if (e.detail) { // 自定義元件觸發事件時提供的detail物件
switch (e.detail) {
case "hidden": //隱藏 懸浮框上的評論
this.setData({
isFixCommentShow: false
});
break;
case "fixRefresh": //重新整理懸浮框
this.setData({
fixRefresh: true
});
break;
case "commentRefresh": //重新整理評論
this.setData({
commentRefresh: Math.random()
});
break;
case "createPoster": //生成海報元件
self.setPosterSave();
break;
}
}
}
})
複製程式碼
父頁面引用子元件,子元件傳送的資訊,可以通過bind的方法監聽到,來獲取到具體的傳參值。
觸發事件
自定義元件觸發事件時,需要使用 triggerEvent方法,指定事件名、detail物件和事件選項:
<!-- 頁面 page.wxml -->
<another-component bindcustomevent="pageEventListener1">
<my-component bindcustomevent="pageEventListener2"></my-component>
</another-component>
<!-- 元件 another-component.wxml -->
<view bindcustomevent="anotherEventListener">
<slot />
</view>
<!-- 元件 my-component.wxml -->
<view bindcustomevent="myEventListener">
<slot />
</view>
複製程式碼
//元件中js
Component({
properties: {},
methods: {
onTap: function(){
var myEventDetail = {} // detail物件,提供給事件監聽函式
var myEventOption = {} // 觸發事件的選項
this.triggerEvent('myevent', myEventDetail, myEventOption)
//myEventOption的一些配置:
this.triggerEvent('customevent', {}, { bubbles: true }) // 會依次觸發 pageEventListener2 、 pageEventListener1
this.triggerEvent('customevent', {}, { bubbles: true, composed: true }) // 會依次觸發 pageEventListener2 、 anotherEventListener 、 pageEventListener1
}
}
});
複製程式碼
myEventOption 的配置:
- bubbles(Boolean):事件是否冒泡
- composed(Boolean):事件是否可以穿越元件邊界,為false時,事件將只能在引用元件的節點樹上觸發,不進入其他任何元件內部
- capturePhase(Boolean):事件是否擁有捕獲階段
需要強調一點:建議大家不要在元件上bind太多的監聽,一方面以後管理起來會比較麻煩,另一方面首次載入如果呼叫過多方法會引起資料渲染的卡頓。
Component官方文件: developers.weixin.qq.com/miniprogram…
往期回顧: