写在前面的话
上篇博文《微信小程序实战(1)· 开篇示例 》介绍了本系列课程的背景,本篇博文继续以该示例出发,介绍实战开发中,关于组件方法的运用。
组件实战
参考:微信小程序官网文档
背景说明
通常,使用微信小程序都会借助现成的UI组件,就像 Vue 前端开发中,我们使用 ElementUI 中的表格、下拉框等组件一样,对于半路出家的后端程序猿更是如此,不可能全部元素都自己开发,有现成封装好的还不用吗。
博主开发微信小程序经常采用的是 Vant 或 WeUI,都很好用,只需要简单配置引入后,即可在页面开发中按需使用这些功能。
例如,您可以在 app.json,或某页面.json,使用如下方式引入 Vant 的组件。
"usingComponents": {
"van-button": "/pages/vant/button/index",
},
然后,在具体的 WXML 页面就可以直接使用:
<van-row>
<van-col span="24">
<van-button size="large" plain type="primary" bindtap="submit">提交工单</van-button>
</van-col>
</van-row>
好了,大致了解组件的用途了,那组件到底是个什么东西,接下来详细介绍。
基础用法
Step1、在 components 目录下创建一个新文件夹,例如 myComponent。
Step2、在 myComponent 文件夹中创建以下文件,和页面开发基本一致。
- myComponent.js:组件的逻辑。
- myComponent.json:组件的配置。
- myComponent.wxml:组件的结构。
- myComponent.wxss:组件的样式。
Step3、编写 myComponent.js
Component({
properties: {
title: {
type: String,
value: '默认标题'
}
},
data: {
// 组件内部数据
},
methods: {
// 组件内部方法
handleClick() {
this.triggerEvent('click');
}
}
});
Step4、编写myComponent.json
{
"component": true
}
Step5、编写myComponent.wxml
<view class="my-component" bindtap="handleClick">
<text>{{title}}</text>
</view>
Step6、编写myComponent.wxss
.my-component {
padding: 10px;
background-color: #f0f0f0;
border: 1px solid #ccc;
}
Step7、使用组件
在需要使用该组件的页面中(例如 index
页面),你需要在 index.json
中引入组件,并在 index.wxml
中使用它,几个核心组成分别如下。
{
"usingComponents": {
"my-component": "/components/myComponent/myComponent"
}
}
<view>
<my-component title="Hello World" bind:click="handleComponentClick"></my-component>
</view>
Page({
handleComponentClick() {
wx.showToast({
title: '组件被点击',
icon: 'success'
});
}
});
至此,运行一下效果,可以看的明白组件的用处了吧。
其实相当于封装公用的部分,各个页面可以快速复用,基本任意前端框架都拥有组件能力,就像 Vue.component。
实战说明
上面基础用法看完,应该大致了解组件的来龙去脉了,那实际开发中,哪些东西可以考虑封装呢,这边以实例进一步补充说明。
本次开发安全巡检小程序的时候,涉及众多表单页面,表单元素里面难免涉及下拉框选项。
那么,传统的做法有几种:picker、actionSheet、自定义模态框等,前两者比较适合数据内容少的情况,如果数据较多,只能自定义模态框的方式,还需要增加上分页或搜索功能。
那分析当前场景,几个表单项都是涉及众多数据元素的情况,那只有自定义开发弹窗了。
好的,那就开发,三下五除二,开发了第一个页面如下,效果还不错。
可以展示信息,可以搜索,可以控制弹窗隐藏和显示,基本具备了。
可是还有很多表单页面,这部分代码量着实不小,所有页面都要拷贝这些代码过去吗?基本HTML、JS、CSS三个部分都要搬了,真的要做搬运工了?
其实不然,这其实你如果还想不到封装组件,那就白做开发这么多年了。
分析了一下前因后果,决定封装一个 showData 数据展示组件,并把组件与父组件的展示一同考虑进去,包括查询数据的接口信息。
Step1、编写JS
var app = getApp();
var ace = require("../../utils/ace.js");
Component({
/**
* 组件的属性列表
*/
properties: {
url: { //接口地址
type: String, value: ''
},
textContent: { //文本内容
type: String, value: '选择一下:'
},
code: { //Key的属性
type: String, value: 'valueCode'
},
name: { //Name的属性
type: String, value: 'valueName'
},
ex: { //额外的属性
type: String, value: 'validFlag'
},
},
/**
* 组件的初始数据
*/
data: {
dataList: [], query: '',
},
created() {
// 组件创建时的初始化逻辑
console.log('组件已创建');
},
attached() {
let that = this
// 组件被插入到页面时的逻辑
console.log('组件已附加到页面');
// 访问 properties 中的属性
const url = this.properties.url || '';
console.log('url 的值:', url);
//也可以用data获取
//const url2 = this.data.url || '';
if (url) {
ace.sendGet(url, function (data) {
if (data) {
that.setData({
dataList: data
})
}
})
}
},
ready() {
// 组件视图渲染完成时的逻辑
console.log('组件已准备就绪');
},
/**
* 组件的方法列表
*/
methods: {
/**
* 搜索内容
*/
searchProduct(e) {
let that = this
let value = e.detail
let url = that.data.url
if (value && url) {
if (url.indexOf("?") !== -1) {
url += '&query=' + value
} else {
url += '?query=' + value
}
}
ace.sendGet(url, function (data) {
if (data) {
that.setData({
dataList: data, query: value
})
}
})
},
/**
* 点击事件
*/
clickHandle(e) {
let id = e.currentTarget.dataset.id || ''
if(id){
this.triggerEvent('myevent', { data: id});
}
},
/**
* 关闭事件
*/
closeHandle: function () {
this.triggerEvent('myclose');
}
},
});
Step2、编写HTML(CSS就不贴出来了)
<van-popup show="true" round position="bottom" bind:close="closeHandle">
<view class="select-company">
<van-search value="{{ query }}" placeholder="请输入搜索关键词"
bind:change="searchProduct"/>
<view class="title">{{textContent}}</view>
<view class="company-list ">
<view class="item" wx:for="{{dataList}}" wx:key="index" bindtap="clickHandle"
data-id="{{ item[code] }}">
<view class="count">名称:{{item[name]}}</view>
<view class="count"> | 类型:{{item[ex]}}</view>
</view>
</view>
</view>
</van-popup>
Step3、注册到全局json或页面级json
"usingComponents": {
"showData": "/components/showData/showData",
}
Step4、具体页面使用组件
<showData url="xjCheckType?userCode={{payNo}}" bind:myevent="handleMyEvent" bind:myclose="handleMyClose"
wx:if="{{showDataFlag}}"></showData>
至此,搞定收工,效果和原先单独开发效果一样。
总结陈词
这里说一个组件封装的思路和技巧,实战开发中,往往不会第一时间就想到功能的可封装性,这并不要求,完全可以等功能开发完毕后,再将第一个版本使用组件,复制一份,最终可以用组件完美复刻功能,即为成功,也是常见思路。
此篇文章是《微信小程序实战》系列的第二篇,后续该专栏会继续分享小程序实战中运用的技能,希望可以帮助到大家。
💗 后续会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。