一、基础概念与核心配置(1-10 题)

1. 什么是微信小程序?它的核心特性有哪些?

解析

微信小程序是微信生态内的轻量级应用,无需下载安装即可使用,基于微信提供的框架运行。核心特性包括:

  • 免安装 / 触手可及:通过微信扫码、搜索等方式直接打开,降低用户使用门槛;
  • 用完即走:不占用手机存储空间,关闭后不常驻后台(除非有后台运行能力配置);
  • 技术栈独特:采用 WXML(视图层)、WXSS(样式层)、JS(逻辑层)、JSON(配置层),而非传统 H5 技术栈;
  • 原生能力调用:可直接调用微信原生 API(如支付、定位、相机),功能比 H5 更强大;
  • 性能接近原生:拥有独立的渲染线程和逻辑线程,避免单线程阻塞,加载速度快于 H5。
2. 小程序与 H5 的主要区别是什么?

解析:核心区别集中在运行环境、权限、性能等维度,具体如下:

维度

微信小程序

H5

运行环境

微信内置浏览器(基于 Chromium 内核优化)

普通浏览器(如 Chrome、Safari 等)

权限能力

可调用微信原生 API(支付、通讯录、蓝牙)

仅能使用浏览器提供的 API(如定位需用户授权)

性能

双线程(渲染 / 逻辑分离),无 DOM 操作阻塞

单线程(JS 与 DOM 渲染互斥,易卡顿)

缓存机制

提供 wx.setStorage 等原生缓存 API,容量约 10MB

依赖浏览器缓存(localStorage、sessionStorage),容量约 5MB

发布与审核

需通过微信公众平台审核,发布后实时生效

无需审核,部署到服务器即可访问

3. 小程序的核心配置文件有哪些?各自的作用是什么?

解析:小程序有 4 类核心配置文件,作用分工明确:

  1. app.json:全局配置,控制小程序的整体行为,如页面路径(pages)、窗口样式(window)、底部 TabBar(tabBar)、网络超时时间(networkTimeout)等;

示例:"pages": ["pages/index/index", "pages/logs/logs"] 定义小程序的所有页面路径,第一个路径为首页。

  1. page.json:页面单独配置,覆盖 app.json 中 window 节点的配置,如当前页面的导航栏标题(navigationBarTitleText)、是否允许下拉刷新(enablePullDownRefresh)等;
  1. app.js:小程序入口逻辑文件,定义 App 实例,处理应用生命周期(如 onLaunch、onShow),并可全局存储数据(如用户信息);
  1. project.config.json:项目配置文件,记录开发者工具的个性化设置(如项目名称、AppID、编译配置),便于团队协作时统一开发环境。
4. 小程序的目录结构中,pages 文件夹下的每个页面通常包含哪些文件?

解析:每个页面需包含 4 个同名文件(后缀不同),缺一不可:

  • .wxml:视图层文件,类似 HTML,用于定义页面结构,支持小程序内置组件(如 <view>、<button>)和模板语法(如 {{}} 数据绑定);
  • .wxss:样式层文件,类似 CSS,扩展了 rpx 自适应单位(1rpx = 屏幕宽度 / 750),且支持 @import 导入外部样式;
  • .js:逻辑层文件,定义 Page 实例,处理页面生命周期(如 onLoad、onTap)、事件绑定(如 bindtap)和数据管理(data 节点);
  • .json:页面配置文件,仅能配置 window 相关属性,用于自定义当前页面的导航栏、背景色等。
5. 小程序的 “双线程模型” 是什么?它解决了什么问题?

解析

  • 双线程模型定义:小程序分为 渲染线程(负责页面渲染,运行在视图层)和 逻辑线程(负责业务逻辑,运行在逻辑层),两者通过微信原生的 “JSBridge” 通信,数据传递需通过 setData 实现。
  • 解决的问题:传统 H5 是单线程模型(JS 执行与 DOM 渲染互斥),若 JS 执行时间过长,会导致页面卡顿。双线程模型将逻辑与渲染分离,避免逻辑层 JS 阻塞渲染层,提升页面流畅度;同时,逻辑层无法直接操作 DOM,也避免了 XSS 等安全风险。
6. 小程序的 AppID 有什么作用?测试环境和正式环境的 AppID 有区别吗?

解析

  • AppID 作用:AppID 是小程序的唯一标识,用于:① 关联微信公众平台账号;② 调用微信开放平台 API(如支付、登录、分享);③ 区分开发环境与正式环境;④ 小程序发布审核的唯一凭证。
  • 环境区别
    • 测试环境(测试号 AppID):仅用于开发调试,无法调用正式版 API(如支付、获取用户手机号),且小程序无法被非开发者账号搜索到;
    • 正式环境(已认证账号的 AppID):需通过微信公众平台认证(个人号 / 企业号),可调用所有开放 API,发布后可被所有微信用户访问。
7. 小程序的 “页面栈” 是什么?最多能容纳多少个页面?

解析

  • 页面栈定义:小程序通过栈(先进后出)管理页面跳转,每次用 wx.navigateTo 打开新页面时,页面会入栈;点击返回按钮或调用 wx.navigateBack 时,页面会出栈。
  • 容量限制:页面栈最多容纳 10 个页面,若超过限制,调用 wx.navigateTo 会失败。此时需用 wx.redirectTo(关闭当前页面后入栈)或 wx.switchTab(清空栈后跳转到 TabBar 页面)规避。
  • 注意:可通过 getCurrentPages() 获取当前页面栈实例,但不建议修改栈内数据(可能导致页面状态异常),仅用于获取页面路径、参数等信息。
8. 小程序的 WXSS 与 CSS 有哪些区别?

解析:WXSS 是 CSS 的扩展,新增了 3 个核心特性:

  1. 自适应单位 rpx:CSS 用 px(固定像素),WXSS 用 rpx(相对像素),1rpx = 屏幕宽度 / 750,适配所有设备(如 750px 设计稿中,1rpx = 1px;375px 手机中,1rpx = 0.5px);
  1. 样式隔离:默认情况下,页面的 WXSS 仅作用于当前页面,组件的 WXSS 仅作用于组件内部(通过 styleIsolation 配置可修改隔离规则),避免样式污染;
  1. 全局样式与局部样式:app.wxss 是全局样式,作用于所有页面;页面的 .wxss 是局部样式,优先级高于全局样式(若选择器权重相同)。

此外,WXSS 不支持 CSS 的部分属性(如 background-attachment、marquee)。

