微信小程序之自定义组件的使用、介绍、案例分享

微信小程序自定义组件介绍

自定义组件发开文档
类似vue或者react中的自定义组件, 小程序允许我们使用自定义组件的方式来构建页面.

自定义组件的使用

1. 创建组件(js,json,wxml,wxss)

在这里插入图片描述

在这里插入图片描述

2. 在父组件 json文件中 注册组件

"usingComponents": {
"cell":"/components/cell/cell",
}
}

在这里插入图片描述

3. 使用组件

<cell ></cell>

在这里插入图片描述

组件的样式

1. 隔离样式(默认页面与组件的样式是相互隔离的)

//在子组件cell.js 允许样式隔离
options:{
// 样式隔离:apply-shared 父影响子,shared父子相互影响, 
//isolated相互隔离
    styleIsolation:"isolated",
},

02 在子组件cell.wxml 使用外部类

2. 外部类

  • 01 在子组件cell.js定义外部类
 externalClasses:["cell-class"],
  • 02 在子组件cell.wxml 使用外部类
<view class="cell cell-class" > 我是组件里的cell</view>
  • 03 在父组件页面com.wxml 使用外部类
<cell cell-class="mycell"></cell>
  • 04 在父组件页面com.wxss 设置外部类的样式
.mycell{
line-height: 120rpx !important;
color: #f70;
}

完整图片代码
在这里插入图片描述

自定义组件插槽

1.默认插槽(text)

  • 01 在父组件–页面com.wxml 中定义默认插槽
<cell>
<text>鸡蛋50倍</text>
</cell>
  • 02 在子组件–cell.wxml中接收插槽内容(slot)
<view class="cell cell-class" > 
我是组件里的cell-
<slot></slot>
</view>

图片完整代码
在这里插入图片描述

2.命名插槽

  • 01 在父组件–页面com.wxml 中定义命名插槽
<cell>
<text slot="prv">😋</text>
<text slot="next">🎉</text>
</cell>
  • 02 在子组件–cell.js中 设置允许多个插槽
 options:{
//允许多个插槽
    multipleSlots:true,
},
  • 03 在子组件–cell.wxml中接收命名插槽内容
<view class="cell cell-class" > 
<slot name="prv"></slot>
<slot name="next"></slot>
</view>

在这里插入图片描述

组件传参

1. 父传子

  • 01在父组件-com.wxml定义组件的属性(title/num)
<cell title="中美两国和平相处" num="{{2}}"></cell>
  • 02 在子组件 cell.js 接收父组件的属性并定义
properties: {
    title:{
      type:String,
      value:""
},
    num:{
// 定义类型
      type:Number,
// 定义默认值
      value:1
}
},
  • 03 在子组件 cell.wxml 使用父组件传过来的参
<view class="cell"> 
<text>{{title}}</text>
<text>{{num}}</text>
</view>

在这里插入图片描述

2. 子传父

  • 01 在子组件cell.js 定义data 自己的数据
data: {
    count:1
},
  • 02 在子组件cell.js 生命周期 attached挂载更新count
lifetimes:{
attached(){
console.log(this.data)
// count的值为父组件传递的num值
this.setData({count:this.data.num})
}
},
  • 03 在子组件 cell.js 定义组件方法
methods: {
tapHd(){
this.setData({count:this.data.count+1})
}
}
  • 04 在子组件页面 cell.wxml 绑定单击事件并使用在子组件定义的数据data
<view class="cell" bindtap="tapHd"> 
<text>{{title}}</text>
<text>{{count}}</text>
</view>

在这里插入图片描述

自定义组件js文件中Components里面的参数

1. 生命周期 lifetime

  • attach 组件的挂载

2. data数据
3. methods 方法
4. properties 属性(只读)
5. externalClasses 外部类
6. options 选项

  • multipleSlots 多个插槽
//允许多个插槽
    multipleSlots:true
  • styleIsolation (默认样式隔离)
    styleIsolation:"isolated",  样式隔离
// 样式隔离:apply-shared 父影响子,shared父子相互影响,
// isolated相互隔离

