小程序开发学习笔记

1. 小程序简介

小程序与普通网页开发的区别

1、运行环境不同

网页运行在浏览器环境中,小程序运行在微信环境中。​网页开发渲染线程和脚本线程是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应,而在小程序中,二者是分开的,分别运行在不同的线程中。
在这里插入图片描述

2、API不同

由于运行环境的不同,所以小程序中,无法调用 DOM 和 BOM 的 API
但是,小程序中可以调用微信环境提供的各种 API,例如:地理定位、扫码、支付。

3、开发模式不同

网页的开发模式:浏览器 + 代码编辑器
小程序有自己的一套标准开发模式:

  • 申请小程序开发账号
  • 安装小程序开发者工具
  • 创建和配置小程序项目

2. 开始

注册小程序账号

进入小程序注册页 根据指引填写信息和提交相应的资料,就可以拥有自己的小程序帐号。
在这里插入图片描述

获取小程序的AppID

小程序管理平台 ,我们可以管理自己的小程序的权限,查看数据报表,发布小程序等操作。

在菜单 开发管理->开发设置->开发者ID可以看到小程序的 AppID ,其相当于小程序平台的一个身份证。
在这里插入图片描述

安装开发者工具

微信开发者工具是官方推荐使用的小程序开发工具,它提供的主要功能如下:

① 快速创建小程序项目
② 代码的查看和编辑
③ 对小程序功能进行调试
④ 小程序的预览和发布

推荐下载和安装最新的稳定版(Stable Build)的微信开发者工具,进入开发者工具下载网址 下载适合的版本,这里我选择的是Windows64位。
在这里插入图片描述
下载后按照指示即可完成安装
在这里插入图片描述

创建小程序项目

进入小程序开发者工具,选择小程序点击+
在这里插入图片描述
填写项目名称,选择代码存放的硬盘路径,填入刚刚申请到的小程序的 AppID。勾选 “不使用云服务” ,选择JavaScript语言,点击新建。
注意: 要选择一个空的目录才可以创建项目
在这里插入图片描述
这样,你就得到了你的第一个小程序。
在这里插入图片描述
可以在模拟器上查看项目效果,也可以在真机上预览项目效果
在这里插入图片描述

3. 小程序代码构成

整体结构

  • pages 用来存放所有小程序的页面
  • utils 用来存放工具性质的模块(例如:格式化时间的自定义模块)
  • app.js 小程序项目的入口文件
  • app.json 小程序项目的全局配置文件
  • app.wxss 小程序项目的全局样式文件
  • project.config.json 工具配置,在工具上做的任何配置都会写入到这个文件。
  • 项目根目录中的 project.config.jsonproject.private.config.json 文件可以对项目进行配置,project.private.config.json 中的相同设置优先级高于 project.config.json
  • sitemap.json 用来配置小程序及其页面是否允许被微信索引
    在这里插入图片描述

page文件

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

  • .js 文件:页面的脚本文件,存放页面的数据、事件处理函数等
  • .json 文件:当前页面的配置文件,配置窗口的外观、表现等
  • .wxml文件:充当的就是类似 HTML 的角色,包含页面的模板结构
  • .wxss 文件:当前页面的样式表文件

在这里插入图片描述

json 文件

app.json 是当前小程序的全局配置,包括了小程序的所有页面路径、窗口外观、界面表现、底部 tab 等。

  • pages:用来记录当前小程序所有页面的路径
  • window:全局定义小程序所有页面的背景色、文字颜色等
  • style:全局定义小程序组件所使用的样式版本
  • sitemapLocation:用来指明 sitemap.json 的位置
{
  "pages":[
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "Weixin",
    "navigationBarTextStyle":"black"
  },
  "style": "v2",
  "sitemapLocation": "sitemap.json"
}

project.config.json 是项目配置文件,用来记录我们对小程序开发工具所做的个性化配置,例如:

  • setting 中保存项目的编译设置
  • projectname 中保存的是项目名称,只在新建项目时读取
  • appid 中保存的是项目的 appid,只在新建项目时读取

小程序根目录下的 sitemap.json 文件用于配置小程序及其页面是否允许被微信索引,文件内容为一个 JSON 对象,如果没有 sitemap.json ,则默认为所有页面都允许被索引;

当开发者允许微信索引时,微信会通过爬虫的形式,为小程序的页面内容建立索引。当用户的搜索词条触发该索引时,小程序的页面将可能展示在搜索结果中。

如下,所有页面都会被微信索引(默认情况)

{
  "rules":[{
    "action": "allow",
    "page": "*"
  }]
}

配置 path/to/page 页面被索引,其余页面不被索引

{
  "rules":[{
    "action": "allow",
    "page": "path/to/page"
  }, {
    "action": "disallow",
    "page": "*"
  }]
}

每一个小程序页面也可以使用同名 .json 文件来对本页面的窗口表现进行配置,页面中配置项会覆盖 app.json 的 window 中相同的配置项
在这里插入图片描述

我们在app.json的pages配置中输入新建的页面,就可以自动生成对应的文件夹。
在这里插入图片描述
注意:只需要调整 app.json -> pages 数组中页面路径的前后顺序,即可修改项目的首页。小程序会把排在第一位的页面,当作项目首页进行渲染

WXML

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

WXML 和 HTML 的区别

(1) 标签名称不同

  • HTML (div, span, img, a)
  • WXML(view, text, image, navigator)

(2)属性节点不同

  • <a href="#">超链接</a>
  • <navigator url="/pages/home/home"></navigator>

(3)提供了类似于 Vue 中的模板语法

  • 数据绑定( {{message}} )
  • 列表渲染(wx:for)
  • 条件渲染(wx:if)

WXSS

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

WXSS 和 CSS 的区别

(1)新增了 rpx 尺寸单位

  • CSS 中需要手动进行像素单位换算,例如 rem
  • WXSS 在底层支持新的尺寸单位 rpx,在不同大小的屏幕上小程序会自动进行换算。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

(2)提供了全局的样式和局部样式

  • 项目根目录中的 app.wxss 会作用于所有小程序页面
  • 局部页面的 .wxss 样式仅对当前页面生效

(3) WXSS 仅支持部分 CSS 选择器

  • .class 和 #id
  • element(组件)
  • 并集选择器、后代选择器
  • ::after 和 ::before 等伪类选择器

JS 逻辑交互