9. 小程序的 JSON 配置中,tabBar 的作用是什么?核心属性有哪些?

解析

  • tabBar 作用:用于实现小程序底部 / 顶部的导航栏(最多支持 5 个 Tab),点击 Tab 可切换页面,且切换时会清空页面栈(仅保留当前 Tab 页面)。
  • 核心属性
    • list:必填,Tab 列表(数组,最少 2 个、最多 5 个),每个 Tab 包含 pagePath(页面路径,必须在 pages 中定义)、text(Tab 文字)、iconPath(未选中时图标路径)、selectedIconPath(选中时图标路径);
    • position:可选,Tab 位置(bottom 或 top),默认 bottom;若为 top,则不显示图标;
    • color:可选,未选中 Tab 文字颜色;
    • selectedColor:可选,选中 Tab 文字颜色;
    • backgroundColor:可选,Tab 背景色;
    • borderStyle:可选,Tab 边框颜色(仅支持 black 或 white)。
10. 小程序的 “分包加载” 是什么?它的优势和配置方式是什么?

解析

  • 分包加载定义:将小程序的代码拆分为 “主包” 和 “分包”,主包包含首页和公共资源(如 app.js、app.json),分包包含其他页面;用户打开小程序时,先加载主包,进入分包页面时再加载对应分包,减少初始加载时间。
  • 优势:① 降低主包体积(主包默认限制 2MB,分包总限制 20MB);② 提升首屏加载速度,优化用户体验。
  • 配置方式:在 app.json 中添加 subpackages 节点:

"subpackages": [

{

"root": "packageA", // 分包根目录

"name": "packageA", // 分包名称(可选)

"pages": ["pages/cat/cat", "pages/dog/dog"] // 分包内页面路径

}

]

若需指定某个分包为 “独立分包”(可单独加载,不依赖主包),需在分包配置中添加 "independent": true。

二、生命周期与页面交互(11-20 题)

11. 小程序的应用生命周期有哪些?各自的触发时机是什么?

解析:应用生命周期在 app.js 中通过 App 实例定义,共 4 个:

  1. onLaunch:小程序初始化完成时触发(全局仅触发 1 次),可用于初始化全局数据(如获取用户登录状态)、调用启动接口;
  1. onShow:小程序启动或从后台切换到前台时触发(每次切换都会触发),可用于更新页面数据(如刷新用户信息);
  1. onHide:小程序从前台切换到后台时触发(如用户按 Home 键、打开其他 App),可用于保存当前页面状态(如暂停定时器);
  1. onError:小程序发生脚本错误或 API 调用失败时触发,可用于错误上报(如上报到 Sentry)。
12. 小程序的页面生命周期有哪些?触发顺序是什么?

解析:页面生命周期在页面的 .js 中通过 Page 实例定义,核心生命周期及触发顺序如下(以首次打开页面为例):

  1. onLoad:页面加载时触发(仅触发 1 次),可接收页面跳转的参数(如 options.id),常用于初始化数据(如调用接口获取详情);
  1. onShow:页面显示时触发(每次切换到该页面都会触发),可用于刷新页面数据(如返回页面时重新请求列表);
  1. onReady:页面初次渲染完成时触发(仅触发 1 次),可用于操作页面 DOM 或组件(如获取组件实例 this.selectComponent('#myComponent'));
  1. onHide:页面隐藏时触发(如跳转到其他页面、切换到后台),可用于暂停操作(如暂停视频播放);
  1. onUnload:页面卸载时触发(如调用 wx.redirectTo、wx.navigateBack 关闭页面),可用于清理资源(如清除定时器、取消接口请求)。
13. 应用生命周期 onLaunch 和页面生命周期 onLoad 哪个先触发?为什么?

解析onLaunch 先触发

原因:小程序初始化流程为:① 启动小程序 → ② 执行 app.js 中的 App 实例 → ③ 触发 onLaunch(初始化完成) → ④ 根据 app.json 中的 pages 配置加载首页 → ⑤ 执行首页的 Page 实例 → ⑥ 触发首页的 onLoad。因此,应用初始化完成(onLaunch)后,才会加载页面并触发页面的 onLoad。

14. 小程序中如何实现页面跳转?有哪些跳转方式?各自的区别是什么?

解析:小程序提供 5 种页面跳转方式,核心区别在于是否保留当前页面、是否能跳转到 TabBar 页面:

跳转 API

是否保留当前页面

是否能跳转到 TabBar 页面

页面栈变化

wx.navigateTo

是(入栈)

栈长度 + 1(最多 10 层)

wx.redirectTo

否(出栈后入栈)

栈长度不变(替换当前页面)

wx.switchTab

否(清空栈)

是(仅能跳转到 TabBar)

栈仅保留目标 Tab 页面

wx.reLaunch

否(清空栈)

栈仅保留目标页面

wx.navigateBack

否(出栈)

栈长度 - 1(可指定返回层数)

示例:跳转到非 TabBar 页面用 wx.navigateTo,跳转到 TabBar 页面必须用 wx.switchTab。

15. 小程序中如何传递页面参数?接收参数的方式是什么?

解析:传递参数主要通过 URL 拼接和全局存储两种方式:

  1. URL 拼接(常用,适用于跳转时传递少量数据)
    • 传递:跳转时在 url 后拼接参数(键值对形式,用 ? 分隔参数,& 分隔多个参数),如:

wx.navigateTo({

url: '/pages/detail/detail?id=123&name=苹果' // 传递 id=123、name=苹果

})

    • 接收:在目标页面的 onLoad 生命周期中通过 options 参数获取,如:

onLoad(options) {

console.log(options.id); // 123

console.log(options.name); // 苹果

}

  1. 全局存储(适用于传递大量数据或跨页面共享数据)
    • 传递:在 app.js 中定义全局数据,如 globalData: { userInfo: {} },然后在页面中通过 getApp().globalData.userInfo = data 赋值;
    • 接收:在目标页面中通过 const app = getApp(); console.log(app.globalData.userInfo) 获取。
16. 小程序中如何实现下拉刷新?需要配置哪些属性?

解析:实现下拉刷新需两步配置:

  1. 开启下拉刷新
    • 全局开启:在 app.json 的 window 节点中设置 "enablePullDownRefresh": true(所有页面生效);
    • 页面单独开启:在页面的 .json 文件中设置 "enablePullDownRefresh": true(仅当前页面生效,优先级高于全局)。
  1. 处理下拉刷新逻辑:在页面的 .js 中实现 onPullDownRefresh 生命周期,用于触发刷新操作(如重新请求接口),刷新完成后需调用 wx.stopPullDownRefresh() 关闭刷新动画,示例:

