微信小程序学习笔记-自定义组件

组定义组件方式

  • 方式一: 局部注册

  • 方式二: 全局注册

  • 自定义组件位置

  • 定义组件

<!--/components/home/home.wxml -->
<view>
  <block wx:for="{{nav}}" wx:key="*this">
    <text class="item">{{item}}</text> 
  </block>
</view>
  • 开启组件配置 目的就是允许外部注册组件
// /components/home/home.json
{
  "component": true, // 必须设置true 
  "usingComponents": {}
}
  • 局部注册组件 哪里使用 哪里注册
// /pages/index/index.json
{
  "component":true,
  "usingComponents": {
    "home-cpn":"/components/home/home"
  }
}
  • 使用组件
<!-- /pages/index/index.wxml -->
<view>
  <home-cpn></home-cpn>
  <home-cpn></home-cpn>
</view>

显示

  • 全局注册组件
// /app.json
{
 "usingComponents": {
    "home-cpn":"/components/home/home"
  }
}

// /pages/index/index.json
{
  "component":true
}

组件样式隔离机制

  • 组件内部默认采用styleIsolation:isolated。如果组件内部使用class类样式名称和页面class类样式名称相同,互不影响。

组件使用类样式.item

<!-- /components/home.home.wxml -->
<view>
  <block wx:for="{{nav}}" wx:key="*this">
    <text class="item">{{item}}</text> 
  </block>
</view>

组件类样式item

/* /components/home.home.wxss */

.item {
  color:pink;
}

页面类样式.item

/* /pages/index/index.wxss */

.item{
  color:skyblue;
}

页面视图使用类样式.item

<view>
  <home-cpn></home-cpn>
  <home-cpn></home-cpn>
  <text class="item">你好</text>
</view>

结果

  • 如果页面需要使用组件类样式,那么修改样式隔离机制如下

组件业务层 styleIsolation:'shared'

// /components/home/home.js
Component({
 options: {
   styleIsolation:'shared'  
 }
})

组件样式

/*  /components/home/home.wxss */

.item {
  color:pink;
}

页面样式

/* /pages/index/index.wxss */

.item {
  color:skyblue; /*此时页面设置的样式被组件样式覆盖*/
}

效果

  • 如果组件需要使用页面类样式,那么设置如下。组件不设置类样式.item而是直接使用页面设置的类样式.item
// /components/home/home/js
Component({
  options:{
    styleIsolation:'apply-shared'
  }
})

页面类样式.item

/* /pages/index/index.wxss */
.item {
  color:skyblue;
}

效果

组件通信之页面传递数据给组件

  • 组件位置

  • 页面业务层数据

// /pages/index/idnex.js

Page({
  data: {
    movies: [
      {id:'001',title:'霸王别姬',comment:'人生如戏,戏如人生'},
      {id:'002',title:'活着',comment:'国家走了一小段弯路,对于一代人就是蹉跎了一辈子'}
    ]
  }
})
  • 页面视图层 使用自定义组件movie-cpn并且通过自定义属性titlecomment传递数据
<!-- /pages/index/index.wxml  -->
<view>
  <block wx:for="{{movies}}" wx:key="id" wx:for-item="movie">
    <movie-cpn title="{{movie.title}}" comment="{{movie.comment}}"></movie-cpn>
  </block>
</view>

  • 组件业务层接收数据。使用properties接收
// /components/movie/movie.js

Component({
  properties: {
    title: {
      type:String, // 指定数据类型
      value: '岁月神偷', // 默认默认值
    },
    comment: {
      type: String,
      value: '当你发现时间是贼的时候,它早已偷走了你的一切'
    }
  }
})
  • 组件视图层
<!-- /components/movie/movie.wxml  -->
<view class="content">
  <text>电影名称:{{title}}</text>
  <text>电影评论:{{comment}}</text>
</view>
  • 显示结果

组件传递数据给页面

  • 组件位置
  • 页面业务层初始化状态
// /pages/index/index.js
Page({
  data: {
    counter:0,
  }
})
  • 页面视图层使用组件监听自定义事件
<!-- /pages/index/index.wxml -->
<view>
  <!-- 自定义属性counter传递数据给组件 -->
  <!-- bind:changeCounter监听组件传递过来的方法 -->
  <count-cpn counter="{{counter}}" bind:changeCounter="changeCounter"></count-cpn>
</view>
  • 页面业务层编写事件回调处理函数
// /pages/index/index.js
 changeCounter (event) {
    let {counter} = this.data
    this.setData({counter:counter+event.detail})
  }
  • 组件接收数据并且发布事件this.triggerEvent('changeCounter',数据)
//  /components/count/count.js
Component({
  properties: {
    counter: {
      type: Number,
      value: 0
    }
  },
  methods: {
    handleChangeCounter (event) {
      const {count} = event.currentTarget.dataset
      this.triggerEvent('changeCounter',count) // 发布
    }
    
  }
})
  • 组件视图层

通过 bind:tap="handleChangeCounterdata-*实现优化,实现一个事件回调处理函数根据data-count正负数判断加法还是减法。

<view>
 <text>{{counter}}</text>
 <button type="primary" bind:tap="handleChangeCounter" data-count="{{1}}">+1</button>
 <button type="warn" bind:tap="handleChangeCounter" data-count="{{-1}}">-1</button>
</view>

效果显示