小程序中的 JS 文件分为三大类

  • app.js:是整个小程序项目的入口文件,通过调用 App() 函数来启动整个小程序
  • 页面的 .js 文件:是页面的入口文件,通过调用 Page() 函数来创建并运行页面
  • 普通的 .js 文件:是普通的功能模块文件,用来封装公共的函数或属性供页面使用

4. 小程序的宿主环境

微信客户端给小程序所提供的环境是宿主环境宿主环境(host environment)指的是程序运行所必须的依赖环境。小程序借助宿主环境提供的能力,可以完成许多普通网页无法完成的功能,例如:微信扫码、微信支付、微信登录、地理定位、etc…

小程序开发过程中需要面对的是两大操作系统 iOSAndroid 的微信客户端,以及用于辅助开发的小程序开发者工具。

安卓版的微信 App 是不能在 iOS 环境下运行的,脱离了宿主环境的软件是没有任何意义的!
在这里插入图片描述

渲染层和逻辑层

小程序的运行环境分成渲染层和逻辑层,其中

  • WXML 模板和 WXSS 样式工作在渲染层
  • JS 脚本工作在逻辑层。

小程序的渲染层和逻辑层分别由2个线程管理

  • 渲染层的界面使用了WebView 进行渲染;
  • 逻辑层采用JsCore线程运行JS脚本。

一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端(Native指微信客户端)做中转,逻辑层发送网络请求也经由Native转发,小程序的通信模型下图所示。
在这里插入图片描述

小程序启动的过程

(1)微信客户端在打开小程序之前,会把整个小程序的代码包下载到本地

(2)通过 app.json 的 pages 字段就可以知道当前小程序的所有页面路径,第一个页面index.js就是这个小程序的首页 。 微信客户端会把首页的代码装载进来,通过小程序底层的一些机制,渲染出这个首页

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

小程序启动之后,在 app.js 定义的 App 实例的 onLaunch 回调会被执行。
注意:整个小程序只有一个 App 实例,是全部页面共享的。

App({
  onLaunch: function () {
    // 小程序启动之后 触发
  }
})

(3)小程序启动完成

页面渲染的过程

(1)微信客户端会先根据.json 配置生成一个界面,顶部的颜色和文字你都可以在这个 json 文件里边定义好。
(2)紧接着客户端就会装载这个页面的 WXML 结构和 WXSS 样式。
(3)最后客户端会装载.js

// .js 文件
Page({
// 页面的初始数据
  data: {
  },

// 生命周期函数--监听页面加载
  onLoad(options) {
  },

// 生命周期函数--监听页面初次渲染完成
  onReady() {
  },

  // 生命周期函数--监听页面显示
  onShow() {
  },

  // 生命周期函数--监听页面隐藏
  onHide() {
  },
 // 生命周期函数--监听页面卸载
  onUnload() {
  },
// 页面相关事件处理函数--监听用户下拉动作
  onPullDownRefresh() {
  },
// 页面上拉触底事件的处理函数
  onReachBottom() {
  },
//用户点击右上角分享
  onShareAppMessage() {
  }
})

Page 是一个页面构造器,这个构造器就生成了一个页面。在生成页面的时候,小程序框架会把 data 数据和 index.wxml 一起渲染出最终的结构。

组件

小程序中的组件也是由宿主环境提供的,开发者可以基于组件快速搭建出漂亮的页面结构。

像 HTML 的 div, p 等标签一样,在小程序里边,你只需要在 WXML 写上对应的组件标签名字就可以把该组件显示在界面上,

<map> </map>

官方把小程序的组件分为:

  • 视图容器
  • 基础内容
  • 表单组件
  • 导航组件
  • 媒体组件
  • map 地图组件
  • canvas 画布组件
  • 开放能力
  • 无障碍访问
  • 导航栏

视图容器

1、view

  • 普通视图区域
  • 类似于 HTML 中的 div,是一个块级元素
  • 常用来实现页面的布局效果

WXML

<view class='container1'> 
   <view>A</view>
   <view>B</view>
   <view>C</view>
</view>

WXSS

/* pages/list/list.wxss */
.container1 view{
  width: 100px;
  height: 100px;
  text-align: center;
  line-height: 100px;
}
.container1 view:nth-child(1){
  background-color: lightgreen;
}

.container1 view:nth-child(2){
  background-color: lightpink ;
}
.container1 view:nth-child(3){
  background-color: lightskyblue;
}

.container1{
  display: flex;
  justify-content: space-around;
}

在这里插入图片描述

2、 scroll-view

  • 可滚动的视图区域
  • 常用来实现滚动列表效果

WXML

<!-- scroll-y属性:允许纵向滚动 -->
<!-- scroll-x属性:允许横向滚动 -->
<!-- 使用竖向滚动时,需要给scroll-view一个固定高度,通过 WXSS 设置 height -->
<scroll-view class='container1' scroll-y> 
   <view>A</view>
   <view>B</view>
   <view>C</view>
</scroll-view>

WXSS

/* pages/list/list.wxss */
.container1 view{
  width: 100px;
  height: 100px;
  text-align: center;
  line-height: 100px;
}
.container1 view:nth-child(1){
  background-color: lightgreen;
}

.container1 view:nth-child(2){
  background-color: lightpink ;
}
.container1 view:nth-child(3){
  background-color: lightskyblue;
}

.container1{
  border: 1px solid red;
  height: 150px;
  width: 100px;
}

在这里插入图片描述

3、swiperswiper-item

  • 轮播图容器组件 和 轮播图 item 组件

WXML

<!-- 	indicator-dots 是否显示面板指示点 -->
<swiper class="swiper-container" indicator-dots>
  <swiper-item>
      <view class="item">A</view>
  </swiper-item>
  <swiper-item>
      <view class="item">B</view>
  </swiper-item>
  <swiper-item>
      <view class="item">C</view>
  </swiper-item>
</swiper>

WXSS

/* pages/list/list.wxss */
.swiper-container{
  height: 150px;
}
.item{
  height: 100%;
  line-height: 150px;
  text-align: center;
}
swiper-item:nth-child(1) .item{
  background-color: lightgreen;
}

swiper-item:nth-child(2) .item{
  background-color: lightpink ;
}
swiper-item:nth-child(3) .item{
  background-color: lightskyblue;
}

在这里插入图片描述
常见属性属性

基础内容组件

1、text

  • 文本组件
  • 类似于 HTML 中的 span 标签,是一个行内元素

通过 text 组件的 user-select 属性可以实现长按选中文本内容的效果(其他的不可以):

