微信小程序作为一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。对于开发者而言,小程序是一种全新的开放能力,它基于微信提供的框架和API,让开发者能够快速构建出高质量的本地应用。本指南将从基础入门讲起,逐步深入到高级实战技巧,并提供常见问题的解决方案,帮助你从入门走向精通。

一、入门基础:环境搭建与项目结构

在开始编写代码之前,我们需要搭建好开发环境并了解小程序的基本构成。

1.1 开发工具的安装与使用

微信官方提供了“微信开发者工具”,它是小程序开发的主要IDE。你可以访问微信公众平台下载对应操作系统的版本。

安装步骤:

  1. 下载安装包并安装。
  2. 打开开发者工具,使用微信扫码登录。
  3. 选择“小程序”项目,填写项目目录和AppID(在公众平台账号后台可获取,若仅为学习,可选择“不使用云服务”并创建测试号)。

1.2 小程序项目结构

一个标准的小程序项目主要包含以下几种类型的文件,它们必须存放在指定的目录下:

  • .json 配置文件:全局配置(app.json)和页面配置(page.json)。
  • .wxml 模板文件:类似于HTML,用于描述页面的结构。
  • .wxss 样式文件:类似于CSS,用于描述页面的样式。
  • .js 逻辑文件:用于处理页面的交互逻辑、数据绑定和网络请求。

示例项目结构:

miniprogram/
├── app.js              // 小程序入口文件
├── app.json            // 全局配置
├── app.wxss            // 全局样式
├── pages/              // 页面目录
│   ├── index/          // 首页
│   │   ├── index.js    // 首页逻辑
│   │   ├── index.json  // 首页配置
│   │   ├── index.wxml  // 首页结构
│   │   └── index.wxss  // 首页样式
│   └── logs/           // 日志页
│       ├── logs.js
│       ├── logs.json
│       ├── logs.wxml
│       └── logs.wxss
└── utils/              // 工具类
    └── util.js

1.3 全局配置 app.json

app.json 是小程序的全局配置文件,决定了小程序的所有页面路径、界面表现、网络超时时间等。

常用配置项:

  • pages: 定义所有页面路径,数组的第一项是小程序的初始页面。
  • window: 定义小程序所有页面的顶部表现,如导航栏背景色、标题文字等。
  • tabBar: 如果小程序是一个多 tab 应用,可以通过该配置指定 tab栏的表现。

代码示例:

{
  "pages": [
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window": {
    "navigationBarTitleText": "我的小程序",
    "navigationBarBackgroundColor": "#007AFF",
    "navigationBarTextStyle": "white"
  },
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页",
        "iconPath": "images/home.png",
        "selectedIconPath": "images/home-selected.png"
      },
      {
        "pagePath": "pages/logs/logs",
        "text": "日志",
        "iconPath": "images/log.png",
        "selectedIconPath": "images/log-selected.png"
      }
    ]
  }
}

二、核心开发技术:WXML 与 WXSS

小程序的视图层由 WXML 和 WXSS 组成,它们分别负责结构的搭建和样式的定义。

2.1 WXML 数据绑定与列表渲染

WXML 支持数据绑定、列表渲染、条件渲染等,语法使用双大括号 {{ }}

数据绑定:.js 文件中定义 data 对象,在 .wxml 中通过 {{ variable }} 引用。

JS代码 (index.js):

Page({
  data: {
    message: 'Hello, Mini Program!',
    userInfo: {
      name: '张三',
      age: 25
    }
  }
})

WXML代码 (index.wxml):

<view>{{ message }}</view>
<view>姓名: {{ userInfo.name }}, 年龄: {{ userInfo.age }}</view>

列表渲染 (wx:for): 用于循环渲染一个数组,生成多个相同的组件结构。

JS代码 (index.js):

Page({
  data: {
    items: [
      { id: 1, name: '苹果' },
      { id: 2, name: '香蕉' },
      { id: 3, name: '橙子' }
    ]
  }
})

WXML代码 (index.wxml):

