目录
一、配置篇
(1)官网链接:
(2)项目分析
(3)调试器
(4)预览体验
(5)配置文件
(6)配置pages
(7)配置windows字段
(8)tabbar配置
9.页面配置(局部配置)
10.config.json配置文件和sass配置
11.sitemap.json文件
二、开发基础篇
1.rpx单位
2. view组件(容器)
3. swiper组件(轮播图)
4. image组件(图像)
7. scroll-view组件 (滚动效果)
8. svg字体图标的使用
9. background-image样式(背景图片)
10.bind(事件)
11.事件的传递数据 data
12.事件传参
13. 声明和绑定数据
14.setData()修改数据
15.双向数据·绑定
16.列表渲染
17.列表渲染进阶
18.条件渲染
三、生命周期
启动阶段
运行阶段
销毁阶段
页面生命周期
组件生命周期
四、开发篇(中级)
1.发起网络请求
2.界面交互 - loading加载提示框
3.界面交互 - 模拟对话框
4.本地存储
5.编程式导航
6. 上拉加载(获取更多数据)
7.下拉刷新(重置更多数据)
8. scroll-view组件 (实现上拉加载和下拉刷新)
五、自定义组件
1.自定义组件(注册组件)
2.自定义组件(数据和方法)
3.自定义组件(属性)
在页面中使用 properties定义的数据
在页面中传递 properties:
4.自定义组件(wxml中的slot)
5.自定义组件(组件样式隔离)
styleIsolation 的值说明:
使用场景:
6.自定义组件(数据监听器)
7.自定义组件(父往子传值)
8.自定义组件(子往父传值)
步骤 1: 在子组件中定义并触发事件
步骤 2: 在父组件中监听子组件的事件
9.组件通信,获取组件实例
步骤 1: 定义组件
步骤 2: 在页面中使用组件
步骤 3: 在页面脚本中获取组件实例
10.组件的生命周期
六、开发篇(高级)
1.构建npm
2.自定义构建npm
3.Vant组件库的使用
4.分包加载
分包的好处:
分包的规则:
如何进行分包:
注意事项:
5.独立分包
独立分包的特点:
如何配置独立分包:
6.分包预下载
分包预下载的配置:
分包预下载的规则:
七、开发篇(能力拓展)
1.获取微信的用户信息
2.转发功能
使用页面内转发按钮
3.分享到朋友圈
4.手机号验证组件
5.客服功能
6.全局数据共享
7.页面间通信
8.事件总线
一、配置篇
(1)官网链接:
- AppID和AppSecret
- 微信小程序开发工具(需要联网)
- 新建项目时勾选不使用云服务
(2)项目分析
完整的小程序项目分为主体文件和页面文件
主体文件:(全局生效)
- app.js 小程序入口文件
- app.json 小程序的全局配置文件
- app.wxss 小程序的全局样式
页面文件:(局部生效)
每个页面由四个文件组成,且每个页面文件只对当前页面有效
.js 页面逻辑
.wxml 页面结构
.wxss 页面样式
.json 页面配置
注意:页面的组成必须有 .js文件和.wxml文件
(3)调试器
- Console 查看控制台打印的信息
- Network 查看请求信息
- AppData 查看当前页面的数据
- Storage 查看本地存储的数据
(4)预览体验
点击上方的预览,通过微信扫描的方式,在当前手机上查看预览的效果
(5)配置文件
- app.json 小程序全局配置文件,配置全局属性和路由
- 页面.json 小程序页面的配置文件,配置当前页面的窗口样式和标题
- project.config.json 小程序项目的配置文件,保存项目中一些配置信息和开发者的个人设置
- sitemap.json 配置小程序以及页面是否被微信索引,提高微信在搜索引擎中搜索到的概率
(6)配置pages
在app.json中可以从pages中查看当前的页面
配置pages字段时,需要注意:
- 页面路由不需要写文件后缀
- 小程序中页面的新增或减少都需要对pages数组进行修改
- 未指定entryPagePath(首页路径),pages数组中的第一项默认为小程序的初始页面
(7)配置windows字段
示例代码:
"window": {"navigationBarTextStyle": "black","navigationBarBackgroundColor": "#242424","navigationStyle": "custom","navigationBarTitleText": "你好世界","enablePullDownRefresh": true,"backgroundColor": "#383838","backgroundTextStyle": "dark"}
(8)tabbar配置
至少两个tabbar,最多5个tabbar
其中selectedColor为当前所选tabbar文件的颜色
color 为tabbar的背景颜色
borderStyle 为tabbar的border颜色
示例代码:
"tabBar": {"selectedColor": "#30c7c9", "color": "#666","borderStyle": "black","list": [{"pagePath": "pages/index/index","text": "首页","iconPath": "/assets/tabbar/index.png","selectedIconPath": "/assets/tabbar/indexSelected.png"},{"pagePath": "pages/community/community","text": "社区","iconPath": "/assets/tabbar/community.png","selectedIconPath": "/assets/tabbar/communitySelected.png"},{"pagePath": "pages/person/person","text": "个人","iconPath": "/assets/tabbar/person.png","selectedIconPath": "/assets/tabbar/personSelected.png"}]}
9.页面配置(局部配置)
在每个页面的 json文件中可以配置每个页面独有的样式,当app.json与页面.json都设置时,当前的页面会以页面.json为准进行配置
10.config.json配置文件和sass配置
创建项目时,会生成两个config.json文件(project.config.json和project.private.config.json),用于保存开发者在工具上的个性化配置,当重新安装开发者工具或换电脑工作时,只需要载入同一项目的代码包,开发者工具就会自动恢复到当前开发者性的个性化配置。
sass配置:
在project.config.json中的setting新增:
"useCompilerPlugins":["sass"],
修改为sass格式的样式后记得将所使用的wxss后缀都改为scss后缀样式文件
测试是否生效,可以在sass文件上写入
text{color: red;
}
查看该页面的文字是否为红色就知道是否生效了
记得在详细中勾选(将JS编译成ESS)
11.sitemap.json文件
配置小程序以及页面是否运行被微信检索,提高微信内容被用户搜索到的概率
当开发者允许微信索引时,微信会以爬虫的形式,为小程序的页面内容建立索引,当用户的搜索词条触发索引时,小程序的页面将可能展示在搜索结果中
sitemap.json默认所有页面都能被索引
二、开发基础篇
1.rpx单位
rpx单位和px单位的区别
rpx单位 能根据不同的设备的屏幕宽度进行自适应缩放(推荐)
px单位 是固定的宽度,不能自适应缩放
2. view组件(容器)
<vew></view>容器组件,相当于JavaScript中的<div></div>
3. swiper组件(轮播图)
<swiper
autoplay interval="2000"
indicator-dots
indicator-color="#fff"
indicator-active-color="#f5f6f7" >
<swiper-item> 轮播图内容A </swiper-item>
<swiper-item> 轮播图内容B </swiper-item>
<swiper-item> 轮播图内容C </swiper-item>
</swiper>
4. image组件(图像)
src:图片资源地址
mode:图片缩放模式
show-menu-by-longpress:长按图片显示菜单
lazy-load:图片懒加载(滑动到一定的距离以后显示图片)
注意:默认image的宽度为320px,高度为240px
5. navigation组件(导航跳转)
url:当前的小程序内的跳转链接
open-type:跳转方式
- navigate:保留当前页面,跳转到某个页面(不能是tabbar页面)
- redirect:关闭当前页面,跳转到某个页面(不能是tabbar页面)
- switchTab:跳转到tabBar页面,并关闭其他非tabBar页面
- reLaunch:关闭所有页面,打开到应用的某个页面
- navigateBack:关闭当前页面,返回上一级页面或多级页面
- 页面传参:跳转路径使用?分隔路径与参数,参数键与参数值用=相连,不同的参数使用&进行分隔
- 当open-type="switchTab"不支持传参
- 页面接参:onLoad(options)生命周期函数中获取所传递的参数
7. scroll-view组件 (滚动效果)
scroll-x:允许横向滚动
scroll-y:允许纵向滚动
8. svg字体图标的使用
iconfont矢量图标库链接:
iconfont-阿里巴巴矢量图标库https://www.iconfont.cn/当选择好图标后在我的项目
点击项目设置,勾选Base64
在Font class中点击复制代码
点击出现的css后缀文件名,将跳转页面,将其里面的所有代码都复制到项目中创建的iconfont\iconfont.scss文件(注意后缀)
最后在app.json添加下面代码:
记得以分号结尾,否则出现异常
@import "./iconfont/iconfont.scss";
使用:(图标的样式名在iconfont.scss中查看)
<text class="iconfont 图标的样式名"></text>
9. background-image样式(背景图片)
background-image不支持本地路径,使用网路图片或base64,或者使用<image/>组件
使用:
background-image:url(网络路径) ;
10.bind(事件)
小程序中不能通过on的方式绑定事件,也没有click等事件,小程序使用bind方法,click事件需要tap事件来进行代替
有两种绑定事件的方式:
- bind后面跟上冒号,冒号后面加上事件名:<view bind:tap="fnName" ></view>
- bind后面跟上事件名:<view bindtap="fnName" ></view>
对于输入框绑定事件的方式:
- bind后面跟上冒号,冒号后面加上事件名:<view bind:input="fnName" ></view>
- bind后面跟上事件名:<view bindinput="fnName" ></view>
对于事件的处理函数写到.js文件中,在.js文件中需要调用小程序提供的Page方法来注册小程序的页面,我们可以在Page方法中创建事件处理函数
示例代码(index.wxml):
<button bind:tap="handler">点击我发起事件</button><input type="input" bindinput="getInputValue"/>
(index.js):
Page({handler(event){console.log(event)},getInputValue(event){console.log(event)console.log(event.detail.value)}
})
事件分为:冒泡事件和非冒泡事件
- 冒泡事件:当一个组件的事件触发后,该事件会向父节点传递
- 非冒泡事件:当一个组件的事件触发后,该事件不会向父节点传递
- 使用bind绑定单点事件,会触发事件冒泡,想阻止事件冒泡,使用catch来绑定事件
推荐使用catch来绑定事件,因为这样触发子组件的时候,父组件不会触发。
而使用bind来绑定事件,这样触发子组件时,父组件也会触发
11.事件的传递数据 data
在组件上通过data-*的方式定义需要传递的数据,其中*是自定义数据:
<view data-id="100" bindtap="handler"></view>通过事件获取自定义数据
.wxml 中发送数据的方式:(id=100,name="关注我")
<button data-id="100" data-name="关注我" bind:tap="handler">点击我发起事件</button>
.js 文件中在方法获取的方式:
可以使用target,也可以使用currentTarget
handler(event){console.log(event.target.dataset.id)console.log(event.currentTarget.dataset.id)console.log(event.target.dataset.name)console.log(event.currentTarget.dataset.name)}
target和currentTarget的区别
-
target
:触发事件的原始组件,即事件最初发生的组件。在捕获阶段的每个节点上,target
都是最初触发事件的那个组件。target
将会是内部view
的组件实例,因为事件是从这里开始的。 -
currentTarget
:事件当前所在的组件,事件绑定在哪个组件上,currentTarget
就是指向哪个组件。在冒泡阶段,这个属性会变化,但target
永远是触发事件的那个组件。currentTarget
将会根据事件处理函数的绑定位置而变化。如果事件处理函数是绑定在外部view
上的,那么在捕获或冒泡阶段处理事件时,currentTarget
将会是外部view
的组件实例。
12.事件传参
除了使用data-*进行传递参数外,还可以使用mark标记传递参数
mark是自定义属性,在组件上添加,用于识别target节点,同时mark还可以用于承载一些自定义数据
在组件上使用mark自定义属性的方式将数据传递给事件处理函数
<view mark:id="100" mark:name="关注我" bindtap="handler" ></view>
然后通过事件对象获取自定义数据
通过mark不仅可以获取该触发事件的节点,以及父事件上的所有节点
handler(event){console.log(event.mark.id)console.log(event.mark.name)}
13. 声明和绑定数据
在.js中使用Page()方法的data对象中进行声明定义
在.wxml中使用Mustache语法(双大括号{{}} )将变量包起来,从而绑定数据
在{{ }}内部可以进行算数运算、三元运算、逻辑判断(只写表达式)
// index.js
Page({data:{headLine:'我的标题',person:{name:'小昊',area:'海南'}}
})
.wxml:
<View>{{headLine}}</View><view>我的名字是{{person.name}}</view><view>我来自{{person.area}}</view>
14.setData()修改数据
小程序中不推荐通过赋值的方式进行修改,这样赋值的方式修改数据是无法改变页面的数据
而是通过setData()方法进行修改,setData()方法接收对象作为参数,key是需要修改的数据,value是最新的值
setData()的作用:更新数据、驱动视图更新
js:
// index.js
Page({data:{count:1},increment(event){this.setData({count:this.data.count += 1})console.log(this.data.count)}
})
wxml:
<view>{{count}}</view><button bind:tap="increment">count+1</button>
使用Object.assign将多个对象合并为一个对象
const userInfo = Object.assign(this.data.person,{ age : 21 );
使用delete删除单个属性
delete this.data.userInfo.age
15.双向数据·绑定
在wxml中的<input value="{{value}}" />是普通属性的绑定是单向的
希望用户在输入数据时改变data中的数据,在对应的属性之前添加model前缀即可
<input model:value = "{{value}}" />(只能是单一字段的绑定,不能是data的路径,不支持数组和对象)
16.列表渲染
通过循环遍历一个数组或对象,将其每个元素渲染到页面上
每一项的变量名默认为item,下标默认变量名为index
使用wx:for遍历时,建议加上wx:key
因为wx:key以两种形式提供:
- 字符串:代表遍历array中的item的某个属性,该属性需要列表中唯一的字符串或数字,且不能动态改变
- 保留关键字this代表在for循环中的item本身,item本身是一个唯一的字符串或数字时可以使用
注意:
- 如果不使用 wx:key,会报一个warming,明确知道该列表是静态的,以后的数据不会改变,可以选择忽略
- 在wx:key添加属性值时,不需要使用双大括号语法,直接遍历array中的item的某个属性
.js:
data:{fruitList:[{id:1,name:'苹果'},{id:2,name:'橙子'},{id:3,name:'雪梨'},]},
.wxml:
<view wx:for="{{fruitList}}" wx:key="id" >水果:{{item.name}}-{{item.id}}</view>
17.列表渲染进阶
如果对默认的变量名和下标进行修改,可以使用wx:for-item和wx:for-index
- wx:for-item 指定数组当前元素的变量名
- wx:for-index 指定数组当前下标的变量名
例如:
<view wx:for="{{fruitList}}" wx:key="id" wx:for-item="fruitItem" wx:for-index="fruitIndex" >水果:{{fruitItem.name}}-{{fruitIndex}}</view>
wx:for 用在<block/>标签上,以渲染一个包含多个节点的结构块
- <block/>并不是一个组件,它仅仅是一个包装元素,不会在页面进行任何的渲染,只接收控制属性
- <block/>标签在wxml可以用于组织代码结构,支持列表渲染,条件渲染等
18.条件渲染
两种条件渲染方式:
- 使用wx:if、wx:elif、wx:else属性组
- 使用hidden属性
示例代码:
<view wx:if="{{score>=90}}">优秀</view><view wx:elif="{{score>=60}}">合格</view><view wx:else>不合格</view>
<view hidden="{{!isFlag}}">详细内容</view>
wx:if 和hidden二者的区别:
- wx:if 当条件为true是显示出来,否则结构不会显示,通过移除或新增节点的方式实现
- hidden 当条件为true会将结构隐藏,否则结构会显示出来,通过display样式属性实现
三、生命周期
小程序的生命周期指的是小程序从启动到关闭的整个过程,这个过程可以分为几个阶段,每个阶段都有其特定的生命周期函数。以下是小程序的主要生命周期及其对应的函数:
启动阶段
- onLaunch:当小程序初始化完成时,会触发
onLaunch
(全局只触发一次)。 - onShow:当小程序启动,或从后台进入前台显示时,会触发
onShow
。
运行阶段
- onHide:当小程序从前台进入后台时,会触发
onHide
。
销毁阶段
- onUnload:当小程序关闭时,会触发
onUnload
。
页面生命周期
除了整个小程序的生命周期外,每个页面也有自己的生命周期:
-
onLoad:监听页面加载,一个页面只调用一次。
-
onShow:监听页面显示,每次打开页面都会调用。
-
onReady:监听页面初次渲染完成,一个页面只调用一次。
-
onHide:监听页面隐藏。
-
onUnload:监听页面卸载。
组件生命周期
小程序的组件也有自己的生命周期,包括:
-
created:在组件实例刚刚被创建时执行。
-
attached:在组件实例进入页面节点树时执行。
-
ready:在组件在视图层布局完成后执行。
-
moved:在组件实例被移动到节点树另一个位置时执行。
-
detached:在组件实例被从页面节点树移除时执行。
-
error:每当组件方法抛出错误时执行。
示例:
Component({// 组件的对外属性properties: {// ...},// 组件的内部数据data: {// ...},// 组件生命周期函数created: function() {console.log('created');},attached: function() {console.log('attached');},ready: function() {console.log('ready');},moved: function() {console.log('moved');},detached: function() {console.log('detached');},// 组件方法抛出错误时触发error: function(err) {console.error('error:', err);},// 页面生命周期函数pageLifetimes: {show: function() {// 页面被展示时触发console.log('page show');},hide: function() {// 页面被隐藏时触发console.log('page hide');},resize: function(size) {// 页面尺寸变化时触发console.log('page resize:', size);}},// 组件方法methods: {// ...}
});
四、开发篇(中级)
1.发起网络请求
发起网络请求获取数据,需要使用wx.request()接口API
wx.request请求的域名必须在微信公众平台进行配置,如果使用wx.request请求进行配置的域名,在控制台会有相应的错误
在方法中写请求:
getData(){wx.request({url: 'url', //请求路径method:'GET', //请求方法data:{}, //请求参数header:{}, //请求头success:(res)=>{}, //调用API成功响应fail:(err)=>{}, //调用API失败响应complete:(res)=>{} //无论是否请求成功,都会执行})}
2.界面交互 - loading加载提示框
loading提示框配合网络请求使用,对应的API有两个:
- wx.showLoading()显示loading提示框
- wx.hideLoading()关闭loading提示框
示例代码:
wx.showLoading({title: '加载中', // 提示的内容mask: true, // 是否显示透明蒙层,防止触摸穿透
})
wx.hideLoading();
3.界面交互 - 模拟对话框
wx.showModal() 用于显示模态对话框,可以用来提示用户进行确认操作或者展示信息。
wx.showToast() 用于显示消息提示框,可以用来显示一些简短的通知信息。
示例:
wx.showModal({title: '提示',content: '这是一个模态弹窗',showCancel: true,cancelText: '取消',cancelColor: '#000000',confirmText: '确定',confirmColor: '#3CC51F',success (res) {if (res.confirm) {console.log('用户点击确定')} else if (res.cancel) {console.log('用户点击取消')}},fail (err) {console.error(err)},complete (res) {console.log(res)}
})
wx.showToast({title: '已完成',icon: 'success',duration: 2000
})
4.本地存储
小程序本地存储是小程序在使用API将数据存储到用户的设备上,方便小程序下次启动时快速地读取这些数据
注意:对象的类型数据可以直接进行存储获取,无需使用JSON.stringfy()、JSON.parse()转换
同步APi:
存储:wx.setStorageSync()
获取:wx.getStorageSync()
删除:wx.removeStorageSync()
清空:wx.clearStorageSync()
异步API:
存储:wx.setStorage()
获取:wx.getStorage()
删除:wx.removeStorage()
清空:wx.clearStorage()
存储需要key 和 value、获取和删除只需要key、清空无需参数
5.编程式导航
- wx.navigateTo():保留当前页面,跳转到某个页面,但是不能跳转到tabbar
- wx.redirectTo():关闭当前页面,跳转到某个页面,但是不允许跳转到tabbar
- wx.switchTab():跳转到tabbar页面,路径不能带参数
- wx.reLaunch():关闭所有页面,打开某个页面
- wx.navigateBack():关闭当前页面,返回上一个页面
注意:跳转到的页面使用onLoad钩子函数中通过形参接收
6. 上拉加载(获取更多数据)
实现上拉加载的方式:
- 在app.json或者page.json中配置举例底部的距离:onReachBottomDistanc,默认为50px
- 在页面.js中定义onReachBottom事件监听用户上拉加载
7.下拉刷新(重置更多数据)
实现下拉刷新的方式:
- 在app.json或者page.json中开启允许下拉,同时配置窗口、loading样式等
- 在页面.js中定义onPullDownRefresh事件监听用户下拉刷新
8. scroll-view组件 (实现上拉加载和下拉刷新)
scroll-view组件常用的属性
- scroll-x: 是否允许横向滚动,默认为
false
。 - scroll-y: 是否允许纵向滚动,默认为
false
。 - upper-threshold: 距离顶部/左边多远时触发 bindscrolltoupper事件中的所绑定的函数,默认值为
50
。 - lower-threshold: 距离底部/右边多远时触发 bindscrolltolower事件中的所绑定的函数,默认值为
50
。 - bindscroll: 滚动时触发的事件。
- bindscrolltoupper: 滚动到顶部/左边时触发的事件。
- bindscrolltolower: 滚动到底部/右边时触发的事件。
五、自定义组件
1.自定义组件(注册组件)
组件分为公共组件和页面组件两种,因此注册组件的方式:
- 全局注册:在app.json文件中配置usingComponents进行注册,注册后可以在任意页面使用
- 局部注册:在页面的json文件中配置usingComponents进行注册,注册后只能在当前页面使用
在usingComponents中进行注册组件是,需要提供 自定义组件名 和 自定义组件的文件路径
在组件中注册好后,直接将自定义组件的组件名当做组件标签名使用即可
2.自定义组件(数据和方法)
组件数据和方法需要再组件.js的Component方法中进行定义,Component创建自定义组件
data:定义组件的内部数据
methods:在组件中事件处理程序需要写到methods中才生效
3.自定义组件(属性)
Properties是指组件对外的属性,主要用于接收使用传递给组件内部的数据
在页面中使用 properties定义的数据
my-component.js:
Component({properties: {// 字符串类型属性title: {type: String,value: '默认标题'},// 数字类型属性count: {type: Number,value: 0},// 布尔类型属性disabled: {type: Boolean,value: false},// 对象类型属性userInfo: {type: Object,value: {}},// 数组类型属性items: {type: Array,value: []}},// 组件数据data: {// ...},// 组件方法methods: {// ...}
});
my-component.wxml:
<view class="component"><text>{{title}}</text><view wx:for="{{items}}" wx:key="unique"><text>{{item}}</text></view><button disabled="{{disabled}}">点击我</button>
</view>
在页面中传递 properties:
<my-component title="我的标题" count="10" disabled="{{isDisabled}}" userInfo="{{userInfo}}" items="{{itemList}}"></my-component>
4.自定义组件(wxml中的slot)
slot 是用来定义组件插槽的,它允许开发者向组件内部插入自定义内容。以下是一个简单的示例,展示如何在自定义组件中使用 slot
。(默认一个组件的wxml中只能有一个slot )
wxml:(自定义一个含有slot组件)
<!-- /components/my-component/my-component.wxml -->
<view><view>这是一个自定义组件</view><!-- 这里定义了一个默认插槽 --><slot></slot>
</view>
wxml:(所使用的在slot中填写内容)
<!-- /pages/index/index.wxml -->
<view><my-component><!-- 这里的内容会插入到 my-component 组件的 slot 中 --><view>这是插入到组件插槽中的内容</view></my-component>
</view>
如果使用多个slot时,需要在js中的
Component({})
5.自定义组件(组件样式隔离)
在微信小程序中,Component
构造器用于定义自定义组件。其中,options
对象允许开发者配置组件的一些选项,styleIsolation
就是其中之一,用于控制组件样式的隔离程度。
styleIsolation
有以下几个可选值:
-
isolated
:表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响。这是默认值。 -
apply-shared
:表示页面样式将影响到自定义组件,但自定义组件的样式不会影响页面。 -
shared
:表示页面样式和自定义组件样式将互相影响。
Component({options: {styleIsolation: 'isolated' // 或者 'apply-shared' 或 'shared'},// 其他组件定义
})
styleIsolation 的值说明:
-
isolated
:样式隔离是最严格的,组件内部的样式不会影响到外部,外部的样式也不会影响到组件内部。这种隔离确保了组件样式的独立性,但是可能导致组件与页面整体样式不协调。 -
apply-shared
:组件外部的样式可以应用到组件内部,但组件内部的样式不会影响到外部。适用于希望页面样式能够影响到组件的情况。 -
shared
:组件内外样式相互影响,适用于组件和页面样式高度一致,或者开发者希望直接控制组件样式的情况。
使用场景:
- 当你需要确保组件样式不影响外部页面,或者外部页面样式不影响组件时,应使用
isolated
。 - 当你需要页面样式能够影响到组件,但不希望组件样式影响到页面时,应使用
apply-shared
。 - 当你需要组件和页面样式完全共享,不进行隔离时,应使用
shared
。
6.自定义组件(数据监听器)
在.js中监听数据,一旦数据发生了变化就会调用相应的监听器方法
// component.js
Component({properties: {// 定义组件属性,可由外部传入myProperty: {type: String,value: 'initial value'}},data: {// 定义组件内部数据myInternalData: 'initial internal value'},observers: {// 监听组件属性 myProperty 的变化'myProperty': function(newVal, oldVal) {console.log(`myProperty changed from ${oldVal} to${newVal}`);// 假设我们根据 myProperty 的变化来更新内部数据this.setData({myInternalData: `Updated due to myProperty change: ${newVal}`});},// 监听组件内部数据 myInternalData 的变化'myInternalData': function(newVal, oldVal) {console.log(`myInternalData changed from ${oldVal} to${newVal}`);// 可以在这里执行其他逻辑,比如调用函数},// 监听多个属性的变化'myProperty, myInternalData': function(newVal, oldVal) {// newVal 和 oldVal 将是数组形式,分别包含新值和旧值console.log(`either myProperty or myInternalData changed`);}},methods: {// 组件方法updateProperty(value) {// 更新属性,这将触发监听器this.setData({myProperty: value});}}
});
7.自定义组件(父往子传值)
父组件往子组件传递数据,需要两个步骤:
- 在父组件wxml中使用数据绑定的方式向子组件传递动态数据
- 子组件内部使用propertiess接收父组件传递的数据
示例:
(1)在子组件中的properties中定义待会要接收父组件传递来的值,名为myMessage
// child-component.js
Component({properties: {// 定义一个属性,用于接收从父组件传递的值myMessage: {type: String,value: '默认值'}},data: {// 子组件的内部数据},methods: {// 子组件的方法}
});
(2)子组件可以直接使用
<!-- child-component.wxml -->
<view>{{myMessage}}</view>
(3)父组件向子组件传递值:
<!-- parent-page.wxml -->
<view><!-- 引入子组件,并通过属性传递值 --><child-component my-message="Hello from Parent!"></child-component>
</view>
(4)别忘了在父组件中注册子组件
// parent-page.json
{"usingComponents": {"child-component": "/path/to/child-component"}
}
8.自定义组件(子往父传值)
子组件向父组件传递数据,需要两个步骤:
- 自定义组件内部使用triggerEvent方法发射一个自定义事件,同时携带数据
- 自定义组件标签上通过bind方法监听发射的事件,同时绑定事件处理函数,在事件函数中通过事件对象获取传递的数据
步骤 1: 在子组件中定义并触发事件
首先,在子组件的方法中,使用 this.triggerEvent
方法来定义并触发一个事件,同时可以将数据作为事件的参数传递。
// child-component.js
Component({methods: {// 假设这个方法会在某个情况下被调用,例如按钮点击onChildButtonTap() {// 定义要传递给父组件的数据let sendData = { message: 'Hello from Child!' };// 触发自定义事件,并将数据传递给父组件this.triggerEvent('childEvent', sendData);}}
});
在子组件的 WXML 文件中,你可以绑定一个事件处理函数,比如按钮的点击事件:
// child-component.js
Component({methods: {// 假设这个方法会在某个情况下被调用,例如按钮点击onChildButtonTap() {// 定义要传递给父组件的数据let sendData = { message: 'Hello from Child!' };// 触发自定义事件,并将数据传递给父组件this.triggerEvent('childEvent', sendData);}}
});
步骤 2: 在父组件中监听子组件的事件
在父组件的 WXML 文件中,你可以使用 bind
或 catch
前缀来监听子组件触发的事件。
<!-- parent-page.wxml -->
<view><!-- 监听子组件的 childEvent 事件 --><child-component bind:childEvent="onChildEvent"></child-component>
</view>
在父组件的 JS 文件中,定义事件处理函数来接收子组件传递的数据:
// parent-page.js
Page({data: {// 父组件的数据},methods: {// 处理子组件传递的事件onChildEvent: function(event) {// event.detail 包含子组件传递的数据console.log(event.detail.message); // 输出: Hello from Child!}}
});
9.组件通信,获取组件实例
父组件使用this.selectComponent方法,获取子组件实例对象,这样可以直接访问子组件的任意数据和方法
this.selectComponent方法在调用时需要传入一个匹配选择器selector
步骤 1: 定义组件
首先,确保你已经在页面的 JSON 配置文件中注册了自定义组件。
// page.json
{"usingComponents": {"my-component": "/path/to/my-component"}
}
然后,定义组件本身。
// my-component.js
Component({data: {// 组件内部数据},methods: {// 组件内部方法customMethod() {console.log('Custom method called');}}
});
步骤 2: 在页面中使用组件
在页面的 WXML 文件中,使用定义好的组件。
注意:这里给组件设置了 id
属性,这将用于后续的选择操作。
<!-- page.wxml -->
<view><my-component id="myComponent"></my-component>
</view>
步骤 3: 在页面脚本中获取组件实例
在页面的 JS 文件中,使用 selectComponent
方法来获取组件实例。
// page.js
Page({onReady: function() {// 使用 selectComponent 方法获取组件实例var myComponent = this.selectComponent('#myComponent');// 现在可以调用组件内部的方法或访问其数据if (myComponent) {myComponent.customMethod(); // 调用组件内部的方法console.log(myComponent.data); // 访问组件内部的数据}}
});
注意:
selectComponent
方法仅在自定义组件的attached
钩子之后才能调用,因为在这之前组件实例可能尚未生成。- 使用
selectComponent
时,传入的参数是组件的id
选择器(以#
开头)。 - 如果组件定义了
externalClasses
或options
中的addGlobalClass
,那么在选择器中可能需要考虑这些全局样式类的影响。
10.组件的生命周期
微信小程序自定义组件的生命周期函数实际上包括以下五个主要阶段:
-
created
:在组件实例刚刚被创建时触发。此时不能调用setData
,通常用于执行组件的初始化操作。 -
attached
:在组件实例进入页面节点树时触发。此时可以访问this.data
,对数据进行初始化操作。 -
ready
:在组件布局完成后触发。此时可以获取节点信息(如使用this.createSelectorQuery
)。 -
moved
:在组件实例被移动到另一个节点时触发。 -
detached
:在组件实例从页面节点树移除时触发。此时可以执行一些清理操作,例如取消网络请求或定时器。
六、开发篇(高级)
1.构建npm
通过 点击工具 => 构建npm,构建完成后,会默认在小程序项目根目录的node_modules同级目录下生成miniprogram_npm目录,里面存放着构建完成以后的npm包,也就是小程序运行过程中真正使用的包
2.自定义构建npm
在实际的开发中开发人员对目录结构进行调整优化,将小程序源码放到miniprogram目录下
需要开发者在project.config.json中指定 node_modules 的位置和目标 miniprogram_npm 的位置
具体配置:
- 配置 project.config.json 的 miniprogramRoot 指定小程序源码目录
- 配置 project.config.json 的 setting.packNpmManually 为 true ,开启自定义 node_modules和 miniprogram_npm 位置的构建 npm 方式
- 配置 project.config.json 的 setting.packNpmRelationList项, 指定 packgeJsonPath 和 miniprogramNpmDisDir 的位置、
3.Vant组件库的使用
介绍 - Vant Weapp (vant-ui.github.io)https://vant-ui.github.io/vant-weapp/#/home
使用npm 进行安装
npm i @vant/weapp -S --production
具体的操作根据官方文档进行,只需要两个步骤:
- 将组件在app.json中进行全局注册或在index.json中进行局部注册
- 引入组件后,可以在wxml中直接使用组件
注意:在app.json中将"style":"v2"去除,如果不关闭将造成部分组件样式混乱
4.分包加载
小程序分包是微信小程序提供的一种优化手段,允许开发者将小程序分成多个部分(称为分包),以减少首次启动时的加载时间,提升用户体验。以下是关于小程序分包的一些主要概念和步骤:
分包的好处:
- 减少主包大小:将不常用的功能模块放在分包中,可以显著减少主包的大小。
- 按需加载:用户在使用到特定功能时,才会加载对应的分包,从而加快首次打开速度。
- 并行下载:当小程序需要多个分包时,这些分包可以并行下载,提高下载效率。
分包的规则:
- 主包:小程序启动时必须加载的包,包含启动页、TabBar 页面等。
- 分包:非启动时必须加载的包,可以包含多个页面。
- 子包:分包可以进一步细分为子包。
如何进行分包:
-
配置分包:在
app.json
中配置subpackages
或subPackages
字段,定义分包的结构。
每个分包结构的三个常用字段:
- root:分包单点根目录,该目录下的所有文件都会被打包成一个独立的包
- name:分包的别名,用于在代码中引用该分包
- pages:指定当前分包中包含了哪些页面
{"pages": ["pages/index"],"subpackages": [{"root": "packageA","pages": ["pages/cat/cat", "pages/dog/ddog"]},{"root": "packageB","pages": ["pages/apple/apple", "pages/orange/orange"]}]
}
-
划分页面:根据配置,将不同的页面放置到对应的分包目录中。
-
引用分包资源:在分包内使用
require
或import
引用本地资源时,需要使用相对路径。引用主包的资源时,可以使用../../
等相对路径或绝对路径。 -
分包预下载:可以在
app.json
中配置preloadRule
,定义分包的预下载规则,使得在特定条件下提前下载分包,减少用户等待时间。
注意事项:
- 分包之间不能互相嵌套。
- 分包名不能与主包名相同。
- 整个小程序所有分包的大小不超过20MB
- 分包的大小限制与主包相同,单个分包或主包大小不能超过2MB。
5.独立分包
微信小程序的独立分包是小程序分包策略中的一种特殊形式,它允许某些分包不依赖于主包即可独立运行。这意味着当用户打开小程序时,可以只下载并启动特定的分包,而不必加载整个小程序的主包,这对于优化首次启动速度和减少不必要资源的下载非常有帮助。
以下是关于微信小程序独立分包的一些关键点:
独立分包的特点:
- 独立性:独立分包可以独立于主包运行,不需要下载主包即可启动。
- 快速启动:用户可以直接打开独立分包中的页面,减少了下载和启动时间。
- 特定场景:适用于某些功能模块,如营销活动页面,可以快速响应用户的操作。
如何配置独立分包:
- 配置
-independent
字段:在app.json
的subpackages
或subPackages
配置中,为需要配置为独立分包的包添加"independent": true
。
{"pages": ["pages/index"],"subpackages": [{"root": "packageA","pages": ["pages/independent/independent"],"independent": true}]
}
注意事项:
- 独立分包中不能依赖主包和其他分包中的资源
- 主包中的app.wxss对独立分包无效
- App只能在主包中定义,独立分包不能定义App,会造成无法预期的行为
6.分包预下载
分包预下载是微信小程序提供的一项功能,它允许开发者配置某些分包在特定条件下提前下载,以减少用户在使用过程中的等待时间。这种策略能够提升用户体验,特别是对于那些不希望用户在访问特定功能时出现明显加载延迟的场景。
分包预下载的配置:
配置preloadRule
:在app.json
中,可以通过preloadRule
字段来定义分包的预下载规则。
{"pages": ["pages/index"],"subpackages": [{"root": "subpackageA","pages": ["pages/a", "pages/b"]},{"root": "subpackageB","pages": ["pages/c", "pages/d"]}],"preloadRule": {"subpackageA": {"network": "wifi","packages": ["subpackageB"]}}
}
在上面的配置中,subpackageA
的预下载规则被设置为当用户处于WiFi网络环境下时,提前下载subpackageB
。
分包预下载的规则:
network
字段:指定触发预下载的网络条件,可以是all
(不限网络环境)、wifi
(仅在WiFi环境下)等。packages
字段:指定当满足network
条件时,需要预下载的分包。
七、开发篇(能力拓展)
1.获取微信的用户信息
- 使用
wx.getUserProfile
API:这是推荐的方式,可以获取用户的基本信息。
使用wx.getUserProfile
API,可以获取用户的公开信息,这些信息通常包括以下字段:
- nickName:用户的昵称。
- avatarUrl:用户的头像图片链接。
- gender:用户的性别,值为
0
时表示未知,为1
时表示男性,为2
时表示女性。 - country:用户所在国家。
- province:用户所在省份。
- city:用户所在城市。
示例:(通过wx.getUserProfile API 获取微信头像的URL)
// 在wxml文件中
<button bindtap="getUserProfile">获取用户信息</button>// 在js文件中
Page({getUserProfile() {wx.getUserProfile({desc: '用于完善会员资料',success: (res) => {console.log(res.userInfo.avatarUrl); // 用户微信头像的URLthis.setData({userAvatar: res.userInfo.avatarUrl});},fail: (err) => {console.error(err);}});}
});
2.转发功能
微信小程序提供了转发功能,允许用户将小程序的页面分享给微信好友或群聊。以下是实现微信小程序转发功能的方法:
使用页面内转发按钮
在小程序的页面中,你可以使用button
组件,并设置open-type
为share
来实现转发功能。
<!-- 在wxml文件中 -->
<button open-type="share">分享给好友</button>
使用wx.shareAppMessage
方法
你也可以在页面的JavaScript逻辑中调用wx.shareAppMessage
方法来手动触发转发功能。
// 在js文件中
Page({onShareAppMessage: function (options) {// 设置转发内容var shareObj = {title: "分享标题", // 分享标题desc: "分享描述", // 分享描述path: '/page/user?id=123', // 分享路径,该路径需要真实存在并可访问imageUrl: '', // 分享图标,建议大小为 5:4success: function (res) {// 分享成功的回调函数},fail: function (res) {// 分享失败的回调函数}};// 返回分享内容return shareObj;}
});
3.分享到朋友圈
分享给好友和分享到朋友圈。每种分享方式都有对应的API或方法。
onShareAppMessage
:用于处理分享给好友的逻辑。onShareTimeline
:用于处理分享到朋友圈的逻辑。
Page({// 处理分享给好友的逻辑onShareAppMessage: function (options) {return {title: '分享给好友的标题',path: '/pages/index/index', // 分享的页面路径imageUrl: 'https://example.com/path/to/image.png' // 分享显示的图片};},// 处理分享到朋友圈的逻辑onShareTimeline: function () {return {title: '分享到朋友圈的标题',query: '参数=值', // 分享链接携带的参数imageUrl: 'https://example.com/path/to/image.png' // 分享显示的图片};}
});
4.手机号验证组件
在微信小程序中,open-type
属性用于button
组件,可以触发不同的功能。关于获取手机号,微信小程序提供了两种方式:getPhoneNumber
和 getRealTimePhoneNumber
。以下是这两个属性的解释和使用方法。
getPhoneNumber
这个属性用于获取用户绑定的手机号。用户点击按钮后,如果用户已经授权,可以直接获取到用户的手机号信息。在页面的JavaScript文件中,你需要定义getPhoneNumber
事件处理函数:
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号</button>
getRealTimePhoneNumber
这个属性是getPhoneNumber
的升级版,它允许开发者实时获取用户授权的手机号,而不需要用户手动点击按钮。这个功能在用户同意授权后立即生效。在页面的JavaScript文件中,你需要定义getRealTimePhoneNumber
事件处理函数:
<button open-type="getRealTimePhoneNumber" bindgetrealtimephonenumber="getRealTimePhoneNumber">实时获取手机号</button>
注意:
- 目前接口针对非个人开发者,且完成认证的小程序
- 两种验证组件都需要付费使用,每个小程序账号都有1000次体验额度
5.客服功能
在你的小程序页面中,可以通过以下代码添加“客服”按钮:
<button open-type="contact">联系客服</button>
在页面的JavaScript文件中,你可以监听contact
事件:
Page({onContact: function() {// 打开客服聊天界面wx.openCustomerServiceConversation({account: '公众号账号' // 填写客服账号});}
});
也可以在微信公众后台,绑定后的客服账号,可以登录 网页端客服 或 移动端小程序 客服接收、发送客服信息
6.全局数据共享
在小程序中使用getApp()方法获取到小程序全局唯一的App实例,因此在App()方法中添加全局共享的数据、方法、从而实现页面、组件的数据传值。
app.js:
App({globalData: {token: '' // 这里可以定义一些全局数据,如登录状态、用户信息等},setToken: function(token) {// 设置全局数据的方法this.globalData.token = token;}
});
在登录用户时
const appInstance = getApp();
// 在某个页面或组件中定义login方法
Page({login: function() {// 假设这是登录的逻辑// 这里应该有用户登录的逻辑,比如调用API获取tokenvar token = "设置token的值"; // 假设这是从服务器获取的tokenappInstance.setToken(token);}
});
获取对应的token值
const appInstance = getApp();
Page({onLoad: function(options) {// 获取小程序实例// 检查是否已经设置了tokenif (appInstance.globalData.token) {// 如果已经设置了token,可以在这里处理tokenconsole.log('token已设置:', appInstance.globalData.token);} else {// 如果还没有设置token,可以在这里处理登录逻辑console.log('token尚未设置,需要登录');// 调用登录方法或API获取token}}
});
注意:
- 不要在App()方法中使用getApp(),使用this就可以获取app实例
- 通过getApp()获取实例后,不要私自调用生命周期函数
7.页面间通信
事件监听:
- 在源页面中,可以通过
wx.navigateTo
等导航方法设置success
回调函数,并在回调函数中触发事件。 - 在目标页面中,可以通过监听事件来接收源页面传递的数据。
假设我们有两个页面:pageA
和pageB
。
在pageA
中,我们想要将一些数据传递给pageB
Page({onLoad: function(options) {var appInstance = getApp();appInstance.globalData.dataFromPageA = "这是从pageA传递的数据";wx.navigateTo({url: '/pageB/pageB',success: function(res) {// 触发事件var eventChannel = res.eventChannel;eventChannel.emit('someData', appInstance.globalData.dataFromPageA);}});}
});
在pageB
中,我们监听事件并获取传递的数据:
Page({onLoad: function(options) {// 监听事件var eventChannel = this.getOpenerEventChannel();eventChannel.on('someData', function(data) {console.log('pageB接收到的数据:', data);});}
});
8.事件总线
事件总线是发布-订阅模式的一种实现,是一种集中式事件处理机制,允许不同组件之间进行彼此通信,常用于两个非父子关系组件和兄弟组件之间的通讯,使用第三方发布订阅的JS包,实现事件总线的功能
安装第三方发布订阅的JS包
npm install pubsub-js
无论发布消息还是订阅消息都需要导入PubSub包,在js文件中导入:
import PubSub from 'pubsub-js'
在方法中发布和订阅消息:
发布消息:
PubSub.publish(自定义事件名,数据)
订阅消息:
- msg:自定义事件名称
- data:传递来的数据
PubSub.subscribe(自定义事件,(msg,data)=>{})