<!-- 长按不可复制 -->
<view>
手机号哈哈哈哈
</view>
<!-- 长按可复制 -->
<text user-select>
烤肉哈哈哈哈哈
</text>

注意:这里需要用预览实现长按效果,模拟器不行。
在这里插入图片描述

2、rich-text

  • 富文本组件
  • 支持把 HTML 字符串渲染为 WXML 结构
<rich-text nodes="<h1 style='color:pink'>你好</h1>"></rich-text>

在这里插入图片描述

button 按钮组件

功能比 HTML 中的 button 按钮丰富,常见属性如下

  • size:default、mini
  • type: primary(绿色)、default(白色)、warn(红色)
  • plain:按钮是否镂空,背景色透明
<button type="primary"  plain open-type="share" >hh</button>

image 图片组件

image 组件默认宽度约 300px、高度约 240px

<image></image>
image{
  border: 1px solid red;
  border-style: solid;
}

在这里插入图片描述
image 组件的 mode 属性用来指定图片的裁剪和缩放模式
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

API

宿主环境提供了丰富的API,可以很方便调起微信提供的能力。wx对象是小程序的宿主环境所提供的全局对象,几乎所有小程序的API都挂载在wx对象底下(除了Page/App等特殊的构造器)。

1、wx.on* 开头的 API 是监听某个事件发生的API接口,接受一个 Callback 函数作为参数。当该事件触发时,会调用 Callback 函数。

// 监听窗口尺寸变化的事件
wx.onWindowResize(function callback) 

2、 同步 API

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

3、异步 API

多数 API 接口为异步接口 ,都接受一个Object作为参数。API的Object参数一般由success、fail、complete三个回调来接收接口调用结果

wx.request({
url: 'test.php',
data: {},
header: { 'content-type': 'application/json' },
success: function(res) {
 // 收到https服务成功后返回
 console.log(res.data)
},
fail: function() {
 // 发生网络错误等情况触发
},
complete: function() {
 // 成功或者失败后触发
}
})

4、wx.get* 开头的API是获取宿主环境数据的接口。
5、wx.set* 开头的API是写入数据到宿主环境的接口。

事件

用户在渲染层的行为反馈以及组件的部分状态反馈抽象为渲染层传递给逻辑层事件
在这里插入图片描述
事件是通过bindtap这个属性绑定在组件上的,同时在当前页面的Page构造器中定义对应的事件处理函数tapName,当用户点击该view区域时,达到触发条件生成事件tap,该事件处理函数tapName会被执行,同时还会收到一个事件对象event。

WXML

<!-- page.wxml -->
<view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view>

js文件

// page.js
   Page({
  tapName: function(event) {
    console.log(event)
  }
})

常见的事件类型如下:
在这里插入图片描述
在这里插入图片描述

事件绑定与冒泡捕获

以key="value"的形式绑定事件,

  • key以bind或者catch开头,然后跟上事件的类型,如bindtapcatchtouchstart。自基础库版本1.5.0起,bind和catch后可以紧跟一个冒号,其含义不变,如bind:tap、catch:touchstart。同时bind和catch前还可以加上capture-来表示捕获阶段。
  • value是一个字符串,需要在对应的页面Page构造器中定义同名的函数,否则触发事件时在控制台会有报错信息。

bind和capture-bind的含义分别代表事件的冒泡阶段和捕获阶段,其触发的顺序如图
在这里插入图片描述
点击 inner view 会先后调用handleTap2、handleTap4、handleTap3、handleTap1。

<view
  id="outer"
  bind:touchstart="handleTap1"
  capture-bind:touchstart="handleTap2"
>
  outer view
  <view
    id="inner"
    bind:touchstart="handleTap3"
    capture-bind:touchstart="handleTap4"
  >
    inner view
  </view>
</view>

bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡。如果将上面代码中的第一个capture-bind改为capture-catch,将只触发handleTap2(capture-catch将中断捕获阶段和取消冒泡阶段)

<view
  id="outer"
  bind:touchstart="handleTap1"
  capture-catch:touchstart="handleTap2"
>
  outer view
  <view
    id="inner"
    bind:touchstart="handleTap3"
    capture-bind:touchstart="handleTap4"
  >
    inner view
  </view>
</view>

Page.prototype.setData

Page.prototype.setData(Object data, Function callback)函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data 的值(同步)。

  • Object 以 key: value 的形式表示,将 this.data 中的 key 对应的值改变成 value。其中 key 可以以数据路径的形式给出,支持改变数组中的某一项或对象的某个属性,如 array[2].messagea.b.c.d,并且不需要在 this.data 中预先定义。
  • 直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。
<button type="primary"  bindtap="btnTapHandler">{{count}}</button>
Page({
// 页面的初始数据
  data: {
    count:0
  },
  btnTapHandler(){
    this.setData({
      count:this.data.count+1
    })
  },
 })

dataset

在组件节点中可以自定义数据,然后在事件中可以获取这些自定义的节点数据,用于事件的逻辑处理。

自定义数据以data-开头,多个单词由连字符 - 连接。这种写法中,连字符写法会转换成驼峰写法,而大写字符会自动转成小写字符。如:

  • data-element-type ,最终会呈现为 event.currentTarget.dataset.elementType ;
  • data-elementType ,最终会呈现为 event.currentTarget.dataset.elementtype 。
<button type="primary"  bindtap="btnTapHandler" data-elementType="2022" data-element-type="2024" >{{count}}</button>
btnTapHandler(event){
    console.log(event.currentTarget.dataset);
    this.setData({
      count:this.data.count+1
    })
  },

在这里插入图片描述

bindinput

在小程序中,通过 input 事件来响应文本框的输入事件。键盘输入时触发,event.detail = {value, cursor, keyCode},value为文本框变化后的值,keyCode 为键值。

2.1.0 起支持,处理函数可以直接 return 一个字符串,将替换输入框的内容。

<input type="text" 	placeholder="hello"  bindinput="inputHandler"/>
 inputHandler(event){
    console.log(event.detail.value);
  },

5. WXML

单向绑定

WXML

注意:属性值必须被包裹在双引号(或单引号)中

<view>{{info}}</view>
<image src='{{image_src}}' mode="widthFix"></image>

WXSS

data: {
    info:"hello",
    image_src:'../../image/1.jpeg'

  },

在这里插入图片描述
注意:没有被定义的变量的或者是被设置为 undefined 的变量不会被同步到 wxml 中

双向绑定

在 WXML 中,普通的属性的绑定是单向的。如果用户修改了输入框里的值,却不会同时改变 this.data.value 。

