首先在微信小程序中不論是 ES6
或者是 commonJS
模塊化語法都是支持的,在傳統的web項目中我個人是習慣統一使用 ES6
模塊化語法進行開發的。
在最初我也是將小程序中所有的通用方法抽離成單獨的文件,并使用export
或 export default
導出,使用 import
引入。
注意點
但是!在實際開發中,小程序的js文件是不支持絕對路徑引入的!這意味著如果你需要在你的頁面中引入一個公用方法,你必須使用 ../../../xxx/xxx.js
的方式,當你同一個頁面引入多個模塊時,這種寫法絕對會極大的打擊你的開發熱情。
解決方式
那我們該如何解決這么長的引入路徑呢,在web項目中,我們常常會使用路徑別名的方式,例如 webpack或vite 中的 resolve.alias
來縮短引入的路徑。
alias:{"@src":path.resolve("src"),
但是在原生微信小程序中,雖然可以通過 gulp 或者 webpack 等一些前端工程化的工具對小程序進行一些改造,但是作為一個開源項目我希望它的啟動過程不需要太多額外配置。最好是能夠使用原生的語法去實現。
最終我選擇了在 app.js中新增一個require
方法用于引入模塊,這樣在頁面內引入模塊時,我們只需要使用app的實例來進行模塊引入,這樣可以實現使用與app.js
文件的相對路徑來引入文件.
//app.jsApp({require(path){returnpath}})
使用方式
//使用基于app.js的相對路徑來引入文件,這樣就避免了寫很多"../"constapp=getApp()constupload=app.require("lib/upload")
當然這樣做也不是特別方便,首先是代碼提示的不健全,使用以上方式的話可能對于參數或者一些返回值的提示不到位,但是影響不大。如果之后我摸索出了其他比較好的實現方式再寫一篇文章解析。其次是必須使用全局統一使用commonJS 的模塊化語法啦,不過這一點的話問題不大。
小程序中并沒有提供特殊的模塊化方式,比較常用的就是將一些方法抽離為單獨的js文件,然后再引入。想要避免一個頁面文件代碼太長的話最好的方式是組件化,但是在小程序中,認為寫組件真的是一件很不爽的事情。
小程序組件擁有自己的生命周期,而且引入時必須在頁面json中提前定義,由于組件是掛在在shadow root節點上,如果想要和頁面共享樣式例如colorUI的全局樣式還需要寫入單獨的配置項styleIsolation。整體開發體驗相比vue而言比較割裂。
基于以上的一些個人看法,我在寫小程序時比較少使用組件,如果是需要抽離wxml或者是js我通常使用以下的方法。
wxml模塊化
在小程序中我通常使用 模板template
進行抽離復用,微信小程序模板文檔 ,模板相較于組件抽離的僅僅是部分的頁面,不包含功能部分的抽離。
以下是我抽離的一個模板,這是一個文章的列表項,它并沒有什么單獨的功能,但是代碼很長并且卻在很多頁面中復用到,于是我將它進行了一個抽離。把樣式都通過行內樣式的方式寫上,這樣在哪里引入都是一樣的樣式。
<!--文章列表項--><importsrc='./avatar'/><templatename="post-item"><viewclass="marginpadding-smbg-whiteradiusflexshadow"style="position:relative;height:350rpx;border-radius:10rpx;"><!--背景蒙版--><viewstyle="position:absolute;top:0;left:0;width:100%;height:100%;border-radius:10rpx;"><imagestyle="filter:blur(2px)grayscale(80%)opacity(80%)"lazy-load="{{true}}"src="{{imgList[0]}}"mode="aspectFill"></image></view><viewstyle="position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(30,30,30,0.8);border-radius:10rpx;"></view><viewstyle="z-index:10;width:100%;"class="text-white"><!--文章標題--><viewclass="text-xl"><textclass="cu-tagmargin-right-smbg-colorradius">{{topic}}</text><textclass="text-bold">{{title}}</text></view><!--文章內容--><viewclass="margin-top-xstext-smtext-cut">{{content}}</view><viewclass="flexalign-endjustify-betweenmargin-top"><!--文章圖片--><viewclass="flexalign-center"><viewclass="margin-xs"style="width:120rpx;height:120rpx;"wx:for="{{imgList}}"wx:key="{{index}}"wx:if="{{index<3}}"><imageclass="radius"src="{{item}}"mode="aspectFill"></image></view></view><!--瀏覽量-點贊數--><viewclass="bg-colorflexalign-centertext-whitetext-smradius"style="padding:4px12px;"><viewclass="cuIcon-attention"></view><viewclass="margin-left-xs">{{viewNum||0}}</view><viewclass="cuIcon-likemargin-left"></view><viewclass="margin-left-xs">{{favorNum||0}}</view></view></view><!--發布時間--><viewclass="margin-top-xsflexalign-centertext-smtext-grayjustify-betweenpadding-lr-xs"><viewclass="flexalign-center"><templateis="avatar"data="{{size:45,avatarUrl:user.avatarUrl}}"/><viewclass="margin-left-xs">{{user.nickName}}</view></view><view>{{createTime}}</view></view></view></view></template>
在頁面中使用的時候需要提前引入,由于可以引入多個模板,因此使用時需要使用 is屬性
聲明使用的是哪一個template,數據的話可以通過data
屬性傳入,這里的示例是我將遍歷的item解構后再賦值進去。
<!--某個頁面--><importsrc='../../template/post-item'/><templatedata="{{...item}}"is="post-item"/>
當然使用template進行模塊化進行抽離的模板代碼可不能包涵太多的功能邏輯,具體的使用還是需要根據業務來噢。
js模塊化
在小程序中最基本的js模塊化就是直接抽離js文件,例如一些全局通用的方法,下面展示一個全局上傳方法的封裝
//lib/upload.js//上傳方法module.exports=asyncfunctionupload(path){returnawaitwx.cloud.uploadFile({cloudPath:newDate().getTime()+path.substring(path.lastIndexOf(".")),filePath:path,})}
//pages/form/form.jsconstapp=getApp()constupload=app.require("lib/upload")Page({asyncsubmit(){wx.showLoading({mask:true,title:"發布中"})constimgList=[]for(letimgofthis.data.form.imgList){constuploadRes=awaitupload(img)imgList.push(uploadRes.fileID)}//...其他業務代碼}})
當然以上的辦法對于通用方法來說很方便,但是對于與 頁面操作的邏輯耦合性 很高的一些業務代碼,這樣子抽離并不方便。
在vue2中我們可以使用mixin的方法模塊化代碼,在vue3中我們可以使用hook的方式模塊化代碼,但是在小程序中并沒有以上兩者的支持,最初我想仿照 vue3的hook 方式進行頁面js封裝改造,但最終實現的效果不理想,于是選擇了實現一個模仿vue2 mixin 的方法來實現模塊化。
具體代碼其他博主有實現過,因此我就直接拿來使用了,具體代碼如下。如果不了解vue中mixin的使用方法的可以自行去官網看文檔,這里不做過多介紹。
//mixin.js//保存原生的Page函數constoriginPage=Page//定義小程序內置的屬性/方法constprop=['data','properties','options']constmethods=['onLoad','onReady','onShow','onHide','onUnload','onPullDownRefresh','onReachBottom','onShareAppMessage','onPageScroll','onTabItemTap']Page=(options)=>{if(Array.isArray(options.mixins)){constmixins=options.mixinsdeleteoptions.mixinsmixins.forEach((mixin)=>{for(let[key,value]ofObject.entries(mixin)){if(prop.includes(key)){//混入屬性options[key]={...value,...options[key]}}elseif(methods.includes(key)){//混入原生方法constoriginFunc=options[key]options[key]=function(...args){value.call(this,...args)returnoriginFunc&&originFunc.call(this,...args)}}else{//混入普通方法options={...mixin,...options}}}})}originPage(options)}
實現的原理是改造小程序中的Page()函數,小程序的每一個頁面都是通過調用Page({option})
方法來實現的,在option
參數中傳入頁面相關的data和聲明周期函數及其他方法。
我們通過在Page方法的參數option
中增加一個mixin
屬性,這個屬性可以傳入一個數組,數組即是每一個要混入的模塊,每一個模塊的結構其實與參數option
是一樣的,我們只需要將所有混入的模塊與頁面自身的option進行一個參數和方法的合并就能實現一個mixin
的功能。
使用的方法是現在app.js中引入mixin.js
//app.jsrequire("./mixins.js")App({//...其他代碼})
然后我們寫一個常規頁面的js,業務代碼大家不用看,主要關注Page的屬性中多了一個mixins選項,而mixins
數組中有一個topic
模塊。
//pages/form/form.jsconstapp=getApp()constupload=app.require("lib/upload")constto=app.require("lib/awaitTo")constdb=wx.cloud.database()Page({mixins:[require("./mixins/topic")],data:{user:wx.getStorageSync('user'),form:{title:"",topic:"",content:"",imgList:[]}},chooseImg(){wx.chooseImage({count:9-this.data.form.imgList.length,sizeType:['original'],//可以指定是原圖還是壓縮圖,默認二者都有sourceType:['album','camera'],//從相冊選擇success:(res)=>{res.tempFilePaths=res.tempFilePathsif(this.data.form.imgList.length!=0){this.setData({"form.imgList":this.data.form.imgList.concat(res.tempFilePaths)})}else{this.setData({"form.imgList":res.tempFilePaths})}}});},asyncdelImg(e){constindex=e.currentTarget.dataset.indexconsttemp=this.data.form.imgListtemp.splice(index,1)this.setData({"form.imgList":temp})}})
由于 topic
內都是關聯性較強的屬性與方法,因此就可以抽離出來,這樣頁面的js就會更加精簡啦,如果有更多的代碼就根據自己對于功能的判斷進行抽離,然后放在頁面對于mixin目錄中即可!
////pages/form/mixin/topic.jsconstdb=wx.cloud.database()module.exports={data:{topic:{flag:false,list:[]},},onLoad(options){this.getTopic()},asyncgetTopic(){constres=awaitdb.collection("topic").get()this.setData({"topic.list":res.data})},clearTopic(){this.setData({"form.topic":""})},toggleTopic(e){console.log(e.currentTarget.dataset)constflag=e.currentTarget.dataset.flagthis.setData({"topic.flag":flag})},}
注意點
但是使用mixin
也有著與vue中同樣的問題就是變量及方法的來源不好追溯,變量是在那個位置定義的比較難以定位,這時就更加依賴開發者的開發規范以及命名方式了,再不濟也可以每一個方法寫一個獨有的注釋嘛~
感謝你能夠認真閱讀完這篇文章,希望小編分享的“小程序中怎么進行模塊化處理”這篇文章對大家有幫助,同時也希望大家多多支持本站,關注本站行業資訊頻道,更多相關知識等著你來學習!
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...
2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...
:喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...
在實際的經濟生活中,中央銀行的三大法寶一般認為是存款準備金政策、公開市場業務政策以及再貼現政策。利用以上這三三大法寶,中央銀行需要對市場金融秩序進行宏觀調控,實現對市場內信用總量進行統一的收縮或者擴張操作。央銀三大法寶的詳情介紹1、存款準備金政策:中央銀行通過對存款準備金率進行調控,從而影響金融機構的實際影響能力,間接的來調控市場內貨幣的供應總量;2、公開市場業務政策:公開市場業務政策即意味著中央...
ene指標是什么意思?接下來就來為大家介紹一下,一起來看看吧。ene指標又被稱為軌道線,在兩條平行的阻力線和支排線之間形成的范圍叫做趨勢軌道,根據這一軌道形成的上下線叫做軌道線。軌道線在確立之后,投資者可以判斷股價運行過程中的方向。計算公式1、LOWER=(1-M2/100)*收盤價的N日簡單移動平均2、UPPER=(1 M1/100)*收盤價的N日簡單移動平均ene軌道線看1、ENE緩慢向下運行...
(資料圖片僅供參考)最近這段時間總有小伙伴問小編句容瓦屋山好玩嗎是什么,小編為此在網上搜尋了一些有關于句容瓦屋山好玩嗎的知識送給大家,希望能解答各位小伙伴的疑惑。好玩,瓦屋山在江蘇句容市的南端,北與道教圣地茅山相呼應,西鄰東屏湖國際度假村,南靠碧波蕩漾的天目湖,距鎮江市區50多公里。瓦屋山的自然風景由五山四湖組成,方圓約30平方公里。這里植被茂盛,峰巒奇秀。置身山中,耳聽林濤合著鳥鳴,眼望青山伴著...