【全栈第二课】微信小程序快速入门-CSDN博客

76 阅读21分钟

前言

学习来源:www.bilibili.com/video/BV183…

笔记大部分来自黑马程序员提供的ppt,部分来于自己总结

一、起步

简介

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

image-20230519214503687

注册账号和微信开发者工具

注册

mp.weixin.qq.com/

主体类型为个人

开发工具

developers.weixin.qq.com/miniprogram…

微信开发者工具页面组成

image-20230519215125872

小程序代码构成

项目结构

image-20230519215208373

页面的组成部分

image-20230519215225954

JSON配置文件

JSON配置文件的作用

JSON 是一种数据格式,在实际开发中,JSON 总是以配置文件的形式出现。小程序项目中也不例外:通过不同的 .json 配置文件,可以对小程序项目进行不同级别的配置。

小程序项目中有 4 种 json 配置文件,分别是:

  • 项目根目录中的 app.json
  • 配置文件项目根目录中的 project.config.json
  • 配置文件项目根目录中的 sitemap.json
  • 配置文件每个页面文件夹中的 .json 配置文件

app.json 文件

app.json 是当前小程序的全局配置,包括了小程序的所有页面路径、窗口外观、界面表现、底部 tab 等。Demo 项目里边的 app.json 配置内容如下:

image-20230519215944213

project.config.json 文件

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

  • setting 中保存了编译相关的配置
  • projectname 中保存的是项目名称
  • appid 中保存的是小程序的账号 ID

sitemap.json 文件

微信现已开放小程序内搜索,效果类似于 PC 网页的 SEO。sitemap.json 文件用来配置小程序页面是否允许微信索引

当开发者允许微信索引时,微信会通过爬虫的形式,为小程序的页面内容建立索引。当用户的搜索关键字和页面的索引匹配成功的时候,小程序的页面将可能展示在搜索结果中。

image-20230519220148055

注意:sitemap 的索引提示是默认开启的,如需要关闭 sitemap 的索引提示,可在小程序项目配置文件 project.config.json 的 setting 中配置字段 checkSiteMap 为 false

页面的 .json 配置文件

小程序中的每一个页面,可以使用 .json 文件来对本页面的窗口外观进行配置,页面中的配置项会覆盖 app.json 的 window 中相同的配置项

image-20230519220229130

新建小程序页面

只需要在 app.json -> pages 中新增页面的存放路径,小程序开发者工具即可帮我们自动创建对应的页面文件

修改项目首页

只需要调整 app.json -> pages 数组中页面路径的前后顺序,即可修改项目的首页。小程序会把排在第一位的页面,当作项目首页进行渲染

image-20230519220434269

WXML模版

什么是 WXML?

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

WXML 和 HTML 的区别

image-20230519220843385

WXSS样式

什么是 WXSS

类似于网页开发的CSS

区别

image-20230519220934391

JS

没错,就是你想的JS(JavaScript)

分类

image-20230519221107576

宿主环境

是什么?

小程序开发依赖的环境,那么微信就是小程序的宿主环境

小程序借助宿主环境提供的能力,可以完成许多普通网页无法完成的功能,例如:微信扫码、微信支付、微信登录、地理定位、etc…

通信模型

通信主体

通信模型

image-20230519222119444

运行机制

小程序启动的过程

  • 把小程序的代码包下载到本地
  • 解析 app.json
  • 全局配置文件执行 app.js
  • 小程序入口文件,调用 App() 创建小程序实例
  • 渲染小程序首页
  • 小程序启动完成

页面渲染的过程

  • 加载解析页面的 .json
  • 配置文件加载页面的 .wxml 模板和 .wxss 样式
  • 执行页面的 .js 文件,调用 Page() 创建页面实例
  • 页面渲染完成

组件

小程序中组件的分类

小程序中的组件也是由宿主环境提供的,开发者可以基于组件快速搭建出漂亮的页面结构。官方把小程序的组件分为了 9 大类,分别是:

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

常用的视图容器类组件

image-20230519222615626

view 组件的基本使用

image-20230519222643764

scroll-view 组件的基本使用

image-20230519222735076

swiper 和 swiper-item 组件的基本使用

image-20230519222754888

swiper 组件的常用属性

image-20230519222809015

常用的基础内容组件