<input value="{{value}}" />

如果需要在用户输入的同时改变 this.data.value ,需要借助简易双向绑定机制。此时,可以在对应项目之前加入model:前缀:

<input model:value="{{value}}" />

条件渲染

使用 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>

<!-- <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性 -->
<block wx:if="{{true}}">
  <view> view1 </view>
  <view> view2 </view>
</block>

在小程序中,直接使用 hidden="{{ condition }}" 也能控制元素的显示与隐藏:

<view  hidden="{{length>2}}">hello</view>

wx:if vs hidden
(1)运行方式不同

  • wx:if 以动态创建和移除元素的方式,控制元素的展示与隐藏
  • hidden 以切换样式的方式(display: none/block;),控制元素的显示与隐藏

(2)使用建议

  • 频繁切换时,建议使用 hidden
  • 控制条件复杂时,建议使用 wx:if 搭配 wx:elif、wx:else 进行展示与隐藏的切换

列表渲染

在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。

默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item

<view wx:for="{{array}}">
{{index}}--{{item}}
</view>
data:{
	array:[
      '吃饭',
      '睡觉',
      '学习'
    ]
}

在这里插入图片描述

  • 使用 wx:for-item 可以指定数组当前元素的变量名,
  • 使用 wx:for-index 可以指定数组当前下标的变量名:
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
{{idx}}--{{itemName}}
</view>

如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 input 中的输入内容,switch 的选中状态),需要使用 wx:key 来指定列表中项目的唯一的标识符。


如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 input 中的输入内容,switch 的选中状态),需要使用 wx:key 来指定列表中项目的唯一的标识符。

wx:key 的值以两种形式提供

  • 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
  • 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。

当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。

<switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} </switch>

<switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;"> {{item}} </switch>
data: {
    objectArray: [
      {id: 5, unique: 'unique_5'},
      {id: 4, unique: 'unique_4'},
      {id: 3, unique: 'unique_3'},
      {id: 2, unique: 'unique_2'},
      {id: 1, unique: 'unique_1'},
      {id: 0, unique: 'unique_0'},
    ],
    numberArray: [1, 2, 3, 4]
  },

模板

定义模板:使用 name 属性,作为模板的名字。然后在<template/>内定义代码片段,如:

<template name="one">
    <view>{{index}}</view>
    <view>{{color}}</view>
 </template>

 <template is="one" data="{{...wage}}"></template>
 <template is="one" data="{{...wage2}}"></template>
data:{
	wage:{
	      index:1,
	      color:"red"
	    },
   wage2:{
      index:2,
      color:"green"
    },
}

在这里插入图片描述

引用

WXML 提供两种文件引用方式importinclude,具体使用可直接查看官方文档

  • import可以在该文件中使用目标文件定义的template。( import 目标文件中定义的 template,而不会 import 目标文件 import 的 template。)
<!-- item.wxml -->
<template name="item">
  <text>{{text}}</text>
</template>

<!-- index.wxml -->
<import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/>
  • include 可以将目标文件除了 <template/> <wxs/> 外的整个代码引入,相当于是拷贝到 include 位置
<!-- index.wxml -->
<include src="header.wxml"/>
<view> body </view>
<include src="footer.wxml"/>

<!-- header.wxml -->
<view> header </view>
<!-- footer.wxml -->
<view> footer </view>

6. WXSS

WXSS是一套样式语言,用于描述 WXML 的组件样式。

WXSS 具有 CSS 大部分特性,同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。与 CSS 相比,WXSS 扩展的特性有:

  • 尺寸单位rpx
  • 样式导入@import

rpx

rpx 的实现原理非常简单:鉴于不同设备屏幕的大小不同,为了实现屏幕的自动适配,rpx 把所有设备的屏幕,在宽度上等分为 750 份(即:当前屏幕的总宽度为 750rpx)。

  • 在较小的设备上,1rpx 所代表的宽度较小
  • 在较大的设备上,1rpx 所代表的宽度较大

小程序在不同设备上运行的时候,会自动把 rpx 的样式单位换算成对应的像素单位来渲染,从而实现屏幕适配

建议开发微信小程序时设计师用 iPhone6 作为视觉稿的标准。
在这里插入图片描述
开发举例:在 iPhone6 上如果要绘制宽100px,高20px的盒子,换算成rpx单位,宽高分别为 200rpx40rpx

样式导入

使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用;表示语句结束。

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

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

对于内联样式,框架组件上支持使用 styleclass 属性来控制组件的样式。

  • style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。
<view style="color:{{color}};" />
  • class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上.,样式类名之间用空格分隔。
<view class="normal_view" />

全局样式与局部样式

定义在 app.wxss 中的样式为全局样式,作用于每一个页面。

在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器

7. 全局配置

小程序根目录下的 app.json 文件是小程序的全局配置文件。常用的配置项如下:

  • pages: 记录当前小程序所有页面的存放路径
  • window:全局的默认窗口效果
  • tabBar:底部 tab栏效果
  • style:是否启用新版的组件样式

window

用于设置小程序的状态栏、导航条、标题、窗口背景色。

在这里插入图片描述

导航栏区域

属性类型默认值描述最低版本
navigationBarBackgroundColorHexColor#000000导航栏背景颜色,如 #000000不支持red、pink等英文
navigationBarTextStylestringwhite导航栏标题颜色,仅支持 black / white
navigationBarTitleTextstring导航栏标题文字内容
navigationStylestringdefault导航栏样式,仅支持以下值: default 默认样式 custom 自定义导航栏,只保留右上角胶囊按钮iOS/Android 微信客户端 6.6.0,Windows 微信客户端不支持

背景区域

属性类型默认值描述最低版本
backgroundColorHexColor#ffffff窗口的背景色
backgroundTextStylestringdark下拉 loading 的样式,仅支持 dark / light
backgroundColorTopstring#ffffff顶部窗口的背景色,仅 iOS 支持微信客户端 6.5.16
backgroundColorBottomstring#ffffff底部窗口的背景色,仅 iOS 支持微信客户端 6.5.16

页面区域

属性类型默认值描述最低版本
enablePullDownRefreshbooleanfalse是否开启全局的下拉刷新。 详见 Page.onPullDownRefresh
onReachBottomDistancenumber50页面上拉触底事件触发时距页面底部距离,单位为 px。 详见 Page.onReachBottom

注意上拉触底是移动端的专有名词,通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为。

示例
开启下拉刷新才能看到背景区域
在这里插入图片描述

