Files
Neo-ZQYY/_DEL/wechat-miniprogram/steering/view-layer.md
2026-03-15 10:15:02 +08:00

8.4 KiB
Raw Blame History

视图层WXML / WXSS / WXS

官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/view/

WXML — 模板语法

数据绑定

<!-- 简单绑定 -->
<view>{{ message }}</view>

<!-- 组件属性绑定(需在双引号内) -->
<view id="item-{{id}}"></view>

<!-- 控制属性绑定 -->
<view wx:if="{{condition}}"></view>

<!-- 关键字绑定(注意 true/false 需要在 {{}} 内) -->
<checkbox checked="{{false}}"></checkbox>
<!-- ⚠️ 错误写法checked="false" 会被当作字符串 "false",结果为 true -->

<!-- 运算 -->
<view>{{ a + b }} + {{ c }} + d</view>
<view>{{"hello " + name}}</view>
<view>{{object.key}} {{array[0]}}</view>

<!-- 三元运算 -->
<view hidden="{{flag ? true : false}}">Hidden</view>

<!-- 组合(数组) -->
<view wx:for="{{[zero, 1, 2, 3, 4]}}">{{item}}</view>

<!-- 组合(对象) -->
<template is="objectCombine" data="{{for: a, bar: b}}"></template>
<!-- 展开运算符 -->
<template is="objectCombine" data="{{...obj1, ...obj2, e: 5}}"></template>

列表渲染 wx:for

<!-- 基本用法:默认 item 和 index -->
<view wx:for="{{array}}">
  {{index}}: {{item.message}}
</view>

<!-- 自定义变量名 -->
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
  {{idx}}: {{itemName.message}}
</view>

<!-- 嵌套 -->
<view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="i">
  <view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="j">
    <view wx:if="{{i <= j}}">
      {{i}} * {{j}} = {{i * j}}
    </view>
  </view>
</view>

<!-- ⚠️ wx:key 非常重要,用于列表项的唯一标识 -->
<!-- 值为字符串item 的某个 property 名(该 property 值需唯一) -->
<switch wx:for="{{objectArray}}" wx:key="unique">{{item.id}}</switch>

<!-- 值为 *thisitem 本身是唯一字符串或数字 -->
<switch wx:for="{{numberArray}}" wx:key="*this">{{item}}</switch>

wx:key 的作用:当数据改变触发重新渲染时,带有 key 的组件会被重新排序而非重新创建,保持自身状态(如 <input> 的输入内容、<switch> 的选中状态)。

条件渲染

<!-- wx:if / wx:elif / wx:else -->
<view wx:if="{{length > 5}}">1</view>
<view wx:elif="{{length > 2}}">2</view>
<view wx:else>3</view>

<!-- block wx:if不会渲染为真实 DOM -->
<block wx:if="{{true}}">
  <view>view1</view>
  <view>view2</view>
</block>

