AI 摘要

本文系统梳理微信小程序页面制作全流程:先以 WXML 搭建结构,对比 HTML 差异;再用 WXSS 设定样式,详解 rpx、vw/vh 适配与样式导入;接着配置 app.json 管理页面路径、导航栏、标签栏;最后逐一演示 view、scroll-view、swiper、image、video、form 及 input、button 等核心组件的用法与属性,并介绍 WebView 与 Skyline 双渲染引擎的选择策略,为高效开发提供完整指南。

页面制作概述

WXML 概述

在制作微信小程序页面时,页面的结构可以用 WXML 来实现。

WXML 是微信团队为微信小程序开发而设计的一套语言,可以结合微信小程序中的各种组件构建页面结构。

WXML 与 HTML 的区别:

  • HTML 和 WXML 使用的标签不同。HTML 经常使用 div 标签搭建页面结构,而 WXML 则使用 view 标签搭建页面结构。HTML 经常使用 span 标签定义行内文本 ,而 WXML 则使用 text 标签定义行内文本 。
  • WXML 提供了和 Vue.js 中模板语法类似的模板语法,如数据绑定、列表渲染、条件渲染等。
  • HTML 页面可以在浏览器中预览,而 WXML 页面仅能在微信客户端和微信开发者工具中预览。
  • WXML 中的单标签必须在结尾 > 前面加上 /,否则微信开发者工具会报语法错误,而 HTML 中允许省略单标签 > 前面的 /。
  • WXML 中所使用的标签是微信小程序定义的标签,应避免使用 HTML 标签,这样才能保证页面被正确转译。

WXSS 概述

微信小程序提供了一套类似 CSS 的语言 WXSS,通过 WXSS 可以美化页面样式。

WXSS 与 CSS 的区别:

  • 不同的手机屏幕分辨率不同,如果用 CSS 中的 px 单位,会遇到屏幕适配的问题,需要手动进行像素单位换算,而微信小程序提供了一个新的单位 rpx,使用 rpx 单位可以很轻松地适配各种手机屏幕。
  • 在微信小程序中,项目根目录中的 app.wxss 作为全局样式,会作用于当前微信小程序的所有页面,而局部页面的 WXSS 样式仅对当前页面生效,CSS 则没有这样的功能。
  • 在 WXSS 中设置背景图片的时候,可以使用网络图片或者以 Base64 格式编码的图片,不能使用本地图片。

rpx 单位

rpx(Responsive Pixel,自适应像素)是微信小程序独有的、用来解决屏幕适配问题的尺寸单位。

rpx 单位的设计思想是把所有设备的屏幕在宽度上等分为 750 份,即屏幕的总宽度为 750rpx,微信小程序在不同设备上运行的时候,会自动把 rpx 单位换算成对应的像素单位来渲染,从而实现屏幕适配。

vw/vh 单位

在使用 CSS 编写移动端的页面样式时,由于不同手机的屏幕宽高不同,屏幕适配会比较麻烦,针对这类型问题,通过视口单位可以有效解决。

视口表示可视区域的大小,视口单位主要包括 vw(Viewport Width)和 vh(Viewport Height),vw、vh 是相对长度单位,永远以视口作为参考。

在微信小程序中也可以使用 vw 和 vh 单位,使用视口单位时,系统会将视口的宽度和高度分为 100 份,1vw 占用视口宽度的百分之一,1vh 占用视口高度的百分之一。

样式导入

为了避免样式代码冗余,可以将相同的样式代码抽为公共样式,放到一个单独的文件中,通过只修改公共样式实现对所有相关页面样式的修改,从而节约时间、方便管理。

导入公共样式的基本用法:

@import "公共的wxss路径";

页面路径配置

在微信小程序中可以通过全局配置文件(app.json)中的 pages 配置项来配置微信小程序的页面路径。

  • pages 配置项是一个数组,该数组用于指定微信小程序由哪些页面组成,数组中的每一个元素都对应一个页面的路径信息。
  • pages 数组中的第一项为微信小程序的初始页面,开发者可以手动调整数组中元素的顺序以更换初始页面。

示例:页面路径配置

全局配置文件(app.json):

{
    "pages": [
        "pages/index/index"
    ]
}