image-20230519222835392

通过 text 组件的 selectable 属性,实现长按选中文本内容的效果:

image-20230519222844836

通过 rich-text 组件的 nodes 属性节点,把 HTML 字符串渲染为对应的 UI 结构:

image-20230519222916391

其它常用组件

image-20230519222935486

button 按钮的基本使用

image-20230519223022901

image 组件的基本使用

image-20230519223110544

image 组件的 mode 属性

image-20230519223142369

API

小程序中的 API 是由宿主环境提供的,通过这些丰富的小程序 API,开发者可以方便的调用微信提供的能力,例如:获取用户信息、本地存储、支付功能等。

API 的 3 大分类

image-20230519223226889

发布流程和小程序运营

上传代码 -> 提交审核 -> 发布

image-20230519223820787

登录小程序管理后台 -> 管理 -> 版本管理 -> 开发版本,即可查看刚才提交上传的版本了:

image-20230519223846592

审核

image-20230519223905925

发布

image-20230519223928149

查看小程序运营数据的两种方式

image-20230519224004732

二、模版与配置

WXML模版语法

数据绑定

  • 在 data 中定义数据
  • 在 WXML 中使用数据

{{}}取出data定义的数据,和vue的用法一样

<!--pages/list/list.wxml-->

<!-- 1 字符串 -->
<view> {{msg}} </view>
<!-- 2 数字类型 -->
<view>{{num}}</view>
<!-- 3 bool类型  -->
<view> 是否是伪娘: {{isGirl}} </view>
<!-- 4 object类型 -->
<view>{{person.age}}</view>
<view>{{person.height}}</view>
<view>{{person.weight}}</view>
<view>{{person.name}}</view>

<!-- 5 在标签的属性中使用 -->
<view data-num="{{num}}"> 自定义属性</view>

<!-- 
  6 使用bool类型充当属性 checked  
    1 字符串和 花括号之间一定不要存在空格 否则会导致识别失败 
      以下写法就是错误的示范
         <checkbox checked="       {{isChecked}}"> </checkbox>
 -->
 <view>
  <checkbox checked="{{isChecked}}"> </checkbox>
</view>

<!-- 
  7 运算 => 表达式
    1 可以在花括号中 加入 表达式 --  “语句”
    2 表达式
      指的是一些简单 运算 数字运算 字符串 拼接  逻辑运算。。
      1 数字的加减。。
      2 字符串拼接
      3 三元表达式 
    3 语句
      1 复杂的代码段
        1 if else
        2 switch
        3 do while 。。。。
        4 for 。。。
 -->
<view>{{1+1}}</view>
<view>{{'1'+'1'}}</view>
<view>{{ 11%2===0 ? '偶数' : '奇数' }}</view>

