小程序开发

1.基础

1.准备工作

  • 1.注册公众平台账号(免费)
  • 2.下载小程序开发工具(免费)

2.开发步骤

1.第一个小程序

小程序开发_第1张图片

  • 1.小程序的AppID相当于小程序平台的一个身份证,这里使用的是测试号(注意区别于服务号或订阅号的AppID
  • 2.测试号默认不使用云服务,根据需求选择模板,这里选择JS-基础模板

2.小程序代码构成

1.JSON配置

小程序开发_第2张图片

  • 1.JSON是一种数据格式,小程序中的JSON用于静态配置
  • 2.配置文件说明(根目录)
    • 1.app.json:当前小程序的全局配置,具体可参考小程序全局配置说明
      • 1.页面路径
        • 1.pages:用于描述当前小程序所有页面路径,用于让微信客户端清楚当前小程序页面定义的目录
      • 2.界面表现
        • 2.window:用于定义小程序所有页面的顶部背景颜色,文字颜色定义等
      • 3.网络超时时间
      • 4.底部 tab
    • 2.project.config.json:当前小程序开发工具的个性化配置,具体可参考小程序个性化配置说明
    • 3.page.json:当前小程序独立页面的属性配置,具体可参考小程序独立页面配置说明
2.WXML + WXSS + JS
  • 1.网页编程采用的是HTML + CSS + JS组合
  • 2.小程序开发采用WXML + WXSS + JS组合
  • 3.WXML类似于HTML,具体可参考WXML语法参考;WXSS类似于CSS
  • 4.MVVM开发模式(React,Vue):把渲染和逻辑分离
    • 1.网页开发流程中,通过JS操作DOM(对应 HTML的描述产生的树),以引起界面的一些变化响应用户的行为
    • 2.用户点击某个按钮的时候,JS会记录一些状态到JS变量里,同时通过DOM APIDOM的属性或者行为,进而引起界面一些变化
    • 3.当项目越来越大,代码会充斥着非常多的界面交互逻辑和程序的各种状态变量,显然这不是一个很好的开发模式
    • 4.不要让JS直接操控DOMJS只需要管理状态即可,然后再通过一种模板语法来描述状态和界面结构的关系即可,小程序的框架也是用到了这个思路
3.小程序运行环境

小程序开发_第3张图片

  • 1.小程序的运行环境分为
    • 1.渲染层
      • 1.WXML模板和WXSS样式
    • 2.逻辑层
      • 1.JS脚本
  • 2.小程序的渲染层和逻辑层分别由2个线程管理
    • 1.渲染层的界面使用WebView进行渲染
    • 2.逻辑层采用JsCore线程运行JS脚本
    • 3.一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端Native做中转,逻辑层发送网络请求也经由微信客户端转发
4.框架
  • 1.小程序框架系统分为两部分
    • 1.逻辑层(App Service
    • 2.视图层(View
      • 说明:小程序提供了自己的视图层描述语言WXMLWXSS,以及基于JavaScript的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑
  • 2.小程序框架核心
    • 1.响应的数据绑定系统:将数据与视图非常简单地保持同步,当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新
  • 3.数据绑定
    • 1.通过{{ }}的语法把一个变量绑定到界面上,称为数据绑定
    • 2.仅仅通过数据绑定还不够完整的描述状态和界面的关系,还需要if/else, for等控制能力,小程序中这些控制能力都用wx:开头的属性来表达
    <text>{{msg}}text>
    
    this.setData({ msg: "Hello World" })
    

1.列表渲染


<view wx:for="{{array}}"> {{item}} view>
// page.js
Page({
 data: {
   array: [1, 2, 3, 4, 5]
 }
})

2.条件渲染


<view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW view>
<view wx:elif="{{view == 'APP'}}"> APP view>
<view wx:else="{{view == 'MINA'}}"> MINA view>
// page.js
Page({
 data: {
   view: 'MINA'
 }
})

3.模板


<template name="staffName">
 <view>
   FirstName: {{firstName}}, LastName: {{lastName}}
 view>
template>

<template is="staffName" data="{{...staffA}}">template>
<template is="staffName" data="{{...staffB}}">template>
<template is="staffName" data="{{...staffC}}">template>
// page.js
Page({
 data: {
   staffA: {firstName: 'Hulk', lastName: 'Hu'},
   staffB: {firstName: 'Shang', lastName: 'You'},
   staffC: {firstName: 'Gideon', lastName: 'Lin'}
 }
})

4.引用

  • 网页开发渲染线程和脚本线程是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应
  • 小程序中,二者是分开的,分别运行在不同的线程中。网页开发者可以使用到各种浏览器暴露出来的 DOM API,进行 DOM 选中和操作
  • 程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。这一区别导致了前端开发非常熟悉的一些库,例如 jQuery、 Zepto 等,在小程序中是无法运行的。同时 JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包在小程序中也是无法运行的
  • 网页开发者需要面对的环境是各式各样的浏览器,PC 端需要面对 IE、Chrome、QQ浏览器等,在移动端需要面对Safari、Chrome以及 iOS、Android 系统中的各式 WebView 。而小程序开发过程中需要面对的是两大操作系统 iOS 和 Android 的微信客户端,以及用于辅助开发的小程序开发者工具,小程序中三大运行环境也是有所区别的
  • 小程序开发_第4张图片
  • ​网页开发者在开发网页的时候,只需要使用到浏览器,并且搭配上一些辅助工具或者编辑器即可。小程序的开发则有所不同,需要经过申请小程序账号、安装小程序开发者工具、配置项目等等过程方可完成

开始

  • 1.开发小程序的第一步,你需要拥有一个小程序账号,通过这个账号你就可以管理你的小程序
  • 2.申请账号
  • 3.进入小程序注册页 根据指引填写信息和提交相应的资料,就可以拥有自己的小程序账号。
    小程序注册
  • 4.登录 小程序后台 ,我们可以在菜单 “开发”-“开发设置” 看到小程序的 AppID 了

小程序的基本文件结构

小程序开发_第5张图片

  • 1.一个小程序项目必须有这3个描述App的文件,这3个文件是应用程序级别的文件
    小程序开发_第6张图片
    • 1.app.js
    • 2.app.json
    • 3.app.wxss
  • 2.它们必须放在应用程序的根目录下,否则小程序会提示找不到app.json文件
  • 3.接着是和这3个应用程序级别文件平行的pages文件夹
  • 4.一个小程序由若干个页面文件构成,比如图3-1中pages文件夹下就有2个页面,分别是index页面和logs页面。每个页面可以由4个文件构成,分别是:
    • .js
    • .wxml
    • .wxss
    • .json文件
      小程序开发_第7张图片
  • 1.wxml文件类似于我们熟悉的HTML文件,用来编写页面的标签和骨架,不同的是wxml文件里的标签元素不可以使用HTML标签,只能使用小程序自己封装的一些组件,这些组件也是我们后面要重点学习的知识。>* 2.wxss文件的作用类似于我们熟悉的CSS文件,用于编写小程序的样式,实际上小程序的样式编写语言就是CSS,只是把.css文件换成了.wxss文件。
  • 3.json文件用来配置页面的样式与行为。
  • 4.js文件类似于我们前端编程中的JavaScript文件,用来编写小程序的页面逻辑
  • 5.以上4种类型的页面文件的文件名称必须相同,这是要注意的一个地方
  • 小程序的4种页面级别文件同3个应用程序级别文件相比,多出了一个wxml页面标签文件,其他3个的作用基本相似,只不过页面文件作用于页面本身而应用程序文件作用于应用程序整体
  • 除了pages文件夹外,官方的示例项目中还有一个utils文件夹,这个文件夹用来存放一些公共的js文件,比如utils下面的util.js。我们可以任意定义类似于utils文件夹的目录,并放在小程序的任意位置,小程序对此并没有任何限制

从零开始编写一个小程序页面

  • 新建一个项目,并且不勾选【在当前目录中创建quick start项目】这个选项,因为我们要从零开始编写一个项目,所以每个文件都将由自己亲手创建。项目创建后,会出现一个如图3-2所示的错误提示,这是因为现在的项目里还没有任何文件,由于缺少必要的文件,所以小程序会报错。之所以完全新建一个全新的项目,是为了向开发者展示这些常见的错误消息,如果大家不想经历这些错误,那么可以在官方提供的quick start项目上修改

小程序配置

1.全局配置

  • 1.小程序根目录下的app.json文件用来对微信小程序进行全局配置,文件内容为一个JSON对象
    属性 类型 必填 描述 最低版本
    entryPagePath string 小程序默认启动首页
    pages string[] 页面路径列表
    window Object 全局的默认窗口表现
    sitemapLocation string 指明 sitemap.json 的位置
    tabBar Object 底部 tab 栏的表现
    debug boolean 是否开启 debug 模式,默认关闭
    workers string Worker代码放置的目录 1.9.90
    plugins Object 使用到的插件 1.9.6
    networkTimeout Object 网络超时时间
    functionalPages boolean 是否启用插件功能页,默认关闭 2.1.0
    subpackages Object[] 分包结构配置 1.7.3
    requiredBackgroundModes string[] 需要在后台使用的能力,如「音乐播放」
    requiredPrivateInfos string[] 调用的地理位置相关隐私接口
    preloadRule Object 分包预下载规则 2.3.0
    resizable boolean PC小程序是否支持用户任意改变窗口大小(包括最大化窗口);iPad 小程序是否支持屏幕旋转。默认关闭 2.3.0
    usingComponents Object 全局自定义组件配置 开发者工具 1.02.1810190
    permission Object 小程序接口权限相关设置 微信客户端 7.0.0
    style string 指定使用升级后的weui样式 2.8.0
    useExtendedLib Object 指定需要引用的扩展库 2.2.1
    entranceDeclare Object 微信消息用小程序打开 微信客户端 7.0.9
    darkmode boolean 小程序支持 DarkMode 2.11.0
    themeLocation string 指明 theme.json 的位置,darkmode为true为必填 开发者工具 1.03.2004271
    lazyCodeLoading string 配置自定义组件代码按需注入 2.11.1
    singlePage Object 单页模式相关配置 2.12.0
    supportedMaterials Object 聊天素材小程序打开相关配置 2.14.3
    serviceProviderTicket string 定制化型服务商票据
    embeddedAppIdList string[] 半屏小程序 appId 2.20.1
    halfPage Object 视频号直播半屏场景设置 2.18.0
    debugOptions Object 调试相关配置 2.22.1
    enablePassiveEvent Object或boolean touch 事件监听是否为 passive 2.24.1
    resolveAlias Object 自定义模块映射规则
    renderer string 全局默认的渲染后端 2.30.4
    rendererOptions Object 渲染后端选项 2.31.1
    componentFramework string 组件框架,详见相关文档 2.30.4
    miniApp Object 多端模式场景接入身份管理服务时开启小程序授权页相关配置,详见相关文档
    static Object 正常情况下默认所有资源文件都被打包发布到所有平台,可以通过 static 字段配置特定每个目录/文件只能发布到特定的平台(多端场景) 相关文档

1.entryPagePath

  • 1.指定小程序的默认启动路径(首页)
  • 2.常见情景是从微信聊天列表页下拉启动、小程序列表启动等
  • 3.如果不填将默认为pages列表的第一项
  • 4.不支持带页面路径参数

2.pages

小程序开发_第8张图片

{
 "pages": ["pages/index/index", "pages/logs/logs"]
}
  • 1.指定小程序由哪些页面组成,每一项都对应一个页面的路径(含文件名) 信息
  • 2.文件名不需要写文件后缀,框架会自动去寻找对应位置的.json, .js, .wxml, .wxss四个文件进行处理
  • 3.未指定 entryPagePath 时,数组的第一项代表小程序的初始页面(首页)
  • 4.小程序中新增/减少页面,都需要对pages数组进行修改

3.window

属性 类型 默认值 描述 最低版本
navigationBarBackgroundColor HexColor #000000 导航栏背景颜色
navigationBarTextStyle string white 导航栏标题、状态栏颜色,仅支持 black/white
navigationBarTitleText string 导航栏标题文字内容
navigationStyle string default 导航栏样式,仅支持以下值:default默认样式;custom自定义导航栏,只保留右上角胶囊按钮 iOS/Android 微信客户端 6.6.0,Windows 微信客户端不支持
homeButton boolean default 在非首页、非页面栈最底层页面或非tabbar内页面中的导航栏展示home键 微信客户端 8.0.24
backgroundColor HexColor #ffffff 窗口的背景色
backgroundTextStyle string dark 下拉 loading 的样式,仅支持dark/light
backgroundColorTop string #ffffff 顶部窗口的背景色,仅 iOS 支持 微信客户端 6.5.16
backgroundColorBottom string #ffffff 底部窗口的背景色,仅 iOS 支持 微信客户端 6.5.16
enablePullDownRefresh boolean false 是否开启全局的下拉刷新。详见 Page.onPullDownRefresh
onReachBottomDistance number 50 页面上拉触底事件触发时距页面底部距离,单位为 px。详见 Page.onReachBottom
pageOrientation string portrait 屏幕旋转设置,支持 auto / portrait / landscape详见 响应显示区域变化 2.4.0 (auto) / 2.5.0 (landscape)
restartStrategy string homePage 重新启动策略配置 2.8.0
initialRenderingCache string 页面初始渲染缓存配置,支持 static / dynamic 2.11.1
visualEffectInBackground string none 切入系统后台时,隐藏页面内容,保护用户隐私。支持 hidden / none 2.15.0
handleWebviewPreload string static 控制预加载下个页面的时机。支持 static / manual / auto 2.15.0
  • 1.注意
    • 1.HexColor(十六进制颜色值,如#ff00ff
    • 2.用于设置小程序的状态栏、导航条、标题、窗口背景色
    • 3.关于navigationStyle
      • 1.iOS/Android客户端7.0.0以下版本,navigationStyle 只在app.json中生效。
      • 2.iOS/Android客户端6.7.2版本开始,navigationStyle: customweb-view组件无效
      • 3.开启custom后,低版本客户端需做好兼容,开发者工具基础库版本切到1.7.0(不代表最低版本,只供调试用)可方便切到旧视觉
      • 4.Windows客户端3.0及以上版本,为了给用户提供更符合桌面软件的使用体验,统一了小程序窗口的导航栏,navigationStyle: custom不再生效
  • 2.实例
    {
      "window": {
        "navigationBarBackgroundColor": "#ffffff",
        "navigationBarTextStyle": "black",
        "navigationBarTitleText": "微信接口功能演示",
        "backgroundColor": "#eeeeee",
        "backgroundTextStyle": "light"
      }
    }
    
1.restartStrategy
可选值 含义
homePage (默认值)如果从这个页面退出小程序,下次将从首页冷启动
homePageAndLatestPage 如果从这个页面退出小程序,下次冷启动后立刻加载这个页面,页面的参数保持不变(不可用于 tab 页)

tabBar

  • 如果小程序是一个多 tab 应用(客户端窗口的底部或顶部有 tab 栏可以切换页面),可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面
    tabBar
    如果小程序是一个多 tab 应用(客户端窗口的底部或顶部有 tab 栏可以切换页面),可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面。
属性 类型 必填 默认值 描述 最低版本
color HexColor tab 上的文字默认颜色,仅支持十六进制颜色
selectedColor HexColor 是 tab 上的文字选中时的颜色,仅支持十六进制颜色
backgroundColor HexColor 是 tab 的背景色,仅支持十六进制颜色
borderStyle string 否 black tabbar 上边框的颜色, 仅支持 black / white
list Array 是 tab 的列表,详见 list 属性说明,最少 2 个、最多 5 个 tab
position string 否 bottom tabBar 的位置,仅支持 bottom / top
custom boolean 否 false 自定义 tabBar,见详情 2.5.0

2.页面配置

  • 1.每一个小程序页面可使用同名.json文件对本页面的窗口表现进行配置,页面中配置项会覆盖根目录的app.jsonwindow中相同的配置项

小程序运行机制

1.小程序的生命周期

  • 1.小程序从启动到最终被销毁,会经历很多不同的状态,小程序在不同状态下会有不同的表现
    小程序开发_第9张图片

2.小程序启动

  • 1.从用户认知的角度看,广义的小程序启动可以分为两种情况,一种是冷启动,一种是热启动
    • 1.冷启动:如果用户首次打开,或小程序销毁后被用户再次打开,此时小程序需要重新加载启动,即冷启动
    • 2.热启动:如果用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时小程序并未被销毁,只是从后台状态进入前台状态,这个过程就是热启动
  • 2.从小程序生命周期的角度来看,我们一般讲的「启动」专指冷启动,热启动一般被称为后台切前台

3.前台与后台

  • 1.小程序启动后,界面被展示给用户,此时小程序处于「前台」状态。
  • 2.当用户「关闭」小程序时,小程序并没有真正被关闭,而是进入了「后台」状态,此时小程序还可以短暂运行一小段时间,但部分 API 的使用会受到限制。切后台的方式包括但不限于以下几种:
    • 1.点击右上角胶囊按钮离开小程序
    • 2.iOS 从屏幕左侧右滑离开小程序
    • 3.安卓点击返回键离开小程序
    • 4.小程序前台运行时直接把微信切后台(手势或 Home 键)
    • 5.小程序前台运行时直接锁屏
  • 3.当用户再次进入微信并打开小程序,小程序又会重新进入「前台」状态

4.挂起

  • 1.小程序进入「后台」状态一段时间后(目前是 5 秒),微信会停止小程序 JS 线程的执行,小程序进入「挂起」状态。此时小程序的内存状态会被保留,但开发者代码执行会停止,事件和接口回调会在小程序再次进入「前台」时触发。
  • 2.当开发者使用了后台音乐播放、后台地理位置等能力时,小程序可以在「后台」持续运行,不会进入到「挂起」状态

5.小程序销毁

  • 1.如果用户很久没有使用小程序,或者系统资源紧张,小程序会被「销毁」,即完全终止运行。具体而言包括以下几种情形:
    • 1.当小程序进入后台并被「挂起」后,如果很长时间(目前是 30 分钟)都未再次进入前台,小程序会被销毁。
    • 2.当小程序占用系统资源过高,可能会被系统销毁或被微信客户端主动回收。
      • 1.在 iOS 上,当微信客户端在一定时间间隔内连续收到系统内存告警时,会根据一定的策略,主动销毁小程序,并提示用户 「运行内存不足,请重新打开该小程序」。具体策略会持续进行调整优化。
      • 2.建议小程序在必要时使用 wx.onMemoryWarning 监听内存告警事件,进行必要的内存清理
        2.基础库 1.1.0 及以上,1.4.0 以下版本: 当用户从扫一扫、转发等入口(场景值为1007, 1008, 1011, 1025)进入小程序,且没有置顶小程序的情况下退出,小程序会被销毁。

6. 小程序冷启动的页面

  • 小程序冷启动时,打开的页面有以下情况
  • 1.(A 类场景)若启动的场景中不带 path
    基础库 2.8.0 以下版本,进入首页
    基础库 2.8.0 及以上版本遵循「重新启动策略」,可能是首页或上次退出的页面
  • 2.(B 类场景)若启动的场景中带有 path,则启动进入对应 path 的页面

7.重新启动策略

{
 "restartStrategy": "homePage"
}
可选值 含义
homePage (默认值)如果从这个页面退出小程序,下次将从首页冷启动
homePageAndLatestPage 如果从这个页面退出小程序,下次冷启动后立刻加载这个页面,页面的参数保持不变(不可用于 tab 页)
  • 1.小程序冷启动时,如果启动时不带 path(A 类场景),默认情况下将会进入小程序的首页。 在页面对应的 json 文件中(也可以全局配置在 app.json 的 window 段中),指定 restartStrategy 配置项可以改变这个默认的行为,使得从某个页面退出后,下次 A 类场景的冷启动可以回到这个页面
  • 2.注意:即使不配置为 homePage ,小程序如果退出过久(当前默认一天时间,可以使用退出状态来调整),下次冷启动时也将不再遵循 restartStrategy 的配置,而是直接从首页冷启动。
  • 3.无论如何,页面中的状态并不会被保留,如输入框中的文本内容、 checkbox 的勾选状态等都不会还原。如果需要还原或部分还原,需要利用退出状态

8. 小程序热启动的页面

  • 1.小程序热启动时,打开的页面有以下情况
    • (A 类场景)若启动的场景中不带 path,则保留上次的浏览的状态
    • (B 类场景)若启动的场景中带有 path,则 reLaunch 到对应 path 的页面
  • A 类场景常见的有下列场景值
    场景值ID 说明
    1001 发现栏小程序主入口,「最近使用」列表(基础库2.2.4版本起包含「我的小程序」列表)
    1003 星标小程序列表
    1023 系统桌面小图标打开小程序
    1038 从其他小程序返回小程序
    1056 聊天顶部音乐播放器右上角菜单,打开小程序
    1080 客服会话菜单小程序入口,打开小程序
    1083 公众号会话菜单小程序入口 ,打开小程序(只有腾讯客服小程序有)
    1089 聊天主界面下拉,打开小程序/微信聊天主界面下拉,「最近使用」栏(基础库2.2.4版本起包含「我的小程序」栏)
    1090 长按小程序右上角菜单,打开小程序
    1103 发现-小程序主入口我的小程序,打开小程序
    1104 聊天主界面下拉,从我的小程序,打开小程序
    1113 安卓手机负一屏,打开小程序
    1114 安卓手机侧边栏,打开小程序
    1117 后台运行小程序的管理页中,打开小程序

9.退出状态

{
  "restartStrategy": "homePageAndLatestPage"
}

Page({
  onLoad: function() {
    var prevExitState = this.exitState // 尝试获得上一次退出前 onSaveExitState 保存的数据
    if (prevExitState !== undefined) { // 如果是根据 restartStrategy 配置进行的冷启动,就可以获取到
      prevExitState.myDataField === 'myData' 
    }
  },
  onSaveExitState: function() {
    var exitState = { myDataField: 'myData' } // 需要保存的数据
    return {
      data: exitState,
      expireTimeStamp: Date.now() + 24 * 60 * 60 * 1000 // 超时时刻
    }
  }
})

onSaveExitState 返回值可以包含两项:

  • 1.基础库 2.7.4 开始支持,低版本需做兼容处理。
  • 2.每当小程序可能被销毁之前,页面回调函数 onSaveExitState 会被调用。如果想保留页面中的状态,可以在这个回调函数中“保存”一些数据,下次启动时可以通过 exitState 获得这些已保存数据
    字段名 类型 含义
    data Any 需要保存的数据(只能是 JSON 兼容的数据)
    expireTimeStamp Number 超时时刻,在这个时刻后,保存的数据保证一定被丢弃,默认为 (当前时刻 + 1 天)

WXML

  • 1.WXML(WeiXin Markup Language):微信小程序框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构

1.数据绑定

  • 1.数据绑定使用Mustache语法(双大括号)将变量包起来,为了使用户界面与业务数据(内容)分离
  • 2.WXML 中的动态数据均来自对应 Pagedata
  • 3.注意
    • 1.如果双大括号是作用于标签内部(属性)则需要带上双引号
    • 2.如果是作用于两个标签内部则不需要带上双引号
  • 4.数据绑定可以作用于以下几种类型

1.内容


<view> {{message}} view>
// page.js
Page({
 data: {
   message: 'Hello MINA!'
 }
})

2.组件属性

<view id="item-{{id}}"> view>
Page({
 data: {
   id: 0
 }
})
  • 注意:双大括号需要在双引号之内

3.控制属性

<view wx:if="{{condition}}"> view>
Page({
 data: {
   condition: true
 }
})
  • 注意:双大括号需要在双引号之内

4.关键字

  • 1.trueboolean 类型的 true,代表真值
  • 2.falseboolean 类型的 false,代表假值
    <checkbox checked="{{false}}"> checkbox>
    
  • 注意:
    • 1.关键字需要在双引号之内
    • 2.不要直接写checked="false",其计算结果是一个字符串,转成boolean类型后代表真值

5.运算

  • 1.在 {{}} 可以内进行简单的运算,支持的有如下几种方式
1.三元运算
<view hidden="{{flag ? true : false}}"> Hidden view>
2.算数运算

<view> {{a + b}} + {{c}} + d view>
Page({
 data: {
   a: 1,
   b: 2,
   c: 3
 }
})

6.逻辑判断

<view wx:if="{{length > 5}}"> view>

7.字符串运算

<view>{{"hello" + name}}view>
Page({
 data:{
   name: 'MINA'
 }
})

8.数据路径运算

<view>{{object.key}} {{array[0]}}view>
Page({
 data: {
   object: {
     key: 'Hello '
   },
   array: ['MINA']
 }
})

9.组合

  • 1.可以在Mustache(双大括号)内直接进行组合,构成新的对象或数组
1.数组

<view wx:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} view>
Page({
 data: {
   zero: 0
 }
})
2.对象

<template is="objectCombine" data="{{for: a, bar: b}}">template>



<template is="objectCombine" data="{{...obj1, ...obj2, e: 5}}">template>



<template is="objectCombine" data="{{foo, bar}}">template>
Page({
 data: {
   a: 1,
   b: 2
 }
})
// 用扩展运算符 ... 来将一个对象展开
Page({
 data: {
   obj1: {
     a: 1,
     b: 2
   },
   obj2: {
     c: 3,
     d: 4
   }
 }
})
// 如果对象的 key 和 value 相同,也可以间接地表达
Page({
 data: {
   foo: 'my-foo',
   bar: 'my-bar'
 }
})

2.列表渲染

1.wx:for

<view wx:for="{{array}}">
 {{index}}: {{item.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>


<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
 {{idx}}: {{itemName.message}}
view>
Page({
 data: {
   array: [{
     message: 'foo',
   }, {
     message: 'bar'
   }]
 }
})
  • 1.组件上使用wx:for控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件,同时wx:for也可以嵌套
  • 2.默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item
  • 3.使用wx:for-item可以指定数组当前元素的变量名
  • 4.使用wx:for-index可以指定数组当前下标的变量名

2.block wx:for

<block wx:for="{{[1, 2, 3]}}">
 <view> {{index}}: view>
 <view> {{item}} view>
block>
  • 1.wx:for可以用在标签上,以渲染一个包含多节点的结构块

3.wx:key

<switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} switch>
<button bindtap="switch"> Switch button>
<button bindtap="addToFront"> Add to the front button>

<switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;"> {{item}} switch>
<button bindtap="addNumberToFront"> Add to the front button>
Page({
 data: {
   objectArray: [
     {id: 2, unique: 'unique_2'},
     {id: 1, unique: 'unique_1'},
     {id: 0, unique: 'unique_0'},
   ],
   numberArray: [1, 2, 3, 4]
 },
 switch: function(e) {
   const length = this.data.objectArray.length
   for (let i = 0; i < length; ++i) {
     const x = Math.floor(Math.random() * length)
     const y = Math.floor(Math.random() * length)
     const temp = this.data.objectArray[x]
     this.data.objectArray[x] = this.data.objectArray[y]
     this.data.objectArray[y] = temp
   }
   this.setData({
     objectArray: this.data.objectArray
   })
 },
 addToFront: function(e) {
   const length = this.data.objectArray.length
   this.data.objectArray = [{id: length, unique: 'unique_' + length}].concat(this.data.objectArray)
   this.setData({
     objectArray: this.data.objectArray
   })
 },
 addNumberToFront: function(e){
   this.data.numberArray = [ this.data.numberArray.length + 1 ].concat(this.data.numberArray)
   this.setData({
     numberArray: this.data.numberArray
   })
 }
})
  • 1.如果列表中项目的位置会动态改变或有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 input中的输入内容,switch的选中状态),需要使用wx:key 指定列表中项目的唯一的标识符
  • 2.当数据改变触发渲染层重新渲染的时候,会校正带有 key的组件,框架会确保它们被重新排序而不是重新创建,以确保使组件保持自身的状态并且提高列表渲染时的效率
  • 3.wx:key的值以两种形式提供
    • 1.字符串:代表在for循环的arrayitem的某个 property,该property的值需要是列表中唯一的字符串或数字,且不能动态改变
    • 2.保留关键字*this:代表在for循环中的item本身,这种表示需要item本身是一个唯一的字符串或数字
  • 4.如不提供wx:key会报一个warning, 如果明确知道该列表是静态或不必关注其顺序则可以选择忽略
    在这里插入图片描述

4.注意

  • 1.花括号和引号之间如果有空格,将最终被解析成为字符串
    <view wx:for="{{[1,2,3]}} ">
    {{item}}
    view>
    
    <view wx:for="{{[1,2,3] + ' '}}">
    {{item}}
    view>
    
  • 2.当wx:for的值为字符串时,会将字符串解析成字符串数组
    <view wx:for="array">
      {{item}}
    view>
    
    <view wx:for="{{['a','r','r','a','y']}}">
      {{item}}
    view>
    

3.条件渲染

1.wx:if

<view wx:if="{{condition}}"> True view>

<view wx:if="{{length > 5}}"> 1 view>
<view wx:elif="{{length > 2}}"> 2 view>
<view wx:else> 3 view>
  • 1.使用wx:if=""来判断是否需要渲染该代码块

2.block wx:if

<block wx:if="{{true}}">
 <view> view1 view>
 <view> view2 view>
block>
  • 1.因为wx:if是一个控制属性,需要将它添加到一个标签上
  • 2.如果要一次性判断多个组件标签,可以使用一个 标签将多个组件包装起来,并在上边使用wx:if控制属性
  • 3.注意: 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性

3.wx:if 区别 hidden

  • 1.wx:if
    • 1.因为wx:if之中的模板可能包含数据绑定,所以当wx:if 的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染
    • 2.同时wx:if是惰性的,如果初始渲染条件为false,框架什么也不做,在条件第一次为真时才开始局部渲染
  • 2.hidden
    • 1.hidden组件始终会被渲染,只是简单的控制显示与隐
  • 3.总结:
    • 1.wx:if有更高的切换消耗
    • 2.hidden有更高的初始渲染消耗
    • 3.因此如果需要频繁切换的情景下用 hidden 更好,如果运行时条件不大可能改变则wx:if较好

4.模板

  • 1.WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用

1.定义模板


<template name="msgItem">
 <view>
   <text> {{index}}: {{msg}} text>
   <text> Time: {{time}} text>
 view>
template>

2.使用模板

<template is="msgItem" data="{{...item}}"/>
Page({
 data: {
   item: {
     index: 0,
     msg: 'this is a template',
     time: '2016-09-15'
   }
 }
})

在这里插入图片描述

3.动态模板

<template name="odd">
 <view> odd view>
template>
<template name="even">
 <view> even view>
template>

<block wx:for="{{[1, 2, 3, 4, 5]}}">
 <template is="{{item % 2 == 0 ? 'even' : 'odd'}}"/>
block>
  • 1.templateis属性可以使用Mustache语法,来动态决定具体需要渲染哪个模板
  • 2.注意需要带上双引号

4.模板的作用域

  • 1.模板拥有自己的作用域,只能使用data传入的数据以及模板定义文件中定义的模块

5.引用

  • 1.WXML提供两种文件引用方式importinclude

1.import


<template name="item">
 <text>{{text}}text>
template>

<import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/>
  • 1.import可以在该文件中使用目标文件定义的template
1.import 的作用域


<template name="A">
 <text> A template text>
template>

<import src="a.wxml"/>
<template name="B">
 <text> B template text>
template>

<import src="b.wxml"/>
<template is="A"/>  
<template is="B"/>
  • 1.import有作用域的概念,即只会import目标文件中定义的template,而不会 import目标文件importtemplate

2.include


<include src="header.wxml"/>
<view> body view>
<include src="footer.wxml"/>


<view> header view>


<view> footer view>
  • 1.include可以将目标文件除了