接下来是两个自定义组件 item nav 案例分享

item组件效果图

在这里插入图片描述

  1. 父组件com.wxml代码
//wxml代码
<item title="支付" icon="/images/icon01.png"></item>
<item title="相册" icon="/images/icon02.png"></item>
<item title="支付" ></item>

<item title="消息" icon="/images/icon02.png"  badge="{{true}}" tip="3条未读"></item>

<item title="消息" icon="/images/icon02.png"  badge="{{12}}" tip="12条未读"></item>

<item title="消息" icon="/images/icon02.png" showrslot="{{true}}">
  <switch checked="true" slot="right"></switch>
</item>

<item>
  <view slot="title">插槽title</view>
</item>

<item title="新闻" icon="/images/icon02.png"  url="/pages/yidian/yidian" open-type="switchTab"> 
</item>
<item title="首页" icon="/images/icon02.png"  url="/pages/home/home" > 
</item>

<item title="消息" icon="/images/icon02.png" showrslot="{{true}}" itemclass="myitem">
  <switch checked="true" slot="right"></switch>
</item>
  1. 父组件com.js代码
// pages/com/com.js
Page({

  /**
   * 页面的初始数据
   */
  data: {

  },
  cellHd(e){
    console.log(e);
    wx.showToast({
      title: '你点击了'+e.detail,
    })
  },
  1. 父组件com.wxss代码
/* pages/com/com.wxss */
.title{
  line-height: 88rpx;
  background-color: #f0f0f0;
  padding: 0 15rpx;
}
.cell{
  color:red;
}
.mycell{
  line-height: 120rpx !important;
  color:#F70;
}

.myitem{
  line-height: 200rpx !important;
  background-color: #F0f0f0;
 
}
  1. 父组件com.json代码
{
  "usingComponents": {
    "cell":"/components/cell/cell",
    "item":"/components/item/item"
  }
}
  1. 子组件item.wxml代码
<navigator class="item itemclass" url="{{url}}" open-type="{{openType}}" bindtap="itemclick">
  <view class="icon" wx:if="{{icon}}">
    <image src="{{icon}}" mode="aspectFill"></image>
  </view>
  <view class="content">
    <view class="title">
      <view class="title" wx:if="{{title}}">{{title}}</view>
      <slot name="title" wx:else></slot>
    </view>

    <view class="right" wx:if="{{!showrslot}}">
      <view class="tip">{{tip}}</view>
      <view class="badge" wx:if="{{badge}}">
        <view wx:if="{{badge===true}}" class="dot">
        </view>
        <view wx:else class="redbadeg">
          {{badge}}
        </view>
      </view>
      <view class="arrow"></view>
    </view>
    <slot name="right" wx:else></slot>
  </view>
</navigator>

<!-- 
  icon 图标
  conent 内容
  title 标题
  right 右侧
  tip 提示
  badge 红点
  arrow 箭头
 -->
  1. 子组件item.wxss代码
/* components/item/item.wxss */
.item{
  line-height: 88rpx;
 
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.icon{
  margin-left: 30rpx;
  margin-right: 30rpx;   
  height: 100%;
  display: flex;
  align-items: center;
}
.icon image{
  width: 60rpx;
  height: 60rpx;
}
.content{
  padding: 0 30rpx;
  border-bottom: 1rpx solid #ccc;
  display: flex;
  flex:1;

}
.title{
  flex:1;
  color:#333;
  font-size: 32rpx;
}
.right{
  display: flex;
  align-items: center;
}
.right .arrow{
  height: 30rpx;
  width: 30rpx;
  border-top:3rpx solid #999;
  border-right: 3rpx solid #999;
  transform: rotate(45deg);
}

.tip{
  color:#999;
  font-size: 24rpx;
}
.dot{
  height: 14rpx;
  width: 14rpx;
  background-color: #f00;
  border-radius: 12rpx;
  margin-left: 15rpx;

}
.redbadeg{
  font-size: 18rpx;
  color:#fff;  
  border-radius: 18rpx;
  background-color: #f00;
  max-height: 30rpx;
  width: 30rpx;
  line-height: 30rpx;
  text-align: center;
  margin-left: 15rpx;
}

  1. 子组件item.js代码
// components/item/item.js
Component({
  options:{
    multipleSlots:true
  },
  externalClasses:["itemclass"],
  /**
   * 组件的属性列表
   */
  properties: {
    // 标题
    title:{
      type:String,
      value:""
    },
    // 显示右侧插槽
    showrslot:{
      type:Boolean,
      value:false,
    },
    // 图标
    icon:{
      type:String,
      value:""
    },
    tip:{
      type:String,
      value:"",
    },
    badge:{
      type:[Boolean,Number],
      value:false
    },
    url:{
      type:String,
      value:""
    },
    openType:{
      type:String,
      value:"navigate"
    }
  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {
      itemclick(e){
        console.log(e);    
        //发送一个事件 
        this.triggerEvent("itemclick",e.detail)
      }
  }
})
  1. 子组件item.json
{
  "component": true,
  "usingComponents": {}
}

nav自定义导航栏组件

nav效果图
在这里插入图片描述

  1. 父组件navpa.wxml
<nav title="你好渐变标题" color="#fff"></nav>
<image src="https://p.qqan.com/up/2022-10/202210111338422888.jpg"></image>
  1. 父组件navpa.json
{
  "usingComponents": {
    "nav":"/components/nav/nav"
  },
  "navigationStyle":"custom"
}
  1. 子组件nav.wxml
<!--components/nav/nav.wxml-->
<view class="nav" style="padding-top: {{statusBarHeight}}px; height: {{barHeight}}px;">
  <view class="bar" style="width: {{titleWidth}}px; height: {{barHeight}}px; color: {{color}};">
    <view class="btn">
      <view class="back" wx:if="{{pagesLen>1}}"  bindtap="goBack" ><image src="./images/back.svg" mode="aspectFill"></image></view> 
      <view class="home" bindtap="goHome"><image src="./images/home.svg" mode="aspectFit"></image></view>
    </view>
   
     {{title}} {{pagesLen}}
  </view>
</view>

  1. 子组件nav.wxss
/* components/nav/nav.wxss */
.nav{
  background-image: linear-gradient(90deg, rgb(96, 197, 236), rgb(37, 125, 197));
  position: sticky;
}
.nav .bar{
  box-sizing: border-box;
  padding: 0 7px;
  display: flex;
  align-items: center;
   
}
.btn{display: flex;  align-items: center;}
.btn>view{
  height: 40px;
  width: 40px;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
}
.btn image{
  height: 22px;
  width: 22px;
  align-items: center;
}
.btn .back { border-right: 1rpx solid rgba(255,255,255,.5); height: 22px;}
  1. 子组件nav.js
// components/nav/nav.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    "title":{
      type:"string",
      value:""
    },
    "color":{
      type:"string",
      value:"#fff"
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    statusBarHeight:20,
    barHeight:44,
    pagesLen:0,

  },
  lifetimes:{
    attached(){
      // 获取系统信息
     var info =  wx.getSystemInfoSync();
     console.log(info);
    //  更新状态栏的高度
     this.setData({statusBarHeight:info.statusBarHeight})
    //  胶囊的位置
    const res = wx.getMenuButtonBoundingClientRect()
    console.log(res);
    // 标题栏可以使用的宽度(排除右侧胶囊的位置)
    this.setData({titleWidth:res.left});
    // 标题栏高度
    var barHeight = res.height+(res.top-info.statusBarHeight)*2;
    this.setData({barHeight});

    // 获取当前页
    var pages = getCurrentPages();
    console.log(pages);
    //更新页面的长度
    this.setData({pagesLen:pages.length})
    }
  },

  /**
   * 组件的方法列表
   */
  methods: {
      goBack(){
        wx.navigateBack()
      },
      goHome(){
        wx.navigateBack({
          // 返回历史的长度为总页面数
          delta: this.data.pagesLen,
        })
      }
  }
})

  1. 子组件nav.json
{
  "component": true,
  "usingComponents": {}
}

end…
下期见。。。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值