• <td id="ueojn"></td>

      <blockquote id="ueojn"><ruby id="ueojn"></ruby></blockquote>
            <output id="ueojn"><ruby id="ueojn"><address id="ueojn"></address></ruby></output><code id="ueojn"></code>
            北京网站建设>建站知识>开发小记>

            开发小记

            微信小程序自定义组件详解

            来源:未知 作者:admin 时间:2019-04-02 17:05 点击:

            自定义组件能够帮我们更好的复用代码和重构简化代码复杂度。一起来学习一下小程序自定义组件的内容吧。

            从小程序基础库版本 1.6.3 开始,小程序支持简洁的组件化编程。所有自定义组件相关特性都需要基础库版本 1.6.3 或更高。

            开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。自定义组件在使用时与基础组件非常相似

            总览

            image.png

             

            一、Component概念

            Component像页面一样由wxml、wxss、js和json4个文件组成,且需要把这4个文件放在同一个目录?#23567;?#19982;页面不一样的是,Component中的构造函数(也可以称构造器)是Component({}),而页面中的构造函数是Page({})。要编写一个自定义组件,首先需要在 JSON 文件中进行自定义组件声明(将component字段设为true可这一组文件设为自定义组件):

            {
              "component": true
            }
            

            slot

            Component的slot(slot意思是插槽),主要是让你在外部的wxml可以自由的在你的Component的wxml里插入模块。默认情况下,一个组件的wxml只可能有一个slot。需要使用多个时,可以在组件js中声明启用。

            Component({
              options: {
                multipleSlots: true // 在组件定义时的选项中启用多slot支持
              },
              properties: { /* ... */ },
              methods: { /* ... */ }
            })
            

            此时,可以在这个组件的wxml中使用多个slot,以不同的 name 来区分。

            <!-- 组件模板 -->
            <view class="wrapper">
              <slot name="before"></slot>
              <view>这里是组件的内部细节</view>
              <slot name="after"></slot>
            </view>
            

            使用时,用 slot 属性来将节点插入到不同的slot上。

            <!-- 引用组件的页面模板 -->
            <view>
              <component-tag-name>
                <!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 -->
                <view slot="before">这里是插入到组件slot name="before"中的内容</view>
                <!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 -->
                <view slot="after">这里是插入到组件slot name="after"中的内容</view>
              </component-tag-name>
            </view>
            

            组件样式编写注意事项

            • 组件和引用组件的页面不能使用id选择器(#a)、属性选择器([a])和标签名选择器,请改用class选择器。
            • 组件和引用组件的页面中使用后代选择器(.a .b)在一些极端情况下会有非预期的表现,如遇,请避免使用。
            • 子元素选择器(.a>.b)只能用于 view 组件与其子节点之间,用于其他组件可能导致非预期的情况。
            • 继承样式,如 font 、 color ,会从组件外继承到组件内。
            • 除继承样式外, app.wxss 中的样式、组件所在页面的的样式对自定义组件无效。
            #a { } /* 在组件中不能使用 */
            [a] { } /* 在组件中不能使用 */
            button { } /* 在组件中不能使用 */
            .a > .b { } /* 除非 .a 是 view 组件节点,否则不一定会生效 */
            

            外部样式类

            使用外部样式类可以让组件使用指定的组件外样式类,如果希望组件外样式类能够完全影响组件内部,可以将组件构造器中的options.addGlobalClass字段置为true。

            /* 组件 custom-component.js */
            Component({
              externalClasses: ['my-class']
            })
            
            <!-- 组件 custom-component.wxml -->
            <custom-component class="my-class">这段文本的颜色由组件外的 class 决定</custom-component>
            
            /* 组件外的样式定义 */
            .red-text {
              color: red;
            }
            

            创建一个组件

            一个组件需要包括json、wxml、wxss、js四个文件组成,下面我们先看看一个简单的入门:

            <!--components/component/component.wxml-->
            <view class="inner">
                {{innerText}}
            </view>
            <slot></slot>
            

            编写JS文件,组件的属性值和内部数据将被用于组件 wxml 的渲染,其中,属性值是可由组件外部传入的

            // components/component/component.js
            Component({
                /**
                 * 组件的属性列表
                 */
                properties: {
                    innerText: {
                        type: String,
                        value: 'hello world'
                    },
                    myProperties:String
                },
            
                /**
                 * 组件的初始数据
                 */
                data: {
            
                },
            
                /**
                 * 组件的方法列表
                 */
                methods: {
            
                }
            })
            

            设置字体的颜色

            /* components/component/component.wxss */
            .inner{color: red;}
            

            完成对组件的初始化,包括设置属性列表,初始化数据,以?#21543;?#32622;相关的方法。

            使用自定义组件

            使用已注册的自定义组件前,首先要在页面的 json 文件中进行引用声明。此时需要提供每个自定义组件的标签名和?#26434;?#30340;自定义组件文件路径:

            {
              "usingComponents": {
                "component": "/components/component/component"
              }
            }
            

            在page页面下添?#30001;?#26126;过的自定义组件:

            <component></component>
            
            <view>
              <component>
                <!-- 这部分内容将被放置在组件 <slot> 的位置上 -->
                <view>这里是插入到组件slot中的内容</view>
              </component>
            </view>
            

            上?#38477;?#26159;一个最简单的自定义组件。

            注意事项:

            1.?#26434;?#22522;础库的1.5.x版本, 1.5.7 也有部分自定义组件支持。

            2.因为WXML节点标签名只能是小写字母、中划线和下划线的组合,所以自定义组件的标签名也只能包含这些字符。

            3.自定义组件也是可以引用自定义组件的,引用方法类似于页面引用自定义组件的方式(使用 usingComponents 字段)。

            4.自定义组件和使用自定义组件的页面所在项目根目录名不能以“wx-”为前缀,否则会报错。

            5.旧版本的基础库不支持自定义组件,此时,引用自定义组件的节点会变为默认的空节点。

            Component构造器

            使用component构造器,进行构造。 该构造函数用于定义组件。调用Component函数能指定组件的数据,属性和方法。来看看这个完整的列表代码含义:

            Component({
            
              behaviors: [],
            
              properties: {
                myProperty: { // 属性名
                  type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示?#25105;?#31867;型)
                  value: '', // 属性初始值(可选),如果未指定则会根据类型选择一个
                  observer: function (newVal, oldVal) {
                      this._propertyChange(newVal, oldVal);
                   } // 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串, 如:'_propertyChange'
                  
                },
                myProperty2: String // 简化的定义方式
              },
              data: {
                A: [{
                  B: 'init data.A[0].B'
                }]
              }, // 私有数据,可用于模版渲染
            
              lifetimes: {
                // 生命周期函数,可以为函数,或一个在methods段中定义的方法名
                attached: function () { },
                moved: function () { },
                detached: function () { },
              },
            
              // 生命周期函数,可以为函数,或一个在methods段中定义的方法名
              attached: function () { }, // 此处attached的声明会被lifetimes字段中的声明覆盖
              ready: function() { },
            
              pageLifetimes: {
                // 组件所在页面的生命周期函数
                show: function () { },
              },
            
              methods: {
                onMyButtonTap: function () {
                  this.setData({
                    // 更新属性和数据的方法与更新页面数据的方法类似
                    myProperty: 'Test'
                  })
                },
                _myPrivateMethod: function () {
                  // 内部方法建议以下划线开头
                  this.replaceDataOnPath(['A', 0, 'B'], 'myPrivateData') // 这里将 data.A[0].B 设为 'myPrivateData'
                  this.applyDataUpdates()
                },
                _propertyChange: function (newVal, oldVal) {
                    console.log(newVal);
                    console.log(oldVal);
                }
              }
            
            })
            

            组件与数据通信

            组件间的通信方法有以下几种:

            • WXML 数据绑定:用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容数据(自基础库版本 2.0.9 开始,还可以在数据中包含函数)。具体在 组件模板和样式 章节中介绍。
            • 事件:用于子组件向父组件传递数据,可以传递?#25105;?#25968;据。
            • 如果以上两种方式不足以满足需要,父组件还可以通过 this.selectComponent 方法获取子组件实例对象,这样就可以直接访问组件的?#25105;?#25968;据和方法。

            通过在页面中给组件加了一个id值,这样子我们就能查到组件的方法了。

            <compontent id="modal"></compontent>
            
            /*js*/
            var modal = this.setlectComponet('#modal');
            

            这样子就能在外面调用组件里面的?#25105;?#25968;据和方法了。

            • properties:主页面传入数据到组件,相当于Vue的props,是传入外部数据的入口。
            • data:则用于组件的内部数据变化,外部数据没法初始化

            image.png

             

            在 properties 定义段中,属性名采用驼峰写法(propertyName);在 wxml 中,指定属性值时则?#26434;?#20351;用连字符写法(component-tag-name property-name="attr value"),应用于数据绑定时采用驼峰写法(attr="{{propertyName}}")

            传入的数据,不管是简单数据类型,还?#19988;?#29992;类型,都如同值复制一样

            方法函数调用

            methods:需要在组件中调用的方法,都写在这个对象里面。跟Page中的对象里面的方法同级。

            生命周期:可单独某个生命周期放在Components下(旧?#38477;?#23450;义方式,可以保持对 <2.2.3 版本基础库的兼容),也可以放在lifetimes,如果两个地方有同名生命周期,则lifetimes里面的方法会覆盖前者。

            image.png

             
            Component({
              lifetimes: {
                attached: function() {
                  // 在组件实例进入页面节点树时执行
                },
                detached: function() {
                  // 在组件实例被从页面节点树移除时执行
                },
              },
              // 以下是旧?#38477;?#23450;义方式,可以保持对 <2.2.3 版本基础库的兼容
              attached: function() {
                // 在组件实例进入页面节点树时执行
              },
              detached: function() {
                // 在组件实例被从页面节点树移除时执行
              },
              // ...
            })
            

            组件所在的生命周期

            还有一些特殊的生命周期,它们并非与组件有很强的关联,但有时组件需要获知,以便组件内部处理。这样的生命周期称为“组件所在页面的生命周期”,在 pageLifetimes 定义段中定义。其中可用的生命周期包括:

            image.png

             

            生成的组件实例可以在组件的方法、生命周期函数和属性 observer 中通过 this 访问。组件包含一些通用属性和方法

            image.png

            image.png

            image.png

             

            组件传出数据到主页面

            组件间交互的主要形式是自定义事件。

            组件通过 this.triggerEvent() 触发自定义事件,主页面在组件上 bind:myevent="onMyEvent" 来接收自定义事件。

            其中,this.triggerEvent() 方法接收自定义事件名称外,还接收两个对象,eventDetail 和 eventOptions。

            <!-- 在自定义组件中 -->
            <button bindtap="onTap">点击这个按钮将触发“myevent”事件</button>
            
            Component({
              properties: {}
              methods: {
                // 子组件触发自定义事件
                ontap () {
                // 所有要带到主页面的数据,都?#38712;趀ventDetail里面
                var eventDetail = {
                        name:'sssssssss',
                        test:[1,2,3]
                }
                // 触发事件的选项 bubbles是否冒泡,composed是否可穿越组件边界,capturePhase 是否有捕获阶段
                var eventOption = {
                        composed: true
                }
                this.triggerEvent('myevent', eventDetail, eventOption)
                }
              }
            })
            

            触发的事件包括:

            image.png

             

            监听事件

            自定义组件可以触发?#25105;?#30340;事件,引用组件的页面可以监听这些事件。监听自定义组件事件的方法与监听基础组件事件的方法完全一致:

            在Page事件中监听组件中传递过来的值。

            Page({
              onMyEvent: function(e){
                e.detail // 自定义组件触发事件时提供的detail对象
              }
            })
            

            behaviors

            behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的“mixins”或“traits”。

            每个 behavior 可以包含一组属性、数据、生命周期函数和方法,组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数?#19981;?#22312;?#26434;?#26102;机被调用。每个组件可以引用多个 behavior 。 behavior 也可以引用其他 behavior 。

            // my-behavior.js
            module.exports = Behavior({
              behaviors: [],
              properties: {
                myBehaviorProperty: {
                  type: String
                }
              },
              data: {
                myBehaviorData: {}
              },
              attached: function(){},
              methods: {
                myBehaviorMethod: function(){}
              }
            })
            

            组件引用时,在 behaviors 定义段中将它们逐个列出即可。

            // my-component.js
            var myBehavior = require('my-behavior')
            Component({
              behaviors: [myBehavior],
              properties: {
                myProperty: {
                  type: String
                }
              },
              data: {
                myData: {}
              },
              attached: function(){},
              methods: {
                myMethod: function(){}
              }
            })
            

            字段的覆盖和组合规则

            组件和它引用的 behavior 中可以包含同名的字段,对这些字段的处理方法如下:

            如果有同名的属性或方法,组件本身的属性或方法会覆盖 behavior 中的属性或方法,如果引用了多个 behavior ,在定义段中靠后 behavior 中的属性或方法会覆盖靠前的属性或方法;
            如果有同名的数据字段,如果数据是对象类型,会进行对象合并,如果是非对象类型则会进行相互覆盖;
            生命周期函数不会相互覆盖,而是在?#26434;?#35302;发时机被逐个调用。如果同一个 behavior 被一个组件多?#25105;?#29992;,它定义的生命周期函数只会被执行一次。

            内置behavior

            组件间关系

            <custom-ul>
              <custom-li> item 1 </custom-li>
              <custom-li> item 2 </custom-li>
            </custom-ul>
            

            这个例子中, custom-ul 和 custom-li 都是自定义组件,它们有相互间的关系,相互间的通信往往比较复杂。此时在组件定义时加入 relations 定义段,可以解决这样的问题。示例:

            // path/to/custom-ul.js
            Component({
              relations: {
                './custom-li': {
                  type: 'child', // 关联的目标节点应为子节点
                  linked: function(target) {
                    // 每次有custom-li被插入时执行,target是该节点实例对象,触发在该节点attached生命周期之后
                  },
                  linkChanged: function(target) {
                    // 每次有custom-li被移动后执行,target是该节点实例对象,触发在该节点moved生命周期之后
                  },
                  unlinked: function(target) {
                    // 每次有custom-li被移除时执行,target是该节点实例对象,触发在该节点detached生命周期之后
                  }
                }
              },
              methods: {
                _getAllLi: function(){
                  // 使用getRelationNodes可以获得nodes数组,包含所有已关联的custom-li,且是有序的
                  var nodes = this.getRelationNodes('path/to/custom-li')
                }
              },
              ready: function(){
                this._getAllLi()
              }
            })
            
            // path/to/custom-li.js
            Component({
              relations: {
                './custom-ul': {
                  type: 'parent', // 关联的目标节点应为父节点
                  linked: function(target) {
                    // 每次被插入到custom-ul时执行,target是custom-ul节点实例对象,触发在attached生命周期之后
                  },
                  linkChanged: function(target) {
                    // 每次被移动后执行,target是custom-ul节点实例对象,触发在moved生命周期之后
                  },
                  unlinked: function(target) {
                    // 每次被移除时执行,target是custom-ul节点实例对象,触发在detached生命周期之后
                  }
                }
              }
            })

            公司业务:北京网站建设刷百度下拉刷百度指数虚拟主机租用

            如转载,请保留本文链接地址:http://www.ctex.tw/Web/Diary/2032/

            Loading......
            工作时间:

            AM 09:00 ~ 12:00

            PM 14:00 ~ 18:00

            联系方式:

            Tel 010-50933590

            Hp 18701620736

            设计优势

            独立的设计团队 带给您全新的视觉体验

            功能开发

            ?#30475;?#30340;技术实力,完成您想要的任何功能

            售后服务

            完善的售后服务,解决您在使用过程中遇?#38477;?#38382;题

            Copyright © 2010 - 2018 北京顺晟科技发展有限公司 All Rights Reserved

            地址:北京市顺义区南法信政府府前街16号 炫立方 | TEL:010-50933590

            北京网站建设 | 北京网站设计 | 北京SEO公司

            山东十一选五走势图