tabBar

tabBar 是移动端应用常见的页面效果,用于实现多页面的快速切换。小程序中通常将其分为:

  • 底部 tabBar
    在这里插入图片描述

  • 顶部 tabBar
    在这里插入图片描述
    注意:tabBar中只能配置最少 2 个、最多 5 个 tab 页签。当渲染顶部 tabBar 时,不显示 icon,只显示文本。

属性类型必填默认值描述最低版本
colorHexColortab 上的文字默认颜色,仅支持十六进制颜色
selectedColorHexColortab 上的文字选中时的颜色,仅支持十六进制颜色
backgroundColorHexColortab 的背景色,仅支持十六进制颜色
borderStylestringblacktabbar 上边框的颜色, 仅支持 black / white
listArraytab 的列表,详见 list 属性说明,最少 2 个、最多 5 个 tab
positionstringbottomtabBar 的位置,仅支持 bottom / top
custombooleanfalse自定义 tabBar,见详情2.5.0

在这里插入图片描述
其中 list 接受一个数组,只能配置最少 2 个、最多 5 个 tab。tab 按数组的顺序排序,每个项都是一个对象,其属性值如下:

属性类型必填说明
pagePathstring页面路径,必须在 pages 中先定义
textstringtab 上按钮文字
iconPathstring图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。 positiontop 时,不显示 icon。
selectedIconPathstring选中时的图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。 positiontop 时,不显示 icon。

示例

"tabBar": {
    "list": [{
      "pagePath": "pages/home/home",
      "text": "首页",
      "iconPath": "./image/home.png",
      "selectedIconPath": "./image/home-active.png"
    },
    {
      "pagePath": "pages/message/message",
      "text": "消息",
      "iconPath": "./image/message.png",
      "selectedIconPath": "./image/message -active.png"
    }
  ]
  },

在这里插入图片描述

8. 网络数据请求

出于安全性方面的考虑,小程序官方对数据接口的请求做出了如下两个限制:

  • 只能请求 HTTPS 类型的接口
  • 必须将接口的域名添加到信任列表中
  • 域名不能使用 IP 地址(小程序的局域网 IP 除外)或 localhost;
  • 域名必须经过 ICP 备案;
  • 不支持配置父域名,使用子域名
  • 服务器域名一个月内最多可申请 5 次修改

可以通过以下步骤将接口的域名添加到信任列表中:

登录微信小程序管理后台 -> 开发 -> 开发管理 -> 开发设置 -> 服务器域名 -> 修改 request 合法域名

修改后可在:
在这里插入图片描述

跳过 request 合法域名校验

如果后端程序员仅仅提供了 http 协议的接口、暂时没有提供 https 协议的接口。
此时为了不耽误开发的进度,我们可以在微信开发者工具中,临时开启开发环境不校验请求域名、TLS 版本及 HTTPS 证书选项,跳过 request 合法域名的校验。

在这里插入图片描述
注意:跳过 request 合法域名校验的选项,仅限在开发与调试阶段使用!

wx.request

wx.request用于发起 HTTPS 网络请求。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
示例:发起get请求

wx.request({
   url: 'https://www.escook.cn/api/get',
   method:"GET",
   data:{
     name:'zs',
     age:20
   },
   success:res=>{
     console.log(res);
   }
 })

注意事项

跨域问题只存在于基于浏览器的 Web 开发中。由于小程序的宿主环境不是浏览器,而是微信客户端,所以小程序中不存在跨域的问题

Ajax 技术的核心是依赖于浏览器中的 XMLHttpRequest 这个对象,由于小程序的宿主环境是微信客户端,所以小程序中不能叫做“发起 Ajax 请求”,而是叫做发起网络数据请求

9. 页面导航

小程序中实现页面导航的两种方式

(1) 声明式导航

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

(2)编程式导航

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

声明式导航

tabBar 页面指的是被配置为 tabBar 的页面。

1、导航到 tabBar 页面

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

  • url 表示要跳转的页面的地址
  • open-type 表示跳转的方式,必须为 switchTab
<navigator url="/pages/message/message" open-type="switchTab">导航到消息页面</navigator>

2、导航到非tabBar 页面

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

  • url 表示要跳转的页面的地址
  • open-type 表示跳转的方式,必须为 navigate。默认值本身就是navigate,所以该属性可以不写。
<navigator url="/pages/info/info" open-type="navigate">导航到info页面</navigator>
<navigator url="/pages/info/info">导航到info页面</navigator>

3、后退导航

如果要后退到上一页面或多级页面,则需要指定 open-type 属性和 delta 属性,其中:

  • open-type 的值必须是 navigateBack,表示要进行后退导航
  • delta 的值必须是数字,表示要后退的层级
<navigator open-type="navigateBack" delta="1" >返回上一页</navigator>

注意:为了简便,如果只是后退到上一页面,则可以省略 delta 属性,因为其默认值就是 1。

4、声明式导航传参
navigator 组件的 url 属性用来指定将要跳转到的页面的路径。同时,路径的后面还可以携带参数:

参数与路径之间使用 ? 分隔,参数键与参数值用 = 相连,不同参数用&分隔

<navigator url="/pages/info/info?name=zs&age=20" open-type="navigate">导航到info页面</navigator>

编程式导航

1、导航到 tabBar 页面
wx.switchTab(Object object)跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面

属性类型默认值必填说明
urlstring需要跳转的 tabBar 页面的路径 (代码包路径)(需在 app.json 的 tabBar 字段定义的页面),路径后不能带参数
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束的回调函数(调用成功、失败都会执行)

示例

<button bindtap="gotoMessage">跳转到消息界面</button>
gotoMessage(){
    wx.switchTab({
      url: '/pages/message/message',
    })
  },

2、导航到非 tabBar 页面
wx.navigateTo(Object object)保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面

使用 wx.navigateBack 可以返回到原页面。小程序中页面栈最多十层。

属性类型默认值必填说明
urlstring需要跳转的应用内非 tabBar 的页面的路径 (代码包路径), 路径后可以带参数。参数与路径之间使用 ? 分隔,参数键与参数值用 = 相连,不同参数用 & 分隔;如 ‘path?key=value&key2=value2’
eventsObject页面间通信接口,用于监听被打开页面发送到当前页面的数据。基础库 2.7.3 开始支持。
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束的回调函数(调用成功、失败都会执行)

示例

<button bindtap="gotoInfo">跳转到信息界面</button>
gotoInfo(){
    wx.navigateTo({
      url: '/pages/info/info',
    })
  },

3、 后退导航

wx.navigateBack(Object object)关闭当前页面,返回上一页面或多级页面。

属性类型默认值必填说明
deltanumber1返回的页面数,如果 delta 大于现有页面数,则返回到首页。
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束的回调函数(调用成功、失败都会执行)

示例

<button bindtap="goBack">后退</button>
goBack(){
    wx.navigateBack()
},

onLoad(Object query)

onLoad(Object query)在页面加载时触发。一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数

<navigator url="/pages/info/info?name=zs&age=20" open-type="navigate">导航到info页面</navigator>

在这里插入图片描述
一般我们会在data中定义一个query变量,然后通过this.setData赋值给该变量,这样其他函数就可以使用该参数了。

onLoad(options) {
    console.log(options);
    this.setData({
      query:options
    })
},

10. 页面事件

onPullDownRefresh

app.json的window选项中或页面配置中将enablePullDownRefresh设置为true就可以启动下拉刷新。

在实际开发中,推荐使用第 2 种方式,为需要的页面单独开启下拉刷新的效果。

在页面的.js 文件中,通过 onPullDownRefresh() 函数即可监听当前页面的下拉刷新事件。

示例

<view>count的值为:{{count}}</view>
<button bindtap="addCount">加一</button>
addCount(){
    this.setData({
      count:this.data.count+1
    })
},

onPullDownRefresh() {
    this.setData({
      count:0
    })
},

stopPullDownRefresh

当处理完下拉刷新后,下拉刷新的 loading 效果会一直显示,不会主动消失,所以需要手动隐藏下拉刷新的loading 效果。

而调用 wx.stopPullDownRefresh() 可以自动停止当前页面的下拉刷新。

onPullDownRefresh() {
    this.setData({
      count:0
    })
    wx.stopPullDownRefresh();
},

onReachBottom

上拉触底是移动端的专有名词,通过手指在屏幕上的上拉滑动操作,从而加载更多数据的行为

在页面的 .js 文件中,通过 onReachBottom() 函数即可监听当前页面的上拉触底事件

  • 可以在app.jsonwindow选项中或页面配置中设置触发距离onReachBottomDistance
  • 在触发距离内滑动期间,本事件只会被触发一次
 onReachBottom() {
    console.log('触发了上拉触底事件');
  },

案例

滑动页面快到达底部时触发onReachBottom事件,在 onReachBottom事件中请求数据
在这里插入图片描述

<view wx:for="{{colorList}}" wx:key="index" class="num-item" style="background-color: rgb({{item}});">{{item}}</view>
/* pages/contact/contact.wxss */
.num-item{
  border: 1rpx solid #efefef;
  border-radius: 8rpx;
  line-height: 200rpx;
  margin: 15px;
  text-align: center;
  box-shadow: 1rpx,1rpx,6rpx,#aaa;
}
data: {
    colorList:[]
  },
  
getColors(){
    wx.showLoading({
      title: '数据加载中...',
      mask:true
    })
    wx.request({
      url: 'https://www.escook.cn/api/color',
      method:'get',
      success:(res)=>{
        this.setData({
          colorList:this.data.colorList.concat(res.data.data)
        })
      },
      complete:()=>{
        wx.hideLoading()
      }
    })
  },
  
onLoad(options) {
    this.getColors()
  },
  
onReachBottom() {
    this.getColors()
  },

11. 生命周期

APP

包含如下三个生命周期函数,onLaunch只运行一次,而onShowonHide在小程序的生命周期中会运行多次

App({

   //当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
  onLaunch: function () {
    console.log('onLaunch')
  },
  // 也可以使用 wx.onAppShow 绑定监听
  //当小程序启动,或从后台进入前台显示,会触发 onShow
  onShow: function (options) {
    console.log('onShow');
  },
  // 也可以使用 wx.onAppHide 绑定监听
 // 当小程序从前台进入后台,会触发 onHide
  onHide: function () {
    console.log('onHide');
  },
})

注意Object wx.getLaunchOptionsSync()可以获取小程序启动时的参数。

Page

注意:对界面内容进行设置的 API 如wx.setNavigationBarTitle,请在onReady之后进行。

函数类型说明
onLoadfunction监听页面加载,一个页面只调用一次
onShowfunction监听页面显示 ,切换到前台
onReadyfunction监听页面初次渲染完成,一个页面只调用一次
onHidefunction监听页面隐藏
onUnloadfunction监听页面卸载,一个页面只调用一次

12. WXS

WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。

  • WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致。
  • WXS 的运行环境和其他 JavaScript 代码是隔离的,WXS 中不能调用其他 JavaScript 文件中定义的函数,也不能调用小程序提供的API。
  • WXS 函数不能作为组件的事件回调
  • 由于运行环境的差异,在 iOS 设备上小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍。在 android 设备上二者运行效率无差异
<!-- 错误 -->
<button bindtap="m2.toLower">按钮</button>

wxs 不支持类似于 ES6 及以上的语法形式:

  • 不支持:let、const、解构赋值、展开运算符、箭头函数、对象属性简写、etc…
  • 支持:var 定义变量、普通 function 函数等类似于 ES5 的语法

wxs 遵循 CommonJS 规范:

module 对象:每个 wxs 模块均有一个内置的 module 对象

module.exports :通过该属性,可以对外共享本模块的私有变量与函数。

require() 函数:在.wxs模块中引用其他 wxs 文件模块,可以使用 require 函数。

(1)只能引用 .wxs 文件模块,且必须使用相对路径
(2)wxs 模块均为单例,wxs 模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个 wxs 模块对象
(3)如果一个 wxs 模块在定义之后,一直没有被引用,则该模块不会被解析与运行


WXS 代码可以编写在 wxml 文件中的<wxs>标签内,或以.wxs为后缀名的文件内

每一个 .wxs 文件和 <wxs> 标签都是一个单独的模块。每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见。一个模块要想对外暴露其内部的私有变量与函数,只能通过 module.exports 实现

内嵌WXS脚本

wxs 代码可以编写在 wxml 文件中的 <wxs> 标签内,就像 Javascript 代码可以编写在 html 文件中的<script>标签内一样。

wxs标签的参数有:

  • module:当前 <wxs> 标签的模块名(必填字段)。
  • src:引用 .wxs 文件的相对路径。仅当本标签为单闭合标签标签的内容为空时有效。

内联式 WXS如下:

<view>{{m1.toUpper(username)}}</view>
<view>{{m1.msg}}</view>

