小程序的自定义组件
小程序组件的使用
自定义组件
组件的创建
-
根目录下创建
components
文件夹,用于放置所有组件 -
components
文件夹下创建对应组件的文件夹
-
在
对应组件
的文件夹下创建对应
的components
-
components
组件文件夹名字
对应组件的文件夹名字.js
组件的js文件名字.json
组件的json配置文件名字.wxml
组件的布局文件名字.wxss
组件的样式文件
配置对应的组件
-
在
需要使用相应组件的页面
的.josn
文件中进行组件的调用配置
-
usingComponents
组件调用的配置 -
在其中进行对应组件的路径配置,以及组件名字的配置,只和配置组件的名字相关,和组件的本身的名字没关
-
组件的.json 文件
// json不能注释
{
"component": true,
// 组件可以嵌套
"usingComponents": {}
}
- 调用组件的页面的.json 文件
// json 不能注释
"usingComponents": {
// cell 名字,组件的名字,调用组件时,只和这个名字有关,和组件本身的名字无关
// 后面的时组件的路径
"cell" : "/components/cell/cell"
}
使用对应的组件
- 在需要使用组件的页面中,使用配置的组件的名字
<!-- 使用组件 -->
<cell></cell>
插槽的使用
匿名插槽
-
调用组件时,添加其他内容,多个其他内容
-
在组件页面使用
slot
接收,同时接收 -
调用页面
<!-- 组件 -->
<cell>
<!-- 插槽内容 -->
<text>momo的</text>
</cell>
- 组件页面
<view>
<!-- slot 用来接收插槽内容 -->
<slot></slot>
<!-- 这个时组件的内容-->
安全设置
</view>
具名插槽以及多个调用的配置
单个具名插槽
-
使用具名插槽时,插槽内容中的
slot属性的值
,就是组件内容中slot标签
中name的属性值
-
调用页面
<cell>
<text slot="name">momo的</text>
</cell>
- 组件页面
<view>
<!-- 接收 -->
<slot name="name"></slot>
安全设置
</view>
多个具名插槽
- 多个具名插槽需要开启对应的配置
- 在组件的.js文件中,
Component
中配置options
的multipleSlots
Component({
// 组件的配置选项
options : {
// 多个slot的使用
multipleSlots : true
},
})
- 然后就可以使用多个具名插槽了,可以布局了
组件传参
父传子
-
传参与vue很是相似,基本一致
-
在
组件标签中定义
传递参数的中间量,中间量="参数"
-
在组件的
.js
文件中的properties
中接收中间量
,定义类型
,定义默认值
-
调用参数时传递的参数
<!-- 组件 -->
<!-- title 传递参数的中间量 -->
<cell
title="安全设置"
note="手机号,密码"
>
</cell>
- 组件接收参数时的.js文件
Component({
/**
* 组件的属性列表
*/
properties: {
// 定义了title的类型与默认值
// title , note 父组件调用组件时传递过来的参数
title : {
// type 类型
// value 初始默认值
type : String,value : ""
},
note : {
type : String,value : ''
}
},
})
子传父
-
与vue的方法很是相似,但是事件不一样
-
vue
使用emit("发送的事件名字",参数)
发送事件与参数 -
小程序
使用triggerEvent("发送事件的名字",发送的参数)
-
发送事件
seitchChange(e) {
console.log(e);
// 发送事件的方法
// changewitch就是发送的事件
// value 发送事件的detail下的参数
// e.detail.value参数
this.triggerEvent("changwitch",{value : e.detail.value});
}
- 接收事件:
bind:发送的事件的名字="事件的名字"
<!-- 带switch 开关的 -->
<!-- 接收事件 -->
<cell
bind:changwitch="changeswitch"
>
</cell>
- 接收事件的逻辑
// 更改switch事件
changeswitch(e) {
console.log(e)
// 如果
let a = e.detail.value?"已开启" : "已关闭";
wx.showToast({
title: '听筒模式' + a,
})
},
组件与调用组件页面的css关系
-
在组件的.js页面中进行设置外部css,与组件内部css的关系
-
在
Component
中的options
的styleIsolation
-
styleIsolation
中的值有:isolated
隔离,apply-shared
页面样式分享到组件,shared
双向共享
Component({
options:{
styleIsolation:'isolated',
// 样式隔离方式
// isolated 隔离
// apply-shared 页面样式分享到组件
// shared 双向共享
},
})
外部类的定义
- 1.定义外部类名称 可以组件外部定义,class 在组件内容使用
Component({
// cell-class 在组件中插入这个类,可以在外部,使用类改变组件的样式
externalClasses:["cell-class"],
// 01 定义外部类名称 可以组件外部定义,class 在组件内容使用
})
- 2.在组件页面中使用定义的外部类名称
<!-- cell-class就是定义的外部类 -->
<view class="cell cell-class"></view>
- 3.传入外部类
<cell
cell-class="mycell"
title="收藏"
icon="/images/icon02.png"
></cell>
<!-- 03 传入外部类 -->
- 4.定义外部类
/* 05 定义外部类 */
.mycell{ height: 140rpx !important;}
组件的跳转
- 1.传入组件需要跳转的路径的参数
<!-- url 就是定义的路径的参数 -->
<cell
title="安全设置"
note="手机号,密码"
url="/pages/base/base"
>
- 2.定义组件的点击事件
<!-- 定义事件 tapHd -->
<view class="cell" bindtap="tapHd"></view>
- 3.接收传递的参数
properties: {
url : {
type : String,
value : ''
}
},
- 4.定义组件的点击事件逻辑
/**
* 组件的方法列表
*/
methods: {
tapHd() {
// 如果data中的数据url存在
if(this.data.url) {
// 进行微信跳转
wx.navigateTo({
// 因为注册到了data中,当然也可以使用properties进行调用
url: this.data.url,
})
}
}
}
组件的生命周期—lifetimes
created
—组件被创建
- 组件被创建了,早于
attached
attached
—组件实例进入页面节点树时执行
- 每一次组件被调用,加载到页面中时都会被调用
ready
—渲染完毕
- 组件被渲染
move
—移动
- 当组件有移动的时触发
detached
—移除
- 移除组件时触发
error
—错误
- 出错时触发
组件的页面生命周期—pageLifetimes
show
—显示
- 组件页面切换到了前台
hide
—隐藏
- 组件页面切换到了后台
resize
—改变大小时
- 页面的大小被改变时
混合—behaviors
var myBehavior = require('my-behavior')
Component({
behaviors: [myBehavior],
})
监听—observers
observers: {
'numberA, numberB': function(numberA, numberB) {
// 在 numberA 或者 numberB 被设置时,执行这个函数
this.setData({
sum: numberA + numberB
})
}
}
储数据字段—_数据名:""
- 纯数据字段是一些不用于界面渲染的 data 字段,可以用于提升页面更新性能
- 使用
下划线
的方式定义
options: {
pureDataPattern: /^_/ // 指定所有 _ 开头的数据字段为纯数据字段
},
data: {
a: true, // 普通数据字段
_b: true, // 纯数据字段
},
案例—定义组件
- 调用组件页面
html
<!--pages/user/user.wxml-->
<cell
title="安全设置"
note="手机号,密码"
url="/pages/base/base"
>
</cell>
<!-- 带图标的 -->
<cell
title="收藏"
icon="/images/home-h.png"
>
</cell>
<!-- 带switch 开关的 -->
<cell
title="听筒模式"
toggle="{{true}}"
bind:changwitch="changeswitch"
>
</cell>
<!-- 带图标的 -->
<view title="搜索">
<icon slot="iconright" size="20" type="search"></icon>
</view>
<!-- 带插槽的 -->
<cell url="/pages/base/base">
<view slot="title"><text>通知</text><text class="dot"></text></view>
</cell>
<cell url="/pages/base/base">
<view slot="title">
<text>描述</text>
<text class="compu">10元优惠券</text>
</view>
</cell>
- 调用组件页面的
js
// pages/user/user.js
Page({
/**
* 页面的初始数据
*/
data: {
},
changeHd(e){
console.log("页面e",e);
var msg = e.detail.value?'开启':'关闭';
wx.showToast({
title: '听筒模式已'+msg,
icon:'none'
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
- 调用组件页面的
css
/* pages/user/user.wxss */
.title{ color:red !important;}
.mycell{ height: 140rpx !important;}
/* 05 定义外部类 */
.dot{ margin-left: 15rpx; display: inline-block; height: 20rpx; width: 20rpx; border-radius: 10rpx; background-color: orangered;}
.compu{
margin-left:15rpx;
display: inline-block;
padding: 10rpx;
background-color: orange;
color: #fff;
font-size: 18rpx;
border-radius: 6rpx;
}
- 组件页面
html
<!--components/cell/cell.wxml-->
<!-- 02 使用外部类 -->
<view class="cell cell-class" bindtap="tapHd">
<view class="icon">
<image mode="widthFix" wx:if="{{icon!=''}}" src="{{icon}}"></image>
</view>
<view class="content">
<view class="title" wx:if="{{title}}">{{title}}</view>
<slot wx:else name="title"/>
<view class="tip">
<view class="note">{{note}}</view>
<view wx:if="{{toggle}}" class="toggle">
<switch bindchange="toggleChange"></switch>
</view>
<view wx:else>
<view class="arrow" wx:if="{{url}}"></view>
<slot name="iconright" wx:else class="iconright"/>
</view>
</view>
</view>
</view>
- 组件页面的
js
// components/cell/cell.js
Component({
options:{
multipleSlots:true,
// 多个slot
// styleIsolation:'isolated',
// 样式隔离方式
// isolated 隔离
// apply-shared 页面样式分享到组件
// shared 双向共享
},
externalClasses:["cell-class"],
// 01 定义外部类名称 可以组件外部定义,class 在组件内容使用
/**
* 组件的属性列表
*/
properties: {
title:{type:String,value:''},
note:{type:String,value:''},
icon:{type:String,value:''},
url:{type:String,value:''},
toggle:{type:Boolean,value:false}
// 定义了title的类型与默认值
},
lifetimes: {
attached: function() {
// 在组件实例进入页面节点树时执行
console.log(this)
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
tapHd(){
if(this.data.url){ //如果url不为空
wx.navigateTo({
url: this.data.url, //跳转url对应页面
})
}
},
toggleChange(e){
// console.log(e);
this.triggerEvent("change",{value:e.detail.value})
// 发送事件 名称change 值为当前toggle值
}
}
})
- 组件页面的
css
/* components/cell/cell.wxss */
.cell{
display: flex;
height: 88rpx;
}
.icon{
display: flex;
align-items: center;
/* margin-left: 30rpx; */
}
.icon image{ width: 58rpx; height: 58rpx; margin-left:30rpx;}
.cell .content{
border-bottom: 1rpx solid #eee;
flex:1;
display: flex;
justify-content: space-between;
align-items: center;
margin-left:30rpx;
}
.tip{
display: flex;
padding-right:30rpx;
}
.arrow{
height: 26rpx;
width: 26rpx;
border-top:1rpx solid #ccc;
border-right:1rpx solid #ccc;
transform: rotate(45deg);
margin-left: 30rpx;
}
.note{
font-size: 28rpx;
color:#999;
}