原生小程序基础笔记 学习路径 常用核心知识

原生小程序基础笔记

一、小程序目录结构

小程序主要提供了 4 种文件类型:

类型名称作用是否必须存在
.wxml用于页面的布局结构,相当于网页中 .html 文件
.wxss用于页面的样式,相当于网页中的 .css 文件
.js用于页面的逻辑
.json用于页面的配置

文件作用

文件名作用是否必须存在
app.js小程序入口(首先执行的文件)
app.json小程序的全局配置
app.wxss小程序的全局样式
project.config.json小程序开发者工具配置是(会自动创建)
sitemap.json小程序搜索优化

二、配置文件

小程序配置文件是一种json格式的文件。

作用:可以起到快速新建页面、设定小程序首页、设置窗口样式及设置导航栏和底部tabBar等作用。

分类:

  • 全局 app.json
  • 页面 page.json

app.json 是当前小程序的全局配置,包括了:

  • 小程序首页
  • 界面表现
  • 网络超时时间
  • 底部 tab
  • …等配置

1.全局配置

pages

用于配置小程序的页面路径。这个配置项是一个数组,每个元素都是一个字符串,表示小程序包中的一个页面路径。

 App({
     "pages": [
     'pages/index/index',  // 首页
     'pages/about/about',  // 关于页面
     'pages/contact/contact'  // 联系页面
     ...
   ]
     ...
 })
window

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

属性类型默认值说明
navigationBarTitleTextstring空白导航栏标题文字内容
navigationBarTextStylestringblack导航栏标题颜色,仅支持 black / white
navigationBarBackgroundColor16 进制颜色#00000导航栏背景颜色,如 #000000
navigationStylestringdefault导航栏样式,仅支持 default / custom
enablePullDownRefreshbooleanfalse是否开启全局的下拉刷新
… 还有更多
 App({
    ...
    "window": {
     // 导航栏文本颜色
     "navigationBarTextStyle": "black",  
     // 导航栏标题文本
     "navigationBarTitleText": "首页",      
     // 导航栏背景颜色
     "navigationBarBackgroundColor": "#ff0000",  
     // 背景颜色
     "backgroundColor": "#ccc",  
     // 背景文本样式
     "backgroundTextStyle": "light",   
     // 启用下拉刷新
     "enablePullDownRefresh": true    
     ...
   },
    ...
 })
tabBar

常见配置属性

属性类型默认值是否必须说明
listarraytab 的列表,详见 list 属性说明,最少 2 个、最多 5 个 tab
color16 进制颜色tab 上的文字默认颜色,仅支持十六进制颜色
selectedColor16 进制颜色tab 上的文字选中时的颜色,仅支持十六进制颜色
backgroundColor16 进制颜色tab 的背景色,仅只持 16 进制颜色
borderStylestringblacktabbar 上边框的颜色, 仅支持 black / white
positionstringbottomtabBar 的位置,仅支持 bottom / top

上述配置中 list 具体又包含以下内容:

属性类型默认值是否必须说明
pagePathstring页面路径,必须在 pages 中先定义
textstringtab 上按钮文字
iconPathstring图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片,当 position 为 top 时,不显示 icon
selectedIconPathstring选中时的图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片,当 position 为 top 时,不显示 icon
 App({
    ...
   "tabBar": {
     // 标签栏文字颜色
     "color": "#000000",
     // 选中标签栏文字颜色
     "selectedColor": "#00b26a",   
     // 标签栏背景颜色为白色
     "backgroundColor": "#FFFFFF",     
     // 标签栏边框样式
     "borderStyle": "white",    
     // 标签栏位置在底部
     "position": "bottom",                            
     "list": [
       {
         // 页面路径
         "pagePath": "pages/index/index",
         // tab文字
         "text": "首页",
         // 未选中时的图标路径
         "iconPath": "static/tabbar/home-default.png",           // 选中时的图标路径
         "selectedIconPath": "static/tabbar/home-active.png" 
          ...
       },
    ...
 })

2.页面配置

页面配置只针对某个页面生效,如 index.json 是针对 index 页面生效,demo.json 只针对页面 demo 生效

  • 不用写window字段
  • 优先级比全局配置高

页面配置只针对某个页面生效,如 index.json 是针对 index 页面生效,demo.json 只针对页面 demo 生效

  • 不用写window字段
  • 优先级比全局配置高
pages
  • 用于指定小程序由哪些页面组成,每一项都对应一个页面的 路径(含文件名) 信息。文件名不需要写文件后缀,框架会自动去寻找对应位置的 .json, .js, .wxml, .wxss 四个文件进行处理。
  • 未指定 entryPagePath 时,数组的第一项代表小程序的初始页面(首页)。
  • 可以通过先在pages里写页面路径,然后保存的方式来快速新建页面。 注意:新建的页面,如果路径没在pages里面配置,则无法跳转到该页面

常用配置

属性类型默认值是否必须说明
navigationBarTitleTextstring空白导航栏标题文字内容
navigationBarTextStylestringblack导航栏标题颜色,仅支持 black / white
navigationBarBackgroundColor16 进制颜色#00000导航栏背景颜色,如 #000000
navigationStylestringdefault导航栏样式,仅支持 default / custom
enablePullDownRefreshbooleanfalse是否开启全局的下拉刷新
 {
      // 使用到的自定义组件,这里是一个空对象
     "usingComponents": {},                  
     // 导航栏背景颜色为绿色
     "navigationBarBackgroundColor": "#00b26a", 
     // 导航栏文本颜色为黑色
     "navigationBarTextStyle": "black",  
     // 禁用下拉刷新功能
     "enablePullDownRefresh": false,  
     // 导航栏标题文本为"购物车"
     "navigationBarTitleText": "购物车"
     ... 
 }

三、布局相关

部分选择器标签

组件名(标签)作用与 html 对比
view定义一个块级元素相当于 html 中的 div 标签
text定义一个行内元素相当于 html 中的 span 标签

小程序页面布局中的样式几乎和网页的 css 是一样的,部分选择器

选择器示例含义
类选择器.navs根据类名选择元素
标签选择器text、view根据标签名选择元素
后代选择器.navs text根据标签的嵌套关系选择元素

四、小程序适配 响应式单位rpx

rpx (responsive pixel):规定不管屏幕为多少px,100%的屏幕宽度就是750rpx

100%屏幕的宽度 = 750rpx

实际开发当中设计稿的尺寸都是【以 750px 做为基准】,因此只需要将设计稿中看到的尺寸写成相应的 rpx 即可。

五、wxss引入资源

1.使用图片

wxss中不可以使用本地图片资源,可以使用网络图片,或者将图片转成base64

 page {
   background-image: url("data:image/png;base64,...");
 }
 .ctn{
   background-image: url('https://www.../.png');
 }

2.使用字体图标

wxss中使用字体图标时,字体资源必须是在线链接

 @font-face {
   font-family: "iconfont";
   src: url('//at.alicdn.com/t/c/font_3509481_3gqwsneat14.woff2?t=1675394145994') format('woff2'),
        url('//at.alicdn.com/t/c/font_3509481_3gqwsneat14.woff?t=1675394145994') format('woff'),
        url('//at.alicdn.com/t/c/font_3509481_3gqwsneat14.ttf?t=1675394145994') format('truetype');
 }
 .iconfont {
   font-family: "iconfont" !important;
   font-size: 16px;
   font-style: normal;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
 }
 ​
 .icon-clock:before {
   content: "\e74b";
 }

六、数据绑定

数据绑定步骤

1.在data中定义数据

 Page({
   data: {
     属性1: "值1",
     num:1
     img: '/static/uploads/goods-1.jpg',
     ...
   }
 })

2.在模板中使用数据mustache(插值表达式)语法

 <view>{{num}}</view>
 <image src="{{img}}"/>
 <text>{{ count >20?'成功':'失败' }}</text>

七、事件绑定

1.语法

小程序中绑定事件的语法有两种

 <!-- bind事件名="事件回调" -->
 <button type="warn" bindtap="fn">警告</button>
 <!-- bind:事件名="事件回调" -->
 <button type="primary" bind:tap="fn">成功</button>

2.事件捕获与冒泡

冒泡

bind用于绑定事件冒泡

 <button bind:tap="fn">父</button>

catch用于阻止冒泡

 <button catch:tap="fn">父</button>
捕获

capture 用于绑定事件捕获

capture-bind只能用冒号形式

 <button capturn-bind:tap="fn">父</button>

capture-catch可以阻止冒泡、捕获事件

 <button capturn-catch:tap="fn">父</button>

3.事件传参

错误写法: 小程序会以为 事件函数名称就是 “printNum(1)” ,那么它就会去找“printNum(1)” 这个函数 而不是 “printNum"

<!-- 错误写法 -->
 <view class="item" data-num="1" bindtap="printNum(1)" />

正确写法:通过自定义属性传递

 <view class="item" data-num="1" bindtap="printNum">
 Page({
   // e是事件对象,一般命名e/ev/event
   printNum(e) {
     const num = e.currentTarget.dataset.num;
     console.log(num);
   },
 });

target及currentTarget的区别

target:事件发生地。事件真实发生的元素。 currentTarget: 事件绑定地。bind事件书写的那个元素。

事件对象属性

属性类型说明
typeString事件类型
timeStampInteger页面打开到触发事件所经过的毫秒数
targetObject触发事件的组件的一些属性值集合
currentTargetObject当前组件的一些属性值集合
detailObject额外的信息
markObject承载额外数据
touchesArray触摸事件,当前停留在屏幕中的触摸点信息的数组
changedTouchesArray触摸事件,当前变化的触摸点信息的数组

注意

mark和dataset的区别

  • mark 会包含从触发事件的节点到根节点上所有的 mark: 属性值;
  • dataset 仅包含一个节点的 data- 属性值

七、获取和设置data数据

小程序的渲染层与逻辑层

  1. WXML 模板和 WXSS 样式工作在渲染层JS 脚本工作在逻辑层
  2. 小程序的渲染层逻辑层分别由2个线程管理,两个线程的通信会经由微信客户端做中转

直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致

 this.setData({
   属性名1: 新值1,
   属性名2: 新值2
 })
 ​
 //示例
 Page({
   data: {
     num: 0,
   },
   handleAdd() {
     // 获取data里的数据
     let num = this.data.num;
     // 更新
     this.setData({
       num: ++num,
     });
   }
 });
 ​

注意:

获取data中的数据是this.data.xxx

八、双向绑定与表单元素

获取输入框的值的方式

1.监听事件

 <input bindinput="handleInput" value="name" type="text" placeholder="请输入姓名" />
 Page({
   data: {
     name: "",
   },
   handleInput(e) {
     console.log(e.detail.value);
     const name = e.detail.value;
     this.setData({
       name,
     });
   },
 });

2.简易双向绑定

 <input model:value="{{name}}" type="text" placeholder="请输入姓名" />

注意

  • 并不是所有的表单元素都支持数据双向绑定,其中 input、textarea、slider 组件可以支持。
  • 简易双向绑定不支持路径。(例:页面的数据为{data: {person: {name: ‘’}}},将输入框中的值赋值给person下的name属性)

九、列表渲染

 <!--基础用法-->
 <view wx:for="{{list}}">
     <!-- 
     wx:for 结构内可以使用两个变量
         item  循环项
     index  循环索引
   -->
   {{item}} ------ {{index}}
 </view>
 <!-- 手动指定索引和当前项的变量名  -->
 <view 
     wx:for="{{list}}"
     wx:for-item="value"
     wx:for-index="key"
 >
     {{value}}-------{{key}}
 </view>

注意:引号和大括号 中间不要留有空白

key的用法

wx:key 针对不同的数组类型有不同的写法

*普通数组 wx:key="this"

 Page({
   data: {
     list: [11, 22, 33, 44, 55]
 })
 <view wx:for="{{list}}" wx:key="*this">
     当前索引号:{{index}}-------当前项:{{item}}
 </view>

数组对象 wx:key=“具有唯一性的某个属性名”

 Page({
   data: {
     list2: [{ id: 1, name: '周树人' }, { id: 2, name: '鲁迅' }]
   }
 })
 <view wx:for="{{list2}}" wx:key="id">
     当前索引号:{{index}}-------当前项:{{item.name}}
 </view>

作用:

  1. 性能优化: wx:key 的主要作用是帮助小程序更高效地更新渲染列表。当列表中的某一项发生变化时,小程序会根据 wx:key 所指定的值来快速定位变化的项,而不是重新渲染整个列表。
  2. 唯一性标识: wx:key 用于标识列表中每一项的唯一性。它通常会使用列表项的唯一标识(如数据中的某个属性),确保在列表中的每一项都有一个独特的标识。

十、条件渲染

wx:if

  • 使用 wx:if 可以完全移除或重新渲染包含该指令的节点。
  • 当条件为真时,该节点会被渲染出来,而当条件为假时,该节点将被从 DOM 树中移除。
  • 适用于需要在不同条件下完全切换元素的场景,但频繁切换会有性能开销。
 <view wx:if="{{gender === 1}}">
   男
 </view>
 <view wx:elif="{{gender === 0}}">
   女
 </view>
 <view wx:else>
   未知
 </view>

hidden

  • 使用hidden属性可以简单地隐藏或显示一个节点,但该节点始终存在于 DOM 中。
  • hidden 是通过样式(none/block)来实现元素的显示或隐藏。
  • 适用于频繁切换元素的场景,因为节点一直存在,切换时不需要重新渲染。
 <view hidden="{{isHidden}}">
   这里是hidden盒子
 </view>

十一、image组件

特点:

1.支持 JPG、PNG、SVG、WEBP、GIF 等格式。

2.默认大小为 320px * 240px(相框大小)

3.通过mode属性控制相片在相框的渲染效果

4.支持懒加载

常用属性

属性名类型默认值说明
srcString图片资源地址
modeString‘scaleToFill’图片裁剪、缩放的模式
lazy-loadbooleanfalse图片懒加载,在即将进入一定范围(上下三屏)时才开始加载

mode的常用取值

模式说明
缩放scaleToFill不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素
缩放aspectFit保持纵横比缩放图片,直到图片某一边碰到边界。
缩放aspectFill保持纵横比缩放图片,直到图片完全铺满边界。
缩放widthFix宽度不变,高度自动变化,保持原图宽高比不变
 <image src="./cat.jpg" mode="scaleToFill"/>
 <image src="./cat.jpg" mode="aspectFit"/>
 <image src="./cat.jpg" mode="aspectFill"/>
 <image src="./cat.jpg" mode="widthFix"/>

十二、小程序内置组件

1.swiper轮播图组件

特点:

swiper可以理解为小程序内置的轮播图标签,拥有了它可以让我们特别方便实现轮播功能。

默认宽度 和 高度 为 100% * 150px

常用属性

属性名类型默认值说明
indicator-dotsBooleanfalse是否显示面板指示点
autoplayBooleanfalse是否自动切换
circularBooleanfalse是否衔接轮播

示例

 <swiper indicator-dots autoplay circular>
   <swiper-item>
     <image src=""></image>
   </swiper-item>
   <swiper-item>
     <image src=""></image>
   </swiper-item>
   <swiper-item>
     <image src=""></image>
   </swiper-item>
 </swiper>

2.navigator导航标签

特点:

1.类似以前web中的a标签。

2.块级元素

3.通过 url 来指定跳转的页面

4.还可以跳到其他小程序

常用属性

属性名类型默认值说明
urlstring当前小程序内的跳转链接
open-typestringnavigate跳转方式
targetStringself在哪个目标上发生跳转,默认当前小程序

参考代码

 <!-- 只能打开非 tabBar 页面 -->
 <navigator url="/pages/swiper/index">以默认方式open-type="navigate"跳轮播图页面</navigator>
 ​
 <navigator open-type="redirect" url="/pages/swiper/index">以open-type="redirect"跳轮播图页面</navigator>
 ​
 <!-- 只能打开 tabBar 页面 -->
 <navigator open-type="reLaunch" url="/pages/swiper/index">以open-type="reLaunch"跳轮播图页面</navigator>
 ​
 <!-- open-type="switchTab" 只能跳转tabBar页面,非tabBar页面不能跳转 -->
 <navigator open-type="switchTab" url="/pages/index/index">以open-type="switchTab"跳轮首面</navigator>
 -------跳转其它小程序--------
 <!-- 方式一:通过app-id -->
 <navigator target="miniProgram" app-id="wx7696c66d2245d107">跳转蜜雪冰城</navigator>
 <!-- 方式一:通过short-link -->
 <navigator target="miniProgram" short-link="#小程序://蜜雪冰城/a2FGdG8xwuFeJdB">跳转蜜雪冰城</navigator>

总结

  • navigateTo, redirect 只能打开非 tabBar 页面。
  • switchTab 只能打开 tabBar 页面。
  • reLaunch 可以打开任意页面。
页面栈

1.每次通过navigate方式跳转时,原页面并没有被销毁,而是放入了内存中,这样返回到上级页面时,就能快速打开,而不是重新创建

2.这样多次调用后会形成一个层级结构,我们把这个层级结构就叫做页面栈。

3.小程序宿主环境限制了页面栈的最大层级为 10 层 ,当页面栈到达 10 层之后就没有办法再推入新的页面了

返回按钮

1.一般情况下页面栈长度大于1就会出现返回按钮,否则没有,可通过getCurrentPages()获取页面栈。

2.若页面设置了navigationStyle: “custom”,则不管页面栈长度多少都不会有返回按钮。

open-type

假设小程序当前页面栈为 [ pageA, pageB, pageC ],其中pageA在最底下,pageC在最顶上,也就是用户所看到的界面。则:

1.navigate

使用 open-type=“navigate” url=“pageD” (相当于wx.navigateTo({ url: ‘pageD’ }) )可以往当前页面栈多推入一个 pageD,此时页面栈变成 [ pageA, pageB, pageC, pageD ]

2.navigateBack

使用 open-type=“navigateBack” (相当于 wx.navigateBack()) 可以退出当前页面栈的最顶上页面,此时页面栈变成 [ pageA, pageB, pageC ]

3.redirect

使用open-type=“redirect” url=“pageE” (相当于 wx.redirectTo({ url: ‘pageE’ })) 是替换当前页变成pageE,此时页面栈变成 [ pageA, pageB, pageE ] 。当页面栈到达10层没法再新增的时候,往往就是使用redirectTo这个API进行页面跳转。

4.switchTab

使用open-type=“switchTab” url=“pageF” (相当于wx.switchTab({ url: ‘pageF’ }),此时原来的页面栈会被清空,然后会切到pageF所在的tab页面,页面栈变成 [ pageF ]

5.reLaunch

使用open-type=“reLaunch” url=“pageH” (相当于wx. reLaunch({ url: ‘pageH’ })) 重启小程序,并且打开pageH,此时页面栈为 [ pageH ]

十三、生命周期

分类

  • 应用生命周期
  • 页面生命周期
  • 组件生命周期

1.应用生命周期钩子函数

参考文档:https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html

属性说明
onLaunch生命周期回调——监听小程序初始化。
onShow生命周期回调——监听小程序启动或切前台。
onHide生命周期回调——监听小程序切后台。
onError错误监听函数。

代码

 App({
   /**
    * 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
    */
   onLaunch: function () {
   },
   /**
    * 当小程序启动,或从后台进入前台显示,会触发 onShow
    */
   onShow: function (options) {
   },
   /**
    * 当小程序从前台进入后台,会触发 onHide
    */
   onHide: function () {    
   },
   /**
    * 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
    */
   onError: function (msg) {    
   }
 })

注意:

1.用户在点击右上角的胶囊关闭小程序时,小程序并没有被销毁,只是将小程序置于后台运行了,因此小 onLaunch 并不会重复执行

2.当小程序执行停留在后台约5分钟后小程序会自动被销毁,再次打开小程序时 onLaunch 会再次被执行

场景值

所谓的场景描述的是用户打开小程序的方式,如扫码、搜索、分享等,并且每个场景都对应了一个数值,即场景值,根据这个场景值来判断用户打开小程序的方式,进而分析用户的行为,常见的场景值如下表所示:

场景值 ID说明
1001发现栏小程序主入口
1011扫描二维码
1007单人聊天会话中的小程序消息卡片

获取小程序的声景值只能在全局生周期函数 onLaunch、onShow 中获取,代码如下所示

 // app.js
 App({
   onLaunch(params) {
     // 1001 发现栏小程序主入口
     // 1011 扫描二维码
     // 单人聊天会话中的小程序消息卡片
     console.log(params.scene)
   },
   onShow(params) {
     // 也可以获取场景值ID
     console.log(params.scene)
   },
 })

2.页面生命周期钩子函数

参考文档:https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html

生命周期必填说明
onLoad监听页面加载,若页面没被销毁只会执行 1 次
onShow监听页面显示
onReady监听页面初次渲染完成,只会执行 1 次
onHide监听页面隐藏
onUnload监听页面卸载
onPullDownRefresh监听用户下拉动作
onReachBottom页面上拉触底事件的处理函数
onShareAppMessage用户点击右上角分享

代码

 Page({
   /**
    * 生命周期函数--监听页面加载
    */
   onLoad: function (options) {
   },
   /**
    * 生命周期函数--监听页面初次渲染完成
    */
   onReady: function () {
   },
   /**
    * 生命周期函数--监听页面显示
    */
   onShow: function () {
   },
   /**
    * 生命周期函数--监听页面隐藏
    */
   onHide: function () {
   },
   /**
    * 生命周期函数--监听页面卸载
    */
   onUnload: function () {
   },
   /**
    * 页面相关事件处理函数--监听用户下拉动作
    */
   onPullDownRefresh: function () {
   },
   /**
    * 页面上拉触底事件的处理函数
    */
   onReachBottom: function () {
   },
   /**
    * 用户点击右上角分享
    */
   onShareAppMessage: function () {
   }
 })
页面间传递及接收参数
  • 传递:拼接到页面url中
  • 接收:通过onLoad回调的第一参数。(只能是onLoad钩子
 <navigator url="pages/index/index?id=10086&name=周树人" ></navigator>
 //pages/index/index
 Page({
   data: {
     name: '',
     age: '',
   },
   onLoad(params) {
     // 查看地址中的参数
     console.log(params)
 ​
     // 记录存储地址参数
     this.setData({ ...params })
   },
 })
 <view>姓名:{{name}},年龄:{{age}}</view>

3.组件生命周期钩子函数

参考文档:https://developers.weixin.qq.com/miniprogram/dev/reference/api/Component.html

生命周期参数描述
created在组件实例刚刚被创建时执行,此时还不能调用 setData,一般用于给组件的this添加一些自定义的属性字段
attached在组件实例进入页面节点树时执行,绝大多数初始化工作可以在这个时机进行,例如发请求获取初始数据
ready在组件在视图层布局完成后执行
moved在组件实例被移动到节点树另一个位置时执行
detached在组件实例被从页面节点树移除时执行,适合做一些清理工作
errorObject Error每当组件方法抛出错误时执行
组件所在页面的生命周期

有时,自定义组件的行为依赖于页面状态的变化,此时就需要用到组件所在页面的生命周期。既在组件中监听页面的生命周期的变化。可以监听到的页面生命周期有以下三个:

生命周期参数描述
show组件所在的页面被展示时执行
hide组件所在的页面被隐藏时执行
resizeObject Size组件所在的页面尺寸变化时执行

代码

 Component({
   // 推荐方式
   lifetimes: {
     attached: function() {
       // 在组件实例进入页面节点树时执行
     },
     detached: function() {
       // 在组件实例被从页面节点树移除时执行
     },
   },
   // 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
   attached: function() {
     // 在组件实例进入页面节点树时执行
   },
   detached: function() {
     // 在组件实例被从页面节点树移除时执行
   },
   // 页面生命周期
   pageLifetimes: {
     show: function() {
       // 页面被展示
     },
     hide: function() {
       // 页面被隐藏
     },
     resize: function(size) {
       // 页面尺寸变化
     }
   }
 })

十四、内置API

1.网络请求

wx.request

参考文档:https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html

代码

 // 小程序发起网络请求(调用接口)的方法
 wx.request({
   // 接口地址
   url: 'api/path/xxx',
   // 请求的方法
   method: 'GET|POST|PUT',
   // 请求时的数据
   data: {},
   success(res) {
     // 成功响应的回调
   },
   // ...
 })

示例

 Page({
   onLoad() {
     // 页面加载完成即获取学生列表
     this.getStudentList()
   },
   // 获取学生表表
   getStudentList() {
     // 调用小程序 api
     wx.request({
       url: '',
       method: 'GET',
       success: (res) => {
         console.log(res)
       },
     })
   },
 })
合法域名

小程序规定 wx.request 调用接口的服务器地址(域名)必须事先在小程序的管理后台进行设置,否则是不允许发起网络请求。 解决方案有两个:

1.在小程序管理后台进行设置 (永久性解决)

2.在小程序开发工具中进行设置 (开发阶段临时解决,上线后还是得去后台配置合法域名)

注意:域名有个严格的要求:必须https 协议且已备案!

2.加载提示

wx.showLoading

wx.hideLoading

加载提示框常配合网络请求来使用,用于增加用户体验,对应的 API 有两个,分别为:

  • wx.showLoading 显示加载提示框
  • wx.hideLoading 隐藏加载提示框

它们的语法如下:

 // 显示加载提示
 wx.showLoading({
   title: '正在加载...',
   mask: true,
 })
 // 隐藏加载提示
 wx.hideLoading()

示例

 // pages/index/index.js
 Page({
   // ...省略前面小节代码
   // 获取学生表表
   getStudentList() {
     // 显示提示框
     wx.showLoading({
       title: '正在加载...',
       mask: true,
     })
 ​
     // 发起请求
     wx.request({
       url: '',
       method: 'GET',
       // 这里注意因为 this 的原因,推荐使用箭头函数
       success: (res) => {
         this.setData({
           // 更新 students 数组
           students: res.data.result,
         })
       },
       complete() {
         // 隐藏提示框
         wx.hideLoading()
       },
     })
   },
 })

注意: 调用showLoading的时候还可以传入mask属性用于防止点击穿透!

3.消息提示

wx.showToast

参考文档:https://developers.weixin.qq.com/miniprogram/dev/api/ui/interaction/wx.showToast.html

代码

 wx.showToast({
   title: "请输入姓名",
   icon: "error",
   mask: true,
 });

注意:可以开启mask:true用于节流,防止元素被多次点击

4.本地存储

存储指定数据

  • wx.setStorageSync 同步版本
  • wx.setStorage 异步版本

获取指定数据

  • wx.getStorageSync 同步版本
  • wx.getStorage 异步版本

移除指定数据

  • wx.removeStorageSync 同步版本
  • wx.removeStorage 异步版本

清除所有数据

  • wx.clearStorageSync 同步版本
  • wx.clearStorage 异步版本

参考文档https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.setStorageSync.html

代码

 //同步版本,存储对象类型,不需要JSON.stringify
 wx.setStorageSync("person", {
   name: "张三",
   age: 18,
 });
 ​
 // 异步版本,相同的key会被覆盖
 wx.setStorage({
   key: "name",
   data: "李四",
 });
 ​
 // 同步版本,获取存入的对象类型,不需要JSON.parse,
 wx.getStorageSync("person");
 ​
 // 异步版本,获取存入的数据
 wx.getStorage({
   key: "name",
   success(res) {
     console.log(res.data);
   },
 });
 ​
 // 同步版本,移除指定key的数据
 wx.removeStorageSync("name");
 ​
 // 异步版本,移除指定key的数据
 wx.removeStorage({
   key: 'name'
 });
 ​
 // 同步版本,清空所有本地缓存数据
 wx.clearStorageSync();
 ​
 // 异步版本,清空所有本地缓存数据
 wx.clearStorage()

5.路由相关

编程式路由跳转

参考文档:https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.navigateTo.html

 // 相当于open-type="navigate" 保留当前页面,跳转到应用内的某个页面。
 // 但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面。
 // 小程序中页面栈最多十层
 wx.navigateTo({
     url: "/pages/logs/logs",
 });
 ​
 // 关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。
 // 相当于open-type="redirect"
 wx.redirectTo({
     url: "/pages/logs/logs",
 });
 ​
 // 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面,只能用于跳转tabBar页面
 // 相当于open-type="switchTab" 
 wx.switchTab({
     url: "/pages/logs/logs", // 路径后不能带参数
 });
 ​
 // 关闭所有页面,打开到应用内的某个页面
 // 相当于open-type="reLaunch"
 wx.reLaunch({
     url: "/pages/logs/logs",
 });
 ​
 // 关闭当前页面,返回上一页面或多级页面。
 // 可通过getCurrentPages获取当前的页面栈,决定需要返回几层。
 wx.navigateBack({
     delta: 1, // 返回的页面数,如果delta大于现有页面数,则返回到首页
 });

十五、npm构建

1.默认方式

小程序支持使用 npm 安装第三方包,但是对包有一些限制

核心步骤

1.在根目录中 初始化项目

npm init -y 创建package.json

2.安装依赖

npm i 包

 //举例
 npm i dayjs

3.构建 npm

在微信开发者工具中 点击 ‘工具’ -> ‘构建npm’

4.代码中使用

 import 包名 from '包'
 //举例
 import dayjs from 'dayjs'
 console.log(dayjs().format('YYYY-MM-DD HH:mm:ss'))

2.自定义方式

默认情况下项目目录的最外层是小程序的根目录,通过 project.config.json 可以指定小程序的根目录,这样做的好处是能够优化目录结构,更好的管理项目的代码

 {
   "setting": {
     ...
     "packNpmManually": true, // 启用 npm 构建手动配置
     "packNpmRelationList": [  // 手动构建 npm 配置详情
       {
         "packageJsonPath": "./package.json",
         "miniprogramNpmDistDir": "./src" // 自定义小程序根目录,自己随意起名字
       }
     ],
     ...
   },
   "libVersion": "2.19.4",
   "miniprogramRoot": "src/", // 自定义小程序的根目录
 }

十六、小程序中使用组件库

步骤

1.npm init && npm安装

2.修改app.json去掉"style":“v2”

3.构建npm

4.在app.json和页面.json中注册

5.在页面使用

Vant-Weapp组件库官网:https://vant-contrib.gitee.io/vant-weapp/#/quickstart

十七、自定义组件

自定义组件可理解为允许我们创造自己想要的某些效果的标签。如image是小程序指定的图片标签, border-image 可以是我们自己创造的标签

自定义组件还具有简化页面结构、封装复用代码的功能。

组件化开发是目前前端开发项目的主流方式。

1.使用方法

步骤

1.创建

通常习惯将组件放到独立的目录 components 当中,这个目录需要我们手动进行创建。

组件和页面的结构是一致的,但也是有区别的:

1.组件的配置文件中配置项 component: true

 //components\组件名\index.json
 {
   "component": true,
   "usingComponents": {}
 }
  • 组件的 .js 文件中调用 Component 函数,页面的.js文件中调用Page函数
 //components\组件名\index.js
 Component({
     ...
 })

2.注册

页面注册

在使用组件的页面配置中通过 usingComponents 进行注册,只能在当前页面中使用该组件

全局注册

在 app.json 文件中通过 usingComponents 对自定义组件进行注册,注册的组件可以任意页面中使用全局注册的组件

 "usingComponents": {
    ...
     "组件名": "/components/组件名/index"
   },

3.使用

 <组件名></组件名>

2.组件样式

默认情况下,自定义组件的样式只受到自定义组件 wxss 的影响。

举例

  • 组件A的样式不会影响组件B的样式
  • 组件A的样式不会影响页面的样式
  • 页面的样式不会影响组件A和B的样式

样式隔离注意点

  • app.wxss中的全局样式对组件无效
  • 只有class选择器具有样式隔离效果,id选择器、属性选择器、标签选择器不受样式隔离的影响。建议:在组件和引用组件的页面中建议使用class选择器,不要使用id、属性、标签选择器

样式隔离文档: https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html

3.数据、属性和方法

data数据

在小程序中,用于组件模板渲染的私有数据,需要定义到data中,示例如下:

 Component({
     data: {
     num: 1
   }
     ...
 });
methods方法

在小程序中,事件处理函数和自定义方法需要定义到methods中,示例如下:

 Component({
     ...
     methods: {
     handleAdd() {
       this.setData({
         num: this.data.num + 1
       });
     },
     handleSub() {
       this.setData({
         num: this.data.num - 1
       });
     }
   }
     ...
 });
properties属性

在小程序中,properties是组件的对外属性,用于接收外界传递到组件中的数据,示例如下:

 Component({
     ...
     properties: {
     min: Number,
     max: {
         type: Number,
       value: 10 // value用于指定默认值
     }
   }
     ...
 })

注意:小程序组件中data和properties是完全相等的

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

4.组件生命周期

5.组件插槽

概念

在自定义组件的wxml结构中,我们可以提供一个<slot>节点,用于承载组件使用者提供的wxml结构。插槽可以方便开发者将不确定的、或者希望由用户去确定的交给用户。如自己封装的弹框组件底部不确定用户会放一个按钮还是两个按钮,就可以放过插槽,交给用户自己定。

单个插槽

在小程序中,默认每个自定义组件中只允许使用一个<slot>进行占位。

 <!--components/MyTest2/index.wxml-->
 <view>
   <text>components/MyTest2/index.wxml</text>
   <!-- 对于不确定的内容,可以使用slot进行占位,具体内容交给使用者确定 -->
   <slot></slot>
 </view>
 <my-test2>
   <!-- 这里的内容将被放到组件中<slot>的位置 -->
   <view>
     这里是slot里的内容
   </view>
 </my-test2>
多插槽(具名插槽)

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

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

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

 <view>
   <text>components/MyTest2/index.wxml</text>
   <!-- 对于不确定的内容,可以使用slot进行占位,具体内容交给使用者确定 -->
   <!-- <slot></slot> -->
   <slot name="before"></slot>
   <view>
     ---------这里是分割线--------
   </view>
   <slot name="after"></slot>
 </view>
 <my-test2>
   <!-- 这里的内容将被放到组件中<slot>的位置 -->
   <!-- <view>
     这里是slot里的内容
   </view> -->
   <view slot="before">
     这里是before slot里的内容
   </view>
   <view slot="after">
     这里是after slot里的内容
   </view>
 </my-test2>

6.父子组件间通讯

父子组件间的基本通信方式有以下3种

1.自定义属性

用于父组件向子组件传递数据,只能传递JSON兼容的数据

2.自定义事件

用于子组件向父组件传递数据,可以传递任意数据

3.获取组件实例

父组件可以通过this.selectComponent()获取子组件实例对象

这样可以直接访问子组件的任意数据和方法

自定义属性

核心步骤

1.父组件通过自定义属性传递

 <my-test3 num="{{num}}" />
 // 父组件(页面中)num的值为{{num}}
 Page({
   data: {
     num: 1,
   },
 });

2.子组件通过定义自定义属性接收

 <text>components/MyTest3/index.wxml</text>
 <view>
   子组件内num的值为:{{num}}
 </view>
 <button type="primary">点我+1</button>
 Component({
   properties: {
     num: Number,
   },
 })
自定义事件

核心步骤

1.给子组件上某个元素绑定事件

 <text>components/MyTest3/index.wxml</text>
 <view>
   子组件内num的值为:{{num}}
 </view>
 <button type="primary" bindtap="handleAdd">点我+1</button>

2.在事件回调中通过triggerEvent触发自定义事件并传参

 // components/MyTest3/index.js
 Component({
   properties: {
     num: Number,
   },
   methods: {
     handleAdd() {
       this.setData({
         num: this.properties.num + 1,
       });
       // 触发自定义事件并传参
       this.triggerEvent("add", this.properties.num);
     },
   },
 });

3.父组件监听自定义事件

 <my-test3 num="{{num}}" bind:add="add" />
 父组件(页面中)num的值为{{num}}

4.在回调函数中通过事件对象的detail属性接参

 Page({
   data: {
     num: 1,
   },
   add(ev) {
     // console.log(ev);
     const value = ev.detail;
     this.setData({
       num: value,
     });
   },
 });
获取组件实例
 <my-test3 class="test3" num="{{num}}" bind:add="add" />
 父组件(页面中)num的值为{{num}}
 <button bindtap="getChild">获取子组件实例</button>
 Page({
   data: {
     num: 1,
   },
   add(e) {
     // console.log(e);
     const value = e.detail;
     this.setData({
       num: value,
     });
   },
   getChild() {
     const child = this.selectComponent(".test3");
     console.log(child);
     // 获取子组件里的数据
     const num = child.properties.num;
     // 调用子组件里的方法
     child.handleAdd();
   },
 });

十八、分包

小程序限制每个包代码量不超过2M,如果我们的小程序确实很复杂,代码量操过2M,就需要用到分包

1.配置

参考文档:https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages/basic.html

定义 将小程序拆分成若干个部分叫做分包。 作用:

1.解决项目体积过大

2.提高启动效率

3.方便协同开发

分类:

主包

每个小程序必定含有一个主包

默认启动页面、TabBar 页面,以及公共资源/JS 脚本必须放在主包;

普通分包

1.普通非独立分包

  • 进入普通非独立分包时,主包会被下载
  • 可以使用主包里面的公共资源/JS脚本

2.独立分包

  • 一种特殊类型的分包,可以独立于主包和其他分包运行。
  • 从独立分包中页面进入小程序时,不需要下载主包。不可使用主包里的资源。

配置参考代码

 // json
 "pages": {}, // 和pages同级
 "subPackages": [
     {
       "root": "goods_pkg",
       "pages": [
         "pages/goods_list/index", 
         "pages/goods_detail/index"
       ]
     }
 ]

一个分包可以理解就是一个文件夹

2.预加载

参考文档:https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages/preload.html

分包预加载

概念

在打开小程序启动的时候只下载主包代码,分包并不会下载,因此能够提升小程序启动时的打开速度,但是分包的代码只有在访问到分包的页面时才去下载,这样用户就需要有一定时间的等待(一般不太影响),通过分包预加载技术可以实现提前去下载分包的代码,这样分包页面的访问速度也会得到提升。

小程序通过 preloadRule 配置需要预加载的分包,在 app.json 中进行配置:

  • 指定某个页面路径做为 key,含义是当访问这个页面时会去预加载一个分包
  • network 预加载分包的网络条件,可选值为 all、wifi,默认为 wifi
  • packages 指定要预下载的分包名或根路径
 {
   "preloadRule": {
     "pages/index/index": {
       "network": "wifi",
       "packages": ["goods_pkg"]
     }
   },
 }
 //上述的代码代表的含义是当用户访问到 pages/index/index 时,在 wifi 网络前提下预先下载 goods_pkg 分包的代码。

分包只能提高主包的下载速度,也就是小程序的启动速度。分包预下载可以提高分包的加载速度。

十九、框架接口

框架接口指的是小程序提供的一些全局函数

1.getApp

概念

getApp 是一个全局的函数,调用该函数可以获取小程序应用实例,通过小程序应用实例可实现数据或方法的共享。

示例

 // App.js
 App({
   // 读取本地存储的token数据
   token: wx.getStorageSync('token'),
   onLaunch() {
     // 生命周期
   },
   http(params) {
     // 举例封装网络请求
     wx.request({
       ...params,
       header: {},
     })
   }
 })

在任意页面和组件中调用 getApp 就可以获取小程序的实例

 // 获取小程序实例
 const app = getApp()
 Page({
   onLoad() {
     // 能够读取到全局实全名定义的 token 数据
     console.log(app.token)
 ​
     // 调用全局实例中定义的方法
     app.http({
       url: '',
       method: 'GET'
     })
   },
 })

注意:getApp()能实现类似web中vuex的效果,但getApp()的数据不是响应式的。

2.getCurrentPages

概念 getCurrentPages 获取当前页面栈,页面栈中包含的是页面的实例,数组中第一个元素为首页,最后一个元素为当前页面。

 onUnload() {
   const pages = getCurrentPages();
   console.log(pages);
   pages[0].onLoad();
 }

注意:不要在 App.onLaunch 的时候调用 getCurrentPages(),此时 page 还没有生成

3.Behavior

参考文档:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/behaviors.html

概念

能够将一些公共的逻辑抽离到单独的模块当中。(类似 Vue 的 mixin 的功能)

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

示例

 // pages/index/my-behavior.js
 // 注册一个 behavior
 export default Behavior({
   // 定义初始数据:与 Page 中定义的 data 含义一致
   data: {
     version: 'v1.0.0'
   },
   // 定义方法:与 Page 中定义方法含义一致
   methods: {
     getVersion() {
       return this.data.version
     }
   }
 })

上述代码在 data 中初始了一个数据 version,在 methods 中定义了一个方法 getVersion,接下来将这个 Behavior 对象注入到页面中,在页面中就能够调用 this.getVersion() 就可以获取 version 对应的数据了:

 // pages/index/index.js
 import myBehavior from './my-behavior'
 Page({
   // 将 myBehavior 注入到页面当中
   behaviors: [myBehavior],
   onLoad() {    
     // 该方法来自于 myBehavior 当中
     this.getVersion()
     // 可以访问到在 myBehavior 中初始的数据
     console.log(this.data.version)
   }
 })

二十、获取用户信息

1.获取用户头像

通过<button open-type="chooseAvatar" />获取用户头像方式。

步骤

1.设置 button 的属性 open-type 值为 chooseAvatar

 <button open-type="chooseAvatar" bindchooseavatar="getAvatar">点击获取头像</button>
 <image src="{{avatarUrl}}" mode="widthFix"></image>

2.监听 button 的 chooseavatar 事件

  getAvatar(ev) {
     console.log(ev);
     this.setData({
       avatarUrl: ev.detail.avatarUrl,
     });
   },

注意:open-type 的属性值 chooseAvatar (有大写字母),事件类型 chooseavatar (全部小写字母)。

2.获取用户昵称

通过<input type="nickname">获取用户昵称方式。

参考代码

 <input style="border: 1px solid #ccc;" type="nickname" />
 ​
 <!--注意:需要在真实手机中操作 -->

注意:开发者工具中,有时触发blur事件不一定能获取到用户昵称,多点击几次即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值