onPullDownRefresh() {

// 调用接口重新获取数据

this.getListData().then(() => {

// 关闭下拉刷新动画

wx.stopPullDownRefresh();

});

}

此外,可通过 backgroundColor(下拉刷新区域背景色)和 backgroundTextStyle(刷新图标颜色,仅支持 dark 或 light)自定义刷新样式。

17. 小程序中如何实现上拉加载更多?核心逻辑是什么?

解析:上拉加载更多依赖页面的 onReachBottom 生命周期(页面滚动到底部时触发),核心逻辑如下:

  1. 配置触发距离:在页面的 .json 中设置 onReachBottomDistance(默认 50px,即距离底部 50px 时触发),如 "onReachBottomDistance": 100;
  1. 实现加载逻辑:在页面的 .js 中定义 onReachBottom 方法,需处理 “分页参数” 和 “加载状态”(避免重复请求),示例:

Page({

data: {

list: [],

page: 1, // 当前页码

pageSize: 10, // 每页条数

isLoading: false, // 是否正在加载

hasMore: true // 是否还有更多数据

},

onReachBottom() {

// 若正在加载或无更多数据,直接返回

if (this.data.isLoading || !this.data.hasMore) return;

this.setData({ isLoading: true });

// 调用分页接口

this.getListData(this.data.page + 1).then(res => {

const newList = this.data.list.concat(res.data);

this.setData({

list: newList,

page: this.data.page + 1,

isLoading: false,

hasMore: res.data.length === this.data.pageSize // 若返回数据少于 pageSize,说明无更多

});

});

}

});

18. 小程序中 setData 的作用是什么?使用时需要注意哪些问题?

解析

  • setData 作用:用于修改页面的 data 数据,并触发页面重新渲染(逻辑层数据传递到视图层)。直接修改 this.data 不会触发渲染,必须通过 setData。
  • 注意事项
    1. 异步更新:setData 是异步操作,修改后不能立即获取最新数据,需在 setData 的第二个参数(回调函数)中处理后续逻辑,如:

this.setData({ count: 1 }, () => {

console.log(this.data.count); // 1(正确,回调中获取最新值)

});

console.log(this.data.count); // 0(错误,同步代码中获取旧值)

    1. 避免频繁调用:每次 setData 都会触发渲染,频繁调用(如循环中调用)会导致页面卡顿,建议合并数据后一次性调用;
    1. 不传递冗余数据:仅传递需要修改的字段,避免传递整个 data 对象(如 this.setData({ list: newList }) 而非 this.setData({ data: this.data }));
    1. 不修改页面栈数据:禁止通过 setData 修改 getCurrentPages() 返回的页面栈实例,可能导致页面状态异常。
19. 小程序中如何绑定事件?事件绑定的方式有哪些?

解析:小程序的事件绑定通过 bind 或 catch 前缀实现,核心区别在于是否阻止事件冒泡:

  1. 绑定方式
    • bind + 事件名:绑定事件,不阻止冒泡(如 bindtap 点击事件、bindinput 输入事件);
    • catch + 事件名:绑定事件,阻止冒泡(如 catchtap,常用于避免父组件事件被触发);
    • mut-bind + 事件名:绑定事件,仅触发当前组件的事件,不触发父组件和子组件的同类型事件(较少用)。
  1. 示例(点击事件)
    • WXML:<button bindtap="handleTap" data-id="123">点击</button>(data-* 用于传递自定义参数);
    • JS:

handleTap(e) {

// 通过 e.currentTarget.dataset 获取自定义参数

console.log(e.currentTarget.dataset.id); // 123

}

  1. 常用事件:tap(点击)、input(输入)、change(值改变)、longpress(长按)、scroll(滚动)。
20. 小程序中如何实现表单提交与校验?

解析:表单提交需结合 <form> 组件和 form-type 属性,校验可通过自带属性或自定义逻辑实现:

  1. 表单结构(WXML)

<form bindsubmit="handleSubmit">

<!-- 输入框,通过 name 标识字段 -->

<view class="form-item">

<label>用户名:</label>

<input name="username" placeholder="请输入用户名" required /> <!-- required 自带非空校验 -->

</view>

<view class="form-item">

<label>手机号:</label>

<input name="phone" placeholder="请输入手机号" type="number" bindinput="handlePhoneInput" />

</view>

<!-- 提交按钮,必须设置 form-type="submit" -->

<button form-type="submit">提交</button>

</form>

  1. 表单校验与提交(JS)

Page({

data: {

phone: ''

},

// 实时校验手机号格式

handlePhoneInput(e) {

const phone = e.detail.value;

// 正则校验手机号(11位数字)

if (!/^1[3-9]\d{9}$/.test(phone) && phone) {

wx.showToast({ title: '手机号格式错误', icon: 'none' });

}

this.setData({ phone });

},

// 表单提交

handleSubmit(e) {

const { username, phone } = e.detail.value; // 获取表单所有字段值

// 自定义校验

if (!username) {

wx.showToast({ title: '请输入用户名', icon: 'none' });

return;

}

if (!/^1[3-9]\d{9}$/.test(phone)) {

wx.showToast({ title: '请输入正确的手机号', icon: 'none' });

return;

}

// 校验通过,调用提交接口

wx.request({

url: 'https://api.example.com/submit',

method: 'POST',

data: { username, phone },

success(res) {

wx.showToast({ title: '提交成功' });

}

});

}

});

  1. 核心要点:① 表单按钮需设置 form-type="submit";② 通过 e.detail.value 获取所有表单字段;③ 可结合 required(非空)、type(输入类型)做基础校验,复杂校验需自定义正则。

三、组件开发与通信(21-30 题)

21. 小程序的组件分为哪几类?自定义组件的创建步骤是什么?

解析

  • 组件分类:① 内置组件(微信原生提供,如 <view>、<button>、<swiper>);② 自定义组件(开发者自行开发,可复用);③ 插件组件(第三方提供,需在 app.json 中引入)。
  • 自定义组件创建步骤
    1. 创建组件目录:在项目根目录新建 components 文件夹,再新建组件文件夹(如 my-component);
    1. 创建组件文件:在组件文件夹中新建 4 个文件(my-component.wxml、my-component.wxss、my-component.js、my-component.json);
    1. 配置组件声明:在组件的 .json 文件中设置 "component": true,声明该文件夹为组件,如:

{

"component": true,

"usingComponents": {} // 若组件依赖其他组件,需在此引入

}

    1. 编写组件逻辑:在组件的 .js 中用 Component 构造器定义组件,而非 Page,如:

Component({

properties: {}, // 组件属性(外部传入)

data: {}, // 组件内部数据

methods: {} // 组件方法

});

    1. 使用组件:在需要使用组件的页面的 .json 中引入组件,如:

{

"usingComponents": {

"my-component": "/components/my-component/my-component" // 键为组件名,值为组件路径

}

}

    1. 在页面中使用:在页面的 .wxml 中直接使用组件标签 <my-component></my-component>。
22. 自定义组件的 properties 和 data 有什么区别?如何传递属性给组件?

解析

  • 区别

维度

properties

data

作用

接收外部传入的属性(类似组件的 “参数”)

组件内部的私有数据(类似页面的 data)

可修改性

可通过外部修改(页面调用组件时传递),也可通过 this.setData 内部修改

仅能通过组件内部 this.setData 修改

定义方式

需指定类型(如 String、Number)、默认值,支持校验

直接定义键值对,无需指定类型

  • 传递属性给组件
    1. 组件定义 properties:在组件的 .js 中声明属性,示例:

Component({

properties: {

// 简单声明(指定类型)

title: String,

// 完整声明(指定类型、默认值、校验)

count: {

type: Number, // 类型(必填)

value: 0, // 默认值(可选)

observer(newVal, oldVal) { // 属性值变化时的回调(可选)

console.log('count 从', oldVal, '变为', newVal);

}

}

}

});

    1. 页面传递属性:在页面的 .wxml 中使用组件时,通过 “属性名 = 值” 传递,支持数据绑定,示例:

<!-- 传递静态值 -->

<my-component title="Hello"></my-component>

<!-- 传递动态值(页面 data 中的 count 变量) -->

<my-component count="{{count}}"></my-component>

23. 自定义组件如何向父组件传递事件?父组件如何响应?

解析:组件向父组件传递事件通过 触发自定义事件 实现,步骤如下:

  1. 组件触发自定义事件:在组件的方法中,通过 this.triggerEvent('事件名', 传递的数据, 事件选项) 触发事件,示例:

Component({

methods: {

handleClick() {

// 触发自定义事件 "change",传递数据 { value: 100 }

this.triggerEvent('change', { value: 100 });

}

}

});

  1. 父组件绑定事件并响应:在页面的 .wxml 中,通过 “bind + 自定义事件名” 绑定事件,然后在页面的 .js 中实现响应方法,示例:
    • WXML:<my-component bindchange="handleComponentChange"></my-component>;
    • JS:

Page({

handleComponentChange(e) {

// 通过 e.detail 获取组件传递的数据

console.log('组件传递的值:', e.detail.value); // 100

}

});

  1. 事件选项:triggerEvent 的第三个参数是事件选项(如 bubbles 是否冒泡、composed 是否穿透组件边界),默认均为 false。
24. 自定义组件的生命周期有哪些?与页面生命周期有什么区别?

解析

  • 自定义组件生命周期:通过 Component 构造器的 lifetimes 节点定义,核心生命周期如下:
    1. created:组件实例创建时触发(仅触发 1 次),此时无法访问 this.data 和 DOM,可用于初始化数据;
    1. attached:组件实例挂载到页面节点树时触发(仅触发 1 次),可访问 this.data 和 DOM,常用于初始化 DOM 操作;
    1. ready:组件渲染完成时触发(仅触发 1 次),可用于获取组件尺寸、操作渲染后的 DOM;
    1. moved:组件实例被移动到另一个节点树时触发(较少用);
    1. detached:组件实例从页面节点树中移除时触发(如页面卸载、组件被隐藏),可用于清理资源(如清除定时器);
    1. error:组件发生错误时触发(如脚本错误)。
  • 与页面生命周期的区别
    • 组件生命周期更关注 “组件实例的创建、挂载、卸载”,页面生命周期更关注 “页面的加载、显示、渲染”;
    • 组件无 onLoad、onShow 等页面特有的生命周期,但可通过 pageLifetimes 节点监听所在页面的生命周期(如页面的 onShow、onHide),示例:

Component({

pageLifetimes: {

show() {

// 所在页面显示时触发

},

hide() {

// 所在页面隐藏时触发

}

}

});

25. 小程序的 slot 插槽是什么?如何使用?支持多插槽吗?

解析

  • slot 作用:用于在自定义组件中预留 “占位符”,允许父组件向组件内部插入自定义内容(类似 Vue 的 slot),实现组件内容的灵活定制。
  • 基础使用步骤
    1. 组件中定义 slot:在组件的 .wxml 中添加 <slot> 标签,示例:

<!-- 组件 my-component.wxml -->

<view class="component-container">

<!-- 插槽:父组件可插入内容到这里 -->

<slot></slot>

</view>

    1. 父组件插入内容:在使用组件时,直接在组件标签内写入内容,内容会替换组件中的 <slot>,示例:

<!-- 页面 wxml -->

<my-component>

<!-- 插入到组件 slot 中的内容 -->

<text>这是父组件插入的内容</text>

<button bindtap="handleClick">父组件的按钮</button>

</my-component>

  • 多插槽支持:小程序支持多插槽,但需手动开启:
    1. 组件配置多插槽:在组件的 .js 中设置 options: { multipleSlots: true },示例:

Component({

options: {

multipleSlots: true // 开启多插槽

}

});

    1. 组件定义命名 slot:通过 name 属性区分不同插槽,示例:

<!-- 组件 my-component.wxml -->

<view>

<!-- 头部插槽 -->

<slot name="header"></slot>

<!-- 内容插槽 -->

<slot name="content"></slot>

<!-- 底部插槽 -->

<slot name="footer"></slot>

</view>

    1. 父组件插入多插槽内容:通过 slot 属性指定插入的插槽,示例:

<my-component>

<view slot="header">这是头部内容</view>

<view slot="content">这是内容内容</view>

<view slot="footer">这是底部内容</view>

</my-component>

26. 小程序的组件样式隔离规则是什么?如何修改隔离规则?