<view wx:for="{{items}}" wx:key="id">
  {{index}}: {{item.name}}
</view>

注意wx:key 是为了提高列表渲染的性能,保持节点的唯一性。

2.2 WXSS 样式与尺寸单位

WXSS 在 CSS 的基础上扩展了两个特性:尺寸单位样式导入

尺寸单位 rpx (responsive pixel): rpx 是微信小程序的响应式像素单位,它规定了屏幕宽为 750rpx。无论屏幕宽度是多少,1rpx 的长度都会自动换算。 例如,在 iPhone 6 上,屏幕宽度为 375px,共 750rpx,因此 1rpx = 0.5px。

代码示例:

/* index.wxss */
.container {
  width: 750rpx; /* 在任何屏幕上都占满宽度 */
  height: 200rpx;
  background-color: #f0f0f0;
}

.box {
  /* 使用 flex 布局 */
  display: flex;
  justify-content: center;
  align-items: center;
  width: 50%; /* 百分比相对于父容器 */
  height: 100rpx;
  margin: 10rpx auto;
}

三、逻辑层与数据驱动:JavaScript

小程序的逻辑层主要由 JavaScript 组成,核心是 PageComponent 构造器。

3.1 Page 页面生命周期与事件处理

Page 构造器用于定义页面的数据、生命周期函数和事件处理函数。

生命周期函数:

  • onLoad(options): 页面加载时触发,适合获取初始化数据。
  • onShow(): 页面显示时触发。
  • onReady(): 页面初次渲染完成时触发。
  • onHide(): 页面隐藏时触发。
  • onUnload(): 页面卸载时触发。

事件绑定与处理: 在 WXML 中使用 bindtap 绑定点击事件,在 JS 中定义对应的处理函数。

WXML代码:

<button bindtap="handleClick" data-id="123">点击我</button>

JS代码:

Page({
  // 定义数据
  data: {
    count: 0
  },

  // 点击事件处理函数
  handleClick: function(e) {
    // 获取 data 中的数据
    const currentCount = this.data.count;
    
    // 更新数据 (必须使用 this.setData)
    this.setData({
      count: currentCount + 1
    });

    // 获取 WXML 传递的参数
    const id = e.currentTarget.dataset.id;
    console.log('按钮ID:', id);
  }
})

3.2 模块化开发

为了代码复用,我们可以将公共的逻辑抽离到 utils 目录下,通过 module.exports 导出,在其他页面通过 require 引入。

utils/util.js:

const formatTime = (date) => {
  const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()
  return `${year}/${month}/${day}`
}

module.exports = {
  formatTime: formatTime
}

pages/index/index.js:

const util = require('../../utils/util.js')

Page({
  onLoad: function() {
    const now = new Date()
    console.log(util.formatTime(now)) // 输出: 2023/10/27
  }
})

四、进阶实战:网络请求与 API 调用

小程序提供了丰富的 API 来访问原生能力,如网络请求、本地存储、地理位置等。

4.1 网络请求 (wx.request)

这是最常用的功能,用于与服务器交互。

代码示例:

Page({
  // 发起请求的方法
  fetchData: function() {
    wx.request({
      url: 'https://api.example.com/data', // 替换为实际接口地址
      method: 'GET',
      data: {
        id: 1
      },
      header: {
        'content-type': 'application/json' // 默认值
      },
      success: (res) => {
        console.log('请求成功:', res.data);
        this.setData({
          serverData: res.data
        });
      },
      fail: (err) => {
        console.error('请求失败:', err);
        wx.showToast({
          title: '网络错误',
          icon: 'none'
        });
      },
      complete: () => {
        // 无论成功失败都会执行
        console.log('请求完成');
      }
    });
  }
})

注意wx.request 的回调函数中,success 回调参数 res 包含 statusCode,开发者需要自行判断 statusCode 是否为 200。

4.2 本地数据存储 (wx.setStorageSync)

用于存储用户的偏好设置或临时数据。

代码示例:

// 存储数据
wx.setStorageSync('user_key', { name: 'Alice', token: 'xyz' })

// 读取数据
const data = wx.getStorageSync('user_key')
if (data) {
  console.log('读取到的用户:', data.name)
}

// 删除数据
wx.removeStorageSync('user_key')

// 清空所有数据(慎用)
// wx.clearStorageSync()

五、常见问题解决方案 (Troubleshooting)

在开发过程中,开发者经常会遇到一些棘手的问题。以下是一些高频问题的排查与解决方案。

5.1 网络请求失败 (Request:fail)

问题描述:调用 wx.request 时控制台报错 Request:fail,或者提示 url invalid

原因分析

  1. 域名问题:小程序正式版只支持 https 协议,且域名必须在微信公众平台的“开发设置”-“服务器域名”中配置。
  2. 本地调试:如果是本地开发,未开启“不校验合法域名”。

解决方案

  • 开发阶段:在开发者工具右上角点击“详情” -> “本地设置” -> 勾选“不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书”。
  • 上线阶段:确保你的服务器支持 HTTPS,并在公众平台配置好域名。

5.2 数据更新视图不渲染 (this.setData)

问题描述:修改了 data 中的变量,但页面没有变化。

原因分析: 直接赋值 this.data.count = 10 只是修改了 JS 对象中的值,并没有触发视图层的更新。

错误写法

this.data.count = 10; // 无效

正确写法

this.setData({
  count: 10
});

5.3 样式不生效或错乱

原因分析

  1. WXSS 优先级:小程序组件有默认样式,可能被覆盖。
  2. 单位使用错误:使用了 px 导致在不同屏幕尺寸下显示不一致。
  3. 类名拼写错误:WXML 中的 class 与 WXSS 中的选择器不匹配。

解决方案

  • 尽量使用 rpx 作为单位。
  • 使用开发者工具的“Wxml”面板检查元素绑定的 class 是否正确。
  • 检查 WXSS 是否被全局样式覆盖,可以使用更具体的选择器或 !important(不推荐滥用)。

5.4 页面跳转参数传递失败

问题描述:使用 wx.navigateTo 跳转时,目标页面的 onLoad 接收不到参数。

原因分析: URL 长度有限制,且参数必须进行 encodeURIComponent 编码(如果包含特殊字符)。

代码示例跳转页 (index.js):

const id = 100;
const name = "测试名称";
// 必须使用 encodeURIComponent 对参数值进行编码
const url = `/pages/detail/detail?id=${id}&name=${encodeURIComponent(name)}`;
wx.navigateTo({ url: url });

目标页 (detail.js):

Page({
  onLoad: function(options) {
    // options.id = "100"
    // options.name = "测试名称" (自动解码)
    console.log(options);
  }
})

5.5 小程序审核被拒:涉及用户隐私

问题描述:小程序提交审核时,因为获取用户手机号、头像等信息被拒。

原因分析: 微信对用户隐私保护越来越严格,不再允许开发者直接通过 wx.getUserInfo 获取用户敏感信息。

解决方案

  • 使用 <button> 组件的开放能力(如 open-type="getPhoneNumber" 获取手机号,open-type="getUserInfo" 获取用户信息)。
  • 配合 bindgetuserinfobindgetphonenumber 事件回调获取加密数据,然后传给后端解密。

代码示例 (获取用户信息):

<button open-type="getUserInfo" bindgetuserinfo="handleGetUserInfo">获取用户信息</button>
Page({
  handleGetUserInfo: function(e) {
    console.log(e.detail); // 包含加密的用户信息
    // 将 e.detail 传给后端解密
  }
})

六、总结

微信小程序开发虽然入门门槛相对较低,但要精通并开发出高质量的应用,需要深入理解其数据驱动的视图层、生命周期管理以及网络通信机制。通过本指南的学习,你应该已经掌握了从环境搭建到复杂交互实现的全过程。在实际开发中,多查阅官方文档,善用开发者工具的调试功能,是解决问题的最佳途径。