<!-- 
  8 列表循环
    1 wx:for="{{数组或者对象}}"  wx:for-item="循环项的名称"  wx:for-index="循环项的索引"
    2 wx:key="唯一的值" 用来提高列表渲染的性能
      1 wx:key 绑定一个普通的字符串的时候 那么这个字符串名称 肯定是 循环数组 中的 对象的 唯一属性
      2 wx:key ="*this"  就表示 你的数组 是一个普通的数组  *this 表示是 循环项 
        [1,2,3,44,5]
        ["1","222","adfdf"]
    3 当出现 数组的嵌套循环的时候 尤其要注意  以下绑定的名称 不要重名
        wx:for-item="item" wx:for-index="index"
    4 默认情况下 我们 不写
       wx:for-item="item" wx:for-index="index"
       小程序也会把 循环项的名称 和 索引的名称 item 和 index 
       只有一层循环的话 (wx:for-item="item" wx:for-index="index") 可以省略

  9 对象循环
    1 wx:for="{{对象}}" wx:for-item="对象的值"  wx:for-index="对象的属性"
    2 循环对象的时候 最好把 item和index的名称都修改一下
      wx:for-item="value"  wx:for-index="key"

 -->
 <view>
  <view>数组循环</view>
   <view wx:for="{{list1}}" wx:for-item="item"
  wx:for-index="id" wx:key="id">
     索引:{{id}}--值:{{item.name}}
   </view>
 </view>

 <view>
   <view>对象循环</view>
   <view wx:for="{{person}}" wx:for-item="value"  
  wx:for-index="aaa" wx:key="age">
     属性:{{aaa}}--值:{{value}}
   </view>
 </view>

 <!-- 
   10 block
    1 占位符的标签 
    2 写代码的时候 可以看到这标签存在
    3 页面渲染 小程序会把它移除掉
  -->
  <view>
    <block wx:for="{{list}}" wx:for-item="item"
   wx:for-index="index" wx:key="id"
   class="my_list">
      索引:{{index}} -- 值:{{item.name}}
    </block>
  </view>


  <!-- 
    11 条件渲染
      1 wx:if="{{true/false}}"
        1 if , else , if else
        wx:if
        wx:elif
        wx:else 
      2 hidden 
        1 在标签上直接加入属性 hidden 
        2 hidden="{{true}}"

      3 什么场景下用哪个
        1 当标签不是频繁的切换显示 优先使用 wx:if
          直接把标签从 页面结构给移除掉 
        2 当标签频繁的切换显示的时候 优先使用 hidden
          通过添加样式的方式来切换显示 
          hidden 属性 不要和 样式 display一起使用
   -->
   <view>
     <view>条件渲染</view>
     <view wx:if="{{true}}">显示</view>
     <view wx:if="{{false}}">隐藏</view>

     <view wx:if="{{flase}}">1</view>
     <view wx:elif="{{flase}}">2 </view>
     <view wx:else> 3 </view>

     <view>---------------</view>
     <view hidden>hidden1</view>
     <view hidden="{{false}}" >hidden2</view>

     <view>-----000-------</view>
     <view wx:if="{{false}}">wx:if</view>
     <view hidden  style="display: flex;" >hidden</view>
   </view>

   <!-- 
  1 长按文字复制 selectable
  2 对文本内容 进行 解码
 -->
<text selectable decode>
  text &nbsp; 123 &lt;
</text>
<image mode="bottom" lazy-load src="https://tva2.sinaimg.cn/large/007DFXDhgy1g51jlzfb4lj305k02s0sp.jpg" />
// pages/list/list.js
Page({
  isChecked:true,
  list1:[
    {
      id:0,
      name1:"猪八戒"
    },
    {
      id:1,
      name:"天蓬元帅"
    },
    {
      id:2,
      name:"悟能"
    }
  ],

  /**
   * 页面的初始数据
   */
  data: {
    msg: "hello mina",
    num: 10000,
    isGirl: false,
    person: {
      age: 74,
      height: 145,
      weight: 200,
      name: "富婆"
    }
  },
})

事件绑定

**事件是渲染层到逻辑层的通讯方式。**通过事件可以将用户在渲染层产生的行为,反馈到逻辑层进行业务的处理。

image-20230519224930523

小程序中常用的事件

image-20230519224947075

事件对象的属性列表

image-20230519225007217

target 是触发该事件的源头组件,而 currentTarget 则是当前事件所绑定的组件。

image-20230519225127874

事件传参

image-20230519225441224

image-20230519225500455

条件、列表渲染

和vue一样的道理,不在展示,跟着做个项目救明白了

WXSS模版样式

样式导入

通过@import语法,导入别人写好的样式

image-20230519233218625

全局样式和局部样式

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

在页面的 .wxss 文件中定义的样式为局部样式,只作用于当前页面。

当局部样式和全局样式冲突时,根据就近原则,局部样式会覆盖全局样式当局部样式的权重大于或等于全局样式的权重时,才会覆盖全局的样式

全局配置

全局配置文件及常用的配置项

image-20230519234453289

window

小程序窗口的组成部分

image-20230519234533322

window 节点常用的配置项

image-20230519234551629

设置导航栏的标题

image-20230519234606596

设置导航栏的背景色

image-20230519234625652

设置导航栏的标题颜色

image-20230519234638724

全局开启下拉刷新功能

image-20230519234652528

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

image-20230519234709476

设置下拉刷新时 loading 的样式

image-20230519234725811

设置上拉触底的距离

image-20230519234741299

tabBar

tabBar 的 6 个组成部分

image-20230519234804549

tabBar 节点的配置项

image-20230519234816973

每个 tab 项的配置选项

image-20230519234847327

页面配置