wx:if vs hidden

  • wx:if 是惰性的,条件为 false 时不渲染,切换时销毁/重建
  • hidden 始终渲染,只是切换显示/隐藏(类似 CSS display:none
  • 频繁切换用 hidden,运行时条件不大可能改变用 wx:if

模板 template

<!-- 定义模板 -->
<template name="msgItem">
  <view>
    <text>{{index}}: {{msg}}</text>
    <text>Time: {{time}}</text>
  </view>
</template>

<!-- 使用模板 -->
<template is="msgItem" data="{{...item}}"/>

<!-- 动态模板名 -->
<template is="{{item % 2 == 0 ? 'even' : 'odd'}}"/>

引用

<!-- import引入目标文件中定义的 template -->
<import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/>
<!-- ⚠️ import 有作用域:只会引入目标文件中定义的 template不会引入目标文件 import 的 template不递归 -->

<!-- include将目标文件除 <template/> <wxs/> 外的整个代码引入 -->
<include src="header.wxml"/>
<view>body</view>
<include src="footer.wxml"/>

WXSS — 样式

rpx 单位

rpxresponsive pixel可以根据屏幕宽度进行自适应。规定屏幕宽为 750rpx。

设备 rpx 换算 px px 换算 rpx
iPhone5 1rpx = 0.42px 1px = 2.34rpx
iPhone6 1rpx = 0.5px 1px = 2rpx
iPhone6 Plus 1rpx = 0.552px 1px = 1.81rpx

建议:开发时以 iPhone6 为视觉稿标准750px 宽1px = 1rpx。

样式导入

/* common.wxss */
.small-p { padding: 5px; }

/* app.wxss */
@import "common.wxss";
.middle-p { padding: 15px; }

选择器支持

选择器 示例 说明
.class .intro 类选择器
#id #firstname ID 选择器
element view 元素选择器
element, element view, checkbox 群组选择器
::after view::after 伪元素
::before view::before 伪元素

内联样式

<!-- style动态样式运行时解析尽量避免静态样式写在 style 中 -->
<view style="color:{{color}};"/>

<!-- class静态样式写在 class 中 -->
<view class="normal_view"/>

全局样式与局部样式

  • app.wxss 为全局样式,作用于每个页面
  • 页面的 .wxss 只对当前页面生效,会覆盖 app.wxss 中相同的选择器

WXSWeiXin Script

WXS 是小程序的一套脚本语言,可以在 WXML 中使用。WXS 运行在视图层,比 JS 逻辑层快(不需要跨线程通信)。

<!-- 内联 WXS -->
<wxs module="m1">
var msg = "hello world";
module.exports.message = msg;
</wxs>
<view>{{m1.message}}</view>

<!-- 外部 WXS 文件 -->
<wxs src="./tools.wxs" module="tools"/>
<view>{{tools.msg}}</view>
<view>{{tools.bar(tools.FOO)}}</view>
// tools.wxs
var foo = "'hello world' from tools.wxs"
var bar = function(d) {
  return d
}
module.exports = {
  FOO: foo,
  bar: bar,
}
// ⚠️ WXS 不支持 ES6 语法箭头函数、let/const、解构等
// ⚠️ WXS 中不能调用小程序 APIwx.xxx

WXS 典型用途

  • 格式化数据(日期、金额、文本截断)
  • 在视图层做简单计算,避免 setData 开销
  • 响应事件WXS 事件响应iOS 上性能更好)

事件系统

事件分类

类型 说明 示例
冒泡事件 向父节点传递 tap, longpress, touchstart, touchmove, touchend, touchcancel
非冒泡事件 不向父节点传递 submit, input, scroll 等组件特有事件

事件绑定

<!-- bind不阻止冒泡 -->
<view bindtap="handleTap">Click me</view>
<view bind:tap="handleTap">Click me</view>

<!-- catch阻止冒泡 -->
<view catchtap="handleTap">Click me</view>

<!-- mut-bind互斥事件绑定基础库 2.8.2+ -->
<view mut-bind:tap="handleTap">
  <button mut-bind:tap="handleButtonTap">按钮</button>
</view>
<!-- 同一冒泡路径上的 mut-bind 只会有一个被触发 -->

<!-- capture-bind捕获阶段绑定 -->
<view capture-bind:tap="handleCapture">
  <view bindtap="handleTap">inner</view>
</view>

<!-- capture-catch捕获阶段中断 -->
<view capture-catch:tap="handleCapture">
  <view bindtap="handleTap">inner不会触发</view>
</view>

事件对象

Page({
  handleTap(e) {
    e.type          // 事件类型,如 "tap"
    e.timeStamp     // 事件生成时的时间戳
    e.target        // 触发事件的源组件(可能是子组件)
    e.currentTarget // 事件绑定的当前组件
    e.detail        // 额外信息,如 tap 的 { x, y }
    e.touches       // 触摸事件的触摸点信息数组
    e.changedTouches // 变化的触摸点信息数组
    e.mark          // 事件标记(基础库 2.7.1+

    // target 和 currentTarget 的区别
    e.target.id         // 触发事件的组件 id
    e.target.dataset    // 触发事件的组件的 data-xxx 属性集合
    e.currentTarget.id  // 绑定事件的组件 id
    e.currentTarget.dataset
  }
})

dataset

<!-- data-xxx 属性传递数据 -->
<view data-alpha-beta="1" data-alphaBeta="2" bindtap="handleTap">
  Click
</view>
handleTap(e) {
  e.currentTarget.dataset.alphaBeta // "1"(连字符转驼峰)
  e.currentTarget.dataset.alphabeta // "2"(大写转小写)
}

mark基础库 2.7.1+

<!-- mark 可以在冒泡路径上所有节点收集 -->
<view mark:myMark="last" bindtap="bindViewTap">
  <button mark:anotherMark="leaf" bindtap="bindButtonTap">按钮</button>
</view>
bindButtonTap(e) {
  e.mark // { myMark: "last", anotherMark: "leaf" }
  // mark 会合并冒泡路径上所有的 mark
}

在线查询

如需更详细信息,可抓取: