微信小程序的组件

2年前 (2022) 程序员胖胖胖虎阿
130 0 0

第五单元 小程序组件

一、昨日知识点回顾

1.小程序导航
2.上拉加载和下拉刷新的配置
3.小程序网络请求
4.异步api的promise化

二、本单元知识点概述

(Ⅰ)指定教材

(Ⅱ)知识点概述

(Ⅲ)教学时长

共4课时,180分钟


三、本单元教学目标

(Ⅰ)重点知识目标

1.组件的创建
2.组件通信

(Ⅱ)能力目标

1.掌握组件的创建
2.掌握组件通信

四、本单元知识详讲

5.1. 小程序组件

5.1.1 组件创建

  1. 在项目的根目录中,鼠标右键,创建 components -> test 文件夹

  2. 在新建的 components -> test 文件夹上,鼠标右键,点击“新建 Component”

  3. 为新建的组件命名之后,会自动生成组件对应的 4 个文件,后缀名分别为 .js,.json, .wxml 和 .wxss

  4. 在.json文件中设置component: true

注意:尽量将不同的组件,存放到单独的文件夹中,从而保证清晰的目录结构

5.1.2 组件的引用与样式

  1. 引用组件

    1. 在需要引用组件的页面中,找到页面的 .json 配置文件,新增usingComponents节点

    2. 在 usingComponents 中,通过键值对的形式,注册组件;键为注册的组件名称,值为组件的引用路径

      usingComponents: {
          "组件名": "组件所在路径"
      }
      usingComponents: {
          "my-test": "/component/test/test"
      }
    3. 在页面的 .wxml 文件中,把注册的组件名称,以标签形式在页面上使用,即可把组件展示到页面上

      <组件名></组件名>
      <my-test></my-test>

    注意:注册组件名称时,建议把名称注册为短横线连接的形式,例如 vant-button 或 custom-button

  2. 样式

    • 组件对应 wxss 文件的样式,只对组件 wxml 内的节点生效

    • 注意点:

      1. 组件和引用组件的页面不能使用id选择器(#a)、属性选择器([a])和标签名选择器,请改用class选择器。

      2. 组件和引用组件的页面中使用后代选择器(.a .b)在一些极端情况下会有非预期的表现,如遇,请避免使用。

      3. 子元素选择器(.a>.b)只能用于 view 组件与其子节点之间,用于其他组件可能导致非预期的情况

      4. 继承样式,如 font 、 color ,会从组件外继承到组件内。

      5. 除继承样式外, app.wxss 中的样式、组件所在页面的样式对自定义组件无效。

5.2. 组件的数据与方法

5.2.1 使用data定义组件的私有数据

  • 小程序组件中的 data,和小程序页面中的data 用法一致,只不过组件中的data是定义在Component()函数中

  • 在组件的.js文件中,要访问data中的数据,直接this.data.数据名称即可

  • 在组件的.js文件中,要修改data中的数据,直接调用this.setData()即可

  • 示例代码:

    <!--component/test/test.wxml-->
    <button bindtap="add">点击</button>
    <text>{{ num }}</text>
    // component/test/test.js
    Component({
      // 组件的初始数据
      data: {
        num: 0
      },
      // 组件的方法列表
      methods: {
        add() {
          this.setData({
            num: this.data.num + 1
          })
        }
      }
    })

5.2.2 使用methods定义组件的事件处理函数

  • 和页面不同,组件的事件处理函数,必须定义在 methods 节点中

  • 示例代码:

    // component/test/test.js
    // 组件的方法列表
    methods: {
        add() {
            this.setData({
                num: this.data.num + 1
            })
        }
    }

5.3. properties

5.3.1 properties简介

  • 类似于 vue 组件中的 props,小程序组件中的 properties,是组件的对外属性,用来接收外界传递到组件中的数据

  • 在小程序中,组件的 properties 和 data 的用法类似,它们都是可读可写的

  • 和data的区别

    • data 更倾向于存储组件的私有数据

    • properties 更倾向于存储外界传递到组件中的数据

5.3.2 properties语法结构

  • 声明properties的两种方式

    Component({
        properties: {
            // 完整的定义方式
            propA: {  // 属性名 
                type: String, // 属性类型 
                value: ''   // 属性默认值
            },
            propB: String  // 简化的定义方式
        }
    })
  • 示例代码:

    // component/test/test.js
    // 接收对外传递过来的数据
    properties: {
        msg: { // 接收的数据
            type: String, // 数据类型
            value: 'hello world' // 数据的默认值
        }
    }
  • 注意:type 的可选值为 Number,String、Boolean、Object、Array、null(表示不限制类型)

5.3.3 向组件传递properties的值

  • 可以使用数据绑定的形式,向子组件的属性传递动态数据

  • 示例代码:

    <!--pages/home/home.wxml-->
    <view>
      <my-test msg="hello world2"></my-test>
      <my-test msg="{{ info }}"></my-test>
    </view>
    // pages/home/home.js
    data: {
        info: "我是定义在data中的数据"
    }
  • 注意:在定义 properties 时,属性名采用驼峰写法(propertyName);在 wxml 中,指定属性值时,则对应使用连字符写法(property-name=“attr value”),应用于数据绑定时,采用驼峰写法(attr="{{propertyName}}")

5.3.4 组件内修改properties

  • 小程序中,properties 的值是可读可写的,它的用法与 data 几乎一致,因此可以通过 setData 修改 properties 中任 何属性的值

  • 示例代码:

    <!--component/test/test.wxml-->
    <button bindtap="updateProperties">修改propeoties属性</button>
    // component/test/test.js
    updateProperties() {
        // 获取 properties中的值:this.properties.msg
        console.log(this.properties.msg)
        // 修改 properties中的值
        this.setData({
            msg: 'info'
        })
    }

5.4. 数据监听器

  • 数据监听器可以用于监听和响应任何属性和数据字段的变化,从而执行特定的操作。从小程序基础库版本 2.6.1 开始支持,作用类似于 vue 中的 watch

5.4.1 基本使用方法

语法格式:

Component({
    observers: {
        '字段A, 字段B': function(字段A的新值,字段B的新值) {
            // do something
        }
    }
})

示例代码:

Component({
    // 接收对外传递过来的数据
    properties: {
        msg: { // 接收的数据
            type: String, // 数据类型
            value: 'hello world' // 数据的默认值
        }
    },
    // 组件的初始数据
    data: {
        num: 0
    },
    // 数据监听器
    observers: {
        // 同时监听num和msg的变化,只要num或msg的值有一个发生变化了,就会触发监听器函数
        'num, msg'(newNum, newMsg) {
            // newNum: 监听的num变化以后的值
            // newMsg: 监听的msg变化以后的值
            console.log(newNum, newMsg)
        }
    }
})

5.4.2 监听子数据字段语法

  1. 监听子数据字段的变化

    • 数据监听器支持监听属性或内部数据的变化,可以同时监听多个。一次 setData 最多触发每个监听器一次

    observers: {
        // 如果obj这个对象改变了,数据监听器会响应;如果obj中a的值发生改变了,数据监听器也会响应
        'obj.a'(newValue) {
            // do something
            // newValue: 变化以后的新值
        },
        'arr[1]'(newValue) {
            // do something
            // newValue: 变化以后的新值
        }
    }

    示例代码:

    Component({
        data: {
            arr: [1, 2, 3, 4]
        },
        // 数据监听器
        observers: {
            //如果arr这个数组改变了,数据监听器会响应;如果arr中某一个值发生改变了,数据监听器也会响应
            'arr[2]'(newValue) {
                console.log('改变了')
                console.log(newValue)
            }
        }
    })
  2. 使用通配符**监听所有子数据字段的变化

    • 如果需要监听所有子数据字段的变化,可以使用通配符 **

    observers: {
        'some.field.**': function(field) {
          // 使用 setData 设置 this.data.some.field 本身或其下任何子数据字段时触发
          // (除此以外,使用 setData 设置 this.data.some 也会触发)
          field === this.data.some.field
        }
    }

    示例代码:

    observers: {
        'arr.**'(newValue) {
            console.log(newValue) // 变化以后的整个数组的值
        }
    }

5.5. 插槽

  • 在组件的 wxml 中可以包含 slot 节点,用于承载组件使用者提供的 wxml 结构

  • 默认情况下,一个组件的 wxml 中只能有一个slot。需要使用多 slot 时,可以在组件 js 中声明启用

  • 注意:小程序中目前只有默认插槽和多个插槽,暂不支持作用域插槽

5.5.1 默认插槽

<!--component/test/test.wxml-->
<view>header</view>
<view>
  <!-- 插槽的占位符 -->
  <slot />
</view>
<view>footer</view>
<!--pages/home/home.wxml-->
<view>
  <my-test>
    <view>body</view>
  </my-test>
</view>

5.5.2 多个插槽

  • 在组件中,需要使用多 slot 时,可以在组件 js 中声明options: { multipleSlots: true }启用

    // // component/test/test.js
    Component({
        // 配置多个插槽的使用
        options: {
            multipleSlots: true // 在组件定义时的选项中启用多slot支持
        }
    })
  • 可以在组件的 wxml 中使用多个 slot 标签,以不同的 name 来区分不同的插槽

    <!--component/test/test.wxml-->
    <view>
        <!-- 插槽的占位符 -->
        <slot />
        <view>············</view>
        <slot name="body2" />
        <view>············</view>
        <slot name="body3" />
    </view>
  • 使用时,用 slot 属性来将节点插入到不同的 slot 中

    <!--pages/home/home.wxml-->
    <my-test>
        <view>body1</view>
        <view slot="body2">body2</view>
        <view slot="body3">body3</view>
    </my-test>

5.6. 组件间的通信

5.6.1 组件之间的三种基本通信方式

  1. WXML 数据绑定:用于父组件向子组件的指定属性传递数据,仅能设置 JSON 兼容数据

    1. 在父组件的子组件当中绑定子组件要接收的属性,值为要传递的值

      <!--component/test/test.wxml-->
      <my-test msg="{{ info }}"></my-test>

      Page({
          // 页面的初始数据
          data: {
              info: "我是定义在data中的数据"
          }
      })
    2. 在子组件中通过properties属性中定义要接收的属性

      // component/test/test.js
      Component({
          // 接收对外传递过来的数据
            properties: {
              msg: { // 接收的数据
                type: String, // 数据类型
                value: 'hello world' // 数据的默认值
              }
            }
      })
    3. 渲染数据

      <!--component/test/test.wxml-->
      <view>{{ msg }}</view>
  2. 事件:用于子组件向父组件传递数据,可以传递任意数据

  3. 通过 this.selectComponent 方法获取子组件实例对象来直接访问组件的任意数据和方法

5.6.2 this.selectComponent使用

  • 在小程序的组件中,调用 this.selectComponent(string),可以返回指定组件的实例对象

  • 父组件的 .js 文件中,可以调用 selectComponent 函数并指定 id 或 class 选择器,获取子组件对象

  • 示例代码:

    1. 通过class或id给组件取个名字

       <my-test class="my-test" id="mtTest" msg="{{ info }}"></my-test>
    2. 在onLoad生命周期函数中,通过selectComponent获取组件实例

      Page({
          // 生命周期函数--监听页面加载
          onLoad: function (options) {
              // 获取组件
              const component = this.selectComponent('.my-test');
              console.log(component.data.arr)
          }
      })

5.6.3 通过事件监听实现向父组件传值

  • 事件系统是组件间通信的主要方式之一。自定义组件可以触发任意的事件,引用组件的页面可以监听这些事件

  • 步骤:

    1. 在子组件中,通过triggerEvent('自定义事件的名称', 要传递的值)方法派发一个自定义事件

      <!--component/test/test.wxml-->
      <button bindtap="addNum">数字+1</button>
      methods: {
          addNum() {
              // 1.在子组件中通过triggerEvent,派发一个自定义事件
              this.triggerEvent('addNum', { num: 10 })
          }
      }
    2. 在父组件中,绑定子组件派发过来的自定义事件

      <!--pages/home/home.wxml-->
      <view>
        <my-test bind:addNum="addNum"></my-test>
        <view>{{ num }}</view>
      </view>
    3. 定义事件处理函数,通过ev.detail来接收子组件传递过来的值

      Page({
          addNum(ev) {
              // 通过ev.detail来接收子组件传递过来的值
              //console.log(ev.detail)
              this.setData({
                  num: this.data.num + ev.detail.num
              })
          }
      })

五、本单元知识总结

1.明白下单的流程

六、作业安排

版权声明:程序员胖胖胖虎阿 发表于 2022年10月26日 上午1:00。
转载请注明:微信小程序的组件 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...