小程序中,每个页面都有自己的 .json 配置文件,用来对当前页面的窗口外观、页面效果等进行配置。

小程序中,app.json 中的 window 节点,可以全局配置小程序中每个页面的窗口表现。如果某些小程序页面想要拥有特殊的窗口表现,此时,“页面级别的 .json 配置文件”就可以实现这种需求。注意:当页面配置与全局配置冲突时,根据就近原则,最终的效果以页面配置为准。

常用的配置项

image-20230519235243308

网络数据请求

小程序中网络数据请求的限制

image-20230519235347791

配置 request 合法域名

escook.cn

image-20230519235413392

案例

image-20230520123707584

<!--pages/home/home.wxml-->
<text>pages/home/home.wxml</text>

<swiper indicator-dots circular>
<swiper-item wx:for="{{swiperList}}" wx:key="id" >
  <image src="{{item.image}}"></image>
</swiper-item>
</swiper>

<!-- 九宫格 -->
<view class="grid-list">
  <view class="grid-item" wx:for="{{gridList}}" wx:key="id">
    <image src="{{item.icon}}"/>
    <text>{{item.name}}</text>
  </view>
</view>

<!-- 图片区域 -->
<view class="image-box">
  <image src="/images/link-01.png" mode="widthFix"/>
  <image src="/images/link-02.png" mode="widthFix"/>
</view>
// pages/home/home.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    swiperList: [],
    gridList: []
  },

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

  getSwiperList() {
    wx.request({
      url: 'https://applet-base-api-t.itheima.net/slides',
      method: 'GET',
      success: (res) => {
        console.log(res)
        this.setData({
          swiperList: res.data
        })
      }
    })
  },
  //获取九宫格数据
  getGridList() {
    wx.request({
      url: 'https://applet-base-api-t.itheima.net/categories',
      method: 'GET',
      success: (res) => {
        console.log(res)
        this.setData({
          gridList: res.data
        })
      }
    })
  },

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

  },

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

  },

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

  },

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

  },

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

  },

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

  },

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

  }
})
/* pages/home/home.wxss */
swiper {
  height: 350rpx;
}

swiper image{
  width: 100%;
  height: 100%;
}

.grid-list{
  display: flex;
  flex-wrap: wrap;
  border-left: 1rpx solid #efefef;
  border-top: 1rpx solid #efefef;
}

.grid-item{
  width: 33.33%;
  height: 200rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-right: 1rpx solid #efefef;
  border-bottom: 1rpx solid #efefef;
  box-sizing: border-box;
}

.grid-item image{
  width: 60rpx;
  height: 60rpx;
}

.grid-item text{
  font-size: 24rpx;
  margin-top: 10rpx;
}

.image-box{
  display: flex;
  padding: 50rpx 20rpx;
  justify-content: space-around;
}

.image-box image{
  /* display: flex; */
  /* padding: 0rpx 10rpx; */
  width: 45%;
}

三、视图与逻辑

页面导航

什么是页面导航

页面导航指的是页面之间的相互跳转。例如,浏览器中实现页面导航的方式有如下两种:

  • 链接
  • location.href

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

声明式导航

在页面上声明一个 导航组件

通过点击 组件实现页面跳转

编程式导航

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

声明式导航

image-20230520123932377

image-20230520123951482

image-20230520124001300

编程式导航

image-20230520124054684

image-20230520124138643

image-20230520124227150

image-20230520124234454

导航传参

image-20230520124435106

image-20230520124448540

image-20230520140217137

页面事件

下拉刷新事件

image-20230520140245539

image-20230520140308482

image-20230520140317895

在页面的 .js 文件中,通过 onPullDownRefresh() 函数即可监听当前页面的下拉刷新事件。例如,在页面的 wxml 中有如下的 UI 结构,点击按钮可以让 count 值自增 +1:

image-20230520140328811

image-20230520140531173

上拉触底事件

什么是上拉触底

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

image-20230520140703036

image-20230520140721122

案例

<!--pages/cantact/cantact.wxml-->
<text>pages/cantact/cantact.wxml</text>
<view wx:for="{{colorList}}" wx:key="index" class="num-item" style="background-color: rgba({{item}});">{{item}}
</view>
/* pages/cantact/cantact.wxss */
.num-item {
  border: 10rpx solid #efefef;
  border-radius: 8rpx;
  line-height: 200rpx;
  margin: 350rpx;
  text-align: center;
  text-shadow: 0rpx 0rpx 5rpx #fff;
  box-shadow: 1rpx 1rpx 6rpx #aaa;
} 
// pages/cantact/cantact.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    colorList: [],
    isloading: false
  },

  getColors() {
    this.setData({
      isloading:true
    })
    wx.request({
      url: 'https://applet-base-api-t.itheima.net/api/color',
      method: 'GET',
      success: ({
        data: res
      }) => {
        console.log(res.data)
        this.setData({ //...的意思是对数据进行拼接,不是覆盖。第一个参数是旧数据,第二个参数是新数据
          colorList: [...this.data.colorList, ...res.data]
        })
      },
      complete:() => {
        wx.hideLoading()
        this.setData({
          isloading:false
        })
      }
    })
    wx.showLoading({
      title: '数据加载中',
    })
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    this.getColors()
  },

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

  },

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

  },

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

  },

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

  },

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

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {
    console.log("触发了上拉触底事件")
    if(this.data.isloading) return
    this.getColors()
  },

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

  }
})

生命周期

小程序的启动,表示生命周期的开始

小程序的关闭,表示生命周期的结束

image-20230521112545698

image-20230521112617386

image-20230521112748051

image-20230521112816214

image-20230521112828483

WXS脚本

类似,html中<script>标签

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

wxml 中无法调用在页面的 .js 中定义的函数,但是,wxml 中可以调用 wxs 中定义的函数。因此,小程序中 wxs 的典型应用场景就是“过滤器”。

wxs 和 JavaScript 的关系*

image-20230521113030375

基础语法

image-20230521113054424

image-20230521113107370

WXS的特点

image-20230521113145552

image-20230521113155886

image-20230521113203872

image-20230521113212947

案例

比较简单,直接粘贴代码。

1、首先是把九宫格区域的单元格改成navigator标签,让点击单元格能实现跳转功能

<!--pages/home/home.wxml-->
<!-- 轮播图区域 -->
<swiper indicator-dots circular>
  <swiper-item wx:for="{{swiperList}}" wx:key="id">
    <image src="{{item.image}}"></image>
  </swiper-item>
</swiper>

<!-- 九宫格区域 -->
<view class="grid-list">
  <navigator class="grid-item" wx:for="{{gridList}}" wx:key="id" url="/pages/shoplist/shoplist?id={{item.id}}&title={{item.name}}">
    <image src="{{item.icon}}"></image>
    <text>{{item.name}}</text>
  </navigator>
</view>

<!-- 图片区域 -->
<view class="img-box">
  <image src="/images/link-01.png" mode="widthFix"></image>
  <image src="/images/link-02.png" mode="widthFix"></image>
</view>

2、编写跳转后的页面,每一个视图左边为图片,右边为介绍(通过WXSS来控制)。最后还通过WXS做过滤器对手机号进行分割,效果为分段显示

<!--pages/shoplist/shoplist.wxml-->

<view class="shop-item" wx:for="{{shopList}}" wx:key="id">
  <view class="thumb">
    <image src="{{item.images[0]}}"></image>
  </view>
  <view class="info">
    <text class="shop-title">{{item.name}}</text>
    <text>电话:{{tools.splitPhone(item.phone)}}</text>
    <text>地址:{{item.address}}</text>
    <text>营业时间:{{item.businessHours}}</text>
  </view>
</view>

<wxs src="../../utils/tools.wxs" module="tools"></wxs>

3、样式调整

/* pages/shoplist/shoplist.wxss */
.shop-item {
  display: flex;
  padding: 15rpx;
  border: 1rpx solid #efefef;
  border-radius: 8rpx;
  margin: 15rpx;
  box-shadow: 1rpx 1rpx 15rpx #ddd;
}

.thumb image {
  width: 250rpx;
  height: 250rpx;
  display: block;
  margin-right: 15rpx;
}

.info {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  font-size: 24rpx;
}

