image.png

微信开发者工具下载地址
小程序开发平台

设置外观和代理

外观

image.png

代理

image.png

项目结构

主要目录

  1. pages:存放所有小程序的页面
  2. utils:存放工具性质的模块(例如:格式化时间的自定义模块)
  3. app.js:小程序项目的入口文件
  4. app.json:小程序项目的全局配置文件
  5. app.wxss:小程序项目的全局样式文件(在此文件内写入的样式会被全局生效
  6. project.config.json:项目配置文件
  7. sitemap.json:配置小程序及其页面是否允许被微信索引

    pages目录

    小程序官方建议将所有小程序的页面,都存放在pages目录中,以单独的文件夹存在
    其中,每个页面由4个基本文件组成:

  8. .js文件(页面的脚本文件,存放页面的数据、事件处理函数等)

  9. .json文件(当前页面的配置文件,配置窗口的外观、表现等)
  10. .wxml文件(页面的模板结构文件)
  11. .wxss文件(当前页面的样式表文件)

    JSON配置文件

    通过不同的.json配置文件,可以对小程序项目进行不同级别的配置

  12. 根目录中的app.json配置文件

  13. 根目录中的project.config.json配置文件
  14. 根目录中的sitemap.json配置文件
  15. 每个页面文件夹中的.json配置文件

    app.json

    小程序的全局配置,包括小程序的所有页面路径、窗口外观、界面表现、底部tab等
  • "pages":小程序所有页面的路径
  • "window":全局定义小程序所有页面的背景色、文字颜色等
  • "tabBar":全局定义小程序底部的 tab 栏
  • "style":全局定义小程序组件所使用的样式版本
  • "sitemapLocation":用来指明 sitemap.json 的位置

    1. {
    2. "pages":[
    3. "pages/index/index",
    4. "pages/logs/logs"
    5. ],
    6. "window":{
    7. "backgroundTextStyle":"light",
    8. "navigationBarBackgroundColor": "#fff",
    9. "navigationBarTitleText": "Weixin",
    10. "navigationBarTextStyle":"black"
    11. },
    12. "tabBar": {
    13. "list": [
    14. {
    15. "pagePath": "pages/index/index",
    16. "text": "首页"
    17. }
    18. ]
    19. },
    20. "style": "v2",
    21. "sitemapLocation": "sitemap.json"
    22. }

    project.config.json

    项目配置文件,用来记录我们对小程序开发工具所做的个性化配置

  • setting:编译相关的配置

  • projectname:项目名称
  • appid:账号ID

    sitemap.json

    配置小程序页面是否允许微信索引

  • page:所有页面都能被索引

  • action:是否允许被索引(allow为允许,disallow为不允许)

image.png
注:sitemap的索引提示是默认开启的,如需关闭sitemap的索引提示,在小程序项目配置文件project.config.jsonsetting中配置字段checkSiteMapfalse
image.png

页面的.json配置文件

  1. 小程序中每个页面都可以使用`.json`文件来对本页面的窗口外观进行配置,页面中的配置项会覆盖`app.json``window`中相同的配置项<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652183462583-da886fdb-3eb6-4344-85ba-84ffa067b274.png#clientId=ud1b63a6a-c9a2-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=432&id=ud1184ccc&margin=%5Bobject%20Object%5D&name=image.png&originHeight=432&originWidth=789&originalType=binary&ratio=1&rotation=0&showTitle=false&size=35754&status=done&style=stroke&taskId=u2950efa8-8f21-4f0b-9f40-5ffdcf18fb1&title=&width=789)

新建小程序页面

只需在app.json中的pages节点中新增页面的存放路径,小程序开发者工具会帮我们自动创建对应的页面文件
image.png

WXML模板

什么是 WXML

WXML是小程序框架设计的一套标签语言,用来构建小程序页面的结构,作用类似于网页开发中的 HTML

WXML 和 HTML 的区别

  1. 标签名称不同
    1. HTML(div,span,img,a)
    2. WXML(view,text,image,navigator)
  2. 属性节点不同
    1. <a href="#">超链接</a>
    2. <navigator url="/pages/home/home">超链接</navigator>
  3. 提供了类似于 Vue 中的模板语法

    1. 数据绑定
    2. 列表渲染
    3. 条件渲染

      WXSS样式

      什么是WXSS

      WXSS是一套样式语言,用于描述 WXML 的组件样式,类似于网页开发中的 CSS

      WXSS 和 CSS 的区别

  4. 新增了rpx尺寸单位

    1. CSS 中需要手动进行像素单位换算,例如 rem
    2. WXSS 在底层支持新的尺寸单位rpx,在不同大小的屏幕上小程序会自动进行换算
  5. 提供了全局的样式和局部样式
    1. 项目根目录中的app.wxss会作用域所有小程序页面
    2. 局部页面的.wxss样式仅对当前页面生效
  6. WXSS 仅支持部分 CSS 选择器

    1. .class#id
    2. element
    3. 并集选择器、后代选择器
    4. ::afther::before等伪类选择器

      JS 逻辑交互

      .js 文件的分类

  7. app.js

    1. 整个小程序项目的入口文件,通过调用 App() 函数来启动整个小程序
  8. 页面的 .js 文件
    1. 页面的入口文件,通过调用 Page() 函数来创建并运行页面
  9. 普通的 .js 文件

    1. 普通的功能模块文件,用来封装公共的函数或属性供页面使用

      宿主环境

      程序的宿主环境

      程序运行所必须依赖的环境
      Android 系统iOS 系统是两个不同的宿主环境
      脱离了宿主环境的软件是没有任何意义的
      image.png

      小程序的宿主环境

      image.png

      通信模型

  10. 主体:渲染层和逻辑层

    1. WXML 模板和 WXSS 样式工作在渲染层
    2. JS 脚本工作在逻辑层

image.png

  1. 通信
    1. 渲染层和逻辑层之间的通信
      1. 由微信客户端进行转发
    2. 逻辑层和第三方服务器之间的通信
      1. 由微信客户端进行转发

image.png

运行机制

  1. 启动过程
    1. 把小程序的代码包下载到本地
    2. 解析 app.json全局配置文件
    3. 执行app.js小程序入口文件,调用 App()创建小程序实例
    4. 渲染小程序首页
    5. 小程序启动完成
  2. 渲染过程

    1. 加载解析页面的 .json配置文件
    2. 加载页面的.wxml模板和.wxss样式
    3. 执行页面的.js文件,调用Page()创建页面实例
    4. 页面渲染完成

      组件

      视图容器

  3. view

    1. 普通视图区域
    2. 类似于 HTML 中的 div,是一个块级元素
  4. scroll-view
    1. 可滚动的视图区域
    2. 常用来实现滚动列表效果
  5. swiperswiper-item

    1. 轮播图容器组件 和 轮播图 item 组件

      基础内容

  6. text:文本组件

    1. 类似于 HTML 中的 span 标签,是个行内元素
  7. rich-text:富文本组件
    1. 支持把 HTML 字符串渲染为 WXML 结构
  8. button:按钮组件
    1. 功能比 HTML 中的 button 按钮丰富
    2. 通过 open-type属性可以调用微信提供的各种功能(客服、转发、获取用户授权、获取用户信息等)
  9. image:图片组件
    1. 默认宽度约 300px、高度约240px

      表单组件导航组件媒体组件map 地图组件canvas 画布组件开放能力无障碍访问

      API

      概述:通过小程序 API,可以方便的调用微信提供的能力

      事件监听 API

  • 特点:以on开头,用来监听某些事件的触发
  • 举例:wx.onWindowResize(function callback)监听窗口尺寸变化的事件

    同步 API

  • 特点1:以Sync结尾的 API 都是同步 API

  • 特点2:同步 API 的执行结果,可以通过函数返回值直接获取,如果执行出错会抛出异常
  • 举例:wx.setStorageSync('key','value')向本地存储中写入内容

    异步 API

  • 特点:类似于 Jquery 中的 $.ajax(options)函数,需要通过 successfailcomplete 接收调用的结果

  • 举例:wx.request()发起网络数据请求,通过 success 回调函数接收数据

    组件

    view

    view组件基本使用

  • 实现 flex 横向布局效果:

  • 更多属性请查阅相关文档:view文档链接 ```html // about.wxml A B C

// about.wxss

  1. - 效果图如下所示:
  2. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652190974052-54ae671e-44bb-42b8-9d60-49fe2c213344.png#clientId=u632ea260-7ee1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=184&id=u28e6bf39&margin=%5Bobject%20Object%5D&name=image.png&originHeight=184&originWidth=375&originalType=binary&ratio=1&rotation=0&showTitle=false&size=6047&status=done&style=stroke&taskId=ufee76354-3497-4f49-a9dd-aac8fdc1f65&title=&width=375)
  3. <a name="b1MLd"></a>
  4. ## scroll-view
  5. <a name="hO0nL"></a>
  6. ### scroll-view 组件基本使用
  7. - 实现纵向滚动效果:
  8. - 更多属性请查阅相关文档:[scroll-view文档链接](https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html)
  9. ```html
  10. // scroll.wxml
  11. <scroll-view class="container1" scroll-y>
  12. <view>A</view>
  13. <view>B</view>
  14. <view>C</view>
  15. </scroll-view>
  16. // scroll.wxss
  17. <style> // 使用时要将 style 标签去掉
  18. .container1 view {
  19. width: 100px;
  20. height: 100px;
  21. text-align: center;
  22. line-height: 100px;
  23. }
  24. .container1 view:nth-child(1) {
  25. background-color: lightgreen;
  26. }
  27. .container1 view:nth-child(2) {
  28. background-color: lightskyblue;
  29. }
  30. .container1 view:nth-child(3) {
  31. background-color: lightcoral;
  32. }
  33. .container1 {
  34. border: 1px solid #000;
  35. height: 120px;
  36. width: 100px;
  37. }
  38. </style>
  • 效果图如下所示:

image.png

swiper 和 swiper-item

swiper 和 swiper-item 组件的基本使用

// swiper.wxss

  1. - 效果图如下所示:
  2. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652192447047-a21e2a40-b59a-4ef8-9711-9ec59d6258ee.png#clientId=u632ea260-7ee1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=247&id=u2eca5876&margin=%5Bobject%20Object%5D&name=image.png&originHeight=247&originWidth=375&originalType=binary&ratio=1&rotation=0&showTitle=false&size=6202&status=done&style=stroke&taskId=u1159fd36-c625-4e14-b802-2ec6c4a57ee&title=&width=375)
  3. - `swiper`组件的常用属性
  4. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652192952035-1d39da4b-7158-44f0-9cca-14268bb90fec.png#clientId=u632ea260-7ee1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=382&id=u173e92bc&margin=%5Bobject%20Object%5D&name=image.png&originHeight=382&originWidth=990&originalType=binary&ratio=1&rotation=0&showTitle=false&size=128482&status=done&style=stroke&taskId=u228365f3-f6cd-4847-8ad6-f142e2d73c1&title=&width=990)
  5. <a name="mOMJd"></a>
  6. ## text
  7. <a name="AP6Tx"></a>
  8. ### text 组件基本使用
  9. - `selectable`:实现长按文本选中文本内容的效果
  10. - `user-select`:实现长按文本选中,该属性会将文本显示为`inline-block`效果
  11. - 更多属性请查阅相关文档:[text文档链接](https://developers.weixin.qq.com/miniprogram/dev/component/text.html)
  12. ```html
  13. <view>
  14. 手机号支持长按选中效果
  15. <text selectable>18888888888</text>
  16. <text user-select>我会在手机号后面显示</text>
  17. </view>

rich-text

rich-text 组件基本使用

  • nodes:将该属性节点内的内容渲染为 HTML 元素
  • 更多属性请查阅相关文档:rich-text文档链接 ```html // richText.wxml

// richText.wxss .aqua { color: aqua; }

  1. - 最终效果如下所示:
  2. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652237902136-58d51ba1-6c61-4ad7-a90d-361c0705c52a.png#clientId=u05a5e54a-a5d9-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=176&id=ua6aef54b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=176&originWidth=373&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9613&status=done&style=stroke&taskId=u3dd11d60-cd15-4c31-8048-e01807b3189&title=&width=373)
  3. <a name="qkTMt"></a>
  4. ## button
  5. - `type`:设置按钮类型样式
  6. - `size`:设置按钮大小样式
  7. - `plain`:设置按钮背景色是否透明(默认不透明)
  8. - `disabled`:是否禁用按钮
  9. - `loading`:是否在按钮名称前带上 loading 图标
  10. - 更多属性请查阅相关文档:[button文档链接](https://developers.weixin.qq.com/miniprogram/dev/component/button.html)
  11. ```html
  12. // button.wxml
  13. <!-- type属性使用 -->
  14. <button>默认按钮</button>
  15. <button type="primary">绿色按钮</button>
  16. <button type="default">白色按钮</button>
  17. <button type="warn">红色按钮</button>
  18. <!-- size属性使用 -->
  19. <button type="primary" size="mini">绿色按钮</button>
  20. <button type="default" size="mini">白色按钮</button>
  21. <button type="warn" size="mini">红色按钮</button>
  22. <!-- plain属性使用 -->
  23. <button plain type="primary">绿色按钮</button>
  24. <button plain type="default">白色按钮</button>
  25. <button plain type="warn">红色按钮</button>
  26. <!-- disabled属性使用 -->
  27. <button type="primary" disabled>绿色按钮</button>
  28. <!-- loading属性使用 -->
  29. <button type="primary" loading></button>

最终效果如下所示:
image.png

image

注意:image元素默认宽高为width: 320px; height: 240px; 标签中即使没有 src 路径或 src路径下没有内容,宽高依旧不改变

  • src:图片路径,/默认表示项目根目录
  • mode:指定图片的剪裁模式和缩放模式
    • 缩放模式:
      • scaleToFill(默认值):不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素
      • aspectFit:保持纵横比缩放图片,完全展示图片的长边,会完整地将图片显示出来
      • aspectFill:保持纵横比缩放图片,完全展示图片的短边,会使图片有一定的裁剪
      • widthFix:宽度不变,高度自动变化,保持原图宽高比不变
      • heightFix:高度不变,宽度自动变化,保持原图宽高比不变
    • 剪裁模式:不缩放图片
      • top:只显示图片的顶部区域
      • bottom:只显示图片的底部区域
      • center:只显示图片的中间区域
      • left:只显示图片的左边区域
      • right:只显示图片的右边区域
      • top left:只显示图片的左上区域
      • top right:只显示图片的右上区域
      • bottom left:只显示图片的左下区域
      • bottom right:只显示图片的右下区域
  • lazy-load:图片懒加载,在即将进入一定范围(上下三屏)时才开始加载
  • show-menu-by-longpress:长按图片显示发送给朋友、收藏、保存图片、搜一搜、打开名片/前往群聊/打开小程序(若图片中包含对应二维码或小程序码)的菜单
  • 更多属性请查阅相关文档:image文档链接 ```html微信小程序开发 - 图14
微信小程序开发 - 图15 微信小程序开发 - 图16 微信小程序开发 - 图17 微信小程序开发 - 图18 效果如下图所示:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255399538-924e7385-3886-4248-a05d-db642d94dd8a.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=313&id=u814ebae6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=625&originWidth=439&originalType=binary&ratio=1&rotation=0&showTitle=false&size=212770&status=done&style=stroke&taskId=ufcf4182b-e02a-4e9b-8532-e23c4406c65&title=&width=220)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255454531-33094e92-c867-4367-8027-99c8f10ada0f.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=283&id=u184a1ae1&margin=%5Bobject%20Object%5D&name=image.png&originHeight=565&originWidth=423&originalType=binary&ratio=1&rotation=0&showTitle=false&size=205545&status=done&style=stroke&taskId=ue24d393f-1d47-4101-98c4-7ae84c5525e&title=&width=212)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255507983-9b76dad5-970e-487f-864a-83292ccca155.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=348&id=u8a2e2396&margin=%5Bobject%20Object%5D&name=image.png&originHeight=694&originWidth=429&originalType=binary&ratio=1&rotation=0&showTitle=false&size=280496&status=done&style=stroke&taskId=u63bf9487-56df-406e-9f31-6430f630be2&title=&width=215)html 微信小程序开发 - 图19 微信小程序开发 - 图20 微信小程序开发 - 图21 微信小程序开发 - 图22 微信小程序开发 - 图23 微信小程序开发 - 图24 微信小程序开发 - 图25 微信小程序开发 - 图26 微信小程序开发 - 图27 效果如下图所示:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255802055-b8547918-4540-49cd-85be-047b18b1b115.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=376&id=ua9eb258e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=691&originWidth=419&originalType=binary&ratio=1&rotation=0&showTitle=false&size=88786&status=done&style=stroke&taskId=u4db21cbb-7d97-4fff-92a3-e1aa086db5e&title=&width=228)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255872754-13175715-6760-4e78-9b70-5d0b8093cdfd.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=374&id=u9cec270f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=695&originWidth=424&originalType=binary&ratio=1&rotation=0&showTitle=false&size=211966&status=done&style=stroke&taskId=ude977d5c-e3df-4817-80e2-a64463b50a6&title=&width=228)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255934170-3ee84102-a330-48b7-aecc-f675fc66a874.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=371&id=ube989ed6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=693&originWidth=422&originalType=binary&ratio=1&rotation=0&showTitle=false&size=215528&status=done&style=stroke&taskId=u429ff4f3-f2dc-4012-ad8a-7c125df3ade&title=&width=226)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652255998119-c078de6c-065c-4b1a-9628-919a7462061b.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=550&id=u56319da9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=692&originWidth=425&originalType=binary&ratio=1&rotation=0&showTitle=false&size=261884&status=done&style=stroke&taskId=u75950056-086f-4797-915b-018990b33c7&title=&width=338)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652256051513-cfab36fe-4661-4e9e-b277-48b2f8eea469.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=553&id=ue1c4eb87&margin=%5Bobject%20Object%5D&name=image.png&originHeight=692&originWidth=423&originalType=binary&ratio=1&rotation=0&showTitle=false&size=248555&status=done&style=stroke&taskId=uc7a9dbf5-4bfc-4d5f-922b-0614a25fd29&title=&width=338)html 微信小程序开发 - 图28 ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652256281683-c14db025-6ff4-4f92-a315-ba14884bb8ec.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=557&id=u5125a32b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=742&originWidth=420&originalType=binary&ratio=1&rotation=0&showTitle=false&size=101931&status=done&style=stroke&taskId=u0545740c-ee83-46e6-9d8e-f1255ee7651&title=&width=315) <a name="WPvfq"></a> # WXML模板 <a name="rgrIN"></a> ## 数据绑定 <a name="FRk2T"></a> ### 基本原则 1. 在 data 中定义数据javascript Page({ data: { // 字符串类型 info: ‘init data’, imgSrc: “https://s.cn.bing.net/th?id=OIP-C.nRlAFygdctTCHmIWN7GxRwHaEK&w=333&h=187&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2“, randomNum1: Math.random() * 10, randomNum2: Math.random().toFixed(2) } }) 2. 在 WXML 中使用数据html {{ init }} 微信小程序开发 - 图29 {{ randomNum >= 5 ? ‘随机数大于或等于5’ : ‘随机数小于5’ }} 生成100以内的随机数: {{ randomNum2 100 }} 最终效果如下所示:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652274508094-a8cba32d-0d13-48df-8622-2c7a49ccbcd1.png#clientId=uc52462ba-3e6b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=381&id=ud5f06901&margin=%5Bobject%20Object%5D&name=image.png&originHeight=381&originWidth=416&originalType=binary&ratio=1&rotation=0&showTitle=false&size=101639&status=done&style=none&taskId=u2d281747-3f5e-496d-91b8-d10fc4e44cc&title=&width=416) <a name="i1Kkm"></a> ## 事件绑定 - 定义:在`.js`文件中的`Page()`函数中 - 绑定:在`element`中绑定事件 <a name="cjOBM"></a> ### 常用事件 | 类型 | 绑定方式 | 事件描述 | | --- | --- | --- | | `tap` | bindtap 或 bind:tap | 手指触摸后马上离开,类似于 HTML 的 click 事件 | | `input` | bindinput 或 bind:input | 文本框的输入事件 | | `change` | bindchange 或 bind:change | 状态改变时触发 | <a name="dp80f"></a> #### bindtap 语法格式 1. 通过`bindtap`可以为组件绑定`tap`触摸事件,语法如下:html 2. 在页面的`.js`文件中定义对应的事件处理函数,事件参数通过形参`event(简写:e)`来接收:javascript btnTapHandler(e) { // 按钮的 tap 事件处理函数 console.log(e) // 事件参数对象 e } 结果如下所示:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652318677026-22266d5f-04cb-4935-b7a1-c41c09d03803.png#clientId=u0e7d81c7-fdd3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=201&id=uf8fd4838&margin=%5Bobject%20Object%5D&name=image.png&originHeight=201&originWidth=735&originalType=binary&ratio=1&rotation=0&showTitle=false&size=22436&status=done&style=shadow&taskId=u625f6cc0-6516-4402-b496-06c5da1ea0c&title=&width=735) <a name="nNj1z"></a> #### bindinput 语法格式 1. 通过`bindinput`为文本框绑定**输入**事件:html 2. 在页面的`.js`中定义事件处理函数:javascript inputHandler(e) { console.log(e.detail.value) }, > `e.detail.value`获取 input 框的最新值 结果如下所示:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652318699240-357d9ac4-79e7-4521-ab62-18b20bb8a2c7.png#clientId=u0e7d81c7-fdd3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=43&id=u5e343148&margin=%5Bobject%20Object%5D&name=image.png&originHeight=43&originWidth=415&originalType=binary&ratio=1&rotation=0&showTitle=false&size=901&status=done&style=shadow&taskId=uab4f807f-dd4a-4be9-a0c2-f518c31444d&title=&width=415)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652318706562-4f2e9367-8ef9-4126-8b97-80fa503de506.png#clientId=u0e7d81c7-fdd3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=81&id=u675c2bd5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=81&originWidth=398&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1016&status=done&style=shadow&taskId=u129b8052-6af8-488e-a790-fc3a87823c7&title=&width=398) <a name="TykVI"></a> #### bindinput 实现 v-model 效果html {{ msg }} ```javascript Page({ data: { msg: 'Hello World!' }, inputModel(e) { this.setData({ msg: e.detail.value }) }, }) image.pngimage.png ### 事件对象属性 | 属性 | 类型 | 说明 | | —- | —- | —- | | type | String | 事件类型 | | timeStamp | Integer | 页面打开到触发事件所经过的毫秒数 | | target | Object | 触发事件的组件的一些属性值集合 | | currentTarget | Object | 当前组件的一些属性值合集 | | detail | Object | 额外的信息 | | touches | Array | 触摸事件,当前停留在屏幕中的触摸点信息的数组 | | changedTouches | Array | 触摸事件,当前变化的触摸点信息的数组 | #### targetcurrentTarget的区别 - e.target指向的是触发事件的源头组件,因此,e.target是内部的按钮组件 - e.currentTarget指向的是当前正在触发事件的组件,因此,e.currentTarget是当前源头组件最外部的组件 ### 数据赋值 this.setData() - 使用this.setData()方法,给 Data 中的数据重新赋值 html <view>count值:{{count}}</view> <button type="primary" bindtap="changeCount">Count++</button> javascript changeCount() { this.setData({ count: this.data.count + 1 }) } > 用this.data拿到 Page()中的 data对象 ### 事件传参 - 传递参数:使用`data-=”{{value}}”给事件传参,表示参数名,value表示参数值 - **获取参数值**:使用e.target.dataset,获取事件传递过来的参数值,一般来说是个对象,使用e.target.dataset.info获取指定的参数值 ```html <button type="primary" bindtap="btnTapHandler1" data-info="{{3}}">事件传参</button> ``` ```javascript btnTapHandler1(e) { // 获取的是参数对象 console.log(e.target.dataset); // 获取的是具体的参数值,info 为传来的参数名 console.log(e.target.dataset.info); }, ``` <a name="t7eZO"></a> ## 条件渲染 <a name="t87fu"></a> ### wx:if、wx:elif、wx:else(属性) ```html <view wx:if="{{num >= 95}}">学霸</view> <view wx:elif="{{num >= 90}}">优等生</view> <view wx:elif="{{num >= 60}}">普通生</view> <view wx:else>学渣</view> ``` ```javascript data: { num: 99 }, ``` <a name="AOu3Z"></a> ### block 标签(组件) - 作用:类似 Vue 中的template标签,只用来包裹 ```html <block wx:if="{{true}}"> <view>为 true 显示我</view> <view>为 true 显示我</view> </block> ``` ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652322275327-890f79e3-9ea1-4837-92a8-296cdd09db91.png#clientId=u0e7d81c7-fdd3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=140&id=u28440f93&margin=%5Bobject%20Object%5D&name=image.png&originHeight=187&originWidth=420&originalType=binary&ratio=1&rotation=0&showTitle=false&size=12571&status=done&style=shadow&taskId=uc56bd316-5f62-406b-a534-073c1309ec6&title=&width=315)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652322246905-e21eaf9e-a18b-43fd-b280-491e8a23e323.png#clientId=u0e7d81c7-fdd3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=138&id=u6f96d34d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=155&originWidth=367&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7294&status=done&style=shadow&taskId=ubcfdba12-49a0-47a6-b2d3-01697d546a0&title=&width=327) > 真实渲染时,block标签并不会渲染到页面中 <a name="wYnoo"></a> ### hidden(属性) - 作用:使用display: none;来控制元素的 **显示** 和 **隐藏**,true为**显示**,false`为*隐藏 html <view hidden="{{ false }}">为 true 隐藏我,为 false 显示我</view> image.pngimage.png ## 列表渲染 ### wx:for、wx:for-index、wx:for-item - wx:for-index:指定 index索引的名字 - wx:for-item:指定item值的名字 ```html index:{{idx}},value:{{itemName}}

