微信小程序基础

小程序目录结构

├── pages ······································ 【目录】存放所有的小程序页面
│   │── index ···································· 【目录】index 页面
│   │   ├── index.wxml ······························· 【文件】 index 页面的结构
│   │   ├── index.js ································· 【文件】 index 页面的逻辑
│   │   ├── index.json ······························· 【文件】 index 页面的配置
│   │   └── index.wxss ······························· 【文件】 index 页面的样式
│   └── logs ····································· 【目录】 logs 页面
│       ├── logs.wxml ································ 【文件】 logs 页面的结构
│       └── logs.js ·································· 【文件】 logs 页面的逻辑
└── utils ······································ 【目录】 存放小程序中用到的工具函数
├── app.js ····································· 【文件】 小程序逻辑
├── app.json ··································· 【文件】 小程序的公共配置
├── app.wxss ··································· 【文件】小程序公共样式表
├── project.config.json ························ 【文件】 开发工具配置文件

说明

  • app.js是小程序的入口文件,运行小程序,第一个被运行的就是app.js
  • app.json是小程序的全局配置文件,对小程序每个页面生效
  • app.wxss是小程序的全局样式文件,对小程序每个页面生效
    注意
  • 对于小程序运行而言,app.jsapp.json是必不可少的
  • 对于小程序而言,.js.wxml文件时必不可少的

小程序页面结构

  • 每个小程序页面,是由 .wxml 结构、.js 逻辑文件、.json 配置、.wxss 样式表这四部分组成的

小程序页面中每个文件的作用

  • .wxml : 用来描述当前这个页面的标签结构,同时提供了类似于 Vue 中指令的语法
  • .js : 用来定义当前页面中用到的数据、交互逻辑和响应用户的操作
  • .json : 用来定义当前页面的个性化配置,例如,为每个页面单独配置顶部颜色、是否允许下拉刷新等
  • .wxss : 用来定义样式来美化当前的页面

修改小程序项目的默认首页

  • 打开 app.json 全局配置文件,找到 pages 节点。这个 pages 节点是一个数组,存储了项目中所有页面的访问路径。其中,pages 数组中第一个页面路径,就是小程序项目的默认首页。
  • 所以只需要修改 pages 数组中路径的顺序,就可以可修改小程序的默认首页。

text文本组件的用法

属性类型默认值必填说明
selectablebooleanfalse文本是否可选
spacestring.显示连续空格,可选参数书:ensp、emsp、nbsp
decodebooleanfalse是否解码
  • text 组件相当于行内标签、在同一行显示
  • 除了文本节点以外的其他节点都无法长按选中
<view>
  <!-- 长按文本是否可选 -->
  <text selectable='true'>web</text>
</view>

<view>
  <!-- 显示连续空格的方式 -->
  <view>
    <text space='ensp'>H  a  c  k</text>
  </view>
  <view>
    <text space='emsp'>H  a  c  k</text>
  </view>
  <view>
    <text space='nbsp'>H  a  c  k</text>
  </view>
</view>

<view>
  <text>skyblue</text>
</view>

<view>
  <!-- 是否解码 -->
  <text decode='true'>&nbsp; &lt; &gt; &amp; &apos; &ensp; &emsp;</text>
</view>

view视图容器组件的用法

类似于html中的div

属性类型默认值必填说明
hover-classstringnone指定按下去的样式类。当hover-class="none"时候,没有点击效果
hover-stop-propagationbooleanfalse指定是否阻止本节点的祖先节点出现点击效果
hover-start-timenumber50按住后多久出现点击效果,单位毫秒
hover-stay-timenumber400手指松开后点击效果保留时间,单位毫秒
<view hover-class='box1'>
  <view
    hover-stop-propagation='true'
    hover-class='box'
    hover-start-time='2000'
    hover-stay-time='3000'>
    box1
  </view>
</view>

button组件

属性名类型默认值说明
sizeStringdefault按钮的大小
typeStringdefault按钮的样式类型
plainBooleanfalse按钮是否镂空,背景色透明
disabledBooleanfalse是否按钮
loadingBooleanfalse名称是否带 loading图标
  • button 组件默认独占一行,设置 sizemini 时可以在一行显示多个
<button size='mini' type='primary'>前端</button>
<button size='mini' type='default' disabled='true'>前端</button>
<button size='mini' type='warn' loading='true'>前端</button>

input文本输入框组件的用法

属性名类型默认值说明
valueString.输入框的初始内容
typeString‘text’input 的类型
passwordBooleanfalse是否是密码类型
placeholderSting.输入框为空时占位符
disabledBooleanfalse是否禁用
maxlengthNumber140最大输入长度,设置 -1 时不限制最大长度
<input placeholder='111' type='idcard' placeholder-style="color: skyblue" />

