微信小程序组件

2022/2/15 小程序

微信小程序框架为开发者提供了一系列组件,开发者可以通过组合这些组件进行快速开发。 官方文档 (opens new window)

🌙 组件基础概念

🌙 1. 什么是组件?

  • 组件是视图层的基本组成单元。

  • 组件自带一些功能与微信风格的样式。

  • 一个组件通常包括开始标签结束标签属性用来修饰这个组件,内容在两个标签之内。

    <tagname property="value">
      Content goes here ...
    </tagename>
    
    1
    2
    3

    注意:所有组件与属性都是小写,以连字符-连接

🌙 2. 基础组件都有哪些分类?

官方文档 (opens new window)

主要包含:视图容器、基础内容、表单组件、导航、媒体组件、地图、画布、开放能力等使用场景

🌙 3. 组件共同属性有哪些?

属性名 类型 描述 注解
id String 组件的唯一标示 保持整个页面唯一
class String 组件的样式类 在对应的wxss中定义的样式类
style String 组件的内联样式 可以动态设置的内联样式
hidden Boolean 组件是否显示 所有组件默认显示
data-* Any 自定义属性 组件上触发的事件时,会发送给事件处理函数
bind* / catch* EventHandler 组件的事件

🌙 4. 单个组件自定义特殊属性

几乎所有组件都有各自定义的属性,可以对该组件的功能或样式进行修饰。

比如:

🌙 1.scroll-view 组件 (opens new window)

<view class="container">
  <scroll-view 
    class="scroll-boxa" 
    scroll-y="true"
    upper-threshold="50"
    lower-threshold="50"
    scroll-top="50"
    bindscrolltoupper="scrollToUpper"
    bindscrolltolower="scrollToLower"
    bindscroll="scrollhandle"
    refresher-enabled="true"
    refresher-triggered="true"
    refresher-background="#cba007"
    bindrefresherpulling="refresherPulling"
    > 
    <view class="boxa">第 1 个盒子</view>
    <view class="boxa">第 2 个盒子</view>
    <view class="boxa">第 3 个盒子</view>
    <view class="boxa">第 4 个盒子</view>
    <view class="boxa">第 5 个盒子</view>
    <view class="boxa">第 6 个盒子</view>
  </scroll-view>
  <view style="padding:80rpx 30rpx;">{{msg}}</view>
</view>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
data: {
    msg:'滚动状态提示信息'
  },

  scrollToUpper(){
    console.log("滚动到顶部了")
    this.setData({
      msg:'滚动到顶部了'
    })
  },
  scrollToLower(){
    console.log("滚动到底部了")
    this.setData({
      msg:'滚动到底部了'
    })
  },
  scrollhandle(event){
    console.log(event.detail.scrollTop)
    this.setData({
      msg:'滚动中,滚动距离为:'+event.detail.scrollTop
    })
  },
  refresherPulling(){
    console.log("顶部下拉刷新中...")
    this.setData({
      msg:'顶部下拉刷新中...'
    })
  },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
.container{
  background: #abcdef;
}
.scroll-boxa{
  width: 100%;
  height: 800rpx;
  background: #007cba;
  color: #fff;
}