.shop-title {
  font-weight: bold;
}
// pages/shoplist/shoplist.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    query: {},
    shopList: [],
    page: 1,
    pageSize: 10,
    total: 0,
    isloading: false
  },

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

  // 以分页的形式获取商铺列表数据的方法
  getShopList(cb) {
    this.setData({
      isloading: true
    })
    // 展示 loading 效果
    wx.showLoading({
      title: '数据加载中...'
    })

    wx.request({
      url: `https://applet-base-api-t.itheima.net/categories/${this.data.query.id}/shops`,
      method: 'GET',
      data: {
        _page: this.data.page,
        _limit: this.data.pageSize
      },
      success: (res) => {
        this.setData({
          shopList: [...this.data.shopList, ...res.data],
          total: res.header['X-Total-Count'] - 0
        })
      },
      complete: () => {
        // 隐藏 loading 效果
        wx.hideLoading()
        this.setData({ isloading: false })
        // wx.stopPullDownRefresh()
        cb && cb()
      }
    })
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    wx.setNavigationBarTitle({
      title: this.data.query.title
    })
  },

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

  },

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

  },

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

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
    // 需要重置关键的数据
    this.setData({
      page: 1,
      shopList: [],
      total: 0
    })
    // 重新发起数据请求
    this.getShopList(() => {
      wx.stopPullDownRefresh()
    })
  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
    if (this.data.page * this.data.pageSize >= this.data.total) {
      // 证明没有下一页的数据了
      return wx.showToast({
        title: '数据加载完毕!',
        icon: 'none'
      })
    }
    // 判断是否正在加载其他数据
    if (this.data.isloading) return
    // 页码值 +1
    this.setData({
      page: this.data.page + 1
    })

    // 获取下一页数据
    this.getShopList()
  },

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

  }
})

四、组件

自定义组件

创建与引用

创建

image-20230714162221633

引用

组件的引用方式分为“局部引用”和“全局引用”,顾名思义:

  • 局部引用:组件只能在当前被引用的页面内使用
  • 全局引用:组件可以在每个小程序页面中使用

局部

image-20230714162314856

全局

image-20230714162339482

哪个更好?

根据组件的使用频率和范围,来选择合适的引用方式:

  • 如果某组件在多个页面中经常被用到,建议进行“全局引用”
  • 如果某组件只在特定的页面中被用到,建议进行“局部引用”

组件和页面的区别

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

  • 组件的 .json 文件中需要声明 “component”: true 属性
  • 组件的 .js 文件中调用的是 Component() 函数
  • 组件的事件处理函数需要定义到 methods 节点中,而页面的处理函数是单独拎出来的在Page({})对象里

样式

组件样式隔离

如下:还是很好理解的

image-20230714202712630

注意点

image-20230714202744839

class选择器就是这样式的:

<h1 class = "c1">      html
.c1{}                  css  

修改组件的样式隔离选项

image-20230714202923792

styleIsolation 的可选值

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

数据、方法和属性

image-20230714203023210

image-20230714203036876

image-20230714203047968

data 和 properties 的区别

image-20230714203137776

使用 setData 修改 properties 的值

image-20230714203221372

数据监听器

是什么?

image-20230714203355546

基本用法

1、ui代码

<!--components/test2/test2.wxml-->
<view>{{n1}} + {{n2}} = {{sum}}</view>

<button bindtap="addN1">n1+1</button>
<button bindtap="addN2">n2+1</button>

2、js代码

// components/test2/test2.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {
    n1: 0,
    n2: 0,
    sum: 0
  },

  /**
   * 组件的方法列表
   */
  methods: {
    addN1() {
      this.setData({
        n1: this.data.n1 + 1
      })
    },
    addN2() {
      this.setData({
        n2: this.data.n2 + 1
      })
    }
  },
  //3、监听对象属性的变化
  //数据监听器支持监听对象中单个或多个属性的变化
  observers: {
    'n1, n2': function (newN1, newN2) {
      this.setData({
        sum: newN1 + newN2
      })
    }
  }
})

监听对象属性的变化示例语法:

Component({
	observers:{
		'对象.属性A,对象.属性B':function(形参A,形参B){
			可以直接为属性赋值或者其他对象赋值
		}
	}
})

如果某个对象中需要被监听的属性太多,为了方便,可以使用通配符 ** 来监听对象中所有属性的变化

Component({
	observers:{
		'对象.**':function(形参A,形参B){
			可以直接为属性赋值或者其他对象赋值
		}
	}
})

纯数据字段