image图片组件的用法

  • src – 支持本地和网络上的图片
  • mode – 指定图片的裁剪、缩放的模式
  • image 组件默认的宽度是 300px高度是225px
  • image组件中二维码/小程序码图片不支持长按识别
<image src='/assets/5.jpg' mode='aspectFit'></image>
<image src='https://wx.qlogo.cn/mmhead/Q3auHgzwzM7teJKyb7Oicw6x2rDiaD5BkDPFP2kccFO6a566TzzUyUgA/0' mode='widthFix'></image>

wxss中常用的样式选择器

WXSS 是一套样式语言,用来决定 WXML 的组件应该怎么显示

支持的选择器

  • 标签选择器
  • id选择器
  • class选择器
  • 伪类选择器
  • data-*属性选择器
  • :nth-of-type() 等常用的 css3 选择器
  • 其他…
view {
  font-size: 12px;
}

#box {
  color: skyblue;
}

.box {
  color: lightcoral;
}

.box1::before {
  content: '加油';
  color: lightgreen;
}

view:nth-of-type(4) {
  color: lightseagreen;
}

[data-color='pink'] {
  color: pink;
}

rpx尺寸单位

rpx: 是微信小程序独有的,解决屏幕自适应的尺寸单位

  • 可以根据屏幕宽度进行自适应,不论屏幕大小,规定屏幕宽为 750rpx
  • 通过 rpx 设置元素和字体的大小,小程序在不同尺寸的屏幕上,可以实现自动适配

rpxpx 之间的换算

  • iPhone6 为例,iPhone6 的屏幕宽度为 375px ,共有 750 个物理像素,则 750rpx = 375px = 750 物理像素
  • 1rpx=0.5px=1物理像素
设备rpx 换算 px (屏幕宽度/750)px 换算 rpx (750/屏幕宽度)
iPhone51rpx = 0.42px1px = 2.34rpx
iPhone61rpx = 0.5px1px = 2rpx
iPhone6 Plus1rpx = 0.552px1px = 1.81rpx

那么也就是说:如果在iPhone6上,
如果要绘制宽100px,高20px的盒子,换算成rpx单位,
宽高分别为 200rpx40rpx

@import样式导入

  • 使用 @import 语句可以导入外联样式表
  • 语法格式:@import "wxss 样式表文件的相对路径"
@import "/assets/common/common.wxss";
/* @import "../../assets/common/common.wxss"; */

.box {
  width: 375rpx;
  height: 375rpx;
  background-color: skyblue;
}

全局样式与局部样式

全局样式

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

局部样式

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

注意:当局部样式的权重大于或等于全局样式的权重时,才会覆盖全局的样式效果!

app.json配置文件

小程序根目录下的 app.json 文件用来对微信小程序进行全局配置,它决定了页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。

app.json 配置文件中,最主要的配置节点是:

  • pages 数组:配置小程序的页面路径
  • window 对象:用于设置小程序的状态栏、导航条、标题、窗口背景色
  • tabBar 对象:配置小程序的tab栏效果

pages数组的用法

  • app.json 中的 pages 数组,用来配置小程序的页面路径

基础配置

  • pages 用于指定小程序由哪些页面组成,每一项都对应一个页面的 路径+文件名 信息。
  • 文件名不需要写文件后缀,框架会自动去寻找对应位置的 .json.js.wxml.wxss 四个文件进行处理。

创建页面的另一种方式

  • 打开 app.json --> pages 数组节点 --> 新增页面路径并保存 --> 自动创建路径对应的页面

设置项目的首页

  • 打开 app.json -> pages 数组节点
  • 按需调整数组中路径的顺序,即可修改默认首页

注意事项:

  • 数组的第一项代表小程序的小程序的初始页面也就是首页
  • 小程序中新增/减少页面,都需要对 pages 数组进行修改,否则在运行小程序时就会报错

app.jsonwindow对象的设置

设置导航栏标题文字内容

  • app.json—> window—>navigationBarTextStyle
  • 将属性值修改即可

设置导航栏背景色

  • app.json–>window–>navigationBarBackgroundColor
  • 将属性值修改为指定的颜色就可以

设置导航栏标题颜色

  • app.json --> window --> navigationBarTextStyle
  • 将属性值修改为指定的颜色就可以

全局开启下拉刷新功能

  • app.json --> window --> 把 enablePullDownRefresh 的值设置为 true

通过手指在屏幕上的下拉滑动操作,从而重新加载页面数据的行为

设置下拉刷新窗口的背景色

  • app.json -> window -> backgroundColor

当全局开启下拉刷新功能之后,默认的窗口背景为白色

设置下拉loading的样式

当全局开启下拉刷新功能之后,默认窗口的loading样式为白色

  • app.json --> window --> backgroundTextStyle

设置上拉触底的距离

  • app.json --> window --> onReachBottomDistance

