一、组件(内置基础组件、自定义组件、第三方组件库)
1. 基础组件即官方组件库,可以直接拿来用(developers.weixin.qq.com/miniprogram…
例:
view视图容器,类似div标签
scroll-view可滚动的视图容器,滚动列表效果
swiper轮播图容器组件,swiper-item轮播图item
text文本组件,类似span标签,不会换行,selectable属性实现长按选中文本内容效果
rich-text富文本组件,nodes属性支持把html字符串渲染为wxml结构(nodes="<h1>标题</h1>")
image图片组件,mode属性指定图片裁剪缩放模式(scaleToFill默认不保持横纵比缩放)
button按钮组件,open-type属性可以调用微信提供的各种功能(客服、转发、获取用户授权、信息等)
2. 自定义组件封装(类似于页面,自定义组件拥有自己的 wxml 模板和 wxss 样式)
1>. 创建一个components文件夹用来放置自定义组件
2>. 创建自定义组件(页面)
3>. 定义自定义组件内容
自定义组件js文件
Component({})注册组件页面,配置项:
data:{}组件内部初始数据,
properties:{}接收外面传入的数据,类似于vue中的props,
methods:{}组件方法列表,
observers:{'字段a/对象.属性a/对象.**,字段b':function(字段a新值/属性a的新值/obj,字段b新值){}}数据监听器(监听某些字段的变化,对象属性的变化,如果对象属性太多,可以用对象.**监听对象中所有属性的变化)
纯数据字段:指不用于界面渲染的data字段(既不会展示在界面上,也不会传递给其他组件),有助于提升页面更新的性能。
options:{pureDataPattern:/^_/}字段名符合这个正则表达式(以_开头)的字段将成为纯数据字段
Component({
options: {
pureDataPattern:/^_/,//以_开头的字段将成为纯数据字段
multipleSlots: true // 在组件定义时的选项中启用多 slot 支持
},
/**
* 组件的属性列表
* 类似于vue props,接收外面传入属性
*/
properties: {
// title:String,
title:{
type:String,
valve:'标题'//默认值
}
},
/**
* 组件的初始数据
*/
data: {
content:'我是组件内部数据',
n1:0,
n2:0,
sum:0,
_a:true//纯数据字段
},
/**
* 组件的方法列表
*/
methods: {
show(){
console.log('show method >>>>',this.data.content);
},
addN1(){ this.setData(( n1: this.data.n1 + 1 })),
addN2(){ this.setData({ n2: this.data.n2 + 1 })}
},
//数据监听器,同vue中的watch
observers:{
'n1,n2': function(newn1,newn2){//监听 n1 和 n2 数据的变化
this.setData({sum:newn1 + newn2 })// 通过监听器,自动计算 sum 的值
}
}
})
自定义组件wxml文件
<view class="g-container">
<view>自定义组件</view>
<view>
<view>标题: {{title}}</view>
<view>内容: {{content}}</view>
<button bind:tap="show" type="primary" size="mini">确定</button>
<view>{{n1}} + {{n2}} = {{sum}}</view>
<button bind:tap="addN1" type="primary" size="mini">n1+1</button>
<button bind:tap="addN2" type="primary" size="mini">n2+1</button>
</view>
</view>
4>.注册自定义组件
在要使用自定义组件的页面的json文件中注册自定义组件(”组件名”:”路径”)
{
"navigationBarTitleText": "列表",
"component":true,
"usingComponents": {
"myText":"../../components/MyText/index"
}
}
5>.使用自定义组件
在要使用自定义组件的页面的wxml文件中直接使用传参即可
<view>
<!-- 自定义组件 -->
<myText title="自定义组件"></myText>
</view>
组件与页面区别:
组件json文件需要声明"component":true,
组件js文件用Component({})注册组件页面
页面js文件用Page({})注册页面
组件js文件事件处理函数要定义到methods节点中
页面js文件事件处理函数要定义到与data平齐的节点中
组件样式特点:
-
隔离性:组件与组件、组件与外界页面之间样式互不影响
-
app.wxss 中的全局样式对组件无效
-
只有 class 选择器会有样式隔离效果,id 选择器、属性选择器、标签选择器不受样式隔离的影响
开发过程中有时需要外界页面控制组件样式,可以通过 stylelsolation 修改组件的样式隔离选项,有两种方式:
- 在组件js文件中通过options修改组件的样式隔离选项
Component({
options: {
stylelsolation: 'isolated'//isolated启用样式隔离;apply-shared页面样式可以影响组件样式,但组件样式无法影响页面样式;shared页面组件样式互相影响
},
})
- 在组件json文件中配置
{
"stylelsolation": "isolated"
}
3. 第三方组件库
1>. WeUI:
是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计。 github下载地址 github.com/yuanqingjia…
使用:(以mp-dialog弹框组件为例)
-
通过useExtendedLib扩展库的方式引入,这种方式引入的组件不会计入代码包大小
(1)全局配置文件app.json文件中引入weui
{
"pages": [
"pages/goodsList/index",
"pages/goodsDetail/index"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#f00",
"navigationBarTitleText": "小程序",
"navigationBarTextStyle": "white"
},
"sitemapLocation": "sitemap.json",
"useExtendedLib": {
"weui": true
}
}
(2)在要使用该组件库的页面的json配置文件中注册组件(mp-dialog弹框组件)
{
"navigationBarTitleText": "商品列表",
"usingComponents": {
"myText":"../../components/MyText/index",
"mp-dialog":"weui-miniprogram/dialog/dialog"
}
}
(3)在wxml文件中使用
<view>
<!-- weui组件库 -->
<mp-dialog title="标题" show="{{isShow}}">
<myText id="mytext" title="weui组件库">
<image slot="logo" style="width: 200px;height: 200px;" src="{{src}}"></image>
<view slot="footer">
<view>底部区域</view>
<text>========</text>
</view>
</myText>
</mp-dialog>
<button bind:tap="onAdd">弹框</button>
</view>
(4)js文件逻辑内容
// pages/goodsList/index.js
Page({
/**
* 页面的初始数据
*/
data: {
isShow: false,
},
onAdd() {
const isShow = this.data.isShow;
this.setData({ isShow: !isShow });
}
});
-
通过npm下载构建,包名为weui-miniprogram
2>.vant-weapp:(可能会有版本问题出现组件展示不出来的问题,可以用npm uninstall @vant/weapp卸载,删掉miniprogram_npm目录,然后通过npm i @vant/weapp@1.10.3 -S --production重新下载指定版本)
官网:youzan.github.io/vant-weapp/…
使用:(以van-button/van-dialog组件为例)
(1)安装
npm init -y (初始化生成package.json文件)
npm i @vant/weapp -S --production或者yarn add @vant/weapp --production(安装生成node_modules文件)
(2)修改app.json文件
将 app.json 中的 "style": "v2" 去除,小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。
(3)修改project.config.json文件
在project.config.json文件中的"packNpmRelationList":[]中添加对象(指定package.json文件的路径和小程序安装vant组件库的路径)
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./"
}
],
(4)点击左上角工具 -> 构建 npm,执行完以后项目根目录会增加:“miniprogram_npm”目录,就是vant- weapp的组件。构建完成后,即可引入组件。
(5)在app.json(全局)或index.json中注册组件
"usingComponents": {
"van-button": "@vant/weapp/button/index",
"van-dialog": "@vant/weapp/dialog/index",
"van-uploader": "@vant/weapp/uploader/index",
"van-nav-bar": "@vant/weapp/nav-bar/index"
}
(6)wxml文件中使用组件
<view>
<!-- vant-weapp组件库 -->
<van-button type="primary" size="small" bind:tap="onDialog">主要按钮</van-button>
<van-dialog id="van-dialog" show="{{ isDialog }}" />
<van-uploader file-list="{{ fileList }}" bind:after-read="afterRead" />
<van-nav-bar title="标题" left-text="返回" right-text="按钮" />
</view>
(7)js文件中逻辑代码
Page({
/**
* 页面的初始数据
*/
data: {
isDialog: false,
fileList: [],
},
onDialog() {
const isDialog = this.data.isDialog;
this.setData({ isDialog: !isDialog });
},
afterRead(event){
console.log(event.detail);
},
});
二、组件通讯
1. 父传子(直接传)
1>.父组件json文件中注册子组件
{
"navigationBarTitleText": "列表",
"usingComponents": {
"myText":"../../components/MyText/index"
}
}
2>. wxml文件中使用子组件,在子组件标签中定义要传的属性
<view>
<!-- 父传子 -->
<myText title="自定义组件"></myText>
</view>
3>.子组件js文件中通过prperties配置项接收父组件传入的属性
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多 slot 支持
},
/**
* 组件的属性列表
* 类似于vue props,接收外面传入属性
*/
properties: {
title:''
},
/**
* 组件的初始数据
*/
data: {
content:'我是组件内部数据'
},
/**
* 组件的方法列表
*/
methods: {}
})
4>. 子组件wxml文件中可直接使用
<view class="g-container">
<view>自定义组件</view>
<view>
<view>标题: {{title}}</view>
<view>内容: {{content}}</view>
</view>
</view>
2. 子传父(父组件传递自定义事件到子组件,子组件触发自定义事件,返回数据给父组件)
1>. 父组件js文件中定义事件,接收数据
Page({
/**
* 页面的初始数据
*/
data: {
message: "",
},
bindContent(content) {
console.log("触发自定义事件执行父组件代码", content.detail);
const message = content.detail;
this.setData({ message });
}
});
2>. 父组件wxml中传递事件给子组件
<view>
<!-- 子传父,传递自定义事件到子组件,子组件触发事件,返回数据 -->
<text>{{message}}</text>
<myText bind:getcontent="bindContent"></myText>
</view>
3>. 子组件js文件中触发事件,返回数据给父组件(小程序中无需接收事件,直接触发即可,通过triggerEvent触发,类似于vue中emit)
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多 slot 支持
},
/**
* 组件的属性列表
* 类似于vue props,接收外面传入属性
*/
properties: {
title:''
},
/**
* 组件的初始数据
*/
data: {
content:'我是组件内部数据'
},
/**
* 组件的方法列表
*/
methods: {
show(){
console.log('show method >>>>',this.data.content);
// emit('getcontent',100)
this.triggerEvent('getcontent',this.data.content)
},
}
})
3. 传内容(如图片内容)插槽与具名插槽
1>.父组件wxml文件
<view>
<!-- 插槽 -->
<myText>
<image style="width: 200px;height: 200px;" src="{{src}}"></image>
</myText>
<!-- 具名插槽 -->
<myText>
<image slot="logo" style="width: 200px;height: 200px;" src="{{src}}"></image>
<view slot="footer">
<view>底部区域</view>
<text>========</text>
</view>
</myText>
</view>
2>. 子组件wxml文件
<view class="g-container">
<view>
<view>标题: {{title}}</view>
<view>内容: {{content}}</view>
<view>
<slot></slot>
</view>
<view>
<slot name="logo"></slot>
<slot name="footer"></slot>
</view>
</view>
</view>
4. 组件实例传参(小程序中可以通过this.selectComponent(“id名”)方法获取组件实例,这样就可以直接访问组件的数据和方法了。vue中可以通过ref属性拿到组件实例,从而调用组件中的数据和方法,或者通过expose方法暴露)
1>. 父组件wxml文件中给子组件加个id名
<view>
<!-- 组件实例传参 -->
<myText>
<image id="mytext"
style="width: 200px;height: 200px;" src="{{src}}"></image>
</myText>
<text>{{message}}</text>
<button bind:tap="bindGetInstance">获取子组件实例</button>
</view>
2>. 父组件js文件中调用this.selectComponent(“id名”)方法获取子组件实例
Page({
/**
* 页面的初始数据
*/
data: {},
bindGetInstance() {
//获取子组件实例
const instance = this.selectComponent("#mytext");
//调数据和方法
console.log(instance.data.content);
instance.show();
}
});
3>. 子组件js文件中的数据和方法
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多 slot 支持
},
/**
* 组件的属性列表
* 类似于vue props,接收外面传入属性
*/
properties: {
title:''
},
/**
* 组件的初始数据
*/
data: {
content:'我是组件内部数据'
},
/**
* 组件的方法列表
*/
methods: {
show(){
console.log('show method >>>>',this.data.content);
},
}
})