1.是什么?

概念:纯数据字段指的是那些不用于界面渲染的 data 字段。

应用场景:例如有些情况下,某些 data 中的字段既不会展示在界面上,也不会传递给其他组件,仅仅在当前组件内部使用。带有这种特性的 data 字段适合被设置为纯数据字段。

好处:纯数据字段有助于提升页面更新的性能。

2.使用规则

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

image-20230714215924001

3.使用纯数据字段改造数据监听器案例

image-20230714220004490

组件的生命周期

1.组件全部的生命周期函数

生命周期函数参数描述说明
created在组件实例刚刚被创建时执行
attached在组件实例进入页面节点树时执行
ready在组件在视图层布局完成后执行
moved在组件实例被移动到节点树另一个位置时执行
detached在组件实例被从页面节点树移除时执行
errorObject Error每当组件方法抛出错误时执行
  1. 组件主要的生命周期函数

在小程序组件中,最重要的生命周期函数有 3 个,分别是 created、attached、detached。它们各自的特点如下:

1.组件实例刚被创建好的时候,created 生命周期函数会被触发

  • 此时还不能调用 setData
  • 通常在这个生命周期函数中,只应该用于给组件的 this 添加一些自定义的属性字段

2.在组件完全初始化完毕、进入页面节点树后, attached 生命周期函数会被触发

  • 此时, this.data 已被初始化完毕
  • 这个生命周期很有用,绝大多数初始化的工作可以在这个时机进行(例如发请求获取初始数据)

3.在组件离开页面节点树后, detached 生命周期函数会被触发

  • 退出一个页面时,会触发页面内每个自定义组件的 detached 生命周期函数
  • 此时适合做一些清理性质的工作
  1. lifetimes 节点

image-20230714220435505

组件所在页面的生命周期

1.是什么?

image-20230714220521998

2.pageLifetimes 节点

image-20230714220552857

  1. 生成随机的 RGB 颜色值

image-20230714220614311

image-20230714220716053

插槽

  1. 什么是插槽

image-20230714220810437

  1. 单个插槽

image-20230714220846658

  1. 启用多个插槽

image-20230714220928221

  1. 定义多个插槽

image-20230714220946787

  1. 使用多个插槽

image-20230714221004840

示例:

1.定义模版
<view>
  <slot name="before"></slot>
  <view>这里是组件的内部结构</view>
  <slot name="after"></slot>
</view>

2.注册组件
  "usingComponents": {
    "test4":"./components/test4/test4",
  }

3.使用
<test4>
    <van-button slot="before" type="primary" bindtap="getInfo">按钮</van-button>
    <van-button slot="after" type="danger">按钮</van-button>
</test4>

效果如下:

image-20230714221542893

父子组件之间的通信

1.父子组件之间通信的 3 种方式

image-20230714221629056

  1. 属性绑定

image-20230714221655723

image-20230714222819769

  1. 事件绑定

image-20230714222704245

image-20230714223310835

image-20230714223351262

image-20230714223533999

  1. 获取组件实例

image-20230714223518158

behaviors

  1. 什么是 behaviors

image-20230714224020223

  1. behaviors 的工作方式

image-20230714223737314

  1. 创建 behavior

image-20230714224053987

  1. 导入并使用 behavior

image-20230714225651686

  1. behavior 中所有可用的节点
可用的节点类型是否必填描述
propertiesObject Map同组件的属性
dataObject同组件的数据
methodsObject同自定义组件的方法
behaviorsString Array引入其它的 behavior
createdFunction生命周期函数
attachedFunction生命周期函数
readyFunction生命周期函数
movedFunction生命周期函数
detachedFunction生命周期函数
  1. 同名字段的覆盖和组合规则

组件和它引用的 behavior 中可以包含同名的字段,此时可以参考如下 3 种同名时的处理规则:

  • 同名的数据字段 (data)
  • 同名的属性 (properties) 或方法 (methods)
  • 同名的生命周期函数

使用npm包

小程序对 npm 的支持与限制

image-20230714230136052

Vant Weapp

Vant Weapp 是有赞前端团队开源的一套小程序 UI 组件库,助力开发者快速搭建小程序应用。它所使用的是 MIT 开源许可协议,对商业使用比较友好。