// cycle.js Page({ data: { arr: [‘iPhone’, ‘HUAWEI’, ‘vivo’] } })

  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652323381802-1ef13aa2-046c-4962-90b7-c630598b62f2.png#clientId=u0e7d81c7-fdd3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=148&id=u22f0090f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=148&originWidth=422&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9447&status=done&style=shadow&taskId=ueb36475b-2c23-4977-aac9-8978d869fea&title=&width=422)
  2. <a name="ucub6"></a>
  3. # WXSS
  4. <a name="Um8lZ"></a>
  5. ## 特性:
  6. 1. `rpx`尺寸单位
  7. 1. `@import`样式导入
  8. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22832478/1652324109219-530ea845-6c3f-48fb-9572-18c59bf23a89.png#clientId=u02bd2a5a-3a4f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=254&id=uccdb2c46&margin=%5Bobject%20Object%5D&name=image.png&originHeight=279&originWidth=422&originalType=binary&ratio=1&rotation=0&showTitle=false&size=57603&status=done&style=shadow&taskId=u5b3e80a5-c389-4b9b-a15d-2a041ff6d57&title=&width=383.63635532126955)
  9. <a name="fn8YN"></a>
  10. ## rpx尺寸单位
  11. <a name="GzG0C"></a>
  12. ### 了解
  13. - `rpx`是小程序独有的,用来**解决屏幕适配的尺寸单位**
  14. <a name="FGlMZ"></a>
  15. ### 实现原理
  16. - 鉴于不同设备屏幕的大小不同,为了实现屏幕的自动适配,**rpx** 把所有设备的屏幕在宽度上**等分为 750 份**(即:当前屏幕的总宽度为 **750rpx**)
  17. - 小设备上,1rpx 代表的宽度就小
  18. - 大设备上,1rpx 代表的宽度就大
  19. - 小程序在不同的设备中运行时,会自动将 rpx 单位换算为 px 单位进行渲染,从而实现屏幕适配
  20. <a name="TTTdR"></a>
  21. ## @import (样式导入)
  22. - `@import` 后跟需要导入的外联样式表的相对路径,用 `;` 表示语句结束
  23. ```html
  24. // Pages/index/index.wxml
  25. <view wx:for="{{userList}}" wx:key="id" class="username">
  26. id:{{item.id}} --- value:{{item.name}}
  27. </view>
  28. // common/common.wxss
  29. .username {
  30. color: aqua;
  31. }
  32. // Pages/index.index.wxss
  33. @import "../../common/common.wxss"

image.png

全局样式(app.wxss)

  • 作用于所有页面
    1. view {
    2. padding: 10rpx;
    3. margin: 10rpx;
    4. background-color: #888;
    5. }
    image.png

    当全局样式和局部样式冲突时,根据就近原则,局部样式会覆盖全局样式 当局部样式的权重大于或等于全局样式的权重时,才会覆盖全局的样式

全局配置

window

全局/页面常用配置项

属性名 类型 默认值 说明
navigationBarTitleText String 字符串 导航栏标题文字内容
navigationBarBackgroundColor HexColor #000 导航栏背景颜色
navigationBarTextStyle String white 导航栏标题颜色,black / white
backgroundColor HexColor #fff 窗口的背景色
backgroundTextStyle String light 下拉 loading 的样式,drak / light
enablePullDownRefresh Boolean false 是否全局开启下拉刷新
onReachBottomDistance Number 50 页面上拉触底事件触发时距页面底部距离,单位为 px

tabBar

  • tabBar 中只能配置最少 2 个、最多 5 个 tab 页签
  • 当渲染顶部 tabBar 时,不显示 icon,只显示文本

    节点配置项

    | 属性 | 类型 | 必填 | 默认值 | 描述 | | —- | —- | —- | —- | —- | | position | String | 否 | bottom | tabBar 的位置,bottom / top | | borderStyle | String | 否 | black | tabBar 上边框的颜色,black / white | | color | HexColor | 否 | | tab 上文字的默认(未选中)颜色 | | selectedColor | HexColor | 否 | | tab 上文字选中时的颜色 | | backgroundColor | HexColor | 否 | | tabBar 的背景色 | | list | Array | 是 | | tab 页签的列表,最少2个、最多5个 |

tab 项的配置项

属性 类型 必填 描述
pagePath String 页面路径,页面必须在 pages 中预先定义
text String tab 上显示的文字
iconPath String 未选中时的图标路径; 当前 position 为 top 时,不显示 icon
selectedIconPath String 选中时的图标路径; 当 position 为 top 时,不显示 icon

网络数据请求

限制

  1. 只能请求 HTTPS 类型的接口
  2. 必须将接口的域名添加到信任列表中

    配置 request 合法域名

    配置步骤

  3. 登录微信小程序管理后台

  4. 开发
  5. 开发设置
  6. 服务器域名
  7. 修改 request 合法域名

    注意事项:

    1. 域名只支持 https 协议
    2. 域名不能使用 IP 地址或 localhost
    3. 域名必须经过 ICP 备案
    4. 服务器域名一个月内最多可申请 50 次修改

发起 GET 请求

  1. <!-- index.wxml -->
  2. <button type="primary" bindtap="getInfo">发起GET请求</button>
  3. <!-- index.js -->
  4. Page({
  5. // 发起 GET 请求
  6. getInfo() {
  7. wx.request({
  8. url: 'https://api.muxiaoguo.cn/api/tiangourj?api_key=c342043936758a92',
  9. method: 'GET',
  10. success: (res) => {
  11. console.log(res);
  12. }
  13. })
  14. }
  15. })

发起 POST 请求

  1. <!-- index.wxml -->
  2. <button type="primary" bindtap="postInfo">发起POST请求</button>
  3. <!-- index.js -->
  4. Page({
  5. // 发起 POST 请求
  6. postInfo() {
  7. wx.request({
  8. url: 'https://api.muxiaoguo.cn/api/tianqi?api_key=29abdbf534ebdca5',
  9. methosd: "POST",
  10. data: {
  11. type: 1,
  12. city: "南昌"
  13. },
  14. success(res) {
  15. console.log(res);
  16. }
  17. })
  18. }
  19. })

页面刚加载时请求数据

  1. Page({
  2. onLoad(options) {
  3. // 调用 get 请求事件
  4. this.getInfo()
  5. }
  6. })

跳过 request 合法域名校验

  • 开启后可暂时跳过 https 校验域名,请求 http 接口

    跳过 request 合法域名校验的选项,仅在开发和调试阶段使用

image.png

页面导航

声明式导航(属性实现跳转)

概述

  • 在页面上声明一个 <navigator> 导航组件
  • 通过点击 <navigator> 组件实现页面跳转

    导航 tabBar 页面

  • 使用 <navigator> 组件跳转到指定的 tabBar 页面时,需要指定 url 属性和 open-type 属性,其中:

    • url 表示要跳转的页面地址,必须以 / 开头
    • open-type 表示跳转的方式,必须为 switchTab
      1. <!-- 导航跳转至分类页 -->
      2. <navigator url="/pages/classify/classify" open-type="switchTab">导航至分类页</navigator>

      导航非 tabBar 页面

  • 使用 <navigator> 组件跳转到指定的非 tabBar 页面时,需要指定 url 属性和 open-type 属性,其中:

    • url 表示要跳转的页面地址,必须以 / 开头
    • open-type 表示跳转的方式,必须为 navigate

      在跳转的页面非 tabBar 页面时,可以省略open-type="navigate"属性不写

  1. <!-- 导航跳转至分类页 -->
  2. <navigator url="/pages/contents/contents" open-type="navigate">导航至contents页</navigator>

后退导航

  • 后退上一页面或多级页面,需要指定 delta 属性和 open-type 属性,其中:
    • open-type 的值必须是 navigateBack,表示要进行后退导航
    • delta 的值必须是数字,表示要后退的层级(默认值为 1)

      如果只是后退至上一页面,delta 属性则可以省略不写,因为默认值就为 1 在 tabBar 页面中使用不会生效,只能在非 tabBar 页面使用法

  1. <!-- 后退导航 -->
  2. <navigator open-type="navigateBack" delta="1">返回上一页</navigator>

导航传参

  • 参数和路径之间使用?分隔
  • 参数键和参数值用=连接
  • 不同参数用&分隔

    1. <navigator url="/pages/contents/contents?name=smallfish&age=18">跳转 contents 页</navigator>

    编程式导航(js实现跳转)

    概述

  • 调用小程序的导航 API,实现页面跳转

    导航 tabBar 页面

  • 调用 wx.switchTab(Object Object) 方法,跳转至 tabBar 页面;其中 Object 的参数对象的属性列表如下: | 属性 | 类型 | 是否必选 | 说明 | | —- | —- | —- | —- | | url | string | 是 | 需要跳转的 tabBar 页面路径,路径后不能带参数 | | success | function | 否 | 接口调用成功的回调函数 | | fail | function | 否 | 接口调用失败的回调函数 | | complete | function | 否 | 接口调用结束的回调(调用成功、失败都会执行) |

  1. <!-- 导航到 users 页 -->
  2. <button type="primary" bindtap="gotoUsers">跳转至users页</button>
  3. // 导航到 users 页
  4. gotoUsers() {
  5. wx.switchTab({
  6. url: '/pages/users/users',
  7. })
  8. },

导航非 tabBar 页面

  • 调用 wx.navigateTo(Object Object) 方法,可以跳转至非 tabBar 页面;其中 Object 参数对象的属性列表如下: | 属性 | 类型 | 是否必选 | 说明 | | —- | —- | —- | —- | | url | string | 是 | 跳转至非 tabBar 页面的路径,路径后可带参数 | | success | function | 否 | 接口调用成功的回调 | | fail | function | 否 | 接口调用失败的回调 | | complete | function | 否 | 接口调用结束的回调(调用成功、失败都会执行) |
  1. <!-- 导航至 contents 页 -->
  2. <button type="primary" bindtap="gotoContents">跳转 contents 页</button>
  3. // 导航至非 tabBar 页
  4. gotoContents() {
  5. wx.navigateTo({
  6. url: '/pages/contents/contents',
  7. })
  8. },

后退导航

  • 调用 wx.navigateBack(Object Object) 方法,可以返回上一页或多页;其中 Object 参数对象的属性列表如下: | 属性 | 类型 | 默认值 | 是否必选 | 说明 | | —- | —- | —- | —- | —- | | delta | number | 1 | 否 | 返回的页面数,delta 大于现有页面数,则返回首页 | | success | function | | 否 | 接口调用成功的回调 | | fail | function | | 否 | 接口调用失败的回调 | | complete | function | | 否 | 接口调用结束的回调(调用成功、失败都会执行) |

如果只是后退至上一页面,delta 属性则可以省略不写,因为默认值就为 1 在 tabBar 页面中使用不会生效,只能在非 tabBar 页面使用

  1. <!-- 返回上一页 -->
  2. <button type="primary" bindtap="gotoBack">返回上一页</button>
  3. // 返回上一页
  4. gotoBack() {
  5. wx.navigateBack()
  6. },

导航传参

  • 调用 wx.navigateTo(Object Object) 方法,可携带参数,示例如下: ```html

