小程序组件
小程序组件–视图容器
什么是组件?
- 组件是视图层的基本组成单元。
组件自带一些功能与微信风格的样式。
一个组件通常包括开始标签和结束标签,属性用来修饰这个组件,内容在两个标签之内。
注意:所有组件与属性都是小写,以连字符-连接
-
组件的属性
- 所有组件都有如下的属性:
id,class,style,hidden(组件是否显示),data-(自定义属性),bind/catch(事件绑定)*
- 所有组件都有如下的属性:
组件分类
小程序中,基础组件分为了七大类:视图容器、基础内容、表单组件、导航、多媒体、地图、画布。
在小程序中,通过使用组件可以少写很多代码
关于组件的具体用法,最好的参考资料就是官方文档:
https://developers.weixin.qq.com/miniprogram/dev/component/
视图容器(View Container):
- view标签:基础标签,类似H5中的div,块级标签;view有两种布局方式,block(默认)及flex
- scroll-view:滚动视图,分为水平滚动和垂直滚动。注意滚动视图垂直滚动时一定要设置高度否则的话scroll-view不会生效。
- swiper:滑动视图容器,多用于滑动广告图
- movable-view:可移动区域,这个标签的实现效果多为,在某个区域里面可以进行拖动,缩放等操作
- cover-view:多用于原生组件video,canvas,camera等标签内,作用是覆盖这些原生标签,因为这些原生标签的层级默认高于任何一个原生标签的层级且不受z-index的控制;同时,现在cover-view只支持嵌套cover-view、cover-image,可在cover-view中使用button(嵌套其他标签可能不报错,但是真机调试一定不行的)。
view
- 微信小程序 View 支持两种布局方式:Block (块级)和 Flex(弹性盒子)
- 所有 View 默认都是 block
- 要使用 flex 布局的话需要显式的声明:
- display:flex;
- flex 布局可横向布局和竖向布局,要设置属性 flex-direction ,它有4个可选值:
- row:从左到右的水平方向为主轴
- row-reverse:从右到左的水平方向为主轴
- column:从上到下的垂直方向为主轴
- column-reverse:从下到上的垂直方向为主轴
flex布局(弹性盒子布局)要设置元素在横向上的布局方向,需要设置 justify-content 属性,它有5个值可选:
- flex-start:主轴起点对齐(默认值)
- flex-end:主轴结束点对齐
- center:在主轴中居中对齐
- space-between:两端对齐,除了两端的子元素分别靠向两端的容器之外,其他子元素之间的间隔都相等
- space-around:每个子元素之间的距离相等,两端的子元素距离容器的距离也和其它子元素之间的距离相同
flex布局要设然后我们要设置元素在纵向上的布局方向,需要设置 align-items 属性,它有5个值可选:
- stretch 填充整个容器(默认值)
- flex-start 侧轴的起点对齐 (这里我们手动设置下子 view 的高度,来看的明显一些)
- flex-end 侧轴的终点对齐
- center 在侧轴中居中对齐
- baseline 以子元素的第一行文字对齐
子 View 还有个属性 align-self,可以覆盖父元素的 align-items 属性,它有6个值可选:auto | flex-start | flex-end | center | baseline | stretch (auto 为继承父元素 align-items 属性,其他和 align-items 一致)
比如上面最后一个 baseline 的例子,我们把 item3 设置 align-self:flex-end;
此外还有 flex-wrap 属性,用于控制子 View 是否换行,有3个值可选:
- nowrap:不换行(默认)
- wrap:换行
- wrap-reverse:换行,第一行在最下面
还有子 View 有个 order 属性,可以控制子元素的排列顺序,默认为0。
比如还是上面那个例子,我们把 item3 设置 order:-1; 可以把 item3 排在前面
swiper (轮播图)
滑块视图容器。其中只可放置swiper-item组件,否则会导致未定义的行为。
swiper (轮播图)典型用法示例
wxml中:
<swiper indicator-dots="true" autoplay="true" interval="5000" duration="1000" style='width: 100%'>
<swiper-item wx:for="{{imgUrls}}" wx:for-item="imgItem">
<image src='{{imgItem}}' class="slide-image" width="355" height="150" />
</swiper-item>
</swiper>
js中
data: {imgUrls: [
'http://img02.tooopen.com/images/20150928/tooopen_sy_143912755726.jpg',
'http://img06.tooopen.com/images/20160818/tooopen_sy_175866434296.jpg',
'http://img06.tooopen.com/images/20160818/tooopen_sy_175833047715.jpg'
] }
swiper (轮播图)常用属性
- indicator-dots Boolean 是否显示面板指示点
- autoplay Boolean 是否自动切换
- interval Number 自动切换时间间隔
- duration Number 滑动动画时长
scroll-view
可滚动视图区域。使用竖向滚动时,需要给scroll-view一个固定高度
基础内容组件表单组件等
基础内容组件
- icon 图标
- text 文本
- rich-text nodes属性可为Array和String类型,但推荐使用Array. nodes分为支持两种节点,分别为元素节点(type=node ,默认为元素节点)和文本节点(type=text)
- progress 进度表
icon组件
图标库的类型有上面9种,如果要显示其它图标,可通过image标签自定义,可到下面网址下载
http://www.iconfont.cn/collections/index?spm=a313x.7781069.1998910419.4&type=1
text文本组件
- text文本组件支持转义符 \ ,如换行\n,空格\t,
<text/>
组件内只支持<text/>
嵌套。除了文本节点以外的其他节点都无法长按选中
<view>
<text>你好世界 \t 你好世界</text>
<text>你好世界 \n 你好世界</text>
</view>
由图可得,text文本组件组件是放置在一行里,不同于view组件,每个view组件一行
rich-text富文本
- 是小程序提供的富文本组件,能够在小程序中渲染出富文本字符串。比如可以在一个文本中包含不同的颜色、不同的字号、不用的背景颜色的文本(支持css样式)
- nodes 属性推荐使用 Array 类型,由于组件会将 String 类型转换为 Array 类型,因而性能会有所下降
- nodes现支持两种节点,通过type来区分,分别是元素节点和文本节点,默认是元素节点,在富文本区域里显示的HTML节点。
元素节点:type = node
progress(进度条)
progress组件:是小程序提供的进度条组件,能够实现小程序动态加载的。
导航
navigator 页面链接。
functional-page-navigator 仅在插件的自定义组件中有效,用于跳转到插件功能页。
媒体组件
- audio 音频
- image 图像
- video 视频
- camera 系统相机。该组件是原生组件,使用时请注意相关限制。
- live-player 实时音视频播放。该组件是原生组件,使用时请注意相关限制。
- live-pusher 实时音视频录制。该组件是原生组件,使用时请注意相关限制。
Image组件
在微信小程序中,要显示一张图片,有两种图片加载方式:
加载本地图片
<image class="widget__arrow" src="/image/arrowright.png" mode="aspectFill">
</image>
加载网络图片
直接给’src’这个属性附上地址,它会自动加载。
<image class="image_frame" src=" http://img1.3lian.com/2015/w7/85/d/101.jpg " mode="aspectFill">
</image>
Image组件
- aspectFill 保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。aspectFill同样保持图片的宽高比不会变形。但它让图片完全填满整个容器
- aspectFit 用途:保证图片完整地装进容器,方式:选取宽高缩放值里较大的值来缩放,代价:容器无法装满,出现留白。
- widthfix 宽度不变,高度自动变化,保持原图宽高比不变。
- widthfix属性的最大特点是,图片将不会按照设定的尺寸呈现,比如设置image宽度为750px,高度为340px,如果设置mode=widthfix,则图片最终不会按照750px和340px呈现,除非原始图片切好是这个尺寸。这个属性让宽缩放至指定尺寸,再动态计算高度.
表单组件
button 按钮
checkbox 复选框
form 表单
input 输入框
label 标签
picker 滚动选择器
picker-view 嵌入页面的滚动选择器
radio 单选框
slider 滑动条
switch 开关
textarea 多行输入框
自定义组件
组件化编程
- 组件就是一组功能和逻辑的封装, 以供重复使用
- 开发者根据自身的需求也可以自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。自定义组件在使用时与基础组件非常相似。
自定义组件基本创建步骤及解析
- 类似于页面,一个自定义组件由 json wxml wxss js 4个文件组成。
- 要编写一个自定义组件,新建一个components目录,在components目录右键再新建一个item目录,然后在item目录右键新建一个Component,命名为item,会自动生成item.json、item.wxml、item.js、item.wxss文件:
json配置:
在完成上面item组件的创建以后, 打开item.json
{
"component": true, // 表示item这4个文件是一个定义组件
"usingComponents": {} // 可选项, 此属性表示在这个组件中还可使用其它组件
}
js创建:
打开item.js, 这个文件定义item组件的属性列表, 数据及方法
// 定义的组件
Component({
//组件对外开发的属性
properties: {
content: {
type: String,
value: ''
},
iconTypes: {
type: Array,
vlaue: []
}
},
//组件的私有初始数据
data: {
array:['success', 'info', 'warn', 'waiting', 'cancel', 'download', 'search', 'clear']
},
//组件的方法列表
methods: {
clickMe: function () { // 根据需求定义事件
console.log("you have clicked me");
}
}
})
item.wxss 样式:
- 自定义组件拥有自己的 wxml 模版 和 wxss 样式
- 需要注意的是,wxss样式只能通过类选择器(.class)来指定
/* btn 是组件item.wxml 中的button标签的类样式 */
.btn {
color: red
}
item.wxml 模板:
- item.wxml 的内容就是 组件模板
<view>
<!--使用组件中的content属性-->
<!--给conent一个值hello, hello会传递到item.js中的content属性中, 然后使用{{}}把它取出来 -->
<view>{{content}} word</view>
<!--使用组件中的data-->
<block wx:for='{{array}}'>
<icon type='{{item}}'></icon>
</block>
<!--使用组件中的methods-->
<view>
<button size='mini' bindtap='clickMe' class='btn'>click here</button>
</view>
</view>
<view>根据情况, 可任意增加或减少, 整个页面内容就是组件模板</view>
index页面创建(使用组件)
现在 index.wxml 页面要使用item模板组件, 则需要在index.json中做如下配置:
{
"usingComponents": {
"myitem": "/components/item/item"
}
}
这就表示要使用的组件是在/components/item/item, 组件名称(标签名)是myitem
<view>本页面为index.wxml, 如下的myItem为自定义组件</view>
<view>
<myitem content="你好"></myitem>
</view>
<view>本页面的其它内容</view>
myitem标签展示出来的内容就是上面item.wxml文件中的所有内容
而myitem仅仅是index.wxml中的一个标签
触发相应事件:
在index.wxml中的自定义组件绑定事件, 通过点击自定义组件myitem触发
如上所示, 模板组件会触发一个事件, 再触发成功回调函数 (如下this.triggerEvent)
<view>
<myitem content="你好" bindmyevent="confirm"></myitem> <!-- 给myitem绑定一个点击事件confirm -->
</view>
/*index.js*/
Page({
data: {},
confirm : function() {
console.log("触发成功");
}
})
/*item.js*/
Component(properties:{ },
data: { },
methods: {
clickMe: function () {
console.log("you have clicked me"); // 触发成功回调
this.triggerEvent('myevent'); // triggerEvent触发指定对象的指定事件, 我点击的是myitem标签, this也就表示它
}
}
})
注意:
- 在组件wxss中不应使用ID选择器、属性选择器和标签名选择器。只能用class类选择器
- 在自定义组件的 js 文件中,需要使用 Component() 来注册组件,并提供组件的属性定义、内部数据和自定义方法。
- 组件的属性值和内部数据将被用于组件 wxml 的渲染,其中,属性值是可由组件外部传入的。而组件的data内部数据只能用于组件内部使用,不能从外部传入。
模版数据绑定
- 与普通的 WXML 模版类似,可以使用数据绑定,这样就可以向子组件的属性传递动态数据。就像前面content=“你好” ,组件的属性 content将收到页面传递的数据。
- 注意在wxml中因不区别大小写,如果属性名有多个单词组合,如js中的属性innerText要写成inner-text的形式。在js中变量名中不允许出现“-”。如果想要统一名称,可在js中和wxml中统一用inner_text这样的形式。具体如何表示只是个人习惯。
Page 和 Component
- Component 是 Page 的超集
- 事实上,小程序的页面也可以视为自定义组件。因而,页面也可以使用Component构造器构造,拥有与普通组件一样的定义段与实例方法。但此时要求对应 json 文件中包含usingComponents定义段。其实组件的渲染流程、方式,跟页面没多大区别
自定义组件模版和样式
组件模版
- 组件模版的写法与页面模板相同。组件模版与组件数据结合后生成的节点树,将被插入到组件的引用位置上。
- 在组件模板中可以提供一个 节点,用于承载组件引用时提供的子节点。
- 只有一个slot节点时,组件开始标签和结束标签中间的内容,会插入到组件模块solt节点的位置。
示例:
在item.wxml中添加
<slot></slot>
在index.wxml中添加修改代码
<myitem content="你好">
<view>这里是插入到组件slot中的内容</view>
</myitem>
组件wxml有多个slot
默认情况下,一个组件的wxml中只能有一个slot。需要使用多slot时,可以在组件js中声明启用。
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
},
})
此时,可以在这个组件的wxml中使用多个slot,以不同的 name 来区分。
<view class="wrapper">
<slot name="before"></slot>
<view>这里是组件的内部细节</view>
<slot name="after"></slot>
</view>
使用时,用 slot 属性来将节点插入到不同的slot上。
<view>
<multisolt>
<!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 -->
<view slot="before">这里是插入到组件slot name="before"中的内容</view>
<!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 -->
<view slot="after">这里是插入到组件slot name="after"中的内容</view>
</multisolt>
</view>
</view>
组件样式
- 组件对应 wxss 文件的样式,只对组件wxml内的节点生效。编写组件样式时,需要注意以下几点:
- 组件和引用组件的页面不能使用id选择器(#a)、属性选择器([a])和标签名选择器,请改用class选择器。
- 组件和引用组件的页面中使用后代选择器(.a .b)在一些极端情况下会有非预期的表现,如遇,请避免使用。
- 子元素选择器(.a>.b)只能用于 view 组件与其子节点之间,用于其他组件可能导致非预期的情况。
- 继承样式,如 font 、 color ,会从组件外继承到组件内。
- 除继承样式外, app.wxss 中的样式、组件所在页面的的样式对自定义组件无效。
#a { } /* 在组件中不能使用 /
[a] { } / 在组件中不能使用 /
button { } / 在组件中不能使用 /
.a > .b { } / 除非 .a 是 view 组件节点,否则不一定会生效 */
除此以外,组件可以指定它所在节点的默认样式,使用 :host 选择器(需要包含基础库 1.7.2 或更高版本的开发者工具支持)。
代码示例:
/* 组件 custom-component.wxss */
:host { color: yellow; }
<!-- 页面的 WXML -->
<custom-component>这段文本是黄色的</custom-component>
Component构造器、父子组件传值与组件事件
Component构造器
- Component构造器可用于定义组件,调用Component构造器时可以指定组件的属性、数据、方法等。
属性
properties: {
myProperty: { // 属性名
type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
value: '', // 属性初始值(可选),如果未指定则会根据类型选择一个
observer: function(newVal, oldVal){} // 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串, 如:'_propertyChange'
},
myProperty2: String // 简化的定义方式
}
生命周期函数
注意:在 properties 定义段中,属性名采用驼峰写法(propertyName);在 wxml 中,指定属性值时则对应使用连字符写法(component-tag-name property-name=“attr value”),应用于数据绑定时采用驼峰写法(attr="{{propertyName}}")。
使用 Component 构造器构造页面
- 事实上,小程序的页面也可以视为自定义组件。因而,页面也可以使用 Component 构造器构造,拥有与普通组件一样的定义段与实例方法。但此时要求对应 json 文件中包含 usingComponents 定义段。
- 此时,组件的属性可以用于接收页面的参数,如访问页面 /pages/index/index?paramA=123¶mB=xyz ,如果声明有属性 paramA 或 paramB ,则它们会被赋值为 123 或 xyz 。
组件间通讯与事件
组件间通信与事件
- 组件间的基本通信方式有以下几种。
- WXML 数据绑定:用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容数据。
- 事件:用于子组件向父组件传递数据,可以传递任意数据。
- 如果以上两种方式不足以满足需要,父组件还可以通过 this.selectComponent 方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法。
父组件向子组件传值
- 方法1. page(父组件)在引用组件时能通过属性值设置,在子组件的properties 里面接收父组件传过来的数据
- 方法2、 page在引用组件时通data-xxx设置,子组件中子组件名.js在this.dataset获取:
父组件向子组件传值—方法1
<call-phone phone="88888888"></call-phone>
Component({
properties: {
phone: String //简写
/* phone: { type: String, //类型
value: '', //初始值
observer: function(newVal, oldVal) {} } */
},
attached: function() {
console.log("this.properties.phone:" + this.properties.phone); //控制台打印:"88888888"
},
//...
})
注意:我们不要把data和properties里的变量设置成同一个名字,如果他们名字相同,properties里的会覆盖data里的。
父组件向子组件传值—方法2
<call-phone data-tel="88888888" ></call-phone>
Component({
attached: function() {
console.log("this.dataset.tel:" + this.dataset.tel); //控制台打印:"88888888" // 设置properties值用setData()
this.setData({
phone: this.dataset.tel
});
},
//...
})
<call-phone data-tel="88888888" ></call-phone>
Component({
attached: function() {
console.log("this.dataset.tel:" + this.dataset.tel); //控制台打印:"88888888" // 设置properties值用setData()
this.setData({
phone: this.dataset.tel
});
},
//...
})
子组件中的变量要传到page页面
组件中的变量要传到page页面,可以通过事件触发this.triggerEvent()来实行:
Component({
methods: {
callPhone() {
var myEventDetail = {msg: '来自component的信息', tel: '88888888' }
// detail对象,提供给事件监听函数
var myEventOption = {} // 触发事件的选项
this.triggerEvent('myevent', myEventDetail, myEventOption)
}
}
})
子组件中的变量要传到page页面
<!--index.wxml-->
<!--"bindmyevent"属性与上面"myevent"对应,当自定义组件触发"myevent"事件时,调用"call"方法 -->
<call-phone bindmyevent="call"></call-phone>
//index.js
Page({
call: function(e) {
console.log(e.detail.msg);//控制台打印:"来自component的信息" wx.makePhoneCall({ phoneNumber: e.detail.tel })
}
})
监听事件
- 事件系统是组件间通信的主要方式之一。自定义组件可以触发任意的事件,引用组件的页面可以监听这些事件。
- 监听自定义组件事件的方法与监听基础组件事件的方法完全一致:
<component-tag-name bindmyevent="onMyEvent" />
Page({
onMyEvent: function(e)
{
console.log(e.detail) // 自定义组件触发事件时提供的detail对象
}
})
触发事件
自定义组件触发事件时,需要使用 triggerEvent 方法,指定事件名、detail对象和事件选项:
<!-- 在自定义组件中 -->
<button bindtap="onTap">
点击这个按钮将触发“myevent”事件</button>
Component(
{methods: {
onTap: function(){
var myEventDetail = {} // detail对象,提供给事件监听函数
var myEventOption = {} // 触发事件的选项
this.triggerEvent('myevent', myEventDetail, myEventOption)
}
}
})