贵州做网站公司
贵州做网站公司~专业!靠谱!
10年网站模板开发经验,熟悉国内外开源网站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等网站程序,可为您提供网站建设,网站克隆,仿站,网页设计,网站制作,网站推广优化等服务。我们专注高端营销型网站,企业官网,集团官网,自适应网站,手机网站,网络营销,网站优化,网站服务器环境搭建以及托管运维等。为客户提供一站式网站解决方案!!!

小程序模块化开发(小程序中怎么进行模块化处理)

来源:网络转载 时间:2024-05-09 06:38:56

ES6和commonJS的选择

首先在微信小程序中不论是 ES6 或者是 commonJS 模块化语法都是支持的,在传统的web项目中我个人是习惯统一使用 ES6 模块化语法进行开发的。

在最初我也是将小程序中所有的通用方法抽离成单独的文件,并使用exportexport default 导出,使用 import 引入。

注意点

但是!在实际开发中,小程序的js文件是不支持绝对路径引入的!这意味着如果你需要在你的页面中引入一个公用方法,你必须使用 ../../../xxx/xxx.js 的方式,当你同一个页面引入多个模块时,这种写法绝对会极大的打击你的开发热情。

解决方式

那我们该如何解决这么长的引入路径呢,在web项目中,我们常常会使用路径别名的方式,例如 webpackvite 中的 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中同样的问题就是变量及方法的来源不好追溯,变量是在那个位置定义的比较难以定位,这时就更加依赖开发者的开发规范以及命名方式了,再不济也可以每一个方法写一个独有的注释嘛~

感谢你能够认真阅读完这篇文章,希望小编分享的“小程序中怎么进行模块化处理”这篇文章对大家有帮助,同时也希望大家多多支持本站,关注本站行业资讯频道,更多相关知识等着你来学习!

抖音(Tiktok)是由北京字节跳动科技有限公司(ByteDance)孵化的音乐创意短视频社交网站。它于2016年9月20日上线,主要面向全年龄段的用户,尤其是...

飞极速为您提供高清在线电影、电视剧大全、动画片,综艺等,飞极速在线更新及时,播放速度快,给您带来最好的观影体验!飞极速在线,免费提供日本新番动漫、最新电影和最新...

《南华早报》(英语:South China Morning Post, SCMP)和星期日出版的《星期日南华早报》(英语:Sunday Morning Post...

2022年4月20日消息,腾讯旗下休闲娱乐游戏《QQ堂》将正式停止中国大陆地区的运营。这款游戏将于今日11点关闭服务器,届时玩家将不能正常登录游戏。同时,游戏服务器的官网、论坛、专属客服也均关闭。《QQ堂》于2004年12月29日推出,是腾讯的大型游戏处女作,至今已运营逾17年,曾是很多人的童年。2021年12月,《QQ堂》因项目组战略计划,宣布停运。消息一出一度冲上热搜,不少网友纷纷直呼,&ld...

2013年5月10日,马云卸任阿里巴巴集团CEO,将接力棒传给了与之有13年共事经历的陆兆禧。当时马云发表演讲时表示,10年之间,淘宝能成功、电子商务在中国能成功,是因为人与人之间建立起了信任关系。他也感谢10年来团队给他的信任,也相信新时代是年轻人的时代,希望大家像支持他一样支持继任者陆兆禧及其新团队。马云说,10年前的大家不会愿意从一个素未谋面的人那买一个从未见过的东西。但10年后,每天中国电...

洪都拉斯大蓝洞洪都拉斯蓝色大洞穴世界上最危险的国家:暴力是贫困导致的并发症。洪都拉斯是中美洲的一个多山国家,位于太平洋和加勒比海之间,与危地马拉、萨尔瓦多和尼加拉瓜接壤。国土面积约11.2万平方公里,人口约960万。这里曾经是印第安人的住所,大航海时代的到来改变了这一切。1502年,哥伦布在此登陆,但由于风高浪急,船队几乎倾覆,于是哥伦布将其命名为“洪都拉斯”(意为“深渊”),这成为了一个预言。1...

TOP