新建微信小程序页面的方法:

  • 通过 pages 数组中新增一项来新增页面。
  • 通过项目资源管理器新增页面。

删除微信小程序页面的方法:

  • 对页面文件直接进行删除操作,不会触发代码的自动更新效果。
  • 删除页面需要手动修改全局配置文件(app.json)中的 pages 配置项。

微信小程序页面组件

页面组件概述

微信小程序页面和普通网页都是通过标签来定义页面结构的,但是在微信小程序开发中,更习惯将这些标签称为组件,这些组件自带微信风格的 UI 样式和特定功能效果。

微信小程序提供了丰富的组件,通过组合这些组件可以进行高效开发。

view 组件

view 组件即视图容器,用于定义文档中的分区或节,实现页面的布局效果。

view 组件的基本用法:

<view>...</view>

view 组件的基本属性:

名称描述
hover-class指定手指按下去的样式类
当该属性值为 none 时,没有点击态
hover-stop-propagation指定是否阻止本节点的祖先节点出现点击态
hover-start-time手指按住后多久出现点击态,单位为毫秒
hover-stay-time手指松开后点击态保留时间,单位为毫秒

示例:view 组件

首页页面结构(pages/index/index.wxml):

<view class="container">
    <view hover-class="font">按下我后会改变颜色</view>
    <view hover-class="font" hover-start-time="2000">按下我后会改变颜色(2s后)</view>
</view>

首页页面样式(pages/index/index.wxss):

.font {
    color: red;
}

示例效果:


scroll-view 组件

scroll-view 组件用于实现滚动效果,支持横向滚动和纵向滚动。

scroll-view 组件的基本用法:

<scroll-view>...</scroll-view>

scroll-view 组件的基本属性:

名称描述
scroll-x允许横向滚动,默认值为 false
scroll-y允许纵向滚动,默认值为 false
bindscrolltoupper滚动到顶部/左边时触发的事件
bindscrolltoower滚动到底部/右边时触发的事件
bindscroll滚动时触发的事件

当允许横向滚动、纵向滚动后,还需要使 scroll-view 组件中内容的宽度和高度大于 scroll-view 组件本身的宽度和高度,这样才能滚动。


示例:scroll-view 组件

首页页面结构(pages/index/index.wxml):

<scroll-view scroll-x>
    <view style="width: 200%; height: 100px; background-image: linear-gradient(to bottom right, red, yellow);"></view>
</scroll-view>

示例效果:


image 组件

image 组件用于显示图片。

image 组件的基本用法:

<image src="..."></image>

image 组件的基本属性:

名称描述
src图片资源地址,可以是本地路径或 URL 地址
mode图片剪裁、缩放的模式
可选:
scaleToFill(默认):拉伸图片以充满整个 image 组件
aspectFit:保持宽高比缩放图片,使图片的长边能完全显示出来
aspectFill:保持宽高比缩放图片,只保证图片的短边能完全显示出来,另一个方向将会发生截取
top/bottom/center/left/right:不缩放图片,只显示图片顶/底/中/左/右区域的部分
show-menu-by-longpress是否显示长按图片显示菜单
菜单提供发送给朋友、收藏、保存图片、搜一搜等功能
binderror当错误发生时触发的函数
bindload当图片载入完毕时触发

示例:image 组件

首页页面结构(pages/index/index.wxml):

<view class="container">
    <image src="/images/avatar.jpg"></image>
    <image src="/images/avatar.jpg" mode="aspectFit"></image>
</view>

示例效果:


swiper 组件

swiper 组件用于实现滑块视图容器。

swiper 组件一般与 swiper-item 组件搭配使用。

  • swiper 组件表示滑块视图容器,用于创建一块可以滑动的区域。
  • swiper 组件内部需要嵌套 swiper-item 组件,swiper-item 组件表示滑块视图内容。
  • swiper-item 组件可以嵌套 image 组件、view 组件或其他组件。

swiper 组件的基本用法:

<swiper>
    <swiper-item>
        ...
    </swiper-item>
    ...
</swiper>

swiper 组件的基本属性:

名称描述
indicator-dots是否显示面板指示点
indicator-color指示点颜色
indicator-active-color当前选中的指示点颜色
autoplay是否自动切换
current当前所在滑块的下标索引
interval自动切换时间间隔,单位为毫秒
circular是否采用衔接滑动

示例:swiper 组件

首页页面结构(pages/index/index.wxml):

<swiper>
    <swiper-item>
        <view style="background-color: blue; height: 200px;">0</view>
    </swiper-item>
    <swiper-item>
        <view style="background-color: green; height: 200px;">1</view>
    </swiper-item>
    <swiper-item>
        <view style="background-color: red; height: 200px;">2</view>
    </swiper-item>
</swiper>

示例效果:


text 组件

text 组件用于定义行内文本。

text 组件的基本用法:

<text>...</text>

text 组件的基本属性:

名称描述
user-select文本是否可选,默认值为 false

示例:text 组件

首页页面结构(pages/index/index.wxml):

<text user-select="true" style="font-size: 80rpx;">床前明月光</text>
<text>\n</text>
<text style="font-size: 80rpx;">疑似地上霜</text>

示例效果:


video 组件

video 组件用于播放视频。

video 组件的基本用法:

<video src="..."></video>

video 组件的基本属性:

名称描述
src视频的资源地址,必须是远程视频路径
duration指定视频时长
controls是否显示默认播放控件
autoplay是否自动播放
loop是否循环播放
muted是否静音播放
poster视频封面的图片网络资源地址
bindplay当开始/继续播放时触发 play 事件
bindpause当暂停播放时触发 pause 事件
object-fit当视频大小与 video 组件大小不一致时,调整视频的表现形式
可选 contain 包含/fill 填充/cover 覆盖
initial-time指定视频初始播放位置

示例:video 组件

首页页面结构(pages/index/index.wxml):

<video src="https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/61/60/334576061/334576061_nb2-1-16.mp4"></video>

示例效果:


form 组件

form 组件表示表单容器,没有任何样式,需要配合其他表单组件一起使用,用于提交用户输入的信息和选择的选项。

form 组件的基本用法:

<form>
    ...
</form>

form 组件的基本属性:

名称描述
bindsubmit表单提交时触发事件
bindreset表单重置时触发事件

button 组件

button 组件表示按钮。

button 组件的基本用法:

<button>...</button>

button 组件的基本属性:

名称描述
size按钮的大小,可选 default/mini
type按钮的样式类型,可选 primary/default/warn
plain按钮是否镂空
disabled按钮是否禁用
form-type按钮类型,可选 submit/reset
hover-class指定按钮点击态效果

示例:button 组件

首页页面结构(pages/index/index.wxml):

<button>按钮</button>
<button type="primary">按钮</button>
<button type="warn">按钮</button>

示例效果:


input 组件

input 组件表示输入框。

input 组件的基本用法:

<input/>

input 组件的基本属性:

名称描述
value输入框的初始内容
type输入框的类型
可选 text/number/idcard/safe-password 等
不同的类型会弹出不同的屏幕键盘
password是否是密码类型
placeholder输入框为空时的占位符
placeholder-style指定 placeholder 的样式

示例:input 组件

首页页面结构(pages/index/index.wxml):

<input type="text" placeholder="请输入用户名" style="border: 1px solid #CCCCCC;" />
<input type="text" password="true" placeholder="请输入密码" style="border: 1px solid #CCCCCC;" />

示例效果:


checkbox 组件

checkbox 组件表示复选框。

checkbox 组件一般与 checkbox-group 组件搭配使用。

  • checkbox-group 组件表示多项选择器。
  • checkbox-group 组件内部由多个 checkbox 组件组成,checkbox 组件表示一项选择器。
  • 建议将不同组的 checkbox 组件嵌套在不同的 checkbox-group 组件中,从而方便管理和区分。

checkbox 组件的基本用法:

<checkbox-group>
    <checkbox value="...">...</checkbox>
    ...
</checkbox-group>

checkbox 组件的基本属性:

名称描述
valuecheckbox 组件标识
checked当前是否选中
disabled当前是否禁止选中

示例:checkbox 组件

首页页面结构(pages/index/index.wxml):

<checkbox-group>
    <checkbox value="1">苹果</checkbox>
    <checkbox value="2">西瓜</checkbox>
    <checkbox value="3">芒果</checkbox>
</checkbox-group>

示例效果:


radio 组件

radio 组件表示单选框。

radio 组件一般与 radio-group 组件搭配使用。

  • radio-group 组件表示单项选择器。
  • radio-group 组件内部由多个 radio 组件组成,radio 组件表示一项选择器。
  • 建议将不同组的 radio 组件嵌套在不同的 radio-group 组件中,从而方便管理和区分。

radio 组件的基本用法:

<radio-group>
    <radio value="...">...</radio>
    ...
</radio-group>

radio 组件的基本属性:

名称描述
valuecheckbox 组件标识
checked当前是否选中
disabled当前是否禁止选中

示例:radio 组件

首页页面结构(pages/index/index.wxml):

<radio-group>
    <radio value="1">苹果</radio>
    <radio value="2">西瓜</radio>
    <radio value="3">芒果</radio>
</radio-group>

示例效果:


slider 组件

slider 组件表示滑动选择器。

slider 组件的基本用法:

<slider/>

slider 组件的基本属性:

名称描述
min最小值,默认值为 0
max最大值,默认值为 100
step步长,默认值为 1
value当前取值,默认值为 0
bindchange完成一次拖拽后触发的事件

示例:slider 组件

首页页面结构(pages/index/index.wxml):

<slider min="0" max="100" step="2" />

示例效果:


微信小程序页面配置

Webview

小程序一直以来采用的都是 AppService 和 WebView 的双线程模型的架构方式,WebView 主要负责页面的显示和一些基础的交互功能,而 AppService 则承担了更多的逻辑处理和数据运算等任务。

当小程序基于 WebView 环境时,WebView 中的 DOM 树创建、JS 逻辑、CSS 解析、Layout、样式计算等内容都发生在同一个线程中。

AppService + WebView 双线程模型架构可能存在问题:

  • 由于 JS 引擎限制,内存使用有要求且 JS 解释速度不一。
  • 渲染使用 WebView,对性能和功耗有一定要求,开销较大,无法提供媲美原生的流畅体验。
  • 在一些硬件配置较低的设备中运行小程序时可能出现无法运行或运行后卡顿的情况。

Skyline

为了进一步优化小程序性能,提供更为接近原生的用户体验,微信团队在 WebView 渲染之外新增了一个渲染引擎 Skyline,其使用更精简高效的渲染管线,并带来诸多增强特性,让 Skyline 拥有更接近原生渲染的性能体验。

Skyline 渲染引擎的特点:

  • 界面更不容易被逻辑阻塞,进一步减少卡顿。
  • 无需为每个页面新建一个 JS 引擎实例(Webview),减少了内存、时间开销。
  • 框架可以在页面之间共享更多的资源,进一步减少运行时内存、时间开销。
  • 框架的代码之间无需再通过 JSBridge 进行数据交换,减少了大量通信时间开销。
  • 借助其特点提供了新的页面组件,释放更多高级能力。

一般情况下,微信开发者工具新建的微信小程序项目默认是 Skyline 模式,但如果遇到 Skyline 模式下的渲染兼容问题,可以尝试切换到 Webview 模式。

Skyline 支持按页面粒度开启,也可以在全局配置文件(app.json)中开启。

"renderer": "skyline",
"rendererOptions": {
    "skyline": {
        "defaultDisplayBlock": true,
        "disableABTest": true,
        "sdkVersionBegin": "3.0.0",
        "sdkVersionEnd": "15.255.255"
    }
},
"componentFramework": "glass-easel"

微信开发者工具提供了对齐移动端的 Skyline 渲染引擎,支持 WXML 调试、 WXSS 样式错误提示、新增的特性等,可以在本地设置中开启 Skyline 渲染渲染调试。

在选择渲染模式时,需根据实际场景需要进行权衡,追求性能选 Skyline,追求兼容性选 Webview,无论选择 Skyline 还是 Webview,均需要关注组件或 API 对于这两种模式的兼容和适配。

由于目前 Skyline 存在的问题较多,兼容性并不是很好,故后续均采用 Webview 模式。

{
    "pages": [
        "pages/index/index"
    ],
    "window": {
        "navigationBarTextStyle": "black",
        "navigationStyle": "custom"
    },
    "style": "v2",
    "sitemapLocation": "sitemap.json",
    "lazyCodeLoading": "requiredComponents"
}

页面导航栏

在微信小程序中,有时为了页面美观,需要更改导航栏的样式,可以通过页面配置文件(xx.json)或全局配置文件(app.json)对导航栏的样式进行配置。

页面导航栏全局配置的基本用法:

"window": {
    "navigationBarTextStyle": "...",
    "navigationStyle": "default",
    "navigationBarBackgroundColor": "...",
    "navigationBarTitleText": "..."
}

页面导航栏局部配置的基本用法:

{
    "navigationBarTextStyle": "...",
    "navigationBarBackgroundColor": "...",
    "navigationBarTitleText": "..."
}

页面导航栏的基本配置项:

名称描述
navigationBarTitleText导航栏标题文字内容
navigationBarBackgroundColor导航栏背景颜色
navigationBarTextStyle导航栏标题颜色,只支持 black/white
navigationStyle导航栏样式,只支持 default/custom

示例:页面导航栏

全局配置文件(app.json):

"window": {
    "navigationBarTextStyle": "black",
    "navigationStyle": "default",
    "navigationBarBackgroundColor": "#ffffff",
    "navigationBarTitleText": "WeChat"
}

示例效果:

首页页面配置文件(pages/index/index.json):

{
    "navigationBarTitleText": "首页"
}

示例效果:


navigation-bar 组件

navigation-bar 组件是页面导航条配置节点,用于指定导航栏的一些属性,需要配合 page-meta 组件一起使用。

  • page-meta 组件是页面属性配置节点,用于指定页面的一些属性、监听页面事件,page-meta 组件只能是页面内的第一个节点。
  • navigation-bar 组件只能是 page-meta 组件内的第一个节点。

navigation-bar 组件的基本用法:

<page-meta>
    <navigation title="..." front-color="..." background-color="..."></navigation>
</page-meta>

navigation-bar 组件的基本属性:

名称描述
title导航栏标题文字内容
background-color导航栏背景颜色
front-color导航栏标题颜色,只支持 #ffffff 和 #000000

示例:navigation-bar 组件

首页页面结构(pages/index/index.wxml):

<page-meta>
    <navigation-bar title="欢迎页面" front-color="#000000" background-color="#FFFFFF"></navigation-bar>
</page-meta>

示例效果:


页面标签栏

通过标签栏可以很方便地在多个页面之间进行切换,在微信小程序的全局配置文件(app.json)中添加配置项即可实现标签栏配置。

页面标签栏配置的基本用法:

"tabBar": {
    "color": "...",
    "selectedColor": "...",
    "borderStyle": "...",
    "backgroundColor": "...",
    "list": [{
        "pagePath": "...",
        "text": "...",
        "iconPath": "...",
        "selectedIconPath": "..."
      }, 
      ...
    ]
}

页面标签栏的基本配置项:

名称描述
color标签栏上的文字默认颜色
selectedColor标签栏上的文字选中时的颜色
backgroundColor标签栏的背景色
borderStyle标签栏上边框的颜色,只支持 black/white
list标签栏的列表
数组中的每个元素都是一个代表标签按钮的对象
数组中最少需要配置 2 个标签按钮,最多只能配置 5 个标签按钮
position标签栏的位置,只支持 bottom 底部/top 顶部
custom是否启用自定义标签栏

页面标签栏标签按钮的基本属性:

名称描述
pagePath页面路径,页面必须在 pages 数组中预先定义
text标签按钮上的文字
iconPath未选中时的图标路径
当 position 属性值为 top 时,不显示图标
selectedIconPath选中时的图标路径
当 position 属性值为 top 时,不显示图标

示例:页面标签栏

全局配置文件(app.json):

"pages": [
    "pages/index/index",
    "pages/about/about"
],
"tabBar": {
    "color": "#000000",
    "selectedColor": "#FF0000",
    "borderStyle": "black",
    "backgroundColor": "#FFFFFF",
    "list": [{
        "pagePath": "pages/index/index",
        "text": "首页"
    }, {
        "pagePath": "pages/about/about",
        "text": "联系我们"
    }]
}

示例效果: