一、前言
如果读者接触过前端 JS 开发或者 QT 开发,那么小程序将会简单很多。作者本人的 JS 和 HTML 只是入门水平,但是比较熟悉 QT 的开发,因此熟悉整体前端设计框架和样式表,迁移起来还算不吃力。
如果读者和我一样,只是想快速体验小程序开发,或者是实现一个简单功能,那么我建议可以不用太深入开发框架,专注于每个页面的 JS 业务逻辑和样式表即可,节约开发时间,后续慢慢再去探索各项功能。

二、微信开发者工具使用
微信小程序的开发有其专门的开发套件:微信开发者工具。在官网下载安装后,是如下界面:

可以开发多种应用,点击新建可以选择已有模板,快速创建代码框架:

如果第一次使用,我建议创建测试号,会自动填充一个 AppID,先熟悉开发页面,后续再考虑增加云开发功能,因为这个需要与具体账号绑定。
下图为创建后的页面:

整体风格与 VScode 还有点像,左侧的目录结构 pages 下,就是以页面为单位的文件夹结构,每个页面都有
js:JavaScript,逻辑业务实现;
json:配置文件,用于页面或全局配置;
wxml:描述页面结构和布局,类似HTML;
wxss:描述页面样式,类似CSS但有增强。
如果需要添加新的页面,在 pages 下新建文件夹,然后右键新的文件夹,新建 page 就会自动创建以上四个文件:

名称为 app 的是项目的整体配置文件,新建的 page 会自动添加到 app.json 文件内:

navigationBarTitleText 用于设置小程序的顶部名称。
三、编写页面逻辑:demo分享
1、外观简述
下面是我做的一个简单demo,实现了基本的页面跳转和表单填写。
但是这里没加发送,本章先着重页面逻辑本身,发送逻辑准备单独写一遍文章,涉及到云函数的使用。
当前主要做了一些样式表的尝试,例如长按动画,渐变色按钮,背景等。

两个子页面的内容是一样的,常规的表单收集:

