Skip to content

小程序开发

微信小程序及跨端框架开发指南

📚 内容概览

微信小程序基础

小程序进阶

性能优化

跨端框架

🎯 学习路径

初级(基础开发)

  1. 小程序架构与生命周期
  2. WXML/WXSS 语法
  3. 数据绑定与事件处理
  4. 基础 API 使用

中级(工程化)

  1. 自定义组件开发
  2. 状态管理方案
  3. 网络请求封装
  4. 性能优化

高级(跨端方案)

  1. Taro/uni-app 框架
  2. 跨端架构设计
  3. 小程序云开发
  4. 插件开发

🔥 面试高频

  • 小程序的双线程架构是什么?
  • 小程序的生命周期有哪些?
  • setData 的性能问题?如何优化?
  • 小程序如何实现分包加载?
  • 小程序和 H5 的区别?
  • Taro 和 uni-app 的区别?
  • 小程序如何实现状态管理?
  • 小程序的登录流程?

📊 小程序架构

小程序架构(双线程模型)
├── 渲染层(WebView)
│   ├── WXML(结构)
│   ├── WXSS(样式)
│   └── 组件系统

├── 逻辑层(JSCore)
│   ├── JavaScript 代码
│   ├── 小程序 API
│   └── 数据管理

└── 通信层
    ├── Native(微信客户端)
    ├── JSBridge(双向通信)
    └── setData(数据传输)

🚀 快速开始

小程序项目结构

miniprogram/
├── pages/              # 页面目录
│   ├── index/
│   │   ├── index.js    # 页面逻辑
│   │   ├── index.json  # 页面配置
│   │   ├── index.wxml  # 页面结构
│   │   └── index.wxss  # 页面样式
│   └── ...
├── components/         # 组件目录
├── utils/             # 工具函数
├── app.js             # 小程序逻辑
├── app.json           # 小程序配置
└── app.wxss           # 全局样式

页面开发示例

javascript
// pages/index/index.js
Page({
  data: {
    message: 'Hello World',
    list: []
  },

  onLoad(options) {
    // 页面加载
    this.fetchData();
  },

  onShow() {
    // 页面显示
  },

  onReady() {
    // 页面初次渲染完成
  },

  fetchData() {
    wx.request({
      url: 'https://api.example.com/data',
      success: (res) => {
        this.setData({
          list: res.data
        });
      }
    });
  },

  handleTap(e) {
    console.log('点击事件', e);
  }
});
xml
<!-- pages/index/index.wxml -->
<view class="container">
  <text>{{message}}</text>
  <view wx:for="{{list}}" wx:key="id" bindtap="handleTap">
    {{item.name}}
  </view>
</view>

自定义组件

javascript
// components/custom/custom.js
Component({
  properties: {
    title: {
      type: String,
      value: ''
    }
  },

  data: {
    count: 0
  },

  methods: {
    increment() {
      this.setData({
        count: this.data.count + 1
      });
      this.triggerEvent('change', { count: this.data.count });
    }
  }
});
xml
<!-- components/custom/custom.wxml -->
<view class="custom">
  <text>{{title}}</text>
  <button bindtap="increment">Count: {{count}}</button>
</view>

setData 优化

javascript
// ❌ 不好的做法
this.setData({
  'list[0].name': 'new name',
  'list[1].name': 'new name',
  'list[2].name': 'new name'
});

// ✅ 好的做法
const list = this.data.list.map((item, index) => {
  if (index < 3) {
    return { ...item, name: 'new name' };
  }
  return item;
});
this.setData({ list });

// ✅ 使用 nextTick 合并多次 setData
this.setData({ a: 1 });
this.setData({ b: 2 });
// 会被合并为一次 setData

// ✅ 只更新需要的数据
this.setData({
  'user.name': 'new name' // 只更新 user.name
});

分包加载

json
// app.json
{
  "pages": [
    "pages/index/index",
    "pages/logs/logs"
  ],
  "subpackages": [
    {
      "root": "packageA",
      "pages": [
        "pages/cat/cat",
        "pages/dog/dog"
      ]
    },
    {
      "root": "packageB",
      "name": "pack2",
      "pages": [
        "pages/apple/apple",
        "pages/banana/banana"
      ],
      "independent": true  // 独立分包
    }
  ],
  "preloadRule": {
    "pages/index/index": {
      "network": "all",
      "packages": ["packageA"]
    }
  }
}

网络请求封装

javascript
// utils/request.js
class Request {
  constructor(baseURL) {
    this.baseURL = baseURL;
    this.interceptors = {
      request: [],
      response: []
    };
  }

  request(options) {
    // 请求拦截
    this.interceptors.request.forEach(fn => {
      options = fn(options);
    });

    return new Promise((resolve, reject) => {
      wx.request({
        ...options,
        url: this.baseURL + options.url,
        success: (res) => {
          // 响应拦截
          this.interceptors.response.forEach(fn => {
            res = fn(res);
          });
          resolve(res.data);
        },
        fail: reject
      });
    });
  }

  get(url, data) {
    return this.request({ url, data, method: 'GET' });
  }

  post(url, data) {
    return this.request({ url, data, method: 'POST' });
  }
}

const request = new Request('https://api.example.com');

// 添加请求拦截器
request.interceptors.request.push((config) => {
  const token = wx.getStorageSync('token');
  if (token) {
    config.header = {
      ...config.header,
      Authorization: `Bearer ${token}`
    };
  }
  return config;
});

export default request;

🎨 Taro 跨端开发

javascript
// Taro 使用 React 语法
import { Component } from 'react';
import { View, Text, Button } from '@tarojs/components';
import Taro from '@tarojs/taro';
import './index.scss';

export default class Index extends Component {
  state = {
    count: 0
  };

  componentDidMount() {
    // 生命周期
  }

  increment = () => {
    this.setState({
      count: this.state.count + 1
    });
  };

  render() {
    return (
      <View className="index">
        <Text>{this.state.count}</Text>
        <Button onClick={this.increment}>增加</Button>
      </View>
    );
  }
}

📱 支持平台对比

特性原生小程序Tarouni-app
语法小程序语法React/VueVue
性能⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
跨端能力✅ 多端✅ 多端
生态官方React 生态Vue 生态
学习成本低(会 React)低(会 Vue)
适用场景微信小程序多端应用多端应用

🔧 开发工具

  • 微信开发者工具 - 官方 IDE
  • Taro - 多端统一开发框架
  • uni-app - Vue 多端框架
  • mpvue - Vue 小程序框架(已停止维护)
  • WePY - 类 Vue 语法(已停止维护)

📖 推荐资源

前端面试知识库