<wxs module='m1'>
  function  toUpper(str){
    return str.toUpperCase();
  }
  var msg='success';
  // 不能使用对象的简写形式
  module.exports={
    toUpper:toUpper,
    msg:msg
  }
</wxs>

外联WXS脚本

wxs 代码还可以编写在以 .wxs 为后缀名的文件内,就像 javascript 代码可以编写在以.js 为后缀名的文件中一样

tools.js

function toLower(str){
  return str.toLowerCase()
}
module.exports={
  toLower:toLower
}

引入并使用

<!-- <wxs src="../../utils/tools.wxs" module="m2"></wxs> -->
<wxs src="../../utils/tools.wxs" module="m2"/>
<view>{{m2.toLower(username)}}</view>

13. 组件

自定义组件

1、创建组件

  • 在项目的根目录中,鼠标右键,创建 components -> test 文件夹
  • 在新建的 components -> test 文件夹上,鼠标右键,点击“新建 Component”
  • 键入组件的名称之后回车,会自动生成组件对应的 4 个文件,后缀名分别为 .js.json.wxml.wxss
    在这里插入图片描述

2、引用组件

  • 局部引用:组件只能在当前被引用的页面内使用。在页面的 .json 配置文件中引用组件的方式,叫做局部引用
{
  "usingComponents": {
    "my-test1":"/components/test/test"
  }
}
  • 全局引用:组件可以在每个小程序页面中使用。在 app.json 全局配置文件中引用组件的方式,叫做全局引用
"usingComponents": {
    "my-test2":"./components/test/test"
  },

3、组件和页面的区别

从表面来看,组件和页面都是由 .js、.json、.wxml 和 .wxss 这四个文件组成的。但是,组件和页面的 .js.json 文件有明显的不同

  • 组件的 .json 文件中需要声明 "component": true 属性
  • 组件的 .js 文件中调用的是 Component() 函数
  • 组件的事件处理函数需要定义到 methods 节点中

4、组件样式隔离

默认情况下,自定义组件的样式只受到自定义组件 wxss 的影响。除非以下两种情况:
(1)app.wxss 或页面的wxss中使用了标签名选择器(id 选择器、属性选择器或一些其他特殊选择器)来直接指定样式,这些选择器会影响到页面和全部组件。

(2)指定特殊的样式隔离选项 styleIsolation

// .js文件
Component({
  options: {
    styleIsolation: 'isolated'
  }
})
// 或在.json 文件
"styleIsolation":"shared"

styleIsolation 选项从基础库版本 2.6.5 开始支持。它支持以下取值:

  • isolated 表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(默认值);
  • apply-shared 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面;
  • shared 表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置了 apply-shared 或 shared 的自定义组件。(这个选项在插件中不可用。)

methon

在小程序组件中,事件处理函数和自定义方法需要定义到 methods 节点中,建议自定义方法以_开头(如_showCount),用于区分自定义方法和事件处理函数。

properties

在小程序组件中,properties 是组件的对外属性,用来接收外界传递到组件中的数据

properties: {
      max1:{
        type:Number,
        value:10
      },
      max2:Number
  },
<my-test2 max1="20" max2="30">hhh</my-test2>

执行如下代码,发现data和properties指向同一个对象

console.log(this.data===this.properties); //true
console.log(this.data);
console.log(this.properties);

在这里插入图片描述
properties 属性的值也可以用于页面渲染,或使用 setData 为 properties 中的属性重新赋值

数据监听

数据监听器可以用于监听和响应任何属性和数据字段的变化。

  • 数据监听器监听的是 setData 涉及到的数据字段,即使这些数据字段的值没有发生变化,数据监听器依然会被触发。

  • 如果在数据监听器函数中使用 setData 设置本身监听的数据字段,可能会导致死循环

observers: {
    'numberA, numberB': function(numberA, numberB) {
      // 在 numberA 或者 numberB 被设置时,执行这个函数
      this.setData({
        sum: numberA + numberB
      })
    }
  }

注意:如果监听的是对象,当对象的属性发生变化时,监听事件不会被触发。

数据监听器支持监听属性或内部数据的变化,可以同时监听多个

Component({
  observers: {
    'some.subfield': function(subfield) {
      // 使用 setData 设置 this.data.some.subfield 时触发
      // (除此以外,使用 setData 设置 this.data.some 也会触发)
      subfield === this.data.some.subfield
    },
    'arr[12]': function(arr12) {
      // 使用 setData 设置 this.data.arr[12] 时触发
      // (除此以外,使用 setData 设置 this.data.arr 也会触发)
      arr12 === this.data.arr[12]
    },
  }
})

如果需要监听所有子数据字段的变化,可以使用通配符**

observers: {
    'some.field.**': function(field) {
      // 使用 setData 设置 this.data.some.field 本身或其下任何子数据字段时触发
      // (除此以外,使用 setData 设置 this.data.some 也会触发)
      field === this.data.some.field
    },
  },

仅使用通配符 ** 可以监听全部 setData 。

 observers: {
    '**': function() {
      // 每次 setData 都触发
    },
  }

纯数据字段

有些情况下,某些 data 中的字段(包括 setData 设置的字段)既不会展示在界面上,也不会传递给其他组件,仅仅在当前组件内部使用。此时,可以指定这样的数据字段为纯数据字段,它们将仅仅被记录在 this.data 中,而不参与任何界面渲染过程,这样有助于提升页面更新性能。

指定纯数据字段的方法是在 Component 构造器的 options 定义段中指定 pureDataPattern 为一个正则表达式,字段名符合这个正则表达式的字段将成为纯数据字段。

Component({
  options: {
    pureDataPattern: /^_/ // 指定所有 _ 开头的数据字段为纯数据字段
  },
  data: {
    a: true, // 普通数据字段
    _b: true, // 纯数据字段
  },
  properties: {
    c: Boolean,
    _d: Boolean
  }
  methods: {
    myMethod() {
      this.data._b // 纯数据字段可以在 this.data 中获取
      this.setData({
        c: true, // 普通数据字段
        _d: true, // 纯数据字段
      })
    }
  }
})

组件的生命周期

组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发

最重要的生命周期是 createdattacheddetached,包含一个组件实例生命流程的最主要时间点。

  • created :组件实例刚刚被创建好时, created 生命周期被触发。此时,组件数据 this.data 就是在 Component 构造器中定义的数据 data 。 此时还不能调用 setData 。 通常情况下,这个生命周期只应该用于给组件 this 添加一些自定义属性字段。
  • attached:在组件完全初始化完毕、进入页面节点树后, attached 生命周期被触发。此时, this.data 已被初始化为组件的当前值。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行。
  • detached:在组件离开页面节点树后, detached 生命周期被触发。退出一个页面时,如果组件还在页面节点树中,则 detached 会被触发。