2、代码实现
(1)主页面 index
index.js
javascript
Page({
// 跳转到表单1
goToForm1() {
wx.navigateTo({
url: '/pages/form1/form1'
})
},
// 跳转到表单2
goToForm2() {
wx.navigateTo({
url: '/pages/form2/form2'
})
},
onLoad() {
// 页面加载时执行
}
})
index.wxml
html
<view class="container">
<!-- 主图标 -->
<view class="main-icon">
<image src="/images/railway.png" mode="aspectFit"></image>
</view>
<!-- 背景图片 -->
<image
src="/images/bg.png"
class="background-image"
mode="aspectFill"
></image>
<!-- 按钮区域 -->
<view class="button-group">
<!-- 按钮1 -->
<view class="button-item" bindtap="goToForm1">
<image class="button-icon" src="/images/mail.png"></image>
<text class="button-text">站长信箱</text>
</view>
<!-- 按钮2 -->
<view class="button-item" bindtap="goToForm2">
<image class="button-icon" src="/images/mail.png"></image>
<text class="button-text">党委书记信箱</text>
</view>
</view>
</view>
index.wxss
css
.container {
display: flex;
flex-direction: column;
align-items: center;
padding: 40rpx;
height: 100vh;
}
.main-icon {
margin-top: 100rpx;
margin-bottom: 150rpx;
}
.main-icon image {
width: 200rpx;
height: 200rpx;
border-radius: 20rpx;
box-shadow: 0 8rpx 20rpx rgba(0,0,0,0.1);
}
/* 背景图片样式 */
.background-image {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1; /* 确保背景在最底层 */
}
.button-group {
width: 100%;
display: flex;
flex-direction: column;
gap: 40rpx;
margin-bottom: 500rpx; /* 按钮上移 */
}
.button-item {
background: linear-gradient(135deg, #cadcf7 0%, #7ca9f1 100%);
display: flex;
align-items: center;
border-radius: 20rpx;
padding: 30rpx;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.08);
transition: all 0.3s;
}
.button-item:active {
transform: translateY(2rpx);
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 1);
}
.button-icon {
width: 100rpx;
height: 100rpx;
margin-right: 30rpx; /* 图标右边间距 */
border-radius: 16rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
transition: all 0.3s ease; /* 过渡动画,点击时线性缩放 */
}
.button-item:active .button-icon {
transform: scale(0.90); /* 缩小 */
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
}
.button-text {
font-size: 36rpx;
color: #333;
font-weight: 500;
}
index.json 保持默认
bash
{
"usingComponents": {}
}
(2)表单页面 form1
form1.js
javascript
Page({
data: {
formData: {
name: '',
phone: '',
workplace: '',
remark: ''
},
isFormValid: false
},
// 输入框变化
onInputChange(e) {
const field = e.currentTarget.dataset.field;
const value = e.detail.value;
this.setData({
[`formData.${field}`]: value
}, () => {
this.validateForm();
});
},
// 表单验证
validateForm() {
const { name, phone, workplace, remark } = this.data.formData;
const isValid = name.trim().length > 0 &&
phone.trim().length === 11 &&
option.length > 0;
this.setData({
isFormValid: isValid
});
},
// 表单提交
formSubmit(e) {
const formData = e.detail.value;
// 验证手机号格式
if (!/^1[3-9]\d{9}$/.test(formData.phone)) {
wx.showToast({
title: '手机号格式错误',
icon: 'none'
});
return;
}
// 显示加载中
wx.showLoading({
title: '提交中...',
});
// 模拟提交到服务器
setTimeout(() => {
wx.hideLoading();
// 提交成功提示
wx.showToast({
title: '提交成功',
icon: 'success',
duration: 2000
});
// 清空表单
this.setData({
formData: {
name: '',
phone: '',
remark: ''
},
isFormValid: false
});
// 返回上一页
setTimeout(() => {
wx.navigateBack();
}, 1500);
}, 1500);
},
onLoad() {
// 页面加载
}
})
form1.wxml
html
<view class="form-container">
<!-- 背景图片 -->
<image
src="/images/bg.png"
class="background-image"
mode="aspectFill"
></image>
<form bindsubmit="formSubmit">
<!-- 表单标题 -->
<view class="form-title">站长信件填写</view>
<!-- 提示信息 -->
<text class="tips-title" >特别提示:\n</text>
<text class="tips-text" >请您据实填写诉求建议内容,便于我们与相关科室和部门核实处理,另请如实填写个人信息,便于与您联系。</text>
<!-- 输入项1 -->
<view class="form-item">
<text class="form-label">姓名:</text>
<input
name="name"
type="text"
placeholder="请输入姓名"
placeholder-class="input-placeholder"
class="form-input"
bindinput="onInputChange"
data-field="name"
value="{{formData.name}}"
/>
</view>
<!-- 输入项2 -->
<view class="form-item">
<text class="form-label">电话:</text>
<input
name="phone"
type="number"
placeholder="请输入手机号"
placeholder-class="input-placeholder"
class="form-input"
maxlength="11"
value="{{formData.phone}}"
/>
</view>
<!-- 输入项3 -->
<view class="form-item">
<text class="form-label">单位:</text>
<input
name="workplace"
type="text"
placeholder="请输入单位名称"
placeholder-class="input-placeholder"
class="form-input"
bindinput="onInputChange"
data-field="workplace"
value="{{formData.workplace}}"
/>
</view>
<!-- 文本域 -->
<view class="form-item textarea-item">
<text class="form-label">诉求内容:</text>
<textarea
name="remark"
placeholder="请输入您的诉求内容"
placeholder-class="input-placeholder"
class="form-textarea"
maxlength="65535"
value="{{formData.remark}}"
>
</textarea>
</view>
<!-- 提交按钮 -->
<button
formType="submit"
class="submit-btn"
hover-class="button-hover"
disabled="{{!isFormValid}}"
>
发送信件
</button>
</form>
</view>
form1.wxss
html
.form-container {
padding: 30rpx;
position: relative;
min-height: 100vh;
}
/* 背景图片样式 */
.background-image {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1; /* 确保背景在最底层 */
}
.tips-title{
color: red;
font: bold;
font-size: 40rpx;
}
.tips-text{
color: black;
font: bold;
font-size: 30rpx;
}
.form-title {
font-size: 40rpx;
font-weight: bold;
text-align: center;
margin: 40rpx 0 60rpx;
color: #333;
}
.form-item {
background-color: white;
padding: 30rpx;
margin-bottom: 20rpx;
border-radius: 15rpx;
display: flex;
align-items: center;
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.05);
}
.form-label {
width: 150rpx;
font-size: 32rpx;
color: #333;
flex-shrink: 0;
}
.form-input, .picker-view {
flex: 1;
font-size: 32rpx;
color: #333;
padding: 20rpx 0;
min-height: 60rpx;
}
.form-textarea {
flex: 1;
font-size: 32rpx;
min-height: 200rpx;
padding: 20rpx;
background-color: #fafafa;
border-radius: 10rpx;
}
.textarea-item {
align-items: flex-start;
}
.input-placeholder {
color: #ccc;
font-size: 30rpx;
}
.submit-btn {
margin-top: 60rpx;
background-color: #07c160;
color: white;
border-radius: 20rpx;
font-size: 35rpx;
height: 120rpx;
line-height: 90rpx;
}
.submit-btn-disabled {
background-color: #cccccc;
color: #999;
}
.button-hover {
background-color: #06ad56;
}
其余保持默认,背景图片和图标需要读者自行添加到项目的 images 目录下。
现在应该可以看到右侧的预览已经正常工作了,可以点击开发平台上方的预览或者真机调试,可以用手机扫二维码测试页面效果:

四、结尾
本文简单介绍了微信开发平台的使用,分享了一个简单界面的demo,也算是我个人的一篇笔记,方便未来需要使用时快速构建项目。
我准备在另一篇文章分享如何通过云函数来调用邮箱的 SMTP 功能发送邮件,并实现正式的小程序上线。