// 导航至非 tabBar 页 gotoContents() { wx.navigateTo({ url: ‘/pages/contents/contents?name=smallfish&age=18’, }) },

  1. <a name="qMUyB"></a>
  2. ## onLoad 接收导航参数
  3. ```javascript
  4. onLoad(options) {
  5. // options 就是导航传递的参数对象
  6. console.log(options)
  7. }

页面事件

实现下拉刷新

  1. <view>下拉刷新效果</view>
  2. <view>count:{{ count }}</view>
  3. <button bindtap="addCount">count++</button>
  1. Page({
  2. data: {
  3. count: 0
  4. },
  5. onPullDownRefresh() {
  6. this.setData({
  7. count: 0
  8. })
  9. // 关闭下拉刷新效果
  10. wx.stopPullDownRefresh()
  11. }
  12. })

实现上拉触底

配置上拉触底距离

  • 在页面/全局的.json文件中,通过 onReachBottomDIstance 属性来配置上拉触底距离

    生命周期

  1. 小程序启动,生命周期开始
  2. 小程序关闭,生命周期结束
  3. 中间小程序运行的过程,就是小程序的生命周期

微信小程序开发 - 图37

自动按次序执行

应用生命周期

  • 小程序:启动 -> 运行 -> 销毁
  • app.js 中进行声明,代码如下:

    1. App({
    2. // 小程序初始化完成时,执行此函数,全局只触发一次,做初始化工作
    3. onLaunch(options) {},
    4. // 小程序启动,或从后台进入前台显示时触发
    5. onShow(options) {},
    6. // 小程序从前台进入后台时触发
    7. onHide() {}
    8. })

    页面生命周期

  • 小程序:页面加载 -> 渲染 -> 销毁

  • 在页面对应的.js中进行声明:代码如下:

    1. Page({
    2. onLoad(options) {}, // 监听加载,一个页面只调用一次
    3. onShow() {}, // 监听页面显示
    4. onReady() {}, // 监听页面初次渲染完成,一个页面只调用一次
    5. onHide() {}, // 监听页面隐藏
    6. onUnload() {} // 监听页面卸载,一个页面只调用一次
    7. })

    WXS脚本

  • WXS 是小程序独有的一套脚本语言,结合 WXML,可以构建出页面的结构

    1. wxs 不支持:let 、const 、解构赋值、展开运算符、箭头函数、对象属性简写等
    2. module:模块的名称
    3. src:模块的路径(相对路径)
    4. wxs 中定义的函数不能作为组件的事件回调函数
    5. wxs 不能调用 js 文件中定义的函数
    6. wxs 不能调用小程序提供的 API
    7. 在 ios 设备上,wxs 比 js 快 2~20倍
    8. 在 Android 设备上,二者的运行效率无差异

内联WXS脚本

  1. <!-- m1 wxs模块 -->
  2. <view class="title">m1 模块</view>
  3. <view>{{ m1.toUpper(name) }}</view>
  4. <!-- m1 wxs模块 -->
  5. <wxs module="m1">
  6. module.exports.toUpper = function(str) {
  7. return str.toUpperCase()
  8. }
  9. </wxs>

外链WXS脚本

  1. // xxx.wxml
  2. <!-- m2 wxs模块 -->
  3. <view class="title">m2 模块</view>
  4. <view>{{ m2.toLower(country) }}</view>
  5. <!-- m2 wxs模块 -->
  6. <wxs src="../../utils/tools.wxs" module="m2"></wxs>
  7. // utils/tools.wxs
  8. function toLower(str) {
  9. return str.toLowerCase()
  10. }
  11. module.exports = {
  12. toLower: toLower
  13. }

自定义组件

组件创建

  1. 在项目根目录中,创建components文件夹
  2. 在新建的components文件夹中新建你想要的组件文件夹
  3. 鼠标右键,点击组件文件夹,点击“新建Component”
  4. 输入组件名称后回车,会生成组件对应的 4 个文件,分别是 .js.json.wxml.wxss

    为了保证目录结构清晰,把不同组件存放到单独的目录中

组件引用

局部引用

  • 在页面的.json配置文件中引用组件,示例如下:
    1. // 页面的 .json 文件中,引入组件
    2. ```json
    3. {
    4. "usingComponents": {
    5. "test1": "/components/test1/test1"
    6. }
    7. }

// 在页面的 .wxml 文件中,使用组件

  1. <test1></test1>
  1. <a name="xKQUO"></a>
  2. ### 全局引用
  3. - 在项目根目录下的`app.json`文件中,和`window`节点平级,新增`usingComponents`节点,示例如下:
  4. ```markdown
  5. // 在 app.json 文件中,引入组件
  6. ```json
  7. {
  8. "usingComponents": {
  9. "test1": "/components/test1/test1"
  10. }
  11. }

// xxx.wxml 文件中,使用组件

  1. <test1></test1>
  1. <a name="ruUP9"></a>
  2. ## 全局和局部的区别
  3. - 组件的`.json`需要声明“component”: true 属性
  4. - 组件的`.js`调用的是 Component() 函数
  5. - 组件的事件处理函数需要定义到 methods 节点中
  6. <a name="etHcG"></a>
  7. ## 样式隔离:stylelsolation
  8. :::danger
  9. 注意点:
  10. 1. app.wxss 中的全局样式对组件无效
  11. 1. 只有 class 选择器有样式隔离效果,id、属性、标签选择器不受样式隔离的影响
  12. 1. 在组件和引用组件的页面中建议使用 class 选择器,不要使用 id、属性、标签选择器
  13. :::
  14. - 防止组件内外样式互相干扰;有时,希望外界可以控制组件内部样式
  15. ```javascript
  16. // 方法 1
  17. Component({
  18. options: {
  19. styleIsolation: 'isolated'
  20. }
  21. })
  1. // 方法 2
  2. {
  3. "styleIsolation": "isolated"
  4. }
可选值 默认值 描述
isolated 启用样式隔离,在自定义组件内外,使用class 指定的样式将不会互相影响
apply-shared 页面 WXSS 样式将影响自定义组件,但自定义组件 WXSS 中的样式不会影响页面
shared 页面 WXSS 样式将影响自定义组件,自定义组件 WXSS 样式也会影响页面和其他设置了 apply-shared 或 shared 的自定义组件

事件处理函数和自定义方法:methods

  1. <view>count值是:{{ count }}</view>
  2. <button type="primary" bindtap="addCount">count++</button>
  1. Component({
  2. data: {
  3. count: 0
  4. },
  5. methods: {
  6. addCount() { // 事件处理函数
  7. this.setData({
  8. count: this.data.count + 1
  9. })
  10. this._showCount()
  11. },
  12. _showCount() { // 自定义方法,以 _ 开头
  13. wx.showToast({ // 弹窗方法
  14. title: 'count值为:' + this.data.count,
  15. icon: 'none'
  16. })
  17. }
  18. }

image.png

properties 和 data

  • 类似于 Vue 中的 props
  • 用于接收外界传递到组件中的数据
  • properties 中的数据是可读写的
  • properties 和 data 指向的是同一个对象
  • data:存储组件私有数据
  • properties:存储外界传递到组件中的数据
  1. <test max="15"><test1>
  1. Component({
  2. properties: {
  3. max: Number, // 简单定义类型
  4. max: { // 复杂定义类型
  5. type: Number,
  6. value: 10 // 默认值
  7. }
  8. },
  9. })

数据监听器:observers

  1. <view>{{n1}} + {{n2}} = {{sum}}</view>
  2. <button bindtap="addN1">n1 + 1</button>
  3. <button bindtap="addN2">n2 + 1</button>
  1. Component({
  2. data: {
  3. n1: 0,
  4. n2: 0,
  5. sum: 0
  6. },
  7. methods: {
  8. addN1() {
  9. this.setData({
  10. n1: this.data.n1 + 1
  11. })
  12. },
  13. addN2() {
  14. this.setData({
  15. n2: this.data.n2 + 1
  16. })
  17. },
  18. },
  19. observers: {
  20. 'n1, n2': function(n1, n2) {
  21. this.setData({
  22. sum: n1 + n2
  23. })
  24. }
  25. }
  26. })

:::danger

  • observers中,如果键为对象,需要监听对象中的所有属性,可以使用obj.**方法即可 :::

    纯数据字段

  • 概念:不用于界面渲染的 data 字段

  • 好处:有助于提升页面更新的性能

    1. Component({
    2. options: {
    3. pureDataPattern: /^_/
    4. },
    5. data: {
    6. a: 0,
    7. _b: 10
    8. }
    9. })

    组件的生命周期函数

    1. Component({
    2. lifetimes: {
    3. created() {}, // 组件实例刚被创建时执行
    4. attached() {}, // 组件实例进入页面节点树时执行
    5. ready() {}, // 组件再视图层布局完成后执行
    6. moved() {}, // 组件实例被移动到节点树的另一个位置时执行
    7. detached() {}, // 组件实例被页面节点树移除时执行
    8. error(Object Error) {} // 组件方法抛出错误时执行
    9. }
    10. })

    :::danger

  • created 执行时并不能使用 this.setData

  • attached 执行时可以使用 this.setData :::

    组件所在页面的生命周期函数

    1. Component({
    2. pageLifetimes: {
    3. show() {}, // 组件所在页面被展示时执行
    4. hide() {}, // 组件所在页面被隐藏时执行
    5. resize(size) {} // 组件所在页面尺寸变化时执行
    6. }
    7. })

    插槽

    1. <view>
    2. <view>这是slots组件内部</view>
    3. <slot></slot>
    4. </view>
    1. <slots>
    2. <view>这是要插入到slots组件中的内容</view>
    3. </slots>
  • 使用多个插槽

    1. Component({
    2. options: {
    3. multipleSlots: true // 在组件定义时的选项中启用了多 slot 支持
    4. }
    5. })

    父子组件通信

    属性绑定

  • 父组件向子组件的指定属性设置数据,仅能设置JSON兼容的数据 ```html // pages/home/home.wxml 父组件中,count值为:{{ count }} —————————————

// components/attr/attr.wxml

父组件传过来的count值为:{{count}}

  1. ```javascript
  2. // pages/home/home.js
  3. Page({
  4. data: {
  5. count: 0
  6. },
  7. addCount() {
  8. this.setData({
  9. count: this.data.count + 1
  10. })
  11. }
  12. })
  13. // components/attr/attr.js
  14. Component({
  15. properties: {
  16. count: Number
  17. }
  18. })

事件绑定

  • 子组件向父组件传递数据,可传递任何数据
  1. 在父组件的js中,定义一个函数,这个函数将通过自定义事件的形式,传递给子组件

    1. Page({
    2. data: {
    3. count: 0
    4. },
    5. syncCount(e) {
    6. console.log(e.detail.value);
    7. }
    8. })
  2. 在父组件的wxml中,通过自定义事件的形式,将步骤 1 中定义的函数引用,传递给子组件

    1. <emit count="{{count}}" bind:sync="syncCount"></emit>
  3. 在子组件的 js中,通过调用 this.triggerEvent('自定义事件名称', {/*参数对象*/}),将数据发送到父组件

    1. <view>子组件的count值为:{{count}}</view>
    2. <button type="primary" bindtap="addCount">count+1</button>
    1. Component({
    2. properties: {
    3. count: Number
    4. },
    5. methods: {
    6. addCount() {
    7. this.setData({
    8. count: this.properties.count + 1
    9. })
    10. this.triggerEvent('sync', {value: this.properties.count})
    11. }
    12. }
    13. })
  4. 在父组件的js中,通过 e.detail 获取到子组件传递过来的数据

    1. Page({
    2. syncCount(e) {
    3. this.setData({
    4. count: e.detail.value
    5. })
    6. },
    7. })

    获取组件实例

  • 父组件可通过 this.selectComponent(只能传class或id选择器) 获取子组件实例对象
  • 这样可以直接访问子组件的任意数据和方法

    1. <view>父组件的count值为:{{count}}</view>
    2. <view>----------------------------</view>
    3. <get-instance-obj bind:sync="syncCount" count="{{count}}" class="customA" id="cA"></get-instance-obj>
    4. <button bindtap="getChild">获取子组件实例对象</button>
    1. Page({
    2. data: {
    3. count: 0
    4. },
    5. syncCount(e) {
    6. this.setData({
    7. count: e.detail.value
    8. })
    9. },
    10. getChild() {
    11. const child = this.selectComponent('.customA')
    12. child.addCount()
    13. },
    14. })
    1. <view>子组件的count值为:{{count}}</view>
    2. <button bindtap="addCount">count++</button>
    1. Component({
    2. properties: {
    3. count: Number
    4. },
    5. methods: {
    6. addCount() {
    7. this.setData({
    8. count: this.properties.count + 1
    9. })
    10. this.triggerEvent('sync', {value: this.properties.count})
    11. }
    12. }
    13. })

    behaviors

  • 在项目根目录下创建 behaviors 目录,并创建自己想要的 js 文件

  • 在 js 文件中定义数据、属性、方法、生命周期等节点
  • 在组件中使用 require 导入,在与 data 节点平级,创建 behaviors 节点,为一个数组,数组中的元素便是引入的变量名
    1. module.exports = Behavior({
    2. behaviors: [], // 用来保存引入的其他 behaviors
    3. properties: { // 同组件属性
    4. myBehaviorProperty: {
    5. type: String
    6. }
    7. },
    8. data: { // 同组件数据
    9. myBehaviorData: {}
    10. },
    11. attached: function(){}, // 生命周期函数
    12. methods: { // 同自定义组件的方法
    13. myBehaviorMethod: function(){}
    14. }
    15. })
    1. var myBehavior = require('my-behavior')
    2. Component({
    3. behaviors: [myBehavior] // 使用
    4. })
    image.png

    使用npm包

  1. 不支持依赖于 Node.js 内置库的包
  2. 不支持依赖于浏览器内置对象的包
  3. 不支持依赖于 C++ 插件的包

    API Promise化

  • 通过 miniprogram-api-promise 第三方包,实现 API Promise 化:
    1. npm install --save miniprogram-api-promise@1.0.4
    ```javascript import { promisifyAll } from ‘miniprogram-api-promise’

const wxp = wx.p = {} promisifyAll(wx, wxp)

  1. - 通过额外的配置,将官方提供的、基于回调函数的异步 API,升级改造为基于 Promise 的异步 API,从而提高代码的可读性、维护性、避免回调地狱的问题
  2. - 调用 Promise 化之后的异步 API
  3. ```html
  4. <van-button type="danger" bindtap="getInfo">vant按钮</van-button>
  5. <script>
  6. async getInfo() {
  7. const { data: res } = await wx.p.request({
  8. method: 'GET',
  9. url: 'https://www.escook.cn/api/get',
  10. data: {
  11. name: 'zs',
  12. age: 18
  13. }
  14. })
  15. console.log(res)
  16. }
  17. </script>

安装使用 Vant Weapp

  1. npm i @vant/weapp -S --production
  2. npm i @vant/weapp@1.3.3 -S --production

在项目根目录下右键打开 cmd 命令行窗口,运行如下命令:

  1. # 创建一个 package.json 配置文件
  2. npm init -y
  3. # 在 app.json 中删除 style 节点
  1. {
  2. ...
  3. "setting": {
  4. ...
  5. "packNpmManually": true,
  6. "packNpmRelationList": [
  7. {
  8. "packageJsonPath": "./package.json",
  9. "miniprogramNpmDistDir": "./miniprogram/"
  10. }
  11. ]
  12. }
  13. }
  1. // 注册使用 vant 组件
  2. "usingComponents": {
  3. "van-button": "@vant/weapp/button/index"
  4. }

在开发者工具左上角的 工具 选项中,选择 构建 npm,打开右上角 详情,打开 本地设置,勾选 使用 npm 模块

自定义全局主题(app.wxss)

更多主题样式,请参考:主题配置文件

  1. page{
  2. --button-danger-background-color: #c00000;
  3. --button-danger-border-color: #D60000;
  4. }

:::danger 以上变量皆是 Vant 组件库已经定义好的,作用域组件的样式 :::

全局数据共享 Mobx

  • mobx-miniprogram:创建 Store 实例对象
  • mobx-miniprogram-bindings:把 Store 中的共享数据或方法,绑定到组件或页面中使用

    安装

    1. npm install --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1

    创建 Store 实例

    ```javascript // store/store.js

import { action, observable } from ‘mobx-miniprogram’

export const store = observable({ // 数据字段 numA: 1, numB: 2, // 计算属性 get sum() { return this.numA + this.numB }, // action 方法,用来修改 store 中的数据 updateNum1: action(function (step) { this.numA += step }), updateNum2: action(function (step) { this.numB += step }) })

  1. <a name="uHOPl"></a>
  2. ## 绑定实例到页面
  3. ```html
  4. // 页面的 .wxml 文件
  5. <view>{{numA}} + {{numB}} = {{sum}}</view>
  6. <van-button type="primary" bindtap="btnHandler1" data-step="{{1}}">numA + 1</van-button>
  7. <van-button type="danger" bindtap="btnHandler1" data-step="{{-1}}">numA + 1</van-button>
  8. // 页面的 .js 文件
  9. <script>
  10. import { createStoreBindings } from 'mobx-miniprogram-bindings'
  11. import { store } from '../../store/store'
  12. Page({
  13. btnHandler1(e) {
  14. this.updateNum1(e.target.dataset.step)
  15. },
  16. onLoad() {
  17. this.storeBindings = createStoreBindings(this, {
  18. store, // 数据源
  19. fields: ['numA', 'numB', 'sum'], // 数据字段
  20. actions: ['updateNum1'] // 方法
  21. })
  22. },
  23. onUnload() {
  24. this.storeBindings.destroyStoreBindings()
  25. }
  26. })
  27. </script>

绑定到组件

  1. // numbers.wxml 组件
  2. <view>{{numA}} + {{numB}} = {{sum}}</view>
  3. <van-button type="primary" bindtap="btnHandler2" data-step="{{1}}">numB + 1</van-button>
  4. <van-button type="danger" bindtap="btnHandler2" data-step="{{-1}}">numB + 1</van-button>
  5. // numbers.js 组件
  6. <script>
  7. import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
  8. import { store } from '../../store/store'
  9. Component({
  10. behaviors: [storeBindingsBehavior],
  11. storeBindings: {
  12. store,
  13. fields: {
  14. numA: 'numA',
  15. numB: 'numB',
  16. sum: 'sum'
  17. },
  18. actions: {
  19. updateNum2: 'updateNum2'
  20. }
  21. },
  22. methods: {
  23. btnHandler2(e) {
  24. this.updateNum2(e.target.dataset.step)
  25. </script>

分包

概念:

把一个完整的小程序项目,按照需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载

好处:

  1. 可以优化雄安程序首次启动的时间
  2. 多团队共同开发时可以更好的解耦协作

    构成:

  • 主包:包含 启动页面 或 tabBar 页面,以及所有分包都需要用到的公共资源
  • 分包:只包含当前分包有关的页面和私有资源

image.png

加载规则

  1. 小程序启动时,默认会下载主包并启动主包内页面
    1. tabBar 页面需要放到主包中
  2. 当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后在进行展示

    1. 非 tabBar 页面可以按照功能的不同,划分为不同的分包之后,进行按需下载

      配置

      1. {
      2. "subpackages": [
      3. {
      4. "root": "pkgA", // 分包根目录
      5. "name": "packA", // 分包别名
      6. "pages": [ // 分包下的所有页面路径
      7. "pages/cat/cat",
      8. "pages/dog/dog"
      9. ],
      10. "independent": true // 是否是独立分包,默认为 false
      11. }
      12. ]
      13. }
      :::danger 独立分包引用原则
  3. 主包无法引用独立分包内的私有资源

  4. 独立分包之间,不能相互引用私有资源
  5. 独立分包和普通分包之间,不能相互引用私有资源
  6. 独立分包中不能引用主包内的公共资源 :::

    分包预下载

  • 进入小程序的某个页面时,由框架自动预下载可能需要的分包,从而提升进入后续分包页面时的启动速度
    1. {
    2. "preloadRule": { // 分包预下载的规则
    3. "pages/classify/classify": { // 触发分包预下载的页面路径
    4. // 指定的网络模式下进行预下载
    5. // 默认值为:wifi
    6. // all 为不限网络
    7. "network": "all",
    8. // 进入页面后,预下载哪些分包
    9. // 可通过 root name 指定预下载的分包
    10. "packages": ["pkgA"]
    11. }
    12. },
    13. }