微信小程序:文件引用——include 引入 WXML 片段与条件渲染
一、前言
一个页面如果只有几十行 WXML,全部堆在index.wxml里也还看得懂;但真实项目的页面动辄几百行,头部、正文、底部、侧栏混在一起,改一处样式要在一大段代码里翻找。WXML 提供了文件引用机制,可以把页面拆成多个小片段文件,主页面只保留"在哪里嵌入什么"的结构,逻辑一下子清晰起来。
本文通过一个"科技进展简报"页面,演示用include把页面拆成 header、main、footer、expand 四个片段文件,主页面依次引入前三段,第四段(拓展阅读)则包在wx:if里由两个按钮控制显隐。案例还会对比include、import、自定义组件三者在用途和作用域上的区别。
二、核心概念
include 引入:<include src="/files/header"></include>会把目标文件的代码原样嵌入到当前位置,相当于把那段 WXML 抄了进来。案例用四次include分别引入头部、正文、底部和拓展阅读。
src 路径写法:推荐使用以/开头的绝对路径,从项目根目录算起(不是从当前页面算起),并且不写.wxml后缀。写成src="/files/header"即可,写成/files/header.wxml反而可能找不到文件。
include 与 import 的区别:import只引入目标文件里<template>定义的内容,且必须配合<template is="名字" data="...">才能真正渲染;include则把整个文件除<template>、<wxs>以外的内容全部搬过来,不需要额外调用。本案例引入的是"整段结构",所以用include。
片段文件:files/目录下的四个文件都不是完整页面,没有Page({}),也没有对应的.json,它们只是被切成小块的视图结构。这类文件不能单独访问,只能被别的文件引用。
样式不随引用走:include只搬结构,不搬样式。被引入片段里用到的.header、.main、.footer、.expand这些类名,必须在引用方的 wxss 或全局app.wxss里有定义。案例把这些样式统一写在app.wxss里,所以每个片段都能取到。
wx:if 条件渲染:<view wx:if="{{showFlag}}">里的内容只有在showFlag为 true 时才渲染。区别于hidden,wx:if在条件为 false 时节点会被真正销毁,条件变 true 时重新创建。
setData 更新视图:showExpand与hideExpand两个方法分别调用this.setData({ showFlag: true })和this.setData({ showFlag: false }),数据一变,视图立刻重新计算wx:if。
全局标签选择器:app.wxss里直接写button { background-color: #39c5bb; color: #fff; },会作用到所有页面的所有button组件,案例用它统一按钮配色,省去在每个页面重复写类名。
flex 的 gap 属性:.btn-group用display: flex; gap: 20rpx;让两个按钮横向排列并自动保持 20rpx 间距,不需要给按钮单独加 margin。
三、项目文件结构
文件引用/ ├── app.js 小程序逻辑,注册小程序实例 ├── app.json 全局配置:页面路径、窗口表现 ├── app.wxss 全局样式:片段样式与按钮配色 ├── .eslintrc.js 代码规范配置 ├── sitemap.json 微信索引配置 ├── project.config.json 项目配置(appid、编译设置等) ├── project.private.config.json 项目私有配置 ├── components/ 自定义组件目录 │ └── navigation-bar/ 自定义导航栏组件 │ ├── navigation-bar.js │ ├── navigation-bar.json │ ├── navigation-bar.wxml │ └── navigation-bar.wxss ├── files/ 被引入的 WXML 片段 │ ├── header.wxml 页面头部:大标题 │ ├── main.wxml 正文:科技进展列表 │ ├── footer.wxml 底部:日期 │ └── expand.wxml 拓展阅读:航天规划 └── pages/ 页面目录 └── index/ 首页 ├── index.js 页面逻辑:显隐标志与两个切换方法 ├── index.json 页面配置:注册自定义组件 ├── index.wxml 页面结构:四次 include 与按钮组 └── index.wxss 页面样式:页面级布局骨架四、代码实现
1. pages/index/index.wxml【结构页面】
<navigation-bar title="文件引用" back="{{false}}" color="black" background="#FFF"></navigation-bar> <scroll-view class="scrollarea" scroll-y type="list"> <view class="box"> <include src="/files/header"></include> <include src="/files/main"></include> <include src="/files/footer"></include> <view class="btn-group"> <button bindtap="showExpand">显示扩展内容</button> <button bindtap="hideExpand">隐藏扩展内容</button> </view> <view wx:if="{{showFlag}}"> <include src="/files/expand"></include> </view> </view> </scroll-view>主页面本身非常薄,只有四行include和一组按钮,页面的实际内容全在files/目录下。
2. files/header.wxml【头部片段】
<view class="header"> 2026 年重大科技进展 </view>3. files/main.wxml【正文片段】
<view class="main"> 天问二号小行星探测(2026.7)、轻舟试验飞船(2026.3.30 发射)、地月双向高速激光通信验证(2026.8)、中国空间站常态化运营、九章四号光量子原型机(2026.5)、AI 辅助新药靶点发现、多模态大模型向工业落地深化、核光钟研制成功、柔性光子芯片 </view>4. files/footer.wxml【底部片段】
<view class="footer"> 2026年10月17日 </view>5. files/expand.wxml【拓展阅读片段】
<view class="expand"> 拓展阅读:我国航天后续重大规划<br /> 1、天问三号火星采样返回任务<br /> 2、载人登月工程<br /> 3、大型空间基础设施建设 </view>6. pages/index/index.js【页面数据】
// index.js Page({ data:{ // 控制拓展阅读是否显示,默认不显示 showFlag:false }, // 显示扩展内容 showExpand(){ this.setData({ showFlag:true }) }, // 隐藏扩展内容 hideExpand(){ this.setData({ showFlag:false }) } })7. app.wxss【全局样式】
/**app.wxss**/ .box { margin: 20rpx; padding: 20rpx; border: 6rpx solid #F4C2C8; } .header { text-align: center; margin: 20rpx; color: #1E40AF; font-size: x-large; font-weight: bolder; } .main { font-size: large; text-indent: 2em; margin: 20rpx; line-height: 2em; text-align: justify; color: #475569; } .footer { margin-right: 30rpx; font-size: medium; text-align: right; color: #475569; } /*拓展阅读样式*/ .expand { margin: 20rpx; padding: 20rpx; border: 4rpx solid #F4C2C8; color: #475569; } /*按钮组样式*/ .btn-group { display: flex; gap: 20rpx; margin: 20rpx; } button { background-color: #39c5bb; color: #fff; }8. pages/index/index.wxss【页面样式】
/*index.wxss*/ page { height: 100vh; display: flex; flex-direction: column; } .scrollarea { flex: 1; overflow-y: hidden; }9. pages/index/index.json【页面配置】
{ "usingComponents": { "navigation-bar": "/components/navigation-bar/navigation-bar" } }五、运行效果
页面顶部是自定义导航栏「文件引用」。内容区外围是一圈 6rpx 的浅粉色描边框,框内自上而下依次排布。
最上方是居中、加粗、深蓝色的标题「2026 年重大科技进展」。标题下方是一段正文,首行缩进两个字符,行高为字号的 2 倍,两端对齐,文字颜色是偏灰的深蓝,读起来比较舒展。正文里用顿号把九项科技进展串成一段。再往下是右对齐的日期「2026年10月17日」。
日期下方是一组并排的按钮,两个按钮背景均为青绿色#39c5bb、文字白色,中间自动保持 20rpx 的间距。初始状态下,页面上只有标题、正文、日期和两个按钮,看不到航天规划的内容。点击「显示扩展内容」后,按钮下方会立刻出现一块带浅粉描边的区域,内容是拓展阅读的标题加三条编号列表;点击「隐藏扩展内容」,这块区域又消失,页面回到初始状态。
六、知识点总结
1、include的语义是"把这文件的代码搬到这里"。案例里三次include依次嵌入 header、main、footer,编译后等价于把这三段 WXML 直接写进index.wxml的对应位置,因此它们共享同一个页面作用域。
2、src用的是从项目根目录算起的绝对路径/files/header,并且没有写.wxml后缀。写成相对路径(如../../files/header)也能用,但页面目录层级一变就得跟着改,绝对路径更省心。
3、include与import不能混用:import只认出<template>定义,引入后还得写<template is="xxx" />才渲染;include则把整段结构搬过来,不需要调用。案例引入的是完整结构块,所以选include。此外include会忽略目标文件里的<template>和<wxs>,这两类内容它不搬。
4、样式不会随include一起过来。files/*.wxml里的.header、.main、.footer这些类名,样式必须写在引用方能看到的地方——本案例写在app.wxss(全局样式)里,所以任何页面引用这些片段都能正常显示。如果把样式写在pages/index/index.wxss里,一旦换成别的页面引用同一片段,样式就丢了。
5、files/下的四个文件不是页面,它们是"片段":没有Page({}),没有独立 json,也不能在app.json的pages数组里注册。判断标准很简单——能不能单独打开,能打开的是页面,不能的是片段。
6、include不支持传参。片段里的内容都是写死的文本,主页面无法告诉它"这次显示什么标题"。如果需要参数,就得改用<template>定义 +data传值,或者干脆封装成自定义组件。这是include最大的局限。
7、wx:if="{{showFlag}}"控制拓展阅读的显隐,条件为 false 时整个节点不会创建。这和hidden属性不同:hidden只是把元素藏起来,节点仍然存在于页面结构中,用调试器能看到;wx:if是真正不渲染。内容较重、默认又不需要显示时,用wx:if更省资源。
8、两个按钮分别绑定了showExpand和hideExpand,各自调用setData把showFlag置为 true 或 false。小程序是数据驱动的,不需要手动操作 DOM,只改数据,视图自动跟着变。
9、app.wxss里的button { ... }是标签选择器,会作用到全局所有button组件,案例用它统一了按钮配色。好处是省事,风险是难以针对单个按钮做例外——真要做差异化时,应该改用类选择器,避免污染面过大。
10、.btn-group用display: flex加gap: 20rpx实现按钮横排并自动留间距。相比过去给每个按钮写margin-right的做法,gap不会在最后一个元素后面留出多余空白,也不需要写:last-child { margin-right: 0 }。
11、片段里的换行用的是<br />标签(如 expand.wxml 中的三行规划)。WXML 对<br />的支持与 Web 不同,更稳妥的写法是给每行套一个<view>,或者用\n配合white-space: pre-wrap。案例用<br />能正常断行,但在不同渲染引擎下的表现不如块级元素稳定。
12、include是编译期展开,不是运行时组件,所以它没有独立的作用域、没有样式隔离、也没有生命周期。这也是它与components/navigation-bar那种自定义组件的本质区别:组件是封装,include只是代码分割。
七、拓展思考
当页面越写越长时,拆片段是最低成本的整理手段。比如把一个"个人中心"页面拆成头像区、数据区、功能列表区、设置区四个片段,主文件只剩四行include,改哪块就打开哪个文件,比在几百行里上下翻找快得多。
但include只解决"代码变短",不解决"逻辑复用"。一旦某个片段需要在不同页面显示不同内容,就该升级为<template>(轻量、可传数据、无独立样式)或自定义组件(有独立作用域、可定义属性和事件)。三者的演进路径可以概括为:先include拆分,再template传参,最后组件化封装。