解析

  • 默认样式隔离规则:小程序组件默认开启样式隔离,即:
    1. 组件的 WXSS 仅作用于组件内部,不会影响父组件或其他组件;
    1. 父组件的 WXSS 仅作用于父组件内部,不会影响组件内部;
    1. 全局样式(app.wxss)会作用于组件内部,但组件的局部样式优先级高于全局样式。
  • 修改隔离规则:通过组件的 .js 中 options 节点的 styleIsolation 属性配置,可选值如下:
    1. "isolated"(默认):完全隔离,组件与父组件样式互不影响;
    1. "apply-shared":父组件样式影响组件内部,但组件样式不影响父组件;
    1. "shared":组件与父组件样式互相影响(不推荐,易导致样式污染);
    1. "scoped":类似 Vue 的 scoped,通过给组件节点添加唯一属性(如 data-weui-shadow)实现隔离(较少用)。

示例:


Component({

options: {

styleIsolation: "apply-shared" // 父组件样式影响组件内部

}

});

27. 小程序中如何获取自定义组件的实例?

解析:通过 this.selectComponent(选择器) 方法获取组件实例,可调用组件的方法或修改组件的 properties,步骤如下:

  1. 给组件添加选择器:在页面的 .wxml 中,给组件添加 id 或 class 选择器,示例:

<my-component id="myComponent" count="{{count}}"></my-component>

  1. 获取组件实例:在页面的 .js 中(需在页面 onReady 或组件 ready 后调用,确保组件已渲染),通过 this.selectComponent('#myComponent') 获取实例,示例:

Page({

onReady() {

// 获取组件实例

this.myComponent = this.selectComponent('#myComponent');

// 调用组件的方法(组件需在 methods 中定义该方法)

this.myComponent.handleComponentMethod();

// 修改组件的 properties(需通过 setData)

this.myComponent.setData({ count: 10 });

}

});

注意:① 选择器需符合 CSS 选择器规范(如 #id、.class);② 若组件在循环中(如 wx:for),需通过动态选择器(如 #myComponent-{{index}})获取。

28. 小程序的 behavior 是什么?它的作用是什么?如何使用?

解析

  • behavior 定义:behavior 是小程序的 “行为抽象”,用于提取多个组件的公共逻辑(如数据、方法、生命周期),实现逻辑复用(类似 Vue 的 mixin)。
  • 作用:① 减少代码冗余,多个组件可共享同一套逻辑;② 便于维护,公共逻辑修改时仅需修改 behavior,无需修改所有组件。
  • 使用步骤
    1. 创建 behavior 文件:新建 .js 文件(如 my-behavior.js),用 Behavior 构造器定义,示例:

// my-behavior.js

module.exports = Behavior({

data: {

commonData: '这是公共数据'

},

properties: {

commonProp: String

},

methods: {

commonMethod() {

console.log('这是公共方法');

}

},

lifetimes: {

attached() {

console.log('behavior 的 attached 生命周期');

}

}

});

    1. 组件引入 behavior:在组件的 .js 中,通过 behaviors 数组引入 behavior,示例:

// 引入 behavior

const myBehavior = require('../../behaviors/my-behavior');

Component({

behaviors: [myBehavior], // 引入 behavior,可引入多个

attached() {

// 访问 behavior 的数据

console.log(this.data.commonData); // 这是公共数据

// 调用 behavior 的方法

this.commonMethod(); // 这是公共方法

}

});

  • 优先级:若组件与 behavior 有同名数据 / 方法,组件的优先级高于 behavior;若多个 behavior 有同名数据 / 方法,后引入的 behavior 优先级高于先引入的
29. 小程序的内置组件 scroll-view 有什么作用?使用时需要注意哪些问题?

解析

  • scroll-view 作用:用于实现局部滚动(如横向滚动列表、纵向滚动区域),可替代页面的全局滚动,支持自定义滚动触发事件(如滚动到底部、滚动到顶部)。
  • 核心属性
    • scroll-x:是否允许横向滚动(true/false);
    • scroll-y:是否允许纵向滚动(true/false);
    • scroll-top/scroll-left:控制滚动条位置(需配合 setData 使用);
    • bindscroll:滚动时触发,返回滚动距离(scrollTop/scrollLeft);
    • bindscrolltolower:滚动到底部 / 右边时触发(类似上拉加载);
    • bindscrolltoupper:滚动到顶部 / 左边时触发(类似下拉刷新)。
  • 使用注意事项
    1. 必须设置固定高度 / 宽度:纵向滚动(scroll-y=true)需给 scroll-view 设置固定高度(如 height: 500rpx),横向滚动(scroll-x=true)需设置固定宽度,否则无法滚动;
    1. 避免嵌套滚动:scroll-view 内部不建议再嵌套 scroll-view,可能导致滚动冲突;
    1. 性能优化:若滚动列表项较多,需配合 wx:key 提高渲染性能,避免频繁修改 scroll-top/scroll-left(可能导致卡顿);
    1. 与页面滚动冲突:若页面开启了全局滚动(默认开启),scroll-view 的滚动可能与页面滚动冲突,可通过 catchtouchmove 阻止页面滚动,示例:

<scroll-view scroll-y="true" style="height: 500rpx;" catchtouchmove="(e) => e.stopPropagation()">

<!-- 滚动内容 -->

</scroll-view>

30. 小程序的内置组件 swiper 有什么作用?如何实现自动轮播和无限轮播?

解析

  • swiper 作用:用于实现轮播图(如首页 Banner、图片轮播),内置指示器、切换动画,支持手势滑动。
  • 核心子组件
    • <swiper-item>:轮播图的每一项,必须嵌套在 <swiper> 内,且仅能包含一个根节点;
    • <indicator-dots>:是否显示轮播指示器(true/false)。
  • 实现自动轮播:通过 autoplay 属性(是否自动切换,true/false)和 interval 属性(自动切换间隔时间,单位 ms,默认 5000)实现,示例:

<swiper autoplay="true" interval="3000" indicator-dots="true">

<swiper-item><image src="/images/banner1.jpg" mode="widthFix"></image></swiper-item>

<swiper-item><image src="/images/banner2.jpg" mode="widthFix"></image></swiper-item>

<swiper-item><image src="/images/banner3.jpg" mode="widthFix"></image></swiper-item>

</swiper>

  • 实现无限轮播:小程序的 swiper 默认支持无限轮播,无需额外配置;若需自定义轮播逻辑(如手动控制),可通过 current 属性(当前轮播索引)和 bindchange 事件(轮播切换时触发)实现,示例:

Page({

data: {

current: 0,

bannerList: [1, 2, 3] // 轮播数据

},

handleSwiperChange(e) {

this.setData({ current: e.detail.current });

},

// 手动切换到下一张

nextBanner() {

const { current, bannerList } = this.data;

const nextIndex = current === bannerList.length - 1 ? 0 : current + 1;

this.setData({ current: nextIndex });

}

});

  • 注意事项:① <swiper-item> 内的图片建议设置 mode="widthFix" 保持宽高比;② 轮播图数量较少时(如 1 张),建议关闭自动轮播(autoplay="false"),避免不必要的切换。

四、API 与数据存储(31-40 题)

31. 小程序的网络请求 API wx.request 有什么作用?使用时需要注意哪些问题?

解析

  • wx.request 作用:用于发起 HTTP/HTTPS 请求(类似 H5 的 fetch 或 axios),获取后端数据,支持 GET、POST 等请求方法。
  • 基础用法

wx.request({

url: 'https://api.example.com/getList', // 接口地址(必须是 HTTPS,且已在微信公众平台配置域名)

method: 'GET', // 请求方法(GET/POST/PUT/DELETE,默认 GET)

data: { page: 1, pageSize: 10 }, // 请求参数(GET 会拼到 URL,POST 会放在请求体)

header: { 'content-type': 'application/json' }, // 请求头(POST 需设置为 'application/x-www-form-urlencoded' 时,参数需转成表单格式)

success(res) {

console.log('请求成功', res.data); // res.data 为后端返回的响应数据

},

fail(err) {

console.log('请求失败', err); // 请求错误(如网络异常、域名未配置)

},

complete() {

console.log('请求完成(无论成功/失败都会触发)');

}

});

  • 使用注意事项
    1. 域名配置:请求的 URL 必须是 HTTPS 协议,且域名需在微信公众平台 “开发 → 开发设置 → 服务器域名” 中配置(测试环境可使用 “微信开发者工具 → 详情 → 本地设置 → 不校验合法域名” 规避);
    1. 请求限制:同一域名下的并发请求数不超过 10 个;
    1. 超时时间:可在 app.json 中配置 networkTimeout(默认 60000ms),超时后会触发 fail 回调;
    1. POST 请求参数格式:若后端需要表单格式(application/x-www-form-urlencoded),需将 data 转成 key=value&key=value 格式(可使用 qs.stringify(data));
    1. 错误处理:需处理网络异常、接口返回错误码等情况,避免页面卡住。
32. 小程序的本地存储 API 有哪些?它们的区别是什么?存储限制是什么?

解析

  • 本地存储 API 分类:分为同步 API 和异步 API,共 4 个:
    1. wx.setStorageSync(key, data):同步存储数据(阻塞当前线程,适合简单场景);
    1. wx.getStorageSync(key):同步获取数据;
    1. wx.setStorage({ key, data, success, fail }):异步存储数据(非阻塞,适合复杂场景,需通过回调处理结果);
    1. wx.getStorage({ key, success, fail }):异步获取数据;

此外,还有 wx.removeStorage/wx.removeStorageSync(删除指定 key 的数据)、wx.clearStorage/wx.clearStorageSync(清空所有本地存储)。

  • 同步与异步的区别

维度

同步 API(Sync 后缀)

异步 API(无 Sync 后缀)

执行方式

阻塞当前线程,执行完成后再继续后续代码

非阻塞,代码继续执行,结果通过回调返回

错误处理

需用 try-catch 捕获错误

错误通过 fail 回调返回

使用场景

简单数据存储 / 获取(如初始化数据)

大量数据存储 / 获取(避免阻塞线程)

  • 存储限制
    • 单个 key 的数据大小不超过 1MB
    • 所有 key 的总存储量不超过 10MB
    • 存储的数据类型仅支持:String、Number、Boolean、Object、Array(复杂对象会被转成 JSON 字符串存储,获取时需解析)。
  • 示例(同步存储 / 获取)

// 存储数据

try {

wx.setStorageSync('userInfo', { name: '张三', age: 20 });

} catch (e) {

console.log('存储失败', e);

}

// 获取数据

try {

const userInfo = wx.getStorageSync('userInfo');

console.log(userInfo); // { name: '张三', age: 20 }

} catch (e) {

console.log('获取失败', e);

}

33. 小程序如何获取用户信息?新旧接口有什么区别?

解析:小程序获取用户信息的接口经历过调整,目前主要使用 wx.getUserProfile(推荐)和 wx.getUserInfo(旧接口,限制较多):

  • 旧接口:wx.getUserInfo
    • 作用:获取用户的昵称、头像、性别等信息,但 需用户已授权 scope.userInfo
    • 限制:① 若用户未授权,调用该接口会直接进入 fail 回调,无法主动触发授权弹窗;② 自 2022 年 10 月起,新提交的小程序无法再通过该接口获取用户信息(需用新接口);
    • 示例:

wx.getUserInfo({

success(res) {

console.log('用户信息', res.userInfo); // { nickName: '张三', avatarUrl: 'xxx', ... }

},

fail(err) {

console.log('未授权', err);

}

});

  • 新接口:wx.getUserProfile
    • 作用:替代 wx.getUserInfo,支持主动触发授权弹窗,获取用户信息;
    • 优势:① 无需提前授权,调用时会弹出授权弹窗(用户可选择允许 / 拒绝);② 支持获取 encryptedData(加密数据,需后端解密获取 unionId 等敏感信息);
    • 限制:① 必须在 用户点击事件 中调用(如 bindtap,避免自动触发);② 每次调用都会触发授权弹窗(用户可选择不再授权);
    • 示例:

// WXML:<button bindtap="getUserProfile">获取用户信息</button>

Page({

getUserProfile(e) {

wx.getUserProfile({

desc: '用于完善会员资料', // 必传,说明获取信息的用途(会显示在授权弹窗中)

success(res) {

console.log('用户信息', res.userInfo); // { nickName: '张三', avatarUrl: 'xxx', ... }

// 存储用户信息到本地

wx.setStorageSync('userInfo', res.userInfo);

},

fail(err) {

console.log('用户拒绝授权', err);

}

});

}

});

  • 核心区别:新接口 wx.getUserProfile 可主动触发授权弹窗,旧接口 wx.getUserInfo 依赖提前授权,且新接口是目前官方推荐的方式。
34. 小程序的登录流程是什么?如何获取用户的 openId 和 unionId?

解析:小程序登录的核心是通过微信生态获取用户的唯一标识(openId/unionId),实现用户身份认证,流程如下:

  1. 获取临时登录凭证 code:调用 wx.login() 获取 code(有效期 5 分钟,仅能使用 1 次);
  1. code 换 sessionKey 和 openId:将 code 发送到开发者服务器,服务器调用微信开放平台的 code2Session 接口(https://api.weixin.qq.com/sns/jscode2session),获取 sessionKey(会话密钥)、openId(用户在当前小程序的唯一标识);
  1. 生成自定义登录态:服务器根据 openId 和 sessionKey 生成自定义登录态(如 Token),返回给小程序;
  1. 存储登录态:小程序将 Token 存储到本地(如 wx.setStorageSync('token', token)),后续请求接口时在 header 中携带 Token,实现身份验证。
  • 获取 openId:通过 code2Session 接口直接返回,无需额外操作,示例(服务器端代码,以 Node.js 为例):

const request = require('request');

const appId = '你的小程序 AppID';

const appSecret = '你的小程序 AppSecret';

function code2Session(code) {

return new Promise((resolve, reject) => {

const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${appId}&secret=${appSecret}&js_code=${code}&grant_type=authorization_code`;

request.get(url, (err, res, body) => {

if (err) reject(err);

const data = JSON.parse(body);

// data 包含 openid、session_key、expires_in

resolve(data);

});

});

}

  • 获取 unionId:unionId 是用户在微信开放平台下所有应用(小程序、公众号、App)的唯一标识,需满足以下条件之一:
    1. 小程序已关联到微信开放平台账号(“微信开放平台 → 管理中心 → 关联小程序”);
    1. 用户已授权 wx.getUserProfile,服务器通过 encryptedData(wx.getUserProfile 返回的加密数据)和 sessionKey 解密,获取 unionId(需使用微信提供的解密算法)。
35. 小程序如何调用微信支付?核心流程是什么?

解析:小程序调用微信支付需结合微信支付商户平台和开发者服务器,核心流程如下(需已开通微信支付功能):

  1. 用户发起支付请求:用户在小程序中点击支付按钮,小程序将订单信息(如订单号、金额)发送到开发者服务器;
  1. 服务器生成预支付订单:开发者服务器调用微信支付的 统一下单接口(https://api.mch.weixin.qq.com/pay/unifiedorder),传入商户号、AppID、订单信息等参数,获取 prepay_id(预支付订单号);
  1. 服务器生成支付参数:服务器根据 prepay_id、商户号等参数,按照微信支付的签名规则生成 paySign(支付签名),并将 appId、timeStamp、nonceStr、package(格式为 prepay_id=xxx)、signType(签名类型,如 MD5)、paySign 等参数返回给小程序;
  1. 小程序调起支付:小程序调用 wx.requestPayment 接口,传入服务器返回的支付参数,调起微信支付弹窗;
  1. 支付结果通知:用户支付完成后,微信服务器会向开发者服务器的 notify_url(统一下单时指定)发送支付结果通知,服务器需验证通知的签名,并更新订单状态;
  1. 小程序处理支付结果:wx.requestPayment 的 success/fail/complete 回调会返回支付结果(但最终订单状态需以服务器收到的微信通知为准,避免前端伪造结果)。
  • 小程序端核心代码

// 调用服务器接口获取支付参数

getPayParams(orderId).then(payParams => {

// 调起微信支付

wx.requestPayment({

timeStamp: payParams.timeStamp + '', // 必须是字符串

nonceStr: payParams.nonceStr,

package: payParams.package,

signType: payParams.signType,

paySign: payParams.paySign,

success(res) {

console.log('支付成功', res);

// 跳转支付成功页面

wx.navigateTo({ url: '/pages/paySuccess/paySuccess' });

},

fail(err) {

console.log('支付失败', err);

wx.showToast({ title: '支付失败', icon: 'none' });

}

});

});

  • 注意事项:① 订单金额单位是 “分”(如 1 元需传 100);② 签名必须严格按照微信支付的规则生成,否则会调起失败;③ 必须处理支付结果通知(异步通知),避免漏单。
36. 小程序如何实现分享功能?支持哪些分享方式?

解析:小程序支持 “页面内分享” 和 “右上角菜单分享”,需通过生命周期和 API 配置:

  1. 页面内分享(按钮分享):通过 <button> 组件的 open-type="share" 实现,点击按钮触发分享弹窗,示例:
    • WXML:<button open-type="share">分享给好友</button>;
    • 自定义分享内容:在页面的 .js 中实现 onShareAppMessage 生命周期,返回分享标题、路径、图片,示例:

onShareAppMessage(res) {

// res.from 可判断分享来源(button:按钮分享,menu:右上角菜单分享)

return {

title: '这是分享标题', // 分享标题(默认是小程序名称)

path: '/pages/index/index?shareId=123', // 分享路径(必须是当前小程序的页面,可携带参数)

imageUrl: '/images/share.jpg' // 分享图片(建议尺寸 5:4,默认是页面截图)

};

}

  1. 右上角菜单分享(转发给好友):无需额外按钮,用户点击微信右上角 “...” → “转发” 即可触发,分享内容同样通过 onShareAppMessage 配置。
  1. 分享到朋友圈:通过 onShareTimeline 生命周期实现(仅支持微信 7.0.12 及以上版本),示例:

onShareTimeline() {

return {

title: '这是朋友圈分享标题',

query: 'shareId=123', // 分享路径参数(对应 path 中的查询字符串)

imageUrl: '/images/share.jpg'

};

}

  • 注意事项:① 分享路径必须是小程序的已注册页面(在 app.json 的 pages 中定义);② 分享参数需在目标页面的 onLoad 中通过 options 获取;③ 禁止分享的页面可在页面的 .json 中设置 "disableShareAppMessage": true(禁止转发给好友)或 "disableShareTimeline": true(禁止分享到朋友圈)。
37. 小程序如何获取设备信息?常用的设备信息有哪些?

解析:通过 wx.getSystemInfo 或 wx.getSystemInfoSync 获取设备信息,前者是异步 API,后者是同步 API:

  • 基础用法(同步 API,常用)

try {

const systemInfo = wx.getSystemInfoSync();

console.log(systemInfo);

} catch (e) {

console.log('获取设备信息失败', e);

}

  • 常用设备信息字段
    1. model:设备型号(如 iPhone 13、MI 11);
    1. system:操作系统版本(如 iOS 15.4、Android 12);
    1. pixelRatio:设备像素比(如 2、3,用于计算图片尺寸);
    1. screenWidth/screenHeight:屏幕宽度 / 高度(单位 px);
    1. windowWidth/windowHeight:可使用窗口宽度 / 高度(不含导航栏、状态栏,单位 px);
    1. statusBarHeight:状态栏高度(单位 px,用于自定义导航栏适配);
    1. platform:设备平台(ios/android/devtools,用于处理平台差异);
    1. version:微信版本号(如 7.0.20,用于判断 API 兼容性)。
  • 应用场景:① 适配不同设备的屏幕尺寸(如根据 windowWidth 计算组件宽度);② 处理 iOS 和 Android 的差异(如时间格式、滚动行为);③ 自定义导航栏时,根据 statusBarHeight 计算导航栏高度。
38. 小程序如何实现图片预览功能?

解析:通过 wx.previewImage API 实现图片预览,支持手势缩放、左右滑动切换图片,步骤如下:

  1. 页面结构(WXML):展示图片列表,给每张图片绑定点击事件,传递当前图片索引,示例:

<view class="image-list">

<image

wx:for="{{imageList}}"

wx:key="index"

src="{{item}}"

mode="widthFix"

bindtap="handlePreviewImage"

data-index="{{index}}"

></image>

</view>

  1. 逻辑实现(JS):在点击事件中调用 wx.previewImage,传入当前图片 URL 和所有图片 URL 列表,示例:

Page({

data: {

imageList: [

'https://example.com/image1.jpg',

'https://example.com/image2.jpg',

'https://example.com/image3.jpg'

]

},

handlePreviewImage(e) {

const index = e.currentTarget.dataset.index;

const currentImage = this.data.imageList[index];

// 调用图片预览 API

wx.previewImage({

current: currentImage, // 当前预览的图片 URL

urls: this.data.imageList // 所有可预览的图片 URL 列表(必须是数组)

});

}

});

  • 注意事项:① urls 参数必须是数组,且数组中的 URL 必须是有效的图片地址(支持 HTTP/HTTPS);② 预览的图片支持 JPG、PNG、GIF 等格式;③ 若图片是本地临时文件(如相机拍摄的图片),需传入临时文件路径(如 wx.chooseImage 返回的 tempFilePaths)。
39. 小程序如何实现拍照或选择相册图片功能?

解析:通过 wx.chooseImage API 实现,支持从相册选择图片或调用相机拍照,步骤如下:

  1. 页面结构(WXML):添加按钮触发选择图片事件,展示已选择的图片,示例:

<button bindtap="chooseImage">选择图片(拍照/相册)</button>

<view class="image-list">

<image

wx:for="{{selectedImages}}"

wx:key="index"

src="{{item}}"

mode="widthFix"

bindtap="previewImage"

data-index="{{index}}"

></image>

</view>

  1. 逻辑实现(JS):调用 wx.chooseImage,配置选择来源(相册 / 相机)、最多选择数量等参数,示例:

Page({

data: {

selectedImages: [] // 已选择的图片列表(临时文件路径)

},

chooseImage() {

wx.chooseImage({

count: 3, // 最多选择 3 张图片

sizeType: ['original', 'compressed'], // 可选择原图或压缩图

sourceType: ['album', 'camera'], // 可选择相册或相机(默认两者都有)

success(res) {

// res.tempFilePaths 是选择的图片临时文件路径列表(本地路径,有效期至小程序退出)

const newImages = this.data.selectedImages.concat(res.tempFilePaths);

this.setData({ selectedImages: newImages });

}

});

},

// 预览已选择的图片

previewImage(e) {

const index = e.currentTarget.dataset.index;

wx.previewImage({

current: this.data.selectedImages[index],

urls: this.data.selectedImages

});

}

});

  • 注意事项:① tempFilePaths 是临时路径,若需长期保存,需调用 wx.uploadFile 上传到服务器;② 若仅允许相机拍照,可设置 sourceType: ['camera'];③ 选择的图片大小有限制(默认不超过 10MB,可通过 sizeType 选择压缩图减少大小)。
40. 小程序的 wx.uploadFile API 有什么作用?如何使用它上传图片或文件?

解析

  • wx.uploadFile 作用:用于将本地文件(如图片、文档)上传到开发者服务器,支持进度监听,常用于上传头像、表单附件等场景。
  • 核心参数
    • url:服务器上传接口地址(必须是 HTTPS,且已配置域名);
    • filePath:本地文件路径(如 wx.chooseImage 返回的 tempFilePaths 中的路径);
    • name:文件对应的 key(需与服务器接口约定,如 file);
    • formData:额外的表单参数(如用户 ID、文件类型);
    • success:上传成功回调,返回服务器响应数据;
    • fail:上传失败回调;
    • progress:上传进度回调,返回 progress(进度百分比)、totalBytesSent(已上传字节数)、totalBytesExpectedToSend(预期总字节数)。
  • 上传图片示例

// 1. 先选择图片

wx.chooseImage({

count: 1,

sourceType: ['album', 'camera'],

success(chooseRes) {

const filePath = chooseRes.tempFilePaths[0]; // 选中的图片临时路径

// 2. 上传图片到服务器

wx.uploadFile({

url: 'https://api.example.com/uploadImage', // 服务器上传接口

filePath: filePath,

name: 'file', // 服务器接收文件的 key

formData: {

userId: '123', // 额外参数:用户 ID

fileType: 'image' // 额外参数:文件类型

},

// 监听上传进度

progress(res) {

console.log('上传进度:', res.progress + '%');

},

success(uploadRes) {

// 服务器返回的响应数据(默认是字符串,需转成 JSON)

const data = JSON.parse(uploadRes.data);

if (data.code === 200) {

console.log('上传成功,图片 URL:', data.data.imageUrl);

// 存储图片 URL 到本地或页面数据

}

},

fail(err) {

console.log('上传失败', err);

wx.showToast({ title: '上传失败', icon: 'none' });

}

});

}

});

  • 注意事项:① 服务器接口需支持 multipart/form-data 格式(文件上传的标准格式);② 若上传大文件(如超过 5MB),需确保服务器配置了足够的超时时间;③ 上传成功后,服务器需返回文件的访问 URL(如 CDN 地址),小程序后续可通过该 URL 访问文件。

Logo

纵情码海钱塘涌,杭州开发者创新动! 属于杭州的开发者社区!致力于为杭州地区的开发者提供学习、合作和成长的机会;同时也为企业交流招聘提供舞台!

更多推荐