1.从小程序基础库版本1.6.3开始,小程序支持简洁的组件化编程。查看自己使用的小程序基础库版本,可以通过在开发者工具右侧点击详情查看:
最基本的组件2.小程序的组件,其实就是一个目录,该目录需要包含4个文件:
xxx.jsonxxx.wxmlxxx.wxssxxx.js声明一个组件3.首先需要在json文件中进行自定义组件声明(将component字段设为true可这一组文件设为自定义组件)
{"component":true}4.其次,在要引入组件的页面的json文件内,进行引用声明
{"usingComponents":{//自定义的组件名称:组件路径,注意是相对路径,不能是绝对路径"component-tag-name":"path/to/the/custom/component"}}5.这样,在主页面就可以使用了。
6.相比于vue的组件引入,小程序的方案更简洁。vue组件引入是需要import之后,同时在components里面注册,而小程序的组件只需要在.json里面注册,就可以在wxml里面使用。
使用slot7.和vue相同,小程序也有slot概念。
单一slot8.在组件模板中可以提供一个slot节点,用于承载组件引用时提供的子节点。
//主页面内,addlike是组件addlikeitem"item"my_properties"sssss"text我是被slot插入的文本/text/addlike//addlike组件viewclass"container"viewhello,这里是组件/viewviewhello,{{my_properties}}/viewslot/slot/view//渲染后viewclass"container"viewhello,这里是组件/viewviewhello,{{my_properties}}/viewtext我是被slot插入的文本/text/view多个slot9.如果需要在组件内使用多个slot,需要在组件js中声明启用:
Component({options:{multipleSlots:true//在组件定义时的选项中启用多slot支持},properties:{/*...*/},methods:{/*...*/}})10.使用:
//主页面addlikeitem"item"my_properties"sssss"//在普通的元素上加入slot属性,指定slotname,就可以变成子元素的slot了textslot"slot1"我是被slot1插入的文本/texttextslot"slot2"我是被slot2插入的文本/text/addlike//子页面viewclass"container"viewhello,这里是组件/viewviewhello,{{my_properties}}/viewslotname"slot1"/slotslotname"slot2"/slot/viewComponent构造器11.刚才我们说了,一个组件内应该包括js,wxml,wxss,json四个文件。wxml相当于是HTML,wxss相当于是css,那么js里面应该写什么呢?
12.微信官方提供的案例中:
Component({behaviors:[],properties:{},data:{},//私有数据,可用于模版渲染//生命周期函数,可以为函数,或一个在methods段中定义的方法名attached:function(){},moved:function(){},detached:function(){},methods:{onMyButtonTap:function(){},_myPrivateMethod:function(){},_propertyChange:function(newVal,oldVal){}}})13.里面调用了一个Component构造器。Component构造器可用于定义组件,调用Component构造器时可以指定组件的属性、数据、方法等。具体Component里面可以放什么东西,如下所示:
propertiesObjectMap否相当于是vue的props,通过该属性,外界向组件内传入数据。组件的对外属性,是属性名到属性设置的映射表,属性设置中可包含三个字段,type表示属性类型、value表示属性初始值、observer表示属性值被更改时的响应函数dataObject否组件的内部数据,和properties一同用于组件的模版渲染。也就是说,通过this.data可以同时获得data和propertiesmethodsObject否组件的方法,包括事件响应函数和任意的自定义方法,关于事件响应函数的使用,参见组件事件behaviorsStringArray否类似于mixins和traits的组件间代码复用机制,参见behaviorscreatedFunction否组件生命周期函数,在组件实例进入页面节点树时执行,注意此时不能调用setDataattachedFunction否组件生命周期函数,在组件实例进入页面节点树时执行readyFunction否组件生命周期函数,在组件布局完成后执行,此时可以获取节点信息(使用SelectorQuery)movedFunction否组件生命周期函数,在组件实例被移动到节点树另一个位置时执行detachedFunction否组件生命周期函数,在组件实例被从页面节点树移除时执行relationsObject否组件间关系定义,参见组件间关系optionsObjectMap否一些组件选项,请参见文档其他部分的说明组件与数据通信14.组件化必然要涉及到数据的通信,为了解决数据在组件间的维护问题,vue,react,angular有不同的解决方案。而小程序的解决方案则简洁很多。
主页面传入数据到组件15.properties相当于vue的props,是传入外部数据的入口。
//主页面使用组件aadd_like"{{add_like}}"/a//组件a.js内Component({properties:{add_like:{type:Array,value:[],observer:function(){}}}})16.注意:传入的数据,不管是简单数据类型,还是引用类型,都如同值复制一样(和红宝书里面描述js函数参数传入是值复制还不一样,红宝书里面的意思是:简单数据类型直接复制数值,引用类型复制引用,也就是说在函数内修改参数对象的属性,会影响到函数外对象的属性)。
17.如果是Vue的props,则可以通过.sync来同步,而在小程序子组件里面,调用this.setData()修改父组件内的数据,不会影响到父组件里面的数据,也就是说,子组件property的修改,仿佛和父组件没有任何关系。那么,如果是在子组件内修改父组件的数据,甚至是修改兄弟组件内的数据,有没有简单的方法呢?下面会有讲到
组件传出数据到主页面18.和vue类似,组件间交互的主要形式是自定义事件。
19.组件通过this.triggerEvent()触发自定义事件,主页面在组件上bind:component_method"main_page_mehod"来接收自定义事件。
20.其中,this.triggerEvent()方法接收自定义事件名称外,还接收两个对象,eventDetail和eventOptions。
//子组件触发自定义事件ontap(){//所有要带到主页面的数据,都装在eventDetail里面vareventDetail{name:'sssssssss',test:[1,2,3]}//触发事件的选项bubbles是否冒泡,composed是否可穿越组件边界,capturePhase是否有捕获阶段vareventOption{composed:true}this.triggerEvent('click_btn',eventDetail,eventOption)}//主页面里面main_page_ontap(eventDetail){console.log(eventDetail)//eventDetail//changedTouches//currentTarget//target//type//……//detail哈哈,所有的子组件的数据,都通过该参数的detail属性暴露出来}组件之间数据通信21.和vue提出的vuex的解决方案不同,小程序的组件间的通讯简单小巧。你可以和主页面与组件通讯一样,使用自定义事件来进行通讯,当然更简单方便的方法,是使用小程序提供的relations.
22.relations是Component构造函数中的一个属性,只要两个组件的relations属性产生关联,他们两个之间就可以捕获到对方,并且可以相互访问,修改对方的属性,如同修改自己的属性一样。
Component({relations:{'./path_to_b':{//'./path_to_b'是对方组件的相对路径type:'child',//type可选择两组:parent和child、ancestor和descendantlinked:function(target){}//钩子函数,在组件linked时候被调用target是组件的实例,linkChanged:function(target){}unlinked:function(target){}}},})23.比如说,有两个组件如代码所示:
//组件aslot包含了组件bab/b/a24.他们之间的关系如下图所示:
25.两个组件捕获到对方组件的实例,是通过this.getRelationNodes('./path_to_a')方法。既然获取到了对方组件的实例,那么就可以访问到对方组件上的data,也可以设置对方组件上的data,但是不能调用对方组件上的方法。
//在a组件中Component({relations:{'./path_to_b':{type:'child',linked:function(target){}//target是组件b的实例,linkChanged:function(target){}unlinked:function(target){}}},methods:{test(){varnodesthis.getRelationNodes('./path_to_b')varcomponent_bnodes[0];//获取到b组件的数据console.log(component_b.data.name)//设置父组件的数据//这样的设置是无效的this.setData({component_b.data.name:'ss'})//需要调用对方组件的setData()方法来设置component_b.setData({name:'ss'})}}})//在b组件里面Component({relations:{'./path_to_a':{//注意!必须双方组件都声明relations属性type:'parent'}},data:{name:'dudu'}})26.注意:1.主页面使用组件的时候,不能有数字,比如说component_sub1或component_sub_1,可以在主页面的json里面设置一个新名字
{"usingComponents":{"test_component_subb":"../../../components/test_component_sub2/test_component_sub2"}}27.2.relations里面的路径,比如说这里:
28.
29.是对方组件真实的相对路径,而不是组件间的逻辑路径。
30.3.如果relations没有关联,那么this.getRelationNodes是获取不到对方组件的
31.4.本组件无法获取本组件的实例,使用this.getRelatonsNodes('./path_to_self')会返回一个null
32.4.type可以选择的parent、child、ancestor、descendant
33.现在我们已经可以做到了两个组件之间的数据传递,那么如何在多个组件间传递数据呢?
34.如上图所示,同级的组件b和同级的组件c,b和c之间不可以直接获取,b可以获取到a,c也可以获取到a,而a可以直接获取到b和c。所以,如果想获取到兄弟元素,需要先获取到祖先节点,然后再通过祖先节点获取兄弟节点
35.我在组件b里面,我需要先找到祖先组件a的实例,然后用祖先组件a的实例的getRelationNodes方法获取到组件c的实例。
36.看见没?恐怕我们又要写一大堆重复性的代码了。
37.幸好,微信小程序还提供了behavior属性,这个属性相当于mixin,很容易理解的,是提高代码复用性的一种方法。
38.思路:
39.假设目前有三个组件,组件a,组件b,组件c,其中组件b和组件c是兄弟组件,组建a是b和c的兄弟组件。为了减少代码的重复性,我们把获取父组件的方法,和获取兄弟组件的方法封装一下,封装在behavior的methods中。只要是引入该behavior的组件,都可以便捷的调用方法。
40.实现:
41.新建一个behavior文件,命名无所谓,比如说relation_behavior.js
//在get_relation.js文件里面module.exportsBehavior({methods:{//获取父组件实例的快捷方法_parent(){//如果根据该路径获取到acestor组件为null,则说明this为ancesorvarparentNodethis.getRelationNodes('../record_item/record_item')if(parentNodeparentNode.length!0){returnparentNode[0]}else{returnthis}},//获取兄弟组件实例的快捷方法_sibling(name){varnodethis._parent().getRelationNodes(`../${name}/${name}`)if(nodenode.length0){returnnode[0]}}}})42.然后在组件b,和组件c上引入该behavior,并且调用方法,获取父组件和兄弟组件的实例
//组件b中varrelation_behaviorrequire('./path_to_relation_behavior')Component({behaviors:[relation_behavior],methods:{test(){//获得父组件的实例letparentthis._parent()//访问父组件的数据dconsole.log(parent.data.name)//修改父组件的数据parent.setData({name:'test1'})//获得兄弟组件的实例letsiblingthis._sibling('c')//访问兄弟组件的数据console.log(sibling.data.name)//修改兄弟组件的数据sibling.setData({name:"test"})}}})//组件c中varrelation_behaviorrequire('./path_to_relation_behavior')Component({behaviors:[relation_behavior],methods:{test(){//获得父组件的实例letparentthis._parent()//访问父组件的数据dconsole.log(parent.data.name)//修改父组件的数据parent.setData({name:'test1'})//获得兄弟组件的实例letsiblingthis._sibling('b')//访问兄弟组件的数据console.log(sibling.data.name)//修改兄弟组件的数据sibling.setData({name:"test"})}}})43.同时需要注意,c和b两个组件,从relations属性的角度来说,是a的后代组件。
44.但是组件b和组件c所处的作用域,都是主页面的作用域,传入的property都是主页面的property,这样就保证了组件数据的灵活性。relations像一个隐形的链子一样把一堆组件关联起来,关联起来的组件可以相互访问,修改对方的数据,但是每一个组件都可以从外界独立的获取数据。
45.看了这么多理论的东西,还是需要一个具体的场景来应用。
46.比如说,我们有个一个分享记录图片心情的页面,当用户点击【点赞】的按钮时候,该心情的记录点赞按钮会变红,下面的一栏位置会多出点赞人的名字。
47.如果不通过组件化,很可能的做法是修改一个点赞按钮,然后遍历数据更新数据,最后所有记录列表的状态都会被重新渲染一遍。
48.如果是通过组件化拆分:把点赞的按钮封装为组件b,下面点赞人的框封装为组件c,每一个心情记录都是一个组件a
49.下面是代码实现
//在主页面内viewwx:for'{{feed_item}}'aitem'{{item}}'b/bc/c/aview//在组件a内varbehavior_relationrequire('../../relation_behavior.js)//这里引入上文说的BehaviorComponent({behaviors:[behavior_relation],relations:{'../b/b':{type:'descendant'}}})//在组件b内varbehavior_relationrequire('../../relation_behavior.js)//这里引入上文说的BehaviorComponent({behaviors:[behavior_relation]relations:{'../a/a':{type:'ancestor'}},data:{is_like:false//控制点赞图标的状态},methods:{//当用户点赞的时候onClick(){//修改本组件的状态this.setData({is_like:true})//修改c组件的数据this._sibling('c').setData({likeStr:this._sibling('c').data.likeStr+'我'})}}})//在组件c内varbehavior_relationrequire('../../relation_behavior.js)//这里引入上文说的BehaviorComponent({behaviors:[behavior_relation],relations:{'../a/a':{type:'ancestor'}},data:{likeStr:'晓红,小明'}})50.这样,组件b可以修改组件c中的数据。同时,组件b和组件c又可以通过properties和事件系统,和主页面保持独立的数据通信。
微信小程序组件化的解决方案-微信小程序最难的是组件-微信小程序组件开发
浏览量:2844
时间:
来源:极乐叔
版权声明
即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。
最新资讯
-

即速应用,赋能企业玩转微信小程序智慧经营
作为国内领军的智慧商业经营服务商,即速应用始终秉承“让每个企业都拥有自己的智慧店铺”的愿景,持续赋能更多企业玩转智慧经营。即速应用旗下拥有“小程序搭建工具-即速应用”、“私域流量专家-即客云”等产品,帮助商家打通互联网全生态营销闭环。 -

即客云2.0重磅更新,让微信小程序运营更简单!
即客云作为一款基于企业微信的第三方工具,现从多维度提供超过30种功能,自上线以来,已服务多家企业,受到一致好评。近期,我们根据客户反馈和市场调研正式推出升级版 即客云2.0!更新了私域运营SOP,群日历功能,批量拓客,客户雷达,消息推送,个人欢迎语,帮助企业更好运用企业微信;同时提升了社群运营工作标准化,提升运营效率,帮助企业实现客户增长,玩转私域流量。 -

零代码 + AI 双轮驱动|即速应用解锁人工智能小程序开发新范式
无需代码、无需 AI 算法功底,普通人也能快速搭建智能小程序。即速应用将人工智能与零代码开发深度融合,推出 AI 智能生成能力,用户通过自然语言描述需求,AI 自动生成小程序页面、功能模块与后台配置,覆盖商城、预约、同城、社区团购等全场景。平台内置 AI 智能推荐、智能客服、用户画像分析等能力,一键对接微信生态,打通视频号、企业微信、短信跳转,帮企业快速落地 AI 应用,抢占智慧经营先机,让每家企业都拥有 AI 驱动的智慧店铺。