官方文档地址 youzan.github.io/vant-weapp

1.安装 Vant 组件库

在小程序项目中,安装 Vant 组件库主要分为如下 3 步:

  • 通过 npm 安装(建议指定版本为@1.3.3)
  • 构建 npm 包
  • 修改 app.json

youzan.github.io/vant-weapp/…

2.使用 Vant 组件

image-20230714230340957

3.定制全局主题样式

Vant Weapp 使用 CSS 变量来实现定制主题。 关于 CSS 变量的基本用法,请参考 MDN 文档:developer.mozilla.org/zh-CN/docs/…

4.定制全局主题样式

image-20230714230442432

所有可用的颜色变量,请参考 Vant 官方提供的配置文件:github.com/youzan/vant…

API Promise化

1.基于回调函数的异步 API 的缺点

image-20230714230744808

2.什么是 API Promise 化

API Promise化,指的是通过额外的配置,将官方提供的、基于回调函数的异步 API,升级改造为基于 Promise 的异步 API,从而提高代码的可读性、维护性,避免回调地狱的问题。

3.实现 API Promise 化

image-20230714230843643

4.调用 Promise 化之后的异步 API

image-20230714230858566

全局数据共享

1.什么是全局数据共享

image-20230714230954824

2.小程序中的全局数据共享方案

image-20230714231023772

MobX

1.安装 MobX 相关的包

image-20230714231847788

2.创建 MobX 的 Store 实例

image-20230714231914344

3.将 Store 中的成员绑定到页面中

image-20230714232018856

4.在页面上使用 Store 中的成员

image-20230714232040871

5.将 Store 中的成员绑定到组件中

image-20230714232100309

6.在组件中使用 Store 中的成员

image-20230714232141765

分包

基础概念

1.什么是分包

分包指的是把一个完整的小程序项目,按照需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。

2.分包的好处

对小程序进行分包的好处主要有以下两点:

  • 可以优化小程序首次启动的下载时间
  • 在多团队共同开发时可以更好的解耦协作

3.分包前项目的构成

image-20230714232306330

4.分包后项目的构成

image-20230714232321157

5.分包的加载规则

在小程序启动时,默认会下载主包并启动主包内页面

  • tabBar 页面需要放到主包中

当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示

  • 非 tabBar 页面可以按照功能的不同,划分为不同的分包之后,进行按需下载

6.分包的体积限制

目前,小程序分包的大小有以下两个限制:整个小程序所有分包大小不超过 16M(主包 + 所有分包)单个分包/主包大小不能超过 2M

使用分包

1.配置方法

image-20230714232456823

2.打包原则

  • 小程序会按 subpackages 的配置进行分包,subpackages 之外的目录将被打包到主包中
  • 主包也可以有自己的 pages(即最外层的 pages 字段)
  • tabBar 页面必须在主包内
  • 分包之间不能互相嵌套

3.引用原则

image-20230714232542863

独立分包

1.什么是独立分包

image-20230714232601079

2.独立分包和普通分包的区别

最主要的区别:是否依赖于主包才能运行

  • 普通分包必须依赖于主包才能运行
  • 独立分包可以在不下载主包的情况下,独立运行

3.独立分包的应用场景

开发者可以按需,将某些具有一定功能独立性的页面配置到独立分包中。原因如下:

  • 当小程序从普通的分包页面启动时,需要首先下载主包
  • 而独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度

注意:一个小程序中可以有多个独立分包。

4.独立分包的配置方法

image-20230714232731145

5.引用原则

独立分包和普通分包以及主包之间,是相互隔绝的,不能相互引用彼此的资源!例如:

  • 主包无法引用独立分包内的私有资源
  • 独立分包之间,不能相互引用私有资源
  • 独立分包和普通分包之间,不能相互引用私有资源
  • 特别注意:独立分包中不能引用主包内的公共资源

分包预下载

1.什么是分包预下载

分包预下载指的是:在进入小程序的某个页面时,由框架自动预下载可能需要的分包,从而提升进入后续分包页面时的启动速度。

2.配置分包的预下载

预下载分包的行为,会在进入指定的页面时触发。在 app.json 中,使用 preloadRule 节点定义分包的预下载规则,示例代码如下:

image-20230714232914829

3.分包预下载的限制

image-20230714232927411