生命周期参数描述最低版本
created在组件实例刚刚被创建时执行1.6.3
attached在组件实例进入页面节点树时执行1.6.3
ready在组件在视图层布局完成后执行1.6.3
moved在组件实例被移动到节点树另一个位置时执行1.6.3
detached在组件实例被从页面节点树移除时执行1.6.3
errorObject Error每当组件方法抛出错误时执行2.4.1

在小程序组件中,生命周期函数可以直接定义在 Component 构造器的第一级参数中,可以在 lifetimes 字段内进行声明(这是推荐的方式,其优先级最高)。示例代码如下:

Component({
  lifetimes: {
    attached: function() {
      // 在组件实例进入页面节点树时执行
    },
    detached: function() {
      // 在组件实例被从页面节点树移除时执行
    },
  },
  // 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
  attached: function() {
    // 在组件实例进入页面节点树时执行
  },
  detached: function() {
    // 在组件实例被从页面节点树移除时执行
  },
  // ...
})

有时,自定义组件的行为依赖于页面状态的变化,此时就需要用到组件所在页面的生命周期。组件所在页面的生命周期在 pageLifetimes 定义段中定义。

生命周期参数描述最低版本
show组件所在的页面被展示时执行2.2.3
hide组件所在的页面被隐藏时执行2.2.3
resizeObject Size组件所在的页面尺寸变化时执行2.4.0
Component({
  pageLifetimes: {
    show: function() {
      // 页面被展示
    },
    hide: function() {
      // 页面被隐藏
    },
    resize: function(size) {
      // 页面尺寸变化
    }
  }
})

behaviors

behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的 mixins

每个 behavior 可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。

每个组件可以引用多个 behavior ,behavior 也可以引用其它 behavior

// my-component.js
var myBehavior = require('my-behavior')
Component({
  behaviors: [myBehavior],
  properties: {
    myProperty: {
      type: String
    }
  },
  data: {
    myData: 'my-component-data'
  },
  created: function () {
    console.log('[my-component] created')
  },
  attached: function () { 
    console.log('[my-component] attached')
  },
  ready: function () {
    console.log('[my-component] ready')
  },
  methods: {
    myMethod: function () {
      console.log('[my-component] log by myMethod')
    },
  }
})

而 my-behavior 结构为:

// my-behavior.js
module.exports = Behavior({
  behaviors: [],
  properties: {
    myBehaviorProperty: {
      type: String
    }
  },
  data: {
    myBehaviorData: {}
  },
  methods: {
    myBehaviorMethod: function(){}
  }
})

生命周期函数:attached、created、ready

这将使 my-component 最终结构为:

属性:myBehaviorProperty、myProperty
数据字段:myBehaviorData、myData
方法:myBehaviorMethod、myMethod
生命周期函数:attached、created、ready

当组件触发生命周期时,上例生命周期函数执行顺序为:

[my-behavior] created
[my-component] created
[my-behavior] attached
[my-component] attached
[my-behavior] ready
[my-component] ready

如果同一个 behavior 被一个组件多次引用,它定义的生命周期函数只会被执行一次

内置 behaviors: 自定义组件可以通过引用内置的 behavior 来获得内置组件的一些行为。

Component({
	// 它使得这个自定义组件有类似于表单控件的行为
  behaviors: ['wx://form-field']
})

其他内置behaviors 可查看官方文档

slot

在自定义组件的 wxml 结构中,可以提供一个 <slot> 节点(插槽),用于承载组件使用者提供的 wxml 结构。一个插槽里可以放多个标签

<!-- 组件模板 -->
<view class="wrapper">
  <view>这里是组件的内部节点</view>
  <slot></slot>
</view>

<!-- 引用组件的页面模板 -->
<view>
  <component-tag-name>
    <!-- 这部分内容将被放置在组件 <slot> 的位置上 -->
    <view>这里是插入到组件 slot 中的内容</view>
  </component-tag-name>
</view>

默认情况下,一个组件的 wxml 中只能有一个 slot。需要使用多 slot 时,可以在组件 js 中声明启用。

Component({
  options: {
    multipleSlots: true // 在组件定义时的选项中启用多 slot 支持
  },
  properties: { /* ... */ },
  methods: { /* ... */ }
})

在这个组件的 wxml 中使用多个 slot ,以不同的 name 来区分

<!-- 组件模板 -->
<view class="wrapper">
  <slot name="before"></slot>
  <view>这里是组件的内部细节</view>
  <slot name="after"></slot>
</view>

使用时,用 slot 属性来将节点插入到不同的 slot 上。

<!-- 引用组件的页面模板 -->
<view>
  <component-tag-name>
    <!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 -->
    <view slot="before">这里是插入到组件slot name="before"中的内容</view>
    <!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 -->
    <view slot="after">这里是插入到组件slot name="after"中的内容</view>
  </component-tag-name>
</view>

组件间通信

  • 属性绑定:用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容的数据
  • 事件绑定:用于子组件向父组件传递数据,可以传递任意数据。
  • 获取组件实例:父组件还可以通过 this.selectComponent 方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法。

属性绑定

具体使用可查看13大点中的 properties

事件绑定

home.wxml
在父组件的 wxml 中,通过自定义事件的形式,将函数引用传递给子组件

<my-test4 bind:sync="syncCount"></my-test4>

home.js

syncCount(e){
    console.log(e);
  },

test4.wxml

<button bindtap="onTap">111</button>

test4.js
在子组件的 js 中,通过调用 this.triggerEvent('自定义事件名称', obj) ,将数据发送到父组件

onTap(){
   var q={
     student:'xxx'
   }
   this.triggerEvent('sync',q)
 }

输出如下

在父组件的 js 中,通过 e.detail 获取到子组件传递过来的数据
在这里插入图片描述

获取组件实例

可在父组件里调用 this.selectComponent ,获取子组件的实例对象。调用时需要传入一个匹配选择器 selector,如:this.selectComponent(".my-component")
在这里插入图片描述

<my-test4  class="test4"></my-test4>
<button bindtap="onTap">222</button>
onTap(){
    const child = this.selectComponent('.test4')
    console.log(child);
  },

在这里插入图片描述

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焦妮敲代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值