微信小程序> 小程序自定义组件开发及程序组件化模块化开发指南-微信小程序组件化开发-微信小程序组件开发

小程序自定义组件开发及程序组件化模块化开发指南-微信小程序组件化开发-微信小程序组件开发

浏览量:1875 时间: 来源:老马历写记
1.

小程序提供了模块化,自定义组件,模板,分包加载支持,便于小程序团队开发,实现基础功能模块化、组件化,业务功能分包化,团队成员各司其职,从而有效提升代码重用性和开发效率及质量。

2.

一、JS模块化

3.

js模块化是形式,实质则是js代码重用性,一个地方写,N个地方用,基于这个思想,JS模块化有2个实现方式:

4.

1.写在app.js里,不管是数据,还是函数,其它页面只要getApp(),即可调用;

5.

2.写在一个单独js文件里,然后需要引用的地方,require进来;

6.

建议通用性强并且可以简单实现的代码块,放到app.js,否则请单独创建js文件,然后require。

7.

案例1:app.js中实现的wx.showToast封装

8.

上图,左侧为app.js中封装的app.toast调用后的结果,代码如下:

toast(title,cb){letduration2000;wx.showToast({title:title,icon:"none",duration:duration});if(cbtypeofcb'function'){setTimeout(cb,duration);}},//调用代码//app.toast("URL已成功复制,请在浏览器中打开!");9.

上图右侧为wx.showToast直接调用的默认效果

wx.showToast({title:'URL已成功复制,请在浏览器中打开!',})10.

因为,toast使用率极高,且通常情况下只要文本显示效果,所以利用showToast函数,设置icon为none封装了个toast函数,其它地方使用就很简单啦,app.toast(str)即可,并且增加了toast消失的回调处理。

11.

案例2:单独创建js文件,利用require引入并调用。

12.

由于项目需要,写了个/utils/utils.js,包含StrUtil:format等字符串常用函数,DateUtil:日期format,parse等常用函数,代码如下:

/***StringUtil*--format("{0},say{1}!","Marcus","hello");*--format("name:{name}",{name:"mb"})*/varStrUtil(function(){var_formatfunction(){if(arguments.length0)returnnull;varstrarguments[0],aarguments.length1?arguments[1]:null;if(!a||typeofa!'object'){for(vari1;iarguments.length;i++){varrenewRegExp('\{'+(i-1)+'\}','gm');strstr.replace(re,arguments[i]);}}else{//对象格式化.varrnewRegExp('\{([\s\S]+?)\}','gm'),bnull,_strstr;while((br.exec(_str))!null){strstr.replace(b[0],a[b[1]]);}}returnstr;},_isEmptyfunction(str){if(strundefined||strnull)return!0;if(str0)return!1;strstr+'';return!!str?(str.trim()""||str"null"):!0;},_ltrimfunction(str,c''){str+'';returnstr.replace(newRegExp("^("+c+")+","g"),"");},_rtrimfunction(str,c''){str+'';returnstr.replace(newRegExp("("+c+")+$","g"),"");},_toIntegerfunction(str,val0){letvalueval;try{valueparseInt(str-0);}catch(e){}returnisNaN(value)?val:value;},_toFloatfunction(str,val0){letvalueval;try{valueparseFloat(str-0);}catch(e){}returnisNaN(value)?val:value;},_toFixedfunction(num,scale2){if(numundefined||numnull||isNaN(num))returnnum;letresult(num-0).toFixed(scale);returnresult?result.replace(/.?0+$/,''):result;};return{format:_format,isEmpty:_isEmpty,ltrim:_ltrim,rtrim:_rtrim,toInteger:_toInteger,toFloat:_toFloat,toFixed:_toFixed};})();varDateUtil(function(){var_fp"yyyy-MM-ddhh:mm:ss",_sp"yyyy-MM-dd";/***转换日期对象为日期字符串*@paramllong值*@parampattern格式字符串,例如:yyyy-MM-ddhh:mm:ss*@return符合要求的日期字符串*/var_formatfunction(date,format"yyyy-MM-dd"){datedate||newDate;varo{"M+":date.getMonth()+1,"d+":date.getDate(),"h+":date.getHours(),"m+":date.getMinutes(),"s+":date.getSeconds(),"q+":Math.floor((date.getMonth()+3)/3),"S":date.getMilliseconds()};if(/(y+)/.test(format)){formatformat.replace(RegExp.$1,(date.getFullYear()+"").substr(4-RegExp.$1.length));}for(varkino){if(newRegExp("("+k+")").test(format)){formatformat.replace(RegExp.$1,RegExp.$1.length1?o[k]:("00"+o[k]).substr((""+o[k]).length));}}returnformat;},//字符串转日期_parsefunction(value){lett0;if(value){if(valueinstanceofDate)returnvalue;if(isNaN(value)){if(value.split("-").length2)value+"-01";//yyyy-mmtDate.parse(value.replace(/-/g,"/"));}else{tvalue-0;}}returnt0?newDate():newDate(t);},_addMonthfunction(date,num){numparseInt(num),date(dateinstanceofDate)?date:_parse(date);letydate.getFullYear(),mdate.getMonth(),ddate.getDate();returnnewDate(y,m+num,d);},_addDayfunction(date,num){numparseInt(num),date(dateinstanceofDate)?date:_parse(date);letydate.getFullYear(),mdate.getMonth(),ddate.getDate();returnnewDate(y,m,d+num);},_isLeapYearfunction(year){return(year%4000)||(year%40year%100!0);},_getMonthDaysfunction(year,month){return[0,31,null,31,30,31,30,31,31,30,31,30,31][month]||(_isLeapYear(year)?29:28);},/***获取某年的周数.*/_getWeeksfunction(year){vardays_isLeapYear(year)?366:365;varwnewDate(year,0,1).getDay()||7,w_othersdays-(7-w+1);returnMath.ceil(w_others/7)+1;},/***获取某年第几周的开始日期.*不传参数取本周开始日期.*/_getWeekFisrtDayfunction(year0,week0){letnownewDate;if(year2000||week1){yearnow.getFullYear()weekthis.getWeekNumber(now);}vardnewDate(year,0,1),wd.getDay()||7;returnweek1?_addDay(d,7*(week-1)-w+1):d;},//获取某年第几周的结束日期_getWeekLastDayfunction(year0,week0){yearyear-0,weekweek-0;varfirstDaythis.getWeekFisrtDay(year,week),wfirstDay.getDay()||7;return_addDay(firstDay,7-w);},/***获取某年的某天是第几周,日期或字符串*/_getWeekNumberfunction(now){nowthis.parse(now);varyearnow.getFullYear(),monthnow.getMonth(),daysnow.getDate();//那一天是那一年中的第多少天for(vari0;imonth;i++){days+_getMonthDays(year,i+1);}//那一年第一天是星期几,周日周七varyearFirstDaynewDate(year,0,1).getDay()||7,weeknull;if(yearFirstDay1){weekMath.ceil(days/yearFirstDay);}else{days-(7-yearFirstDay+1),weekMath.ceil(days/7)+1;}returnweek;},_getMonthFstDayfunction(date){return_format(_parse(date),"yyyy-MM")+"-01";},_getMonthLstDayfunction(date){dateDateUtil.parse(date);varyeardate.getFullYear(),monthdate.getMonth();return_format(newDate(year,month,_getMonthDays(year,month+1)),_sp);};return{format:_format,getSmpDate:function(date){return_format(date,_sp);},getFullDate:function(date){return_format(date,_fp);},parse:_parse,addMonth:_addMonth,addDay:_addDay,isLeapYear:_isLeapYear,getWeeks:_getWeeks,getWeekFisrtDay:_getWeekFisrtDay,getWeekLastDay:_getWeekLastDay,getMonthDays:_getMonthDays,getWeekNumber:_getWeekNumber,getMonthFstDay:_getMonthFstDay,getMonthLstDay:_getMonthLstDay,};})();module.exports{StrUtil,DateUtil}13.

由于是Util函数,其它页面使用频率极高,因此直接在app.js引入:

letutilsrequire("utils/util.js");14.

其它页面调用则只要获取app,调用app.utils.DateUtil即可,如:

varappgetApp(),DateUtilapp.utils.DateUtil;Page({/***页面的初始数据*/data:{rec_date:DateUtil.getSmpDate(newDate()),end_date:DateUtil.getSmpDate(newDate()),rec_steps:0,},15.

二、组件化

16.

两种实现方式,其一是通过早期的模板变相实现,另外一个则是后来推出的自定义组件。

17.

1、通过模板实现

18.

1)定义模板:wxml,wxss和js文件,如一个消息提示组件,toptips

19.

/components/tmp_toptips/toptips.wxml

templatename"toptips"viewclass"my-toptips{{icon?'my-toptips_'+icon:'my-toptips_cancel'}}{{animation}}"hidden"{{!visible}}"iconwx:if"{{icon}}"class"my-toptips_icon"type"{{icon}}"size"20"color"#fff"/text{{text}}/text/view/template/components/tmp_toptips/toptips.wxss@-webkit-keyframesnotify-downin{0%{opacity:0;-webkit-transform:translate3d(0,-50px,0);transform:translate3d(0,-50px,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframesnotify-downin{0%{opacity:0;-webkit-transform:translate3d(0,-50px,0);transform:translate3d(0,-50px,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.my-animate-notify-downin{-webkit-animation:notify-downin.3slinearforwards;animation:notify-downin.3slinearforwards}@-webkit-keyframesnotify-upout{0%{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}to{opacity:0;-webkit-transform:translate3d(0,-50px,0);transform:translate3d(0,-50px,0)}}@keyframesnotify-upout{0%{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}to{opacity:0;-webkit-transform:translate3d(0,-50px,0);transform:translate3d(0,-50px,0)}}.my-animate-notify-upout{-webkit-animation:notify-upout.3slinearforwards;animation:notify-upout.3slinearforwards}.my-toptips{position:fixed;z-index:99;padding:20rpx30rpx;box-sizing:border-box;color:#fff;font-size:30rpx;line-height:40rpx;width:100%;top:0;display:flex;flex-direction:row;}.my-toptips_success{background-color:#09bb08!important;}.my-toptips_info{background-color:#10aefe!important;}.my-toptips_warn{background-color:#ffbe00!important;}.my-toptips_cancel{background-color:#e74341!important;}.my-toptips_icon{margin-right:12rpx;width:40rpx;height:40rpx;}.my-toptipstext{flex:1;line-height:1.375}20.

/components/tmp_toptips/toptips.js

/***模块化组件*@param{Object}options配置项*@param{String}options.scope组件的命名空间*@param{Object}options.data组件的动态数据*@param{Object}options.methods组件的事件函数*/classTopTips{constructor(options{}){this.optionsObject.assign({scope:"$my.toptips",icon:`cancel`,hidden:!1,text:``,timer:3000},options);this.pagegetCurrentPages()[getCurrentPages().length-1]this.setDatathis.page.setData.bind(this.page)//初始化组件状态this.setData({[`${this.options.scope}.icon`]:this.options.icon,[`${this.options.scope}.text`]:this.options.text});}/***设置元素显示*/setVisible(){this.setData({[`${this.options.scope}.visible`]:!0,[`${this.options.scope}.animation`]:'my-animate-notify-downin'})}/***设置元素隐藏*/setHidden(timer300){//this.setData({//[`${this.options.scope}.animateCss`]:className,//})setTimeout((){this.setData({[`${this.options.scope}.visible`]:!1,[`${this.options.scope}.animation`]:'my-animate-notify-upout'})},timer)}}exportdefault{show(opts{}){//实例化组件consttopTipsnewTopTips(opts);topTips.setHidden(topTips.options.timer);topTips.setVisible();}}21.

2)目标页面引入模板

22.

wxml文件,引入模板wxml

23.

importsrc"/components/tmp_toptips/toptips.wxml"/

24.

templateis"toptips"data"{{...$my.toptips}}"/

25.

wxss文件,引入模板wxss

26.

@import'/components/tmp_toptips/toptips.wxss';

27.

js文件,引入模板js

28.

import$toptipsfrom'../../../components/tmp_toptips/toptips'

29.

3)目标页面js调用

30.

$toptips.show({text:"模板方式调用!"});

31.

2、自定义组件

32.

1)定义自定义组件,跟普通页面文件构成一样,由json,wxml,wxss,js4个文件构成,最大区别在于js文件是都有的自定义组件结构,还是以上述的消息提示组件,toptips为例:

33.

/components/toptips/toptips.json设置component为true

{"component":true}34.

/components/toptips/toptips.wxml,自定义组件显示内容

viewclass"my-toptips{{icon?'my-toptips_'+icon:'my-toptips_cancel'}}{{animateCss}}"hidden"{{hidden}}"iconwx:if"{{icon}}"class"my-toptips_icon"type"{{icon}}"size"20"color"#fff"/text{{text}}/text/view35.

/components/toptips/toptips.wxss,样式,同/components/tmp_toptips/toptips.wxss

36.

/components/toptips/toptips.js,js文件

//components/component-tag-name.jsComponent({/***组件的属性列表*/properties:{text:{type:String,value:'提示文本'},icon:{type:String,value:'cancel'},timer:{type:Number,value:3000},hidden:{type:Boolean,value:false,observer:function(newVal,oldVal){if(!newValthis.data.timer0){setTimeout((){this.setData({hidden:true})},this.data.timer);}this.setData({animateCss:newVal?"my-animate-notify-upout":"my-animate-notify-downin"});}}},/***组件的初始数据*/data:{animateCss:'my-animate-notify-downin'},/***组件的方法列表*/methods:{}})37.

2)目标页面,引用组件,并通过setData实现toptips显示与否

38.

index.json,定义组件的tag标签

{"navigationBarTitleText":"Js模块化,组件化Demo","usingComponents":{"my-toptips":"/components/toptips/toptips"}}39.

3)目标页面,js调用

showTopTips2(e){this.setData({['toptips.text']:"自定义组件方式调用!",['toptips.hidden']:false});}40.

最终效果图如下:

版权声明

即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。

  • 头条
  • 搜狐
  • 微博
  • 百家
  • 一点资讯
  • 知乎