.boxa{
  width: 80%;
  height: 300rpx;
  line-height: 300rpx;
  text-align: center;
  margin: 4rpx 10%;
  background: red;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

🌙 2.使用 cover-view 解决原生组件层级过高问题

官方文档 (opens new window)

覆盖在原生组件之上的文本视图。

可覆盖的原生组件包括 map (opens new window)video (opens new window)canvas (opens new window)camera (opens new window)live-player (opens new window)live-pusher (opens new window)

只支持嵌套 cover-view (opens new window)cover-image (opens new window),可在 cover-view (opens new window) 中使用 button (opens new window)

<view class="container">
  <view class="page-body">
    <view class="page-section page-section-gap">
      <map
        style="width: 100%; height: 300px;"
        latitude="{{latitude}}"
        longitude="{{longitude}}"
      >
        <cover-view class="cover-view">
          <cover-view class="container">
            <cover-view class="flex-wrp" style="flex-direction:row;">
              <cover-view class="flex-item demo-text-1"></cover-view>
              <cover-view class="flex-item demo-text-2"></cover-view>
              <cover-view class="flex-item demo-text-3"></cover-view>
            </cover-view>
          </cover-view>
        </cover-view>
      </map>

      <video 
        id="myVideo" 
        src="http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400" 
        enable-danmu 
        danmu-btn 
        show-center-play-btn='{{false}}' 
        show-play-btn="{{true}}" 
        controls
        style="width:80%;margin:80rpx 10%;"
      ></video>

      <mfooter num="888" min="8" />

    </view>
  </view>
</view>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Page({
  onShareAppMessage() {
    return {
      title: '自定义分享',
      path: 'comp/cover-view/index'
    }
  },

  data: {
    latitude: 23.099994,
    longitude: 113.324520,
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
.cover-view {
  position: absolute;
  top: calc(50% - 150rpx);
  left: calc(50% - 300rpx);
  /* opacity: .7; */
}

.flex-wrp{
  display:flex;
}

.flex-item{
  width: 200rpx;
  height: 300rpx;
  font-size: 26rpx;
}

.demo-text-1 {
  background: rgba(26, 173, 25, 0.7);
}

.demo-text-2 {
  background: rgba(39, 130, 215, 0.7);
}

.demo-text-3 {
  background: rgba(255, 255, 255, 0.7);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
  "usingComponents": {
    "mfooter": "/components/mfooter/index"
  }
}
1
2
3
4
5

🌙 3.使用 swiper 组件实现轮播图及左右滑动切换效果

官方文档 (opens new window)

<view>

  <swiper 
    class="mswiper"
    indicator-dots="{{true}}"
    indicator-color="#fff"
    indicator-active-color="#666"
    autoplay="true"
    current="0"
    interval="2000"
    duration="300"
    display-multiple-items="1"
    bindchange="swiperChange"
    >
    <block wx:for="{{swiperList}}" wx:for-item="item" wx:for-index="index" wx:key="*this">
      <swiper-item class="mswiper-item mswiper-item-{{index}}">
        {{item}}
      </swiper-item>
    </block>
  </swiper>

  <view style="text-align:center;">当前显示的索引模块是:{{currentIndex}}</view>

</view> 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Page({
  data:{
    currentIndex: 0,
    swiperList:[
      'Page 1',
      'Page 2',
      'Page 3'
    ]
  },
  swiperChange(event){
    console.log(event.detail.current)
    this.setData({
      currentIndex: event.detail.current
    })
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.mswiper{
  height: 400rpx;
  width: 600rpx;
  margin:60rpx 72rpx;
  border: 3rpx solid #ccc;
  text-align: center;
  color: #fff;
}
.mswiper-item{
  line-height: 400rpx;
}
.mswiper-item-0{
  background-color: red;
}
.mswiper-item-1{
  background-color: green;
}
.mswiper-item-2{
  background-color: blue;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

🌙 自定义组件

+Component(Object object) 创建自定义组件,接受一个 Object 类型的参数官方文档 (opens new window)

  • 父组件相关代码
<!--farm/ucomp/index.wxml-->
<view style="margin:30rpx 30rpx;">
  当前页面引入了自定义组件 : mfooter
</view>
<view style="margin:30rpx 30rpx;">
  通信数据 : {{showInfo}}
</view>

<view style="margin:30rpx 30rpx;background:#007cba;color:#fff;padding:20rpx;">组件第一次调用</view>
<mfooter num="888" min="8" bind:footerEvent="childTruggerEventA"/>
<view style="margin:30rpx 30rpx;background:#007cba;color:#fff;padding:20rpx;">组件第二次调用</view>
<mfooter num="999" min="9" bind:footerEvent="childTruggerEventB"/>
1
2
3
4
5
6
7
8
9
10
11
12
  data: {
    showInfo:'初始化父组件显示信息'
  },

  childTruggerEventA(event){
    console.log("888 的组件触发了父组件的事件")
    console.log("接收到组件的数据是:"+event.detail)
    this.setData({
      showInfo:"接收到组件的数据是:"+event.detail
    })
  },
  childTruggerEventB(event){
    console.log("999 的组件触发了父组件的事件")
    console.log("接收到组件的数据是:"+event.detail)
    this.setData({
      showInfo:"接收到组件的数据是:"+event.detail
    })
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
  "usingComponents": {
    "mfooter": "/components/mfooter/index"
  }
}
1
2
3
4
5
  • 子组件相关代码
<view style="margin:30rpx 30rpx;" bindtap="callParentInfoChange">
  传递过来的 num 参数是: {{ num }}
</view>
<view style="margin:30rpx 30rpx;" bindtap="callParentInfoChange">
  传递过来的 min 参数是: {{ min }}
</view>
<view class="header">
  学而时习之,不亦说乎!
</view>
1
2
3
4
5
6
7
8
9
// components/header/index.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    num: Number,
    min: {
      type: Number,
      value: 0,
      observer: function (newVal, oldVal) {
        // 属性值变化时执行 可省略
      }
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    name:"蜡笔小新"
  },

  /**
   * 组件的方法列表
   */
  methods: {
    callParentInfoChange(){
      console.log(this.data.min)
      this.triggerEvent('footerEvent', this.data.min) //myevent自定义名称事件,父组件中使用
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
  "component": true,
  "usingComponents": {}
}
1
2
3
4
/* components/header/index.wxss */
.header{
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 70rpx;
  line-height: 70rpx;
  text-align: center;
  background-color: #007cba;
  color: #fff;
}
1
2
3
4
5
6
7
8
9
10
11
12