小程序
1.小程序简介
小程序和普通网页区别
-
运行环境不同
网页 远行在 浏览器环境上 小程序 运行在 微信环境
-
开发模式不同
网页的开发模式 浏览器+代码编辑器 小程序有自己的一套标准的开发模式 申请小程序账号 安装小程序开发者工具 创建和配置小程序项目
-
API不同
因为运行环境不同,小程序没有办法调用BOM和Dom的API 小程序可以调用微信环境提供的各种API 地理定位 扫码 支付
项目构成
-
项目的基本组成结构
① pages 用来存放所有小程序的页面 * ② utils 用来存放工具性质的模块(例如:格式化时间的自定义模块) * ③ app.js 小程序项目的入口文件 * ④ app.json 小程序项目的全局配置文件 * ⑤ app.wxss 小程序项目的全局样式文件 * ⑥ project.config.json 项目的配置文件 ⑦ sitemap.json 用来配置小程序及其页面是否允许被微信索引
2.小程序有几个文件
页面
-
wxml 小程序页面结构
-
wxss 小程序页面样式文件
-
json 小程序页面配置
-
js 逻辑结构
全局
-
app.wxss 全局样式文件
-
app.json 全局配置文件
-
app.js 入口文件
-
-
3.Json配置文件
JSON 配置文件的作用
JSON 是一种数据格式,在实际开发中,JSON 总是以配置文件的形式出现。小程序项目也不例外:通过不同
的 .json 配置文件,可以对小程序项目进行不同级别的配置。
小程序项目中有 4 种 json 配置文件,分别是: ① 项目根目录中的 app.json 配置文件 ② 项目根目录中的 project.config.json 配置文件 ③ 项目根目录中的 sitemap.json 配置文件 ④ 每个页面文件夹中的 .json 配置文件
app.json 文件
app.json 是当前小程序的全局配置,包括了小程序的所有页面路径、窗口外观、界面表现、底部 tab 等
简单了解下这 4 个配置项的作用: ① pages:用来记录当前小程序所有页面的路径 ② window:全局定义小程序所有页面的背景色、文字颜色等 ③ style:全局定义小程序组件所使用的样式版本 ④ sitemapLocation:用来指明 sitemap.json 的位置
project.config.json 文件
project.config.json 是项目配置文件,用来记录我们对小程序开发工具所做的个性化配置,例如: setting 中保存了编译相关的配置 projectname 中保存的是项目名称 appid 中保存的是小程序的账号 ID
页面的 .json 配置文件
小程序中的每一个页面,可以使用 .json 文件来对本页面的窗口外观进行配置,页面中的配置项会覆盖
app.json 的 window 中相同的配置项。
新建小程序页面
只需要在 app.json -> pages 中新增页面的存放路径,小程序开发者工具即可帮我们自动创建对应的页面文件,
修改项目首页
只需要调整 app.json -> pages 数组中页面路径的前后顺序,即可修改项目的首页。小程序会把排在第一位的页面,当作项目首页进行渲染
4.WXML
什么是 WXML
WXML(WeiXin Markup Language)是小程序框架设计的一套标签语言,用来构建小程序页面的结构,其作
用类似于网页开发中的 HTML。
WXML 和 HTML 的区别
① 标签名称不同 HTML (div, span, img, a) WXML(view, text, image, navigator) ② 属性节点不同 <a href="#">超链接</a> <navigator url="/pages/home/home"></navigator> ③ 提供了类似于 Vue 中的模板语法 数据绑定 列表渲染 条件渲染
5.WXSS 样式
什么是 WXSS
WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式,类似于网页开发中的 CSS。
6.小程序wxss和css的区别
wxss背景图⽚只能引⼊外链,不能使⽤本地图⽚
⼩程序样式使⽤@import引⼊外链样式⽂件,地址为相对路径
尺⼨单位为 rpx , rpx 是响应式像素,可以根据屏幕宽度进⾏⾃适应
7.JS 逻辑交互
小程序中的 .js 文件
一个项目仅仅提供界面展示是不够的,在小程序中,我们通过 .js 文件来处理用户的操作。例如:响应用户的
点击、获取用户的位置等等。
小程序中 .js 文件的分类
小程序中的 JS 文件分为三大类,分别是: ① app.js 是整个小程序项目的入口文件,通过调用 App() 函数来启动整个小程序 ② 页面的 .js 文件 是页面的入口文件,通过调用 Page() 函数来创建并运行页面 ③ 普通的 .js 文件 是普通的功能模块文件,用来封装公共的函数或属性供页面使用
8.组件
1. 小程序中组件的分类
小程序中给我们提供了很多的组件,开发者可以基于组件快速搭建出漂亮的页面结构。官方把小程序的组
件分为了 9 大类,分别是:
① 视图容器
② 基础内容
③ 表单组件
④ 导航组件
⑤ 媒体组件
⑥ map 地图组件
⑦ canvas 画布组件
⑧ 开放能力
⑨ 无障碍访问
常用的视图容器类组件
① view
普通视图区域 类似于 HTML 中的 div,是一个块级元素 常用来实现页面的布局效果
② scroll-view
可滚动的视图区域 常用来实现滚动列表效果
③ swiper 和 swiper-item
轮播图容器组件 和 轮播图 item 组件
swiper 组件的常用属性
indicator-dots boolean false 是否显示面板指示点 indicator-color color rgba(0, 0, 0, .3) 指示点颜色 indicator-active-color color #000000 当前选中的指示点颜色 autoplay boolean false 是否自动切换 interval number 5000 自动切换时间间隔 circular boolean false 是否采用衔接滑动
常用的内容组件
① text
文本组件 类似于 HTML 中的 span 标签,是一个行内元素
② rich-text
富文本组件 支持把 HTML 字符串渲染为 WXML 结构
其它常用组件
① button
按钮组件 功能比 HTML 中的 button 按钮丰富 通过 open-type 属性可以调用微信提供的各种功能(客服、转发、获取用户授权、获取用户信息等)
② image
图片组件 image 组件默认宽度约 300px、高度约 240px
③ navigator(后面课程会专门讲解)
页面导航组件 类似于 HTML 中的 a 链接
image 组件的 mode 属性
image 组件的 mode 属性用来指定图片的裁剪和缩放模式,常用的 mode 属性值如下:
scaleToFill (默认值)缩放模式,不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素 aspectFit 缩放模式,保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。 aspectFill 缩放模式,保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。 widthFix 缩放模式,宽度不变,高度自动变化,保持原图宽高比不变 heightFix 缩放模式,高度不变,宽度自动变化,保持原图宽高比不变
9.API
小程序 API 概述
小程序中的 API 是由宿主环境提供的,通过这些丰富的小程序 API,开发者可以方便的调用微信提供的能力,
例如:获取用户信息、本地存储、支付功能等
小程序 API 的 3 大分类
小程序官方把 API 分为了如下 3 大类:
① 事件监听 API
特点:以 on 开头,用来监听某些事件的触发 举例:wx.onWindowResize(function callback) 监听窗口尺寸变化的事件
② 同步 API
特点1:以 Sync 结尾的 API 都是同步 API 特点2:同步 API 的执行结果,可以通过函数返回值直接获取,如果执行出错会抛出异常 举例:wx.setStorageSync('key', 'value') 向本地存储中写入内容
③ 异步 API
特点:类似于 jQuery 中的 $.ajax(options) 函数,需要通过 success、fail、complete 接收调用的结果 举例:wx.request() 发起网络数据请求,通过 success 回调函数接收数据
10.数据绑定
① 在 data 中定义数据
Page({ data: { info:"hello ", list:[{msg:"122"},{msg:'333'}] }, })
② 在 WXML 中使用数据 Mustache 语法(双大括号)将
<text>{{info}}</text>
11.事件绑定
小程序常用的事件
tap bindtap 或 bind:tap 手指触摸后马上离开,类似于 HTML 中的 click 事件 input bindinput 或 bind:input 文本框的输入事件 change bindchange 或 bind:change 状态改变时触发
事件对象的属性列表
当事件回调触发的时候,会收到一个事件对象 event
type String 事件类型 timeStamp Integer 页面打开到触发事件所经过的毫秒数 target Object 触发事件的组件的一些属性值集合 currentTarget Object 当前组件的一些属性值集合 detail Object 额外的信息 touches Array 触摸事件,当前停留在屏幕中的触摸点信息的数组 changedTouches Array 触摸事件,当前变化的触摸点信息的数组
target 和 currentTarget 的区别
e.target 指向的是触发事件的源头组件,因此,e.target 是内部的按钮组件 e.currentTarget 指向的是当前正在触发事件的那个组件,因此,e.currentTarget 是当前的 view 组件
bindtap 的语法格式
-
通过 bindtap,可以为组件绑定 tap 触摸事件
<button type="primary" bindtap="btnHandler">按钮</button>
-
在页面的 .js 文件中定义对应的事件处理函数,事件参数通过形参 event(一般简写成 e) 来接收
btnHandler(e){ console.log(e) }
-
通过调用 this.setData(dataObject) 方法,可以给页面 data 中的数据重新赋值
Page({ data: { count:1 }, btnHandler(e){ console.log(e) this.setData({ count:this.data.count+1 }) } })
事件传参
-
小程序中的事件传参比较特殊,不能在绑定事件的同时为事件处理函数传递参数
<button type="primary" bindtap="btnHandler" data-info="{{123}}">按钮</button> info 会被解析为参数的名字 数值 2 会被解析为参数的值
-
在事件处理函数中,通过 event.target.dataset.参数名 即可获取到具体参数的值
btnHandler(e){ // dataset是一个对象,包含了所有通过data-* 传递过来的参数项 console.log(e.target.dataset) // 通过dataset可以访问到具体参数的值 console.log(e.target.dataset.info) }
bindInput语法
在小程序中,通过 input 事件来响应文本框的输入事件
-
通过 bindinput,可以为文本框绑定输入事件
<input type="text" bindinput="btnHandler"/>
-
在页面的 .js 文件中定义事件处理函数
btnHandler(e){ // e.detail.value 是变化过后,文本框最新的值 console.log(e.detail.value) }
实现数据同步
12.条件渲染
wx:if
<!-- 在小程序中,使用 wx:if="{{condition}}" 来判断是否需要渲染该代码块 --> <view wx:if="{{condition}}">True</view>
wx:elif 和 wx:else
<view wx:if="{{type===1}}">男</view> <view wx:elif="{{type===2}}">女</view> <view wx:else>保密</view>
结合 block 使用 wx:if
block 并不是一个组件,它只是一个包裹性质的容器,不会在页面中做任何渲染。
<block wx:if="{{true}}"> <view>view1</view> <view>view2</view> </block>
hidden
在小程序中,直接使用 hidden="{{ condition }}" 也能控制元素的显示与隐藏
<view hidden="{{condition}}">条件为true隐藏,条件为false显示</view>
wx:if 与 hidden 的对比
① 运行方式不同 wx:if 以动态创建和移除元素的方式,控制元素的展示与隐藏 hidden 以切换样式的方式(display: none/block;),控制元素的显示与隐藏 ② 使用建议 频繁切换时,建议使用 hidden 控制条件复杂时,建议使用 wx:if 搭配 wx:elif、wx:else 进行展示与隐藏的切换
13.循环渲染
wx:for
通过 wx:for 可以根据指定的数组,循环渲染重复的组件结构
当前循环项的索引用 index 表示;当前循环项用 item 表示
<view wx:for="{{array}}"> 索引是:{{index}} 当前项是{{item}} </view>
手动指定索引和当前项的变量名
使用 wx:for-index 可以指定当前循环项的索引的变量名
使用 wx:for-item 可以指定当前项的变量名
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName"> 索引是:{{idx}} 当前项是{{itemName}} </view>
wx:key 的使用
类似于 Vue 列表渲染中的 :key,小程序在实现列表渲染时,也建议为渲染出来的列表项指定唯一的 key 值,
从而提高渲染的效率,
<view wx:for="{{array}}" wx:key="{{item.id}}"> 索引是:{{index}} 当前项是{{item}} </view>
14.app.json全局配置文件
-
pages:⽤于存放当前⼩程序的所有⻚⾯路径
-
window:⼩程序所有⻚⾯的顶部背景颜⾊,⽂字颜⾊配置。
-
tabBar:⼩程序底部的 Tab ,最少2个,最多5个
15.页面配置
页面配置文件的作用
小程序中,每个页面都有自己的 .json 配置文件,用来对当前页面的窗口外观、页面效果等进行配置
页面配置和全局配置的关系
小程序中,app.json 中的 window 节点,可以全局配置小程序中每个页面的窗口表现。
如果某些小程序页面想要拥有特殊的窗口表现,此时,“页面级别的 .json 配置文件”就可以实现这种需求。
注意:当页面配置与全局配置冲突时,根据就近原则,最终的效果以页面配置为准
16.小程序下拉刷新
⽅案 ⼀ :
开启全局下拉刷新
通过在 app.json 中, 将 "enablePullDownRefresh(哎耐薄 朴的瑞犯四)": true
单组件下拉刷新
通过在 组件 .json ,将 "enablePullDownRefresh": true
⽅案⼆:
scroll-view 四扣楼:使⽤该滚动组件⾃定义刷新,通过 bindscrolltoupper 属性, 当滚动到顶部/左边会触发scrolltoupper事件,利⽤这个属性,实现下拉刷新功能。
17.封装小程序的数据请求
-
在项目中新建http目录,在里面创建一个js文件封装get和post方法
-
在get方法中先用wx.showToast()提示数据加载,然后返回一个promise,在promise的回调函数中通过wx.request瑞快四特()来请求数据,在请求成功的回调中先关闭弹框,再调用promise的resolve方法,传递返回的数据
-
export default返回封装的方法
-
在页面中通过import 导入方法,就可以直接使用了
-
18.⼩程序wx:if和 hidden的区别
<view wx:if="{{isShow}}">wx:if</view> <view hidden="{{isShow}}">hidden</view>
wx:if 有更⾼的切换消耗。 hidden 有更⾼的初始渲染消耗。
使⽤
运⾏时条件变化使⽤wx: if,频繁切换使⽤hidden
19.网络请求
网络请求限制
出于安全考虑,小程序对数据接口的请求有要求:
只能请求https类型的接口
必须将接口的域名添加到信任列表中
配置合法域名
登录小程序公众平台--->开发管理---->开发设置--->服务器域名--->修改合法域名
发起GET请求
wx.request({ url: 'example.php', //仅为示例,并非真实的接口地址 method:'GET', data: { x: '', y: '' }, header: { 'content-type': 'application/json' // 默认值 }, success (res) { console.log(res.data) } })
在页面刚加载时请求数据
/** * 生命周期函数--监听页面加载 */ onLoad(options) { this.getData() },
getData(){ wx.request({ url: 'https://www.escook.cn/slides', //仅为示例,并非真实的接口地址 method:'GET', header: { 'content-type': 'application/json' // 默认值 }, success:(res)=>{ // console.log(res.data) this.setData({ banners:res.data }) } }) },
发起Post请求
wx.request({ url: 'example.php', //仅为示例,并非真实的接口地址 method:'POST', data: { x: '', y: '' }, header: { 'content-type': 'application/json' // 默认值 }, success (res) { console.log(res.data) } })
跳过request合法域名校验
后端程序员仅仅提供了http协议的接口,需要不校验合法域名
微信开发者工具---->详情---->不校验合法域名
没有跨域
跨域只存在于浏览器的web开发中,小程序是运行在微信环境中,小程序不存在跨域问题
Ajax技术的核心是依赖于浏览器的 XMLHttpRequest 对象,小程序是运行在微信环境中没有这个对象,小程序不能叫做ajax请求 叫做发起网络数据请求
网络请求
网络请求限制
出于安全考虑,小程序对数据接口的请求有要求:
只能请求https类型的接口
必须将接口的域名添加到信任列表中
配置合法域名
登录小程序公众平台--->开发管理---->开发设置--->服务器域名--->修改合法域名
发起GET请求
wx.request({ url: 'example.php', //仅为示例,并非真实的接口地址 method:'GET', data: { x: '', y: '' }, header: { 'content-type': 'application/json' // 默认值 }, success (res) { console.log(res.data) } })
在页面刚加载时请求数据
/** * 生命周期函数--监听页面加载 */ onLoad(options) { this.getData() },
getData(){ wx.request({ url: 'https://www.escook.cn/slides', //仅为示例,并非真实的接口地址 method:'GET', header: { 'content-type': 'application/json' // 默认值 }, success:(res)=>{ // console.log(res.data) this.setData({ banners:res.data }) } }) },
发起Post请求
wx.request({ url: 'example.php', //仅为示例,并非真实的接口地址 method:'POST', data: { x: '', y: '' }, header: { 'content-type': 'application/json' // 默认值 }, success (res) { console.log(res.data) } })
跳过request合法域名校验
后端程序员仅仅提供了http协议的接口,需要不校验合法域名
微信开发者工具---->详情---->不校验合法域名
没有跨域
跨域只存在于浏览器的web开发中,小程序是运行在微信环境中,小程序不存在跨域问题
Ajax技术的核心是依赖于浏览器的 XMLHttpRequest 对象,小程序是运行在微信环境中没有这个对象,小程序不能叫做ajax请求 叫做发起网络数据请求
页面导航
页面导航的两种方式
-
声明式导航
在页面上声明 <navigator>导航组件,url属性是导航地址
-
编程式导航
调用小程序的导航API,实现页面跳转
声明式导航
导航到tabBar页面
tabBar页面是被配置为tabBar的页面
navigator组件,需要指定url属性和open-type属性
url: 跳转页面的地址 必须以 / 开头
open-type 跳转的方式 值为switchTab
<navigator url="/pages/home/home" open-type="switchTab">跳转到home</navigator>
导航到非tabBar页面
tabBar页面是被配置为tabBar的页面
navigator组件,需要指定url属性和open-type属性
url: 跳转页面的地址 必须以 / 开头
open-type 跳转的方式 值为navigate
<navigator url="/pages/cart/cart" open-type="navigate">cart</navigator>
导航到非tabBar页面时,open-type="navigate" 可以省略
后退导航
如果要后退到上一页面或多级页面,需要指定open-type和delta属性
open-type 的值必须是navigateBack ,表示要进行后退导航
delta 的值必须是数字,表示后退的层级
<navigator open-type="navigateBack" delta="1">返回</navigator>
如果只是返回到上一页面,可以省略delta=“1”,因为默认值为1
传参
/pages/cart/cart?id=2&name=zs
-
参数和路径直接使用?分割
-
参数名和参数值之间用 =
-
不同参数用 & 分割
<navigator url="/pages/cart/cart?id=2&name=zs" open-type="navigate">跳转到home</navigator> <navigator url="/pages/cart/cart?id={{num}}&name=zs" open-type="navigate">跳转到home</navigator>
编程式导航
导航到tabBar
wx.switchTab({ url: '/pages/home/home', })
导航到非tabBar
wx.navigateTo({ url: '/pages/cart/cart', })
后退导航
wx.navigateBack({ delta:1 })
传参
wx.switchTab({ url: '/pages/cart/cart?id=23&name=zs', }) wx.switchTab({ url: `/pages/cart/cart?id=${this.data.num}&name=zs`, })
在onLoad中接收参数
onLoad(options) { console.log(options,"options") //{id: "23", name: "zs"} },
页面事件
下拉刷新
手指在屏幕上下拉滑动操作,重新加载页面数据
步骤
1启动下拉刷新
-
全局开启下拉刷新
在app.json 的window节点中,enablePullDownRefresh:true
-
局部开启下拉刷新
在页面的.json文件中,enablePullDownRefresh:true
2配置下拉刷新窗口样式
backgroundTextStyle:dark 下拉的loading的效果
backgroundColor 窗口的背景颜色
3监听下拉刷新事件
通过onPullDownRefresh()监听用户下拉事件
4停止下拉刷新动作
// 数据重置成功,调用该函数,关闭下拉刷新的效果 wx.stopPullDownRefresh()
上拉加载
手指在屏幕上上拉滑动操作,加载更多数据
步骤
配置上拉触底距离
-
全局配置 onReachBottomDistance:60
-
局部配置 onReachBottomDistance :60
监听页面的上拉触底事件
/** * 页面上拉触底事件的处理函数 */ onReachBottom() { console.log("触发了上拉触底事件") },
小程序生命周期函数
小程序生命周期
-
onLaunch() 小程序初始化的生命周期钩子函数
-
onShow () 小程序启动或者从后台切换到前台
-
onHide() 切换到后台
页面生命周期
-
onLoad 监听页面加载 只执行一次
-
onReady 监听页面初次渲染完成 只执行一次
-
onShow 监听页面显示 可以执行n次
-
onHide 监听页面隐藏 可以执行n次
-
onUnload 生命周期回调—监听页面卸载
wxs
WXS(WeiXin Script)是小程序的一套脚本语言,结合
WXML
,可以构建出页面的结构。WXML中无法调用页面的js中定义的函数,但是wxml可以调用wxs中定义的函数,所以wxs的应用场景就是过滤器
wxs和JavaScript的关系
wxs类似于JavaScript,但是wxs和JavaScript是完全不同的两种语言
-
wxs有自己的数据类型
number数值类型 string 字符串 boolean布尔 function 函数 array 数组 date日期 object 对象 regexp 正则
-
wxs不支持ES6以上的语法
不支持let const 解构赋值 展开运算符就 箭头函数 对象属性的简写
支持var定义的遍历 普通的function
-
wxs遵循CommJS规范
module 对象
module.exports
require 导入
内嵌wxs脚本
WXS 代码可以编写在 wxml 文件中的 <wxs>
标签内
<wxs>标签必须提供module属性,用来指定当前wxs的模块名称,wxml中访问模块中的成员
<view>{{m1.toUpper(username)}}</view> <view>{{username}}</view> <wxs module="m1"> module.exports.toUpper=function(str){ return str.toUpperCase() } </wxs>
外联的wxs
.wxs
为后缀名的文件内。
utils/tool.wxs
var toFix=function (val){ return val.toFixed(2) } module.exports.toFix = toFix
<view>{{tools.toFix(price)}}</view> <wxs src="../../utils/tool.wxs" module="tools" />
wxs
WXS(WeiXin Script)是小程序的一套脚本语言,结合
WXML
,可以构建出页面的结构。WXML中无法调用页面的js中定义的函数,但是wxml可以调用wxs中定义的函数,所以wxs的应用场景就是过滤器
wxs和JavaScript的关系
wxs类似于JavaScript,但是wxs和JavaScript是完全不同的两种语言
-
wxs有自己的数据类型
number数值类型 string 字符串 boolean布尔 function 函数 array 数组 date日期 object 对象 regexp 正则
-
wxs不支持ES6以上的语法
不支持let const 解构赋值 展开运算符就 箭头函数 对象属性的简写
支持var定义的遍历 普通的function
-
wxs遵循CommJS规范
module 对象
module.exports
require 导入
内嵌wxs脚本
WXS 代码可以编写在 wxml 文件中的 <wxs>
标签内
<wxs>标签必须提供module属性,用来指定当前wxs的模块名称,wxml中访问模块中的成员
<view>{{m1.toUpper(username)}}</view> <view>{{username}}</view> <wxs module="m1"> module.exports.toUpper=function(str){ return str.toUpperCase() } </wxs>
外联的wxs
.wxs
为后缀名的文件内。
utils/tool.wxs
var toFix=function (val){ return val.toFixed(2) } module.exports.toFix = toFix
<view>{{tools.toFix(price)}}</view> <wxs src="../../utils/tool.wxs" module="tools" />
组件
复用性强
创建组件
-
项目根目录下,新建components
-
components---->新建文件夹 mycom--->myCom文件夹右击 新建component 输入组件的名称回车自动生成4个文件
引入组件
全局引入
组件可以在每个小程序页面中使用
多个页面都会用到该组件使用 全局
app.json
注册组件
"usingComponents":{ "my-com":"/components/myCom/myCom" },
使用组件
<my-com></my-com>
局部引入
组件只能在当前被引入的页面中使用
页面的json中
{ "usingComponents": { "my-text":"/components/myText/myTest" } }
使用组件
<my-text></my-text>
组件和页面的区别
都是由4个文件组成 .js .json .wxml .wxss
组件
组件的json文件中需要声明 "component": true,
组件的 .js文件中调用Component() 函数
组件的事件处理函数需要定义到methods中
页面
页面的 .js中调用 Page()方法
样式
一般情况下,自定义组件的样式只对当前组件生效,不会影响到组件之外的ui结构
-
组件myCom的样式不会影响组件myText
-
组件myCom的样式不会影响小程序页面
-
小程序页面的样式不会影响组件myCom和组件myText
app.wxss中的全局样式对组件无效
只有class选择器有样式隔离的影响,id,标签,属性选择器不受样式隔离的影响
建议使用class选择器
data数据
定义组件的数据
data: { count:0 },
methods方法
事件处理函数 和自定义方法定义到methods中
methods: { addCount(){ this.setData({ count:this.data.count+1 }) this.showCount() }, showCount(){ wx.showToast({ title: 'count值为'+this.data.count, }) } }
properties
父传子
properties是组件的对外属性,用来接收外界传递给组件中的数据
//父组件 <my-com tit="2202A大哥们好" num="{{20}}"></my-com>
properties: { tit:{ type:String, //数据类型 value:'hello' //默认值 }, num:Number },
properties和data的区别
-
小程序的组件中,properties属性和data属性用法相同,都是可读可写的但是:
-
data更倾向于存储组件的私有数据
-
properties 存储外界传递给组件的私有数据
-
methods: { addCount(){ console.log(this.data) //{count: 0, tit: "2202A大哥们好", num: 20} console.log(this.properties) // 本质上一样的,都是可读可写的 console.log(this.properties===this.data) //true } }
使用setData修改properties的值
this.setData({ num:this.properties.num+2 })
数据监听器
监听和响应任何属性和数据字段的变化,从而执行特定的操作
Component({ observers:{ '字段A,字段B':function(字段A的新值,字段B的新值){ //代码 } } })
组件生命周期
组件全部生命周期
生命周期 | 参数 | 描述 | 最低版本 |
---|---|---|---|
created | 无 | 在组件实例刚刚被创建时执行 | 1.6.3 |
attached | 无 | 在组件实例进入页面节点树时执行 | 1.6.3 |
ready | 无 | 在组件在视图层布局完成后执行 | 1.6.3 |
moved | 无 | 在组件实例被移动到节点树另一个位置时执行 | 1.6.3 |
detached | 无 | 在组件实例被从页面节点树移除时执行 | 1.6.3 |
error | Object Error | 每当组件方法抛出错误时执行 | 2.4.1 |
组件主要生命周期
在小程序组件中,最重要的生命周期函数有3个,分别是created,attached,detached
组件实例刚刚被创建好的时候,created生命周期函数会被触发
-
不能调用setData
-
用于给组件的this添加一些自定义的属性字段
组件完全初始化完毕,进入页面节点树后,attached生命周期函数会触发
-
this.data已被初始化完毕
-
初始化工作,比如发请求
组件离开页面节点树后,detached生命周期函数会触发
-
退出一个页面时,会触发页面内每个自定义组件的detached生命周期函数
-
清理性质的工作
lifetimes节点
Component({ lifetimes: { attached: function() { // 在组件实例进入页面节点树时执行 }, detached: function() { // 在组件实例被从页面节点树移除时执行 }, }, // 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容 attached: function() { // 在组件实例进入页面节点树时执行 }, detached: function() { // 在组件实例被从页面节点树移除时执行 }, // ... })
组件所在页面的生命周期
自定义组件的行为依赖于页面状态的变化,就需要用到组件所在页面的生命周期
每当触发页面的show生命周期函数的时候,我们希望能够重新生成一个随机的RGB颜色值
生命周期函数 | 参数 | 描述 |
---|---|---|
show | 无 | 组件所在页面被展示时执行 |
hide | 无 | 组件所在页面被隐藏时执行 |
resize | Object Size | 组件所在页面尺寸变化时执行 |
Component({ pageLifetimes: { show: function() { // 页面被展示 }, hide: function() { // 页面被隐藏 }, resize: function(size) { // 页面尺寸变化 } } })
页面展示的时候,重新生成一个随机的RGB颜色值
Component({ pageLifetimes:{ show(){ this._randomColor() } }, methods:{ _randomColor(){ this.setData({ _rgb:{ r:Math.floor(Math.random()*256), g:Math.floor(Math.random()*256), b:Math.floor(Math.random()*256) } }) } } })
插槽
什么是插槽
组件的wxml中可以提供一个<slot>节点,用于承载组件引用时提供的子节点。
传递单个slot
需要使用多 slot 时,可以在组件 js 中声明启用。
options: { multipleSlots: true // 在组件定义时的选项中启用多 slot 支持 },
组件
<text>components/myTest/myTest.wxml</text> <view>hello</view> <slot name="one"></slot> <view>good</view> <slot name="two"></slot>
页面
<my-test> <view slot="one"> <text>123</text> </view> <view slot="two"> <text>345</text> </view> </my-test>
父子组件通信
父子组件之间通信的 3 种方式
① 属性绑定
-
用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容的数据
② 事件绑定
-
用于子组件向父组件传递数据,可以传递任意数据
③ 获取组件实例
-
父组件还可以通过 this.selectComponent() 获取子组件实例对象
-
这样就可以直接访问子组件的任意数据和方法
小程序组件通信
-
父传子
-
在子组件标签绑定属性 传递要传输的变量
-
在子组件中用properties来接收数据 可以直接使用
-
修改本组件的properties数据使用this.setData()
-
-
子传父
-
在子组件标签上定义一个事件,绑定要执行的方法
-
在子组件中通过 this.triggerEvent来触发自定义事件
-
父组件中通过事件对象e来接收传递的数据
-
-
、获取其他组件数据
this.selectComponent色来可特肯破嫩特(".类名") 就获取到组件的数据
npm
js脚本语言,不能单独运行,嵌套在html中使用,在浏览器中运行
浏览器有js引擎,解析js代码的,逐行解析
ECMAScript,BOM,DOM
node
让js运行在服务端的开发环境
node使用的js的语法 ECMAScript 有自己的api ,fs,http,path
模块化开发
一个js文件就是一个模块 每个模块之间是相互独立的 互不影响
模块中定义的内容 必须暴露出去
使用模块 必须引入
module.exports={} require 该导入导出遵循COmmonJS规范,只能应用于服务端
export default import 该导入导出是遵循ES6规范,可以用在前端也可以用在服务端
node的模块
系统模块
按照完node后就自动有的模块 fs,path,http
自定义模块
自己定义的模块
第三方模块
别人写的模块
npm 这个地方可以查询有哪些第三方模块
https://www.npmjs.com/ 网站上搜索自己所需要的包 https://registry.npmjs.org/ 服务器上下载自己需要的包
怎么下载第三方模块
包管理工具 npm cnpm
yarn
下载
npm install --global yarn yarn --version
小程序中对npm的支持
小程序一级开始支持npm按照第三方包,可以提高小程序的开发效率
-
不支持nodeJS内置的包
-
不支持浏览器内置对象的包
-
不支持c++插件的包
原生小程序中使用vant
-
npm安装(@1.3.3)
npm i @vant/weapp@1.3.3
-
去掉app.json 中的"style":"v2"
-
修改 project.config.json
{ ... "setting": { ... "packNpmManually": true, "packNpmRelationList": [ { "packageJsonPath": "./package.json", "miniprogramNpmDistDir": "./" } ] } }
-
构建npm
-
把nodemodules中的@vant拿到项目目录中
-
引入组件 app.json
"usingComponents": { "van-button": "@vant/weapp/dist/button/index" }
全局数据共享
全局数据共享(又叫做:状态管理)是为了解决组件之间数据共享的问题。开发中常用的全局数据共享方案有:Vuex、Redux、MobX 等。而我们微信小程序常用的全局共享方案是:MobX
使用
在小程序中,可使用 mobx-miniprogram 配合 mobx-miniprogram-bindings 实现全局数据共享。其中:
mobx-miniprogram 用来 创建 Store 实例对象 mobx-miniprogram-bindings 用来 把 Store 中的共享数据或方法 , 绑定到组件或页面中使用
安装Mobx相关的包
npm i --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
mobx相关的包安装完后,删除mini-program-npm ,重新构建npm(工具---构建npm)
创建store实例
根目录下新建store/index.js
import {observable,action} from 'mobx-miniprogram' // 创建store实例 export const store = observable({ // 定义共享数据 数据字段 numA:1, numB:1, // 计算属性 get sum(){ return this.numA+this.numB }, // actions 方法 用来修改state中的数据 updateNuma:action(function(n){ this.numA+=n }), updateNumb:action(function(n){ this.numB+=n }) })
把store中的成员绑定到页面中
使用store的手工绑定方式 应用于页面或者组件, 使用createStoreBindings 创建绑定,会返回一个清理函数的对象用于取消绑定
在页面的onUnload(组件detached) 调用清理函数,否则会导致内存泄露
页面的wxml
<view> {{ numA}}+{{numB}}={{sum}} </view> <button data-n="{{4}}" bindtap="handClick">numA</button>
页面的js文件
import {createStoreBindings} from 'mobx-miniprogram-bindings' import {store} from '../../store' Page({ handClick(e){ this.updateNuma(e.target.dataset.n) }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { // 返回一个清理函数的对象用于取消绑定 this.storeBinds=createStoreBindings(this,{ // 绑定store实例 指定要绑定的store store, // fields:['numA','numB','sum'], //数组形式 把store中的数据拿来 // fields:{ //映射形式 // a:'numA', //this.data.a=store.numA // b:'numB' //this.data.b=store.numB // }, // 函数形式 fields:{ numA:()=>store.numA, numB:()=>store.numB, sum:'sum' }, actions:['updateNuma','updateNumb'] }) }, onUnload() { // 调用清理函数 否则将造成内容泄露 this.handClick.destroyStoreBindings() }, })
behavior
behavior绑定适用于Component构造器,使用storeBindingsBehavior和storeBindings定义数据段
语法
import {storeBindingsBehavior} from 'mobx-miniprogram-bindings' Component({ behaviors:[storeBindingsBehavior], storeBindings:{ //配置项 store, fields:['numA','numB'], actions:{ buttonTap:'updateNuma' } } })
组件的wxml
<view>{{numA}}+{{numB}}={{sum}}</view> <button data-n="{{5}}" bindtap="handClick">numA</button>
组件的js
// components/myNumber/myNumber.js import {storeBindingsBehavior} from 'mobx-miniprogram-bindings' import {store} from '../../store' Component({ behaviors:[storeBindingsBehavior], storeBindings:{ // 配置项 store, fields:['numA','numB','sum'], actions:['updateNuma'] }, methods: { handClick(e){ console.log(123) this.updateNuma(e.target.dataset.n) } } })
behaviors
-
behaviors
是用于组件间代码共享的特性分包
把一个完整的小程序项目,按照需求划分为不同的子包,最终打包成不同的分包,用户在使用时按需进行加载
好处:
优化小程序首次启动的下载时间
分包后项目构成
分包后小程序由1个主包和多个分包组成
-
主包:一般只包含项目的启动页面或Tabbar页面
-
分包:只包含和当前分包有关的页面和资源
分包体积限制
-
整个小程序所有包大小不超过16M(主包+分包)
-
单个分包/主包大小不能超过2M
app.json中声明分包的结构
//声明分包的结构 "subPackages": [ { "root":"packageA", //第一个分包的根目录 "pages": [ //分包下所有页面的存放路径 "pages/detail/detail" ] }, { "root":"packageB", "pages": [ "pages/goods/goods" ] } ],
自定义tabBar
根目录下自定义组件新建custom-tab-bar/index
把点击的active定义为共享的数据
store.js
// 创建store实例 export const store = observable({ // 定义共享数据 数据字段 activeTabBarIndex:0, //点击的下标 updateActiveIndex:action(function(index){ this.activeTabBarIndex = index }) })
wxml
<van-tabbar active="{{ active }}" bind:change="onChange"> <van-tabbar-item info="{{item.info?item.info:''}}" wx:for="{{list}}" wx:key="index"> <image slot="icon" src="{{item.iconPath}}" style="width: 25px; height: 25px;" mode="aspectFit"></image> <image slot="icon-active" src="{{item.selectedIconPath}}" style="width: 25px; height: 25px;" mode="aspectFit"></image> {{item.text}} </van-tabbar-item> </van-tabbar>
js
import {storeBindingsBehavior} from "mobx-miniprogram-bindings" import {store} from '../store' Component({ behaviors:[storeBindingsBehavior], storeBindings:{ store, fields:{ sum:'sum', active:'activeTabBarIndex' }, actions:{ updateActive:"updateActiveIndex" } }, observers:{ 'sum':function(val){ this.setData({ 'list[1].info':val }) } }, /** * 组件的初始数据 */ data: { "list": [ { "pagePath": "/pages/home/home", "text": "首页", "iconPath": "/images/tabs/home.png", "selectedIconPath": "/images/tabs/home-active.png" }, { "pagePath": "/pages/message/message", "text": "消息", "iconPath": "/images/tabs/message.png", "selectedIconPath": "/images/tabs/message-active.png", "info":1 }, { "pagePath": "/pages/contact/contact", "text": "联系我们", "iconPath": "/images/tabs/contact.png", "selectedIconPath": "/images/tabs/contact-active.png" }, { "pagePath": "/pages/contact/contact", "text": "联系我们", "iconPath": "/images/tabs/contact.png", "selectedIconPath": "/images/tabs/contact-active.png" } ] }, /** * 组件的方法列表 */ methods: { onChange(event) { // event.detail 的值为当前选中项的索引 // this.setData({ active: event.detail }); this.updateActive(event.detail) wx.switchTab({ url: this.data.list[event.detail].pagePath, }) }, } })
配置信息
-
在
app.json
中的tabBar
项指定custom
字段,同时其余tabBar
相关配置也补充完整。 -
所有 tab 页的 json 里需声明
usingComponents
项,也可以在app.json
全局开启"tabBar":{ "custom":true, "list":[] }
小程序的双向绑定和vue哪里不一样
⼩程序直接使⽤ this.data.key = value 是不能更新到视图中的。必须使⽤ this.setData来更新值。
-
bindtap和catchtap
都是点击事件,bindtap不能阻止冒泡,catchtap能阻止冒泡
小程序路由函数
-
wx.redirectTo() 关闭当前页面,跳转到非tabbar页面。
-
wx.navigateTo() 保留当前页面,跳转到非tabbar页面。
-
wx.navigateBack() 关闭当前页面 通过 getCurrentPages卡瑞特()
获取前的⻚⾯栈,定需要返回⼏层
-
wx.switchTab() 关闭所有的非tabbar页面 跳转到tabbar页面
-
wx.relaunch瑞拉吃() 关闭所有页面 跳转到某一页面