手指在屏幕上的上拉滑动操作,从而加载更多数据的行为

注意: 默认距离为 50px,如果没有特殊需求,建议使用默认值即可

tabBar

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

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

tarbar组成部分

  • backgroundColor:导航条背景色
  • selectedIconPath:选中时的图片路径
  • borderStyletabBar上边框的颜色
  • iconPath:未选中时的图片路径
  • selectedColortab 上的文字选中时的颜色
  • colortab 上的文字默认(未选中)颜色

tarbar节点配置

属性类型必填默认值描述
colorHexColor.tab 上的文字默认颜色,仅支持十六进制颜色
selectedColorHexColor.tab 上的文字选中时的颜色,仅支持十六进制颜色
backgroundColorHexColor.tab 的背景色,仅支持十六进制颜色
borderStylestringblacktabBar 上边框的颜色, 仅支持 black / white
listArray.tab 的列表,详见 list 属性说明,最少 2 个、最多 5 个 tab
positionstringbottomtabBar 的位置,仅支持 bottom/ top
custombooleanfalse自定义 tabBar

** list 节点的配置项**

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

注意:

  • 都不支持网络图片
  • 当 position 为 top 时,不显示 icon。

页面配置

页面配置和局部配置的关系

  • app.json 中的 window 节点,可以全局配置小程序中每个页面的窗口表现;
  • 如果某些小程序页面,想要拥有特殊的窗口表现,此时,“页面级别的 .json 配置文件”就可以实现这种需求;

生命周期

生命周期(Life Cycle)是指一个对象从 创建 -> 运行 -> 销毁 的整个阶段,强调的是一个时间段。

小程序的生命周期

  • 小程序的启动,表示生命周期的开始
  • 小程序的关闭,表示生命周期的结束
  • 中间小程序运行的过程,就是小程序的生命周期

小程序生命周期的两种类型

  • 应用生命周期:特指小程序从启动 --> 运行 --> 销毁的过程;
  • 页面生命周期:特指小程序中,每个页面的加载 --> 渲染 --> 销毁的过程;

注意:页面的生命周期范围较小,应用程序的生命周期范围较大

小程序框架提供的内置函数,会伴随着生命周期,自动按次序执行

生命周期函数的作用:

  • 允许程序员在特定的生命周期时间点上,执行某些特定的操作。例如,页面刚加载的时候,在生命周期函数中自动发起数据请求,获取当前页面的数据;

注意:生命周期强调的是时间段,生命周期函数强调的是时间点。

应用生命周期函数

  • app.js 是小程序执行的入口文件,在 app.js 中必须调用 App() 函数,且只能调用一次。其中,App() 函数是用来注册并执行小程序的。
  • App(Object) 函数接收一个 Object 参数,可以通过这个 Object 参数,指定小程序的生命周期函数。
App({

  /**
   * 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
   */
  onLaunch: function () { },

  /**
   * 当小程序启动,或从后台进入前台显示,会触发 onShow
   */
  onShow: function (options) { },

  /**
   * 当小程序从前台进入后台,会触发 onHide
   */
  onHide: function () { },

  /**
   * 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
   */
  onError: function (msg) { }
})

页面生命周期函数

  • 每个小程序页面,必须拥有自己的 .js 文件,且必须调用 Page() 函数,否则报错。其中 Page() 函数用来注册小程序页面。
  • Page(Object) 函数接收一个 Object 参数,可以通过这个 Object 参数,指定页面的生命周期函数。
//index.js
//获取应用实例
const app = getApp()

Page({

  /**
   * 页面的初始数据
   */
  data: { },

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

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

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

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () { },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () { },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () { },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () { },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () { }
})

数据绑定

.js文件中定义数据

  • .js 文件内定义页面的数据,只需把数据定义在 data 节点下即可

Mustache语法格式

  • data 中的数据绑定到页面中渲染,使用 Mustache 语法(双大括号) 将变量包裹起来即可
<view>{{ info }}</view>

Mustache 语法的主要场景

  • 绑定内容
  • 绑定属性
  • 运算(三元表达式、算术运算、逻辑判断、字符串运算、数据路径运算)
<!-- 页面结构 -->

<!-- 绑定内容和属性 -->
<view id="item-{{id}}">{{ info }}</view>

<!-- 算数运算 -->
<view>{{ 1 + 1 }}</view>

<!-- 三元表达式 -->
<view>{{ id == 10 ? "正确" : "错误" }}</view>
// 页面数据

Page({
  data: {
  	info: 'i miss you',
    id: 10,
    arr: [1, 2, 3]
  }
})

小程序中的事件

bindtap 绑定触摸事件

  • 在小程序中,不存在网页中的 onclick 鼠标点击事件,而是通过 tap 事件来响应触摸行为
  • 在小程序中,可以通过 input 事件来响应文本框内的输入事件
  • 使用 bindinput 为文本框绑定输入事件

data 和 文本框之间的数据同步

  • 在文本框的 input 事件处理函数中,通过事件参数 event ,能够访问到文本框的最新值
  • 语法结构 event.detail.value
  • 通过 this.setData(dataObject) 方法,可以把页面中的 data 数据重新赋值
<!-- 页面结构 -->

<button bindtap='handle' type='warn'>我是按钮</button>

<input bindinput='inputHandle' value='输入框'></input>

<input bindinput='datasync' value='{{ msg }}'></input>
// 页面逻辑

Page({
  data: {
    msg: ''
  },
   
  handle: function (event) {
    console.log('按钮绑定的事件')
    console.log(event)
  },

  inputHandle: function (e) {
    console.log(e)
  },

  // 数据同步演示
  datasync: function (e) {
    console.log(e.detail.value)
    
    this.setData({
      msg: e.detail.value
    })
  }
  
  // coding...
})

小程序中的事件传参

  • 小程序的事件传参比较特殊,不能在为组件绑定事件的同时,为事件处理函数传递参数
  • 小程序会把 bindtap 后指定的值,统一当做事件名称来处理

通过 data-* 自定义属性传参

  • 如果要在组件触发事件处理函数的时候,传递参数,可以为组件提供 data-* 自定义属性传参

获取 data-* 自定义属性中传递的参数

  • 通过事件参数 event-target-dataset.参数名,能够获取 data-* 自定义属性传递到事件处理函数中的参数
<button bindtap='eventHandle' type='primary' data-info='info'>传递参数</button>
// 页面逻辑

Page({
  data: {},
    
  eventHandle: function (e) {
    console.log(e.target.dataset.info)
  }
   
  // coding...
})

wxs脚本简介

  • wxs 是小程序的一套脚本语言,结合 wxml ,可以构建出页面的结构

wxs 的注意事项

  • 没有兼容性
    • wxs 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行
  • javascript 不同
    • wxsjavascript 是不同的语言,有自己的语法,并不和 javascript 一致
  • 隔离性
    - wxs 的运行环境和其他 javascript 代码是隔离的
    - wxs 中不能调用其他 javascript 文件中定义的函数,也不能调用小程序提供的API
  • 不能作为事件回调
    - wxs 函数不能作为组件的事件回调
  • iOS设备上比 javascript 运行快
    - 由于运行环境的差异,在 iOS 设备上小程序内的 wxs 会比 javascript 代码快 2 ~ 20 倍。
    - 在 android 设备上二者运行效率无差异

wxs 遵循 CommonJS 模块化规范

CommonJSjavascript 的模块化规范之一,小程序的脚本语言 wxs 遵循了 CommonJS 规范,因此,使用 wxs 时的体验和使用 node.js 的体验比较相似。

  • module 对象
    - 每个 wxs 都是独立的模块,每个模块均有一个内置的 module 对象,每个模块都有自己独立的作用域。
  • module.exports
    - 由于 wxs 拥有独立作用域,所以在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见,
    - 通过 module.exports 属性,可以对外共享本模块的私有变量与函数。
  • require函数
    - 在 wxs 模块中引用其他 wxs 文件模块,可以使用 require 函数。

wxs基础语法

  • 通过 module.exports 属性,可以对外共享本模块的私有变量与函数
var foo = “‘hello world’ from wxs”; // 定义私有变量 foo
var bar = function (d) {            // 定义私有函数 bar
  return d
}

// 通过 modules.exports 向外共享私有成员
module.exports = {
  FOO: foo, // 向外共享私有变量 foo
  bar: ba, // 向外共享私有函数 bar
};

// module.exports 中挂载 msg 变量
module.exports.msg = “some msg”

使用 require 引入其它 wxs 模块 以及注意事项

  • wxs 模块中引用其他 wxs 文件模块,可以使用 require 函数。
// 使用 require 导入 tools.wxs 脚本
var tools = require("./tools.wxs")

// 得到的 tools 对象,可以直接访问到 tools.wxs 中向外暴露的变量和方法
console.log(tools)

注意事项 :

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

wxs支持的数据类型

  • WXS 语言目前共有以下8种数据类型:
    • number 数值类型
    • string 字符串类型
    • boolean 布尔类型
    • object 对象类型
    • function 函数类型
    • array 数组类型
    • date 日期类型
    • regexp 正则

注意事项

注意:由于wxsjavascript 是不同的语言,有自己的语法,并不和 javascript 一致,
所以在使用以上8种数据类型的时候,一定要先翻阅官方文档,再进行使用!

内嵌wxs脚本

  • wxs 代码可以编写在 wxml 文件中的 <wxs></wxs> 标签内,就像 javascript 代码可以编写在 html 文件中的 <script></script> 标签内一样。
  • wxml 文件中的每个 <wxs></wxs> 标签,必须提供一个 module 属性,用来指定当前 <wxs></wxs> 标签的模块名。在单个 wxml 文件内,建议其值唯一。
  • module 属性值的命名必须符合下面两个规则:
    - 首字符必须是:字母(a-z A-Z),下划线(
    - 剩余字符可以是:字母(a-z A-Z),下划线(
    ), 数字(0-9)
<view>{{ info.msg }}</view>

<wxs module='info'>
  var msg = '我在等风来'

  module.exports = {
    msg: msg
  }
</wxs>

外链wxs脚本

  • wxs 代码可以编写在以 .wxs 为后缀名的文件内,就像 javascript 代码可以编写在以 .js 为后缀名文件中一样。
  • wxml 中如果要引入外联的 wxs 脚本,必须为 <wxs></wxs> 标签添加 modulesrc 属性。
    • module 用来为 <wxs></wxs> 标签指定模块名,作为当前页面访问这个模块的标识名称;
    • src 用来指定当前 <wxs></wxs> 标签要引入的脚本路径,必须是相对路径;
// .wxs 文件

var msg = '风铃响,故人归'
var handle = function (params) {
    return params
}

module.exports = {
  msg: msg,
  handle: handle
}
<wxs src='./ling.wxs' module='feng'></wxs>
<view>{{ feng.msg }}</view>
<view>{{ feng.handle('我在等风') }}</view>

注意:在 wxs中不要使用高级的JS语法

条件渲染

wx:if

  • 在小程序中,使用 wx:if="{{condition}}"来判断是否需要渲染该代码块
  • 也可以用 wx:elifwx:else 来添加一个 else 块
<view wx:if='{{id < 10}}'>JavaScript</view>
<view wx:elif='{{id == 10}}'>HTML</view>
<view wx:else='{{id > 10}}'>CSS</view>

block wx:if

  • 因为 wx:if 是一个控制属性,需要将它添加到一个标签上。
  • 如果要一次性判断多个组件标签,可以使用一个 <block></block> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。
  • <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。
<block wx:if='{{ id == 10 }}'>
  <view>JavaScript</view>
  <view>HTML</view>
  <view>CSS</view>
</block>

hidden

  • 使用 hidden="{{condition}}" 也能控制元素的显示与隐藏
<view hidden='{{ id > 10 }}'>前端三板斧</view>

hiddenwx:if的区别

  • wx:if 控制的区域,框架有一个局部渲染的过程,会根据控制条件的改变,动态创建或销毁对应的 UI结构。
  • wx:if 是惰性的,如果在初始渲染条件为 false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。
  • 相比之下,hidden 就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。
  • 总结:wx:if 有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好。

列表渲染

wx:for

  • 在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。
  • 默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item
<view wx:for='{{ arr }}' wx:key='index'>
  我是{{ item }} -- 索引是 {{ index }}
</view>

block wx:for

  • wx:for 可以用在 <block></block> 标签上,以渲染一个包含多节点的结构块。
<block wx:for='{{ arr }}' wx:key='index'>
  <view>值:{{item}} -- 索引{{index}}</view>
</block>

指定索引和当前项的变量名

  • 使用 wx:for-item 可以指定数组当前元素的变量名
  • 使用 wx:for-index 可以指定数组当前下标的变量名,
<view wx:for='{{ arr }}' wx:for-item='foritem' wx:for-index='forindex' wx:key='index'>
  我是{{ foritem }} -- 索引是 {{ forindex }}
</view>

列表渲染中的 wx:key

  1. wx:key 的作用说明

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

    • 当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。

  2. wx:key 的注意事项
    - key 值必须具有唯一性,且不能动态改变
    - key 的值必须是数字或字符串
    - 保留关键字 *this 代表在 for 循环中的 item 本身,它也可以充当 key 值,但是有以下限制:需要 item 本身是一个唯一的字符串或者数字。

    • 如不提供 wx:key,会报一个 warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。

下拉刷新

  • app.jsonwindow 选项中或页面配置中开启 enablePullDownRefresh
  • 可以通过 wx.startPullDownRefresh() 触发下拉刷新,调用后触发下拉刷新动画,效果与用户手动下拉刷新一致。

注意: 一般情况下,推荐在页面配置中为需要的页面单独开启下拉刷新行为

设置下拉窗口的样式

  • app.jsonwindow 选项中或页面配置中修改 backgroundColorbackgroundTextStyle 选项。
  • backgroundColor 用来配置下拉刷新窗口的背景颜色,仅支持16进制颜色值
  • backgroundTextStyle 用来配置下拉刷新 loading 的样式,仅支持 darklight

监听下拉刷新事件

  • 为页面添加 onPullDownRefresh() 函数,可以监听用户在当前页面的下拉刷新事件。
/**
 * 页面相关事件处理函数--监听用户下拉动作
 */
onPullDownRefresh: function () {
  console.log('触发下拉刷新啦')
}

停止下拉刷新

/**
 * 页面相关事件处理函数--监听用户下拉动作
 */
onPullDownRefresh: function () {
  console.log('触发下拉刷新啦')
    
  wx.stopPullDownRefresh()
}

上拉刷新

  • app.jsonwindow选项中或页面配置中设置触底距离 onReachBottomDistance。单位为px,默认触底距离为 50px
  • 为页面添加 onReachBottom() 函数,可以监听用户在当前页面的上拉触底事件,从而实现上拉加载更多列表数据的效果。
/**
 * 页面上拉触底事件的处理函数
 */
onReachBottom: function () {
  console.log('触发上拉刷新啦')
},

其它事件

页面滑动事件onPageScroll

  • 监听用户滑动页面事件
    • 得到 scrollTop,页面在垂直方向已滚动的距离(单位px
onPageScroll: function (e) {
  console.log(e)
}

分享事件 onShareAppMessage

  • 监听用户点击页面内转发按钮(<button> 组件 open-type="share"

  • 右上角菜单“转发”按钮的行为,并自定义转发内容。
    | 参数 | 类型 | 说明 |
    | :----------: | :------: | :----------------------------------------------------------: |
    | from | String | 转发事件来源。button:页面内转发按钮;menu:右上角转发菜单 |
    | target | Object | 如果 from 值是 button,则 target 是触发这次转发事件的 button,否则为 undefined |
    | webViewUrl | String | 页面中包含组件时,返回当前的url |

  • 自定义转发内容, return 一个 Object 就可以
    | 字段 | 说明 | 默认值 |
    | :--------: | :----------------------------------------------------------: | :---------------------------------------: |
    | title | 转发标题 | 当前小程序名称 |
    | path | 转发路径 | 当前页面 path ,必须是以 / 开头的完整路径 |
    | imageUrl | 自定义图片路径,可以是本地文件路径、代码包文件路径或者网络图片路径。支持PNGJPG。显示图片长宽比是 5:4。 | 使用默认截图 |

Page({
  onShareAppMessage: function (res) {
    if (res.from === 'button') {
      // 来自页面内转发按钮
      console.log(res.target)
    }
    return {
      title: '自定义转发标题',
      path: '/page/user?id=123'
    }
  }
})

点击tab时触发事件ontabItemTap

参数类型说明
indexString被点击 tabItem 的序号,从0开始
pagePathString被点击tabItem 的页面路径
textString被点击 tabItem 的按钮文字
onTabItemTap(item) {
  console.log(item.index)
  console.log(item.pagePath)
  console.log(item.text)
}

声明式导航

<navigator url="/pages/about/about">跳转到 about 页面</navigator>
  • 注意事项
    • url 属性设置需要跳转的路径
    • 页面路径应该以 / 开头,
    • 路径必须提前在 app.jsonpages 节点下声明

导航到 tabBar 页面

navigator组件单纯使用 url 属性,无法导航到 tabBar 页面,必须需要结合 open-type 属性进行导航。

<navigator url="/pages/person/person" open-type="switchTab">跳转到 tabBar 页面</navigator>

后退导航

小程序如果要后退到上一页面或多级页面,需要把 open-type 设置为 navigateBack,同时使用 delta 属性指定后退的层数

<navigator open-type='navigateBack' delta='1'> 返回上一页 </navigator>

<navigator open-type='navigateBack' delta='2'> 返回上上一页 </navigator>

编程式导航

导航到非 tabBar 页面

  • 通过 wx.navigateTo(Object object) 方法,可以跳转到应用内的某个页面。
  • 但是不能跳到 tabbar 页面。
// 跳转到非导航页面
handle: function () {
  wx.navigateTo({
    url: '/pages/about/about',
    success: function () {
      console.log('Hello about')
    }
  })
},

导航到 tabBar 页面

通过 wx.switchTab(Object object) 方法,可以跳转到 tabBar 页面,
并关闭其他所有非 tabBar 页面

// 跳转到 tabBar 页面
tabBarHandle: function () {
  wx.switchTab({
    url: '/pages/person/person',
    success: function() {
      console.log('Hello Person')
    }
  })
},

后退导航

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

handle: function () {
  wx.navigateBack({
    delta: 1
  })
},

twoHandle: function () {
  wx.navigateBack({
    delta: 2
  })
},

导航传参

声明式导航传参

navigator 组件的 url 属性用来指定导航到的页面路径,同时路径后面还可以携带参数,参数与路径之间使用 ? 分隔,参数键与参数值用 = 相连,不同参数用 & 分隔。

<navigator url="/pages/about/about?age=18&name=shuji">跳转到 about 页面</navigator>

编程式导航传参

wx.navigateTo(Object object) 方法的 object 参数中,url 属性用来指定需要跳转的应用内非 tabBar 的页面的路径, 路径后可以带参数。参数与路径之间使用 ? 分隔,参数键与参数值用 = 相连,不同参数用 & 分隔。

// 跳转到 tabBar 页面
tabBarHandle: function () {
  wx.switchTab({
    url: '/pages/person/person?age=18&name=shuji',
    success: function() {
      console.log('Hello Person')
    }
  })
},

接受传递的参数

  • 不论是声明式导航还是编程式导航,最终导航到的页面可以在 onLoad 生命周期函数中接收传递过来的参数。
onLoad: function (options) {
    // 打印传递出来的参数
    console.log(options)
  },

小程序发送get/post请求

  • 小程序发送请求使用 wx.request() 方法
  • Get 案例代码
getData: function () {
  wx.request({
    url: 'xxxx',
    method: 'get',
    success: function (res) {
      console.log(res)
    }
  })
},
  • Post 代码案例
postData: function () {
  wx.request({
    url: 'https://www.liulongbin.top:8082/api/post',
    method: 'post',
    data: {
      name: 'shuji'
    },
    success: function (res) {
      console.log(res)
    }
  })
},

注意: method 如果不进行配置,默认参数是 get 请求方式

组件的创建与引用

组件的创建

  • 在项目的根目录中,鼠标右键,创建 components 文件夹 --> test
  • 在新建的 components -> test 文件夹上,鼠标右键,点击“新建 Component”
  • 为新建的组件命名之后,会自动生成组件对应的 4 个文件,后缀名分别为 .js.json.wxml.wxss
    注意:应当尽量将不同的组件,存放到单独的文件夹中,从而保证清晰的目录结构

组件的引用

  • 在需要引用组件的页面中,找到页面的 .json 配置文件,新增 usingComponents 节点
  • usingComponents 中,通过键值对的形式,注册组件;键为注册的组件名称,值为组件的相对路径
  • 在页面的 .wxml 文件中,把注册的组件名称,以标签形式在页面上使用,即可把组件展示到页面上
{
  "usingComponents": {
    "first-com": "../../component/com01/com01"
  }
}

注册组件名称时,建议把组件名称使用中横线进行连接,例如 vant-button 或 custom-button

小程序组件 – 数据与方法

使用 data 定义组件的私有数据

  • 小程序组件中的 data与小程序页面中的 data 用法一致,区别是:
    • 页面的 data 定义在 Page() 函数中
    • 组件的 data 定义在 Component() 函数中
  • 在组件的 .js 文件中:
    • 如果要访问 data 中的数据,直接使用 this.data.数据名称 即可
    • 如果要为 data 中的数据重新赋值,调用 this.setData({ 数据名称: 新值 }) 即可
  • 在组件的 .wxml 文件中
    • 如果要渲染 data 中的数据,直接使用 {{ 数据名称 }} 即可

使用 methods 定义组件的事件处理函数

  • 和页面不同,组件的事件处理函数,必须定义在 methods 节点中
methods: {
  handle: function () {
    console.log('组件的方法要定义在 methods 中')

    this.setData({
      num: this.data.num + 1
    })

    console.log(this.data.num)
  }
}

小程序组件 – properties

组件的对外属性,用来接收外界传递到组件中的数据。 类似于 Vue 中的 props

  • 组件的 propertiesdata 的用法类似,它们都是可读可写的,只不过:
    - data 更倾向于存储组件的私有数据
    - properties 更倾向于存储外界传递到组件中的数据
properties: {
  a: {				// 属性名
    type: String,	// 属性的数据类型
    value: ''		// 默认值
  }
}

注意:type 的可选值为 Number,String、Boolean、Object、Array、null(表示不限制类型)

向组件传递 properties 的值

使用数据绑定的形式,向子组件的属性传递动态数据

<second-com prop-price="{{ priceData }}"></second-com>

注意:

  • 在定义 properties 时,属性名采用驼峰写法(propertyName);
  • 在 wxml 中,指定属性值时,则对应使用连字符写法(property-name=“attr value”),
  • 应用于数据绑定时,采用驼峰写法(attr="{{propertyName}}")。
// 组件 com02.js
properties: {
  propPrice: {
    type: Number,
    value: 1
  }
},
<!-- 引用组件的页面 -->

<second-com prop-price="{{ priceData }}"></second-com>
<!-- 组件 com02.html -->

<view>{{ propPrice }}</view>

组件内修改 properties

properties 的值是可读可写的,可以通过 setData 修改 properties 中任何属性的值,

methods: {
  handle: function () {
    this.setData({
      propPrice: this.properties.propPrice + 1
    })

    console.log(this.properties.propPrice)
  }
}

小程序组件 – 数据监听器

数据监听器可以用于监听和响应任何属性和数据字段的变化,从而执行特定的操作

observers: {
  'propPrice, num': function (newPropPrice, newNum) {
    console.log(newPropPrice)
    console.log(newNum)
  }
},

监听子数据字段语法

// 监控某个子数据的代码
Component({
  observers: {
    'some.subfield': function (subfield) {
      // 使用 setData 设置 this.data.some.subfield 时触发
      // (除此以外,使用 setData 设置 this.data.some 也会触发)
    },
    'arr[12]': function (arr12) {
      // 使用 setData 设置 this.data.arr[12] 时触发
      // (除此以外,使用 setData 设置 this.data.arr 也会触发)
    }
  }
})
// 使用通配符 ** 监听所有子数据字段的变化
Component({
  observers: {
    'some.field.**': function (field) {
      // 使用 setData 设置 this.data.some.field 本身或其下任何子数据字段时触发
      // (除此以外,使用 setData 设置 this.data.some 也会触发)
      field === this.data.some.field
    }
  }
})

组件的声明周期

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

  • 最重要的生命周期是 created, attached, detached ,包含一个组件实例生命流程的最主要时间点。
    • 组件实例刚刚被创建好时, created 生命周期被触发。此时还不能调用 setData 。 通常情况下,这个生命周期只应该用于给组件 this 添加一些自定义属性字段。
    • 在组件完全初始化完毕、进入页面节点树后, attached 生命周期被触发。此时, this.data 已被初始化完毕。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行。
    • 在组件离开页面节点树后, detached 生命周期被触发。退出一个页面时,如果组件还在页面节点树中,则 detached 会被触发。

小程序插槽的使用

默认插槽

在组件的 wxml 中可以包含 slot 节点,用于承载组件使用者提供的 wxml 结构。

  • 默认情况下,一个组件的 wxml 中只能有一个 slot。需要使用多 slot 时,可以在组件 js 中声明启用。
  • 注意:小程序中目前只有默认插槽和多个插槽,暂不支持作用域插槽。
// 组件模板

<view>
  <view>我是组件</view>
  <slot></slot>
</view>
// 引用组件的页面模板

<second-com>
  <view>你好,我是引用组件</view>
</second-com>

多个插槽

  • 在组件中,需要使用多 slot 时,可以在组件 js 中声明启用。
Component({

  options: {
    multipleSlots: true
  },
    
})
  • 在组件的 wxml 中使用多个 slot 标签,以不同的 name 来区分不同的插槽
// 引用组件的页面模板

<second-com prop-price="{{ priceData }}">
  <view slot="name">你好,这是 name 插槽 </view>
  <view slot="age">你好,这是 age 插槽</view>
</second-com>
  • 使用多个插槽
// 组件插槽
<view>
  <view>我是组件</view>
  <slot name="name"></slot>
  <slot name="age"></slot>
</view>

组件间的通信

组件之间的三种基本通信方式

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

this.selectComponent 使用

父组件的 .js 文件中,可以调用 this.selectComponent(string) 函数并指定 idclass 选择器, 获取子组件对象调用 ,可以返回指定组件的实例对象

// 使用组件的页面模板

<second-com class="second" id="second" prop-price="{{ priceData }}">
  <view slot="name">你好,这是 name 插槽 </view>
  <view slot="age">你好,这是 age 插槽</view>
</second-com>
// 使用组件的 .js 文件,使用方法触发

changeData: function () {
  // console.log(this.selectComponent('#second'))
    
  console.log(this.selectComponent('.second'))
},

不能传递标签选择器(component-a),不然返回的是 null

通过事件监听实现子向父传值

事件系统是组件间通信的主要方式之一。自定义组件可以触发任意的事件,引用组件的页面可以监听这些事件。

实现步骤

  • 在父组件的 js 中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件
  • 在父组件的 wxml 中,通过自定义事件的形式,将步骤一中定义的函数引用,传递给子组件
  • 在子组件的 js 中,通过调用 this.triggerEvent('自定义事件名称', { /* 参数对象 */ }) ,将数据发送到父组件
  • 在父组件的 js 中,通过 e.detail 获取到子组件传递过来的数据
// 使用组件的页面模板自定义 myEvent 事件,接收 getCount 方法

<second-com bind:myEvent="getCount" class="second" id="second" prop-price="{{ priceData }}">
  <view slot="name">你好,这是 name 插槽 </view>
  <view slot="age">你好,这是 age 插槽</view>
</secondcom>
// 使用组件页面 js,生命 getCount 方法

getCount: function (e) {
  console.log(e.detail)
},
// 组件页面

this.triggerEvent('myEvent', {
  count: this.data.num
})
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值