原生微信小程序

1、快速入门

1.1 学习目标
1.2 小程序与普通网页开发的区别
  • 运行环境,小程序是运行在 微信环境中的
  • API ,小程序无法调用 DOM BOM,但他封装好了 一些 API
  • 开发模式
1.3 体验微信小程序
  1. 注册小程序
  2. 激活
  3. 信息登记
1.4 注册
1.5 获取小程序 AppID

在 小程序 官网,进入 开发 => 开发设置 => 即可看到 AppID

1.6 安装微信开发者工具
1.7 扫码登录到微信开发者工具
1.8 设置外观和代理
1.9 新建小程序的步骤
  1. 新建
  2. 不使用云服务
  3. 最后写上 appID
  4. 语言 选择 JavaScript
1.10 查看项目运行效果的两种方式
  • 模拟器上 查看
  • 预览 按钮,需要用手机扫码 查看
1.11 了解微信开发者工具主页面的5个组成部分
  • 帮助 => 开发者文档 ,可以快速跳转到 api 文档 api
1.12 了解项目的基本组成构成
  1. pages 用来存放 所有小程序的页面
  2. utils 用来存放工具性质的模块
  3. app.js 小程序项目的入口文件
  4. app.json 小程序项目的全局配置文件
  5. app.wxss 小程序项目的全局样式文件
  6. project.config.json 项目的配置文件
  7. sitemap.json 用来配置小程序及其页面是否允许被微信索引
1.13 小程序页面的组成部分

小程序官方建议把小程序的页面,都存放在 pages 目录

每个页面都有 四个文件

  • .js 文件,页面的脚本文件,存放页面的数据、事件处理函数等等
  • .json 文件 ,当前页面的配置文件,配置窗口的外观、表现等
  • .wxml 文件 ,页面的模板结构文件
  • .wxss 文件,页面的样式表文件
1.14 认识小程序中的 4 种 配置文件

app.json 文件 就是 小程序 的配置文件

  • 项目 跟目录 种的 app.json => 小程序项目的全局配置文件
  • 跟目录的 project.config.json => 项目的配置文件
  • 根目录种的 sitemao.json => 用来配置小程序及其页面是否允许被微信索引
  • 每个页面文件种的 .json 配置文件
1.15 app.json 配置文件

app.json 是 当前 小程序的全局配置文件,包含了小程序的所有页面路径、窗口外观、界面表面、底部 tab等

{
  // pages  是 用来记录当前小程序所有页面的路径
  "pages":[
    "pages/index/index",
    "pages/logs/logs"
  ],
  // window 全局定义小程序所有页面的背景色、文字颜色等
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "Weixin",
    "navigationBarTextStyle":"black"
  },
  // style 全局定义小程序组件所使用的样式版本
  "style": "v2",
  // sitemapLocation 用来指明 sitemap.json 的存放位置
  "sitemapLocation": "sitemap.json"
}

1.16 project.config.json 配置文件

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

  • setting 中保存了编译相关的配置
  • projectname 保存了项目名称
  • appid 中保存的是 小程序的账号 id
1.17 sitemap.json 文件

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

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

{
  "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
  "rules": [{
    // action 是否允许 被微信索引,allow 是,disallow 不是
  "action": "allow",
    // page * 是所有页面 都被 微信索引
  "page": "*"
  }]
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Iwm8uzkK-1620460593891)(第一章原生微信小程序.assets/image-20210415211439926.png)]

微信小程序 的 调试器 ,会显示一个 黄色的警告,说 什么什么什么 将被索引

如果 不想看到 这个东西

可以在project.config.json 的 setting 中,配置字段 checkSiteMap 为 false

1.18 页面的 json 配置文件

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

1.19 新建小程序页面

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

{
  "pages":[
    "pages/index/index",
    "pages/logs/logs"
    # 在这里 继续 添加就可以
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "Weixin",
    "navigationBarTextStyle":"black"
  },
  "style": "v2",
  "sitemapLocation": "sitemap.json"
}

1.20 修改项目首页

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

1.21 wxml 和 html 的区别

wxml 是 小程序 框架设计的一套 标签语言,用来构建小程序页面的结果,其作用类似于网页开发中的 html

区别

  1. 标签名称不同
  2. 属性节点不同
  3. 提供了类似于 vue 中的模板语法 数据绑定 列表渲染 条件渲染
1.22 wxss 和 css 的区别
  1. wxss 新增了 rpx 尺寸单位
  2. 提供了全局的样式 和局部样式
  3. wxss 仅支持部分 css 选择器
1.23 小程序中 js 文件的 三大分类

app.js

是 整个小程序项目的入口文件 调用 App()函数来启动整个小程序

页面的 .js 文件

是 页面的入口文件,通过调用 Page() 函数来创建并运行页面

普通的 .js文件

是普通的功能模块文件,用来封装 公共 的函数或属性 供页面使用

2、微信小程序的宿主环境

2.1 了解概念

宿主环境 指的是 程序运行所必须的依赖环境

2.2 小程序的 宿主 环境

微信 是小程序 的宿主环境,小程序是基于微信进行安装的

小程序的宿主环境 包含的内容?

  1. 通信模型
  2. 运行机制
  3. 组件
  4. API
2.3 通信主题

小程序中 通信的主体 是 渲染层 和 逻辑层

  1. wxml 模板 和 wxss 样式工作在渲染层
  2. JS 脚本工作再逻辑层
2.4 通信模型
  1. 渲染层 和 逻辑层 之间的通心
  2. 逻辑层 和 第三方 服务器 之间的通信

都是由 微信客户端进行转发

2.5 运行机制

小程序 启动过程

  1. 把小程序的代码包下载到本地
  2. 解析 app.json 全局配置文件
  3. 执行 app.js 小程序入口文件
  4. 渲染小程序首页
  5. 启动完成

页面渲染过程

  1. 加载解析页面 .json 文件
  2. 加载 .wxml wxss
  3. 执行 .js 文件,调用 Page()创建页面实例
  4. 页面渲染完成
2.6 了解常用的视图容器组件
  1. 视图容器
  2. 基础内容
  3. 表单组件
  4. 导航组件
  5. 媒体组件
  6. map地图组件
  7. canvas 画布组件
  8. 开放能力
  9. 无障碍访问

前四个 是最常用的

view 就是 html 的 div

scroll-view 可滚动的视图区域,经常实现滚动列表效果

swiper 轮播图组件

2.7 view 组件的 基本使用

实现横向布局

flex

2.8 scroll-view 组件的基本使用


必须要给容器 加一个 宽度和高度
2.9 swiper 和 swiper-item
<swiper class="swiper-container" indicator-dots>
	<swiper-item>
		<view>Aview>
	swiper-item>
	<swiper-item>
		<view>Bview>
	swiper-item>
	<swiper-item>
		<view>Cview>
	swiper-item>
swiper>
/*  轮播图 */
.swiper-container{
  height: 150px;
}
.swiper-container swiper-item {
  height: 100%;
  line-height: 150px;
  text-align: center;
}
.swiper-container swiper-item:nth-child(1) view{
  background-color: aqua;
}
.swiper-container swiper-item:nth-child(2) view{
  background-color: red;
}
.swiper-container swiper-item:nth-child(3) view{
  background-color: green;
}
2.10 swiper 常用 属性
属性 类型 默认值 说明
indicator-dots boolean false 是否显示面板指示点
indicator-color color rgba() 指示点的颜色
indicator-active-color color #000000 当前选中的指示点的颜色
autoplay boolean false 是否自动切换
interval number 5000 自动切换时间间隔
circular boolean false 是否采用衔接滑动
2.11 text 和 rich-text 组件

text 就是一个 行内元素

rich-text 富文本组件

2.12 button 按钮组件

button

  • 按钮组件
  • 功能比html 中的 button 按钮丰富
  • 通过 open-type 属性 可以调用微信提供的各种功能 (客服、转发、获取用户授权、获取用户信息等等)

image

navigator

2.13 image 图片组件

默认 不指定 src 的 图片组件,也占据一定的宽度和高度

mode值 说明
scaleToFill 默认(缩放模式),不保持纵横比缩放图片,使图片的宽度完全拉甚至填满image元素
aspectFit 缩放模式,保持纵横比缩放图片,使图片的长边能完全显示出来
aspectFill 缩放模式,保持纵横比缩放图片,只保证图片的短边能完全显示出来
widthFix 缩放模式,宽度不变,高度自动变化,保持原图宽高比不变
heightFix 缩放模式,高度不变,宽度自动变化,保持原图宽高不变
2.14 小程序 api 的3 大分类
  • 事件监听 api
    • 以 on 开头,用来 监听 某些事件的触发
  • 同步api
    • 以 Sync 结尾的api
    • 同步API 的执行结果,可以通过 函数返回值 直接获取,如果执行错误会抛出异常
    • 举例: wx.setStorageSync(‘key’,‘value’) 向本地存储中写入内容
  • 异步api
    • wx.request() 发起网络数据请求,通过 success 回调函数接收数据

3、小程序协同工作和发布

3.1 了解权限管理需求、组织结构、开发流程
  • 产品组
  • 设计组
  • 开发组
  • 测试组
  1. 产品组 提出需求
  2. 设计组 设计
  3. 开发组 开发
  4. 产品组 和设计组 体验
  5. 测试组 测试
  6. 发布
3.2 了解小程序管理的两个方面
3.3 开发者权限说明
3.4 了解如何添加项目成员和体验成员
3.5 小程序版本
  • 开发版本
  • 体验版本
  • 审核中的版本
  • 线上版本
3.6 小程序发布上线的主要步骤

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

3.7 基于小程序码进行推广
  • 普通二维码
  • 小程序码

获取小程序码方式

登录小程序管理后台 => 设置 => 基本设置 => 基本信息 => 小程序码及线下物料下载

3.8 查看小程序的运营数据

1、小程序 后台 查看

登录进去后台 点击 统计

2、小程序数据助手

手机微信搜素,小程序数据助手

3.9 总结
  1. 知道如何创建
  2. 了解基本组成结构
  3. 了解小程序页面组成
  4. 常见组件
  5. 协同开发

4、微信小程序基础

4.1 目标
4.2 了解数据绑定的原则
  1. 在 data 中 定义数据
    • 在 页面 对应的 .js 文件中,把数据定义到 data 对象中即可
  2. 在 wxml 中 使用数据

mustache 语法,用 双大括号 即可

{{要绑定数据的名称}}

Page({

  /**
   * 页面的初始数据
   */
  data: {
    info:'hello,world'
  },
)}
<view>{{info}}view>
4.3 动态绑定属性
  • 绑定内容 就是 上边的
  • 绑定属性 src="{{imgSrc}}"
  • 运算(三元运算、算术运算等等)

属性绑定 是和 vue 不一样的

4.4 三元运算
Page({

  /**
   * 页面的初始数据
   */
  data: {
    info:'hello,world',
    randomNum:Math.random()*10  // 生成 十以内的 随机数
  },
)}
     
<view>{{randomNum > = 5 '随机数字大于等于5' : '随机数小于5' }}</view>
4.5 算术运算

{{randomNum * 100}}

4.6 了解什么是事件,以及小程序的事件

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

4.7 事件对象的属性列表

党事件回调触发的时候,会收到一个 事件对象 event

4.8 target 和 currentTarget 的区别

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

<view class="outer-view" bindtap="click">
  <button>按钮button>
view>
 对于 view 而言
 e.target 是 button 组件
 e.currentTarget 是 view 组件
4.9 bindtap 的语法格式
<button type="primary" bindtap="btnTapHandler">按钮button>
// pages/test/test.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    info:'hello,world'
  },
  // 定义按钮的事件处理程序
  btnTapHandler(e){
    console.log(e);
    
  },
)}
4.10 在事件处理函数中为 data 中的数据赋值
  data: {
    info: 'hello,world',
    count: 0,
  },
  // 定义按钮的事件处理程序
  btnTapHandler(e) {
    this.setData({
      count: this.data.count + 1
    })

  },
4.11 事件传参

可以为 组件 提供 data-* 自定义 属性传参,其中 * 代表的是参数的名字

<button bindtap="btnHandler" data-info="{{2}}">事件传参button>

最终 info 会被解析为参数的名字

数值2 会被解析为 参数的值

btnHandler(e){
  // dataset 是一个对象,包含了所有通过data-* 传递过来的参数项
  console.log(e.target.dataset)
  // 访问具体的值
  console.log(e.target.dataset.info)
}
4.12 bindinput 的语法格式
<input bindinput="inputHandle" class="input1">input>
  // 当输入 input 的时候
  inputHandle(e){
    // e.detail.value 是变化过后,文本框最新的值
    console.log(e.detail.value)
  },

4.13 实现文本框和data之间数据的同步
<view>实现 input 和 data 的数据同步view>
<input bindinput="inputHandle2" class="input1" value="{{msg}}">input>
  data: {
    info: 'hello,world',
    count: 0,
    msg: '你好'
  },
  // 实现 input 和 data 的数据同步
  inputHandle2(e) {
    this.setData({
      msg: e.detail.value
    })
  },

4.14 条件渲染 if else
<view wx:if="{{type === 1}}">view>
<view wx:elif="{{type === 2}}">view>
<view wx:else>保密view>
4.15 基于 block 标签 使用 if 条件隐藏

如果要 要一次性控制多个组件的展示与隐藏 , 可以使用 一个 标签将多个组件包装起来,并在 标签上 使用 wx:if 控制属性

<block wx:if="{{true}}">
	<view>1view>
	<view>2view>
block>

在实际中,block 标签并不会渲染到页面上,他只是起到一个临时包裹的作用

4.16 条件渲染-hidden

在小程序中,直接使用 hidden="{{控制条件}}" 也能控制 元素的显示与隐藏

<view hidden="{{ condition }}"> 条件 true 隐藏,false 显示view>
4.17 if 和 hidden 的区别
  • wx:if 以 动态创建 和 移除元素的方式,控制元素的展示与隐藏
  • hidden 以 切换样式的方式 ( display:none/block ) 控制元素的显示与隐藏
  • 频繁切换 建议使用 hidden
  • 控制条件比较复杂,建议用 wx:if 搭配 wx:elif wx:else
4.18 for 循环的基本用法
<view wx:for="{{arr1}}">
  索引时:{{index}}   , item 是 {{item}}
view>
4.19 手动指定索引和当前项的变量名
<view wx:for="{{arr1}}" wx:for-index="ind" wx:for-item="arritem">
  索引时:{{ind}}   , item 是 {{arritem}}
view>
4.20 指定 key 值 提高渲染效率
<view wx:for="{{arr1}}" wx:for-index="ind" wx:for-item="arritem" wx:key="ind">
  索引时:{{ind}}   , item 是 {{arritem}}
view>

wx:key 不需要{{ }} ,直接写 就可以

5、小程序进阶

5.1 了解什么是 wxss 及 和 css 之间的联系

wxss 对 css 进行了 扩充以及修改,以适应微信小程序的开发

  • rpx 尺寸单位
  • @import 样式导入
5.2 rpx

rpx 的实现原理 非常简单,鉴于不同设备屏幕的 大小不同,为了实现屏幕的自动适配,rpx 吧 所有设备的屏幕,在宽度上 等分为 750份,即当前屏幕的总宽度为 750rpx

  • 在 较小的设备上,1 rpx 所代表的宽度 较小
  • 在 较大的设备上,1 rpx 所代表的宽度较大
5.3 rpx 与 px 的单位换算

在 iPhone 6 上,屏幕宽度为 375px ,共有 750 个 物理像素,等分为 750rpx

750rpx = 375px = 750 物理像素

官方建议:开发小程序时,设计师可以用 iPhone6 作为 视觉稿的标签

在 iPhone6 状态下, 1rpx=0.5px ,1px = 2rpx

开发举例,在 iPhone 6 上 如果要绘制 宽 100px 高20px,换算成 rpx单位,宽高分别为200rpx和40rpx

5.4 @import 样式导入

使用 wxss 提供的 @import 语法,可以导入外联的样式表

@import 后 跟上 需要 导入的外联样式表的 相对路径 要用 分号 表示结束

5.5 全局样式

定义在 app.wxss 的样式, 叫做 全局样式,他会应用到 这个小程序内 所有的页面

5.6 句部样式

在 页面的 .wxss 文件写的 css 都是 句部样式,只会作用域当前页面

  • 当前局部样式 和 全局样式 冲突时,采用就近原则,句部样式会覆盖全局样式
  • 当局部样式的 权重大于或者等于 全局样式的权重的时候,才会覆盖全局的样式
5.7 常用的全局配置项以及小程序窗口的组成部分
  • pages 记录当前小程序所有页面的存放路径
  • window 全局设置小程序窗口的外观
  • tabBar 设置小程序底部的 tabBar效果
  • style 是否启用新版的组件样式

小程序的组成部分: 导航栏区域 背景区域(下拉才会显示) 主题区域

5.8 设置导航栏的标题
属性名 类型 默认值 说明
navigationBarTitleText String 字符串 导航栏标题文字内容
navigationBarBackgroundColor 16进制颜色 #000000 导航栏背景颜色
navigationBarTextStyle String white 导航栏标题颜色,black/white
backgroundColor 16进制 #ffffff 窗口的背景色
backgroundTextStyle String dark 下拉loading的样式 dark/light
enablePullDownRefresh boolean false 全局是否开启下拉刷新
onReachBottomDistance number 50 页面上拉触底事件触发时页面底部距离,单位px
5.9 设置导航栏背景色
    "navigationBarBackgroundColor": "#2b4b6b",
5.10 设置导航栏的标题颜色
5.11 全局下拉刷新的功能
    "enablePullDownRefresh": true
5.12 关于模拟器的问题说明

模拟器并不能100% 还原 手机的效果,具体要以手机预览为准

5.13 设置 下拉刷新的窗孔背景颜色
5.14 设置下拉刷新时 loading 的样式
5.15 设置上拉触底的距离

当我们 快 滚动到 页面最底部的时候,就要加载下一页的数据

    "onReachBottomDistance":80
# 默认 时 50 px  如果没有特殊需求,默认是不 修改这个的
5.16 tabBar

移动端常见的效果,用于实现多页面的快速切换

底部 tabbar 顶部 tabbar

  • tabbar 中 只能配置 最少2个 最多5个 tab 页签
  • 当渲染 顶部 tabbar ,不显示 icon 。只显示文本
  "tabBar": {
    "list": [{
      "pagePath": "pages/test/test",
      "text": "text"
    },{
      "pagePath": "pages/list/list",
      "text": "list"
    }]
  },
# 和 window 是  同一级的
4.17 6个组成部分
4.18 了解 tabbar 配置项
5.19 tabbar 案例
5.20 了解页面和全局配置的关系

app.json 可以全局配置 小程序 的 每个页面的窗口外观

每个页面的 .json 配置文件,就可以对 特定页面的 窗口外观

页面配置 会 覆盖掉 全局的页面配置

5.21 页面配置 常用的配置项

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6gjYOFHY-1620460593895)(第一章原生微信小程序.assets/image-20210417080619668.png)]

6、微信小程序数据请求和案例

6.1 小程序网络数据请求的限制
  1. 只能请求 HTTPS 类型 的接口
  2. 必须将 接口的域名 添加到信任列表中
6.2 配置 request 合法域名
  1. 登录到 微信小程序 后台 网页
  2. 找到 开发
  3. 找到开发管理
  4. 找到开发设置
  5. 找到 服务器域名
6.3 发起 get 请求
  // 发起 get 请求
  getInfo(){
    wx.request({
      url: 'https://www.escook.cn/api/get',
      method:'get',
      data:{
        name:'zs',
        age:20
      },
      success:(res)=>{
        console.log(res);
        
      }
    })
  },
6.4 发起 post 请求

改变 methods 的值,换成 post 即可

6.5 了解如何在页面刚刚加载的时候请求数据

找到 页面 .js 的 onload 钩子函数 就行

6.6 如何跳过 request 合法域名校验

我们可以在 详情 本地设置 里面 取消 请求接口的校验

6.7 关于跨域 和 Ajax 的说明

跨域 问题 只存在于基于浏览器的 web 开发中,由于小程序的宿主环境不是浏览器,而是微信客户端,所以小程序中不存在跨域的问题

Ajax 技术的核心 是依赖于 浏览器 的 XMLHttpRequest 这个对象,由于 小程序的 宿主环境 是 微信客户端,所以 小程序中 不能 叫做 发起Ajax 请求,而是叫做 发起网络数据请求

6.8 案例:本地生活
  • 导航栏
  • tabBar
  • 轮播图
  • 九宫格
  • 图片布局

去除 调试器 ,黄色 警告

在 个性化配置.json 文件中, setting 节点下 加入 “checkSiteMap”:false

6.9 设置导航栏
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#2b4b6b",
    "navigationBarTitleText": "本地生活",
    "navigationBarTextStyle":"white"
  },
    # app.json
6.10 配置 tabBar
  "tabBar": {
    "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"
      },
      {
        "pagePath": "pages/contact/contact",
        "text": "联系我们",
        "iconPath": "/images/tabs/contact.png",
        "selectedIconPath": "/images/tabs/contact-active.png"
      }
    ]
  },
6.11 获取轮播图的数据
  onLoad: function (options) {
    this.getSwiperList()
  },
  // 获取轮播图数据
  getSwiperList(){
    wx.request({
      url: 'https://www.escook.cn/slides',
      success:(res)=>{
        console.log(res);
        this.setData({
          swiper:res.data
        })
      }
    })
  },
6.12 渲染轮播图
6.13 获取九宫格数据
6.14 渲染
6.15 首页底部布局效果

7、微信小程序页面导航

7.1 学习目标
7.2 了解小程序中实现导航的两种方式
  • 声明式导航
  • 编程式导航

声明式,在页面上声明一个 navigator 标签

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

7.3 声明式导航-导航到 tabBar页面

在使用 navigator 组件跳转到指定的 tabBar 页面时,需要指定 url 属性 和 open-type 属性

  • url 要跳转到的 地址,必须以 / 开头
  • open-type 表示 跳转的方式,必须为,switchTab,因为我们是跳转到 tabbar 页面

<navigator url="/pages/message/message" open-type="switchTab">点击跳转navigator>
7.4 声明式导航-导航到非 tabBar页面
  • url 要跳转到的 地址,必须以 / 开头
  • open-type 表示 跳转的方式,必须为,navigate,因为我们是跳转到 非tabbar 页面
  • 为了简便,open-type 属性可以不写,也可以导航到 非tabBar页面
<navigator url="/pages/info/info" open-type="navigate">点击跳转到非tabBar页面navigator>
7.5 声明式导航-后退导航

如果我们需要后退到上一页面,或者是 多级页面,则需要指定 open-type 属性 和 delta 属性,其中

open-type 的值 必须是 navigateBack ,表示 后退

delta 的值 必须是 数字,表示后退的层级

<navigator  open-type="navigateBack" delta="1">后退一级navigator>

如果我们只需要 后退一个页面,则可以省略 delta

7.6 编程式导航-导航到 tabBar页面
<button bindtap="gotoMessage">惦记我跳转到 message 页面button>
  //  gotoMessage
  gotoMessage(){
    wx.switchTab({
      url: '/pages/message/message',
    })
  },
7.7 编程式导航-导航到非 tabBar页面

wx.navigateTo

7.8 编程式导航-实现后退导航效果

wx.navigateBack

7.9 导航传参-声明式导航传参

可以在 url 后谜案 拼接参数

  • 参数与路径之间使用 ? 分割
  • 键、值 用 = 相连
  • 不同参数用 & 分割
<navigator url="/pages/info/info?name=zs&age=20" open-type="navigate">点击跳转到非tabBar页面 传参navigator>
7.10 编程式 导航传参

wx.navigateTo

和上面一样,也可以 拼接

7.11 怎么接收页面传递来的参数呢
<navigator url="/pages/info/info?name=zs&age=20" open-type="navigate">点击跳转到非tabBar页面 传参navigator>
  onLoad: function (options) {
    console.log(options);//{name: "zs", age: "20"}
    
  },

8、微信小程序页面事件和上拉触底案例

8.1下拉刷新的定义

下拉刷新是移动端的专有名词,指的是通过手指在屏幕上的下拉滑动操作,从而 从新加载页面数据 的 行为

8.2 启用下拉刷新
  • 全局启用 在app.json 的window 节点中,将 enablePullDownRefresh的值为ture
  • 局部启用 在页面的 .json 文件中那个 将 enablePullDownRefresh的值为ture

实际开发中,推荐使用第二种,并不是所有页面都需要下拉刷新

8.3 配置下拉刷新窗口的样式
{
  "usingComponents": {},
  "enablePullDownRefresh": true,
  "backgroundColor": "#efefef",
  "backgroundTextStyle": "dark"
}
8.4 监听下拉刷新事件

我们可以通过 页面的 .js 文件中的 onPullDownRefresh 事件,监听 下拉刷新的操作

8.5 停止下拉刷新的效果

当我们处理完 下拉刷新后,下拉刷新的 loading 效果 会一直显示,不会主动消失,所以 需要我们 手动处理,在后面调用 wx.stopPullDownRefresh() 就可以了

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
    console.log('出发了下拉刷新');
    // 停止下拉刷新
    wx.stopPullDownRefresh()
    
  },
8.6 上拉触底 的定义

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

在移动端,分页 太丑了, 所以 采用 上拉触底进行 分页

8.7 监听页面的上拉触底的事件

前提是 页面的高度,足够长

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

这个时候一般 用 节流 处理 一下

8.8 上拉触底的距离

默认是 50,也可以在 页面 .json 自定义配置

  "onReachBottomDistance":150
8.9 上拉触底案例
  1. 定义获取随机颜色的方法
  2. 获取数据
  3. 渲染UI
  4. 在上拉触底的时候 获取随机颜色的方法
  5. 添加 loading 提示效果
  6. 对上拉触底进行节流处理
8.10 获取随机颜色的方法

在联系我们页面实现这个案例效果

  /**
   * 页面的初始数据
   */
  data: {
    colorList: [],
  },
  // 获取颜色
  getColors() {
    wx.request({
      url: 'https://www.escook.cn/api/color',
      success: ({
        data: res
      }) => {
        console.log(res);
        this.setData({
          colorList:[...this.data.colorList,...res.data]
        })
      }
    })
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.getColors()
  },
8.11 渲染UI结构梅花页面效果
<view wx:for="{{colorList}}" wx:key="index" class="num-item" style="background-color:rgba({{item}})"></view>
.num-item{
  border: 1px solid #efefef;
  border-radius: 8rpx;
  line-height: 200rpx;
  margin: 15px;
  text-align: center;
  text-shadow: 0rpx 0rpx 5rpx #fff;
  box-shadow: 1rpx 1rpx 6rpx #aaa;
  height: 200rpx;
}
8.12 上拉触底获取随机颜色
  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
    this.getColors()
  },
8.13 添加 loading 提示效果
 // 获取颜色
  getColors() {
    wx.showLoading({
      title: '数据加载中...',
    })
    wx.request({
      url: 'https://www.escook.cn/api/color',
      success: ({
        data: res
      }) => {
        console.log(res);
        this.setData({
          colorList:[...this.data.colorList,...res.data]
        })
      },
      // 因为我们要不论 是 失败还是成功 都要隐藏 loading
      complete:()=>{
        wx.hideLoading()
      }
    })
  },
8.14 介绍为什么要上拉触底进行 节流

在加载中,如果触底,也会 发起请求,这样太浪费性能了

8.15 如何实现 上拉触底 节流
  1. 在 data 中 定义 isloading 节流阀
  2. 在 getColors()方法中 修改 isloading 节流阀的值
  3. 在 onReachBottom 中判断节流阀的值,从而对数据请求进行节流控制
    false 表示 当前没有 进行任何 数据请求
    在 请求方法中,第一行,将 节流阀设置为 true
    在 网络请求 complete 回调函数中,将节流阀设置为 false
    如果 节流阀的值为true ,阻止发起请求
    如果 节流阀的值为false 则发起数据请求
8.16 自定义编译模式

当我们 编写 信息 页 的时候,编译后,是先进入首页,然后 我们在点击 进入 信息页

我们可以 设置 编译 旁边的 编译模式

9、微信小程序生命周期和wxs

9.1 什么是生命周期?

创建 => 运行 => 销毁 =>

9.2 小程序中 生命周期 的两个分类
  • 应用声明周期
  • 页面声明周期
9.3 什么是生命周期函数

是由小程序框架的内置函数,会伴随着生命周期 自动按次序执行
生命周期函数的作用:允许程序员在 特点的时间点,执行某些特定的操作。

9.4 声明周期函数的两个分类
9.5 应用的声明周期函数
App({
	// 小程序初始化完成时,执行此函数,全局只会触发一次,可以做一些初始化的工作
	onLaunch:function(options){
		// 一般对 小程序的 本地数据 进行操作
	},
	
	// 小程序启动,或者 从 后台进入前台显示 的时候触发
	onShow:function(options){},
	
	// 小程序从前台进入后台
	onHide:function(){}
})
9.6 页面的生命周期函数
Page({
	onLoad:function(options){
		// 监听页面加载,一个页面只调用一次
		// 用的最多
	},
	onShow:function(){
		// 监听页面显示
	},
	onReady:function(){
		// 页面初次渲染完成,一个页面只调用一次
		// // 用的最多
	},
	onHide:function(){
		// 页面隐藏
	},
	onUnload:function(){
		// 页面卸载,一个页面只调用一次
	}
})
9.7 wxs 定义

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

9.8 wxs 和 js 的关系
# 1、wxs 有自己的数据类型
#		number 数值类型,string 字符串类型、布尔类型、object 对象类型、function 函数类型、array 数组类型、date 日期类型、regexp 正则
# 2、wxs 不支持类似于 es6 及 以上的语法形式
# 	不支持:let const 解构赋值 展开运算符 箭头函数 对象属性简写等等
#   支持:var 普通 function 函数等 es5
# 3、wxs 遵循 CommonJS 规范
#		module 对象
#		require() 函数
#		module.exports 对象
9.9 内嵌 wxs 脚本

wxs 代码可以编写在 wxml 文件中的 标签内,就像 js 代码 可以编写在 html 文件中的 标签内一样

wxml 文件中 的每个 标签,必须提供 module 属性,用来指定当前 wxs 的模块名称,方便再 wxml 中 访问模块中的成员

<view>{{m1.toUpper(username)}}view>

<wxs module="m1">
	module.exports.toUpper = function(str){
		return str.toUpperCase()
	}
wxs>
9.10 定义外联的 wxs 脚本

wxs 代码还可以编写再 以 .wxs为后缀名的文件内 , 就像 JavaScript代码可以编写再 以 .js 后缀名的文件中一样

# 一般定义再 utils 文件夹内
// tools.wxs 文件
function toLower(str){
	return str.toLowerCase()
}

module.exports = {
	toLower:toLower
}
9.11 使用外联的 wxs 脚本
<view>{{m2.toLower(str)}}</view>
<wxs module="m2" src="../../utils/tool.wxs"></wxs>
# 1、必须 用 module 执行 模块的名称
# 2、src 用来指定 要引入的脚本的路径,且必须是 相对路径
9.12 了解 wxs 的 4个特点
  1. 与 js 不同。为了降低 wxs 的学习成本,wxs大量借鉴了 js
  2. wxs 不能作为组件的 事件回调。wxs典型应用场景就是过滤器,经常配和 Mustache 语法进行使用 这样是错误的,wxs 必须和 mustache 语法配和使用,wxs不能作为组件的事件回调
  3. 隔离性 ,wxs 不能调用 js 中定义的函数,wxs 不能调用小程序提供的API
  4. 性能好。在ios设备上,小程序内的 wxs 会比js 代码快 2~20倍,安卓设备上,基本无差异

10、本地生活综合案例(列表页面)

10.1 目标
  • 页面导航并传参
  • 上拉触底,加载下一页数据
  • 下拉刷新列表数据
10.2 打开项目
10.3 实现导航跳转并传参

<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>
# shoplist
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.setData({
      query: options
    })
    this.getShopList()
  },
10.4 动态设置商铺列表页面的标签内容
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    wx.setNavigationBarTitle({
      title: this.data.query.title
    })
  },
10.5 创建商品列表页面的编译模式
10.6 了解API接口并定义需要的数据节点
10.7 定义 getShopList 方法获取商品列表数据
wx.request({
      url: `https://www.escook.cn/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()
      }
    })
10.8 渲染UI结构
10.9 展示 loading 提示效果
10.10 上拉触底 请求下一页数据
  "onReachBottomDistance": 200,
  /**
   * 页面上拉触底事件的处理函数
   */
  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()
  },
10.11 对上拉触底事件进行节流控制

定义一个节流阀

10.12 演示并分析加载的问题
10.13 判断下一页是否还有数据
10.14 代码编写 判断下一页是否还有数据
10.15 开启下拉刷新
10.16 实现下拉刷新
10.17 解决下拉刷新不会关闭的问题

关闭下拉刷新 是一个 有可能需要的,有可能不需要的,我们可以给他传递一个回调函数,如果传递了这个函数,那就调用,没有就不调用

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

module.exports = {
  formatTime: formatTime
}
  <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>

11、微信小程序自定义组件和样式

11.1 学习目标
  1. 能够知道如何自定义小程序组件
  2. 能够知道小程序组件中 behaviors 的作用
  3. 能够知道如何安装和配置 vant-weapp 组件库
  4. 能够知道如何使用 Mobx 实现全局数据共享
  5. 能够知道如何堆小程序 的 API 进行 Promise 化
11.2 准备项目

用 mp-04 项目

11.3 创建自定义组件
  1. 在项目 跟目录中,创建 components 文件夹,在创建 test 文件夹
  2. 在新建的 components => test 文件上,鼠标右击,点击 “新建Component”
  3. 键入组件的名称之后回车,会自动生成组件对应的四个文件, .js .json .wxml .wxss

每个组件要放到单独的文件夹内,以便区分

11.4 局部引用自定义组件
// 要在那个页面 引用自定义组件,就在那个 页面的 .json 文件中写
{
  "usingComponents": {
    "my-test1":"/components/test1/test1"
  }
}

<!-- 使用 局部自定义组件 -->
<my-test1></my-test1>
11.5 全局引用自定义组件

在 app.json 全局配置文件中 全局引用组件

{
  "pages": [
    "pages/home/home",
    "pages/message/message",
    "pages/contact/contact"
  ],
  "window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#13A7A0",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle": "black"
  },
  "usingComponents":{
    "my-test2":"/components/test2/test2"
  }
}
<my-test2>my-test2>
11.6 全局组件VS局部组件
  • 某个组件多个页面经常用到 建议 全局
  • 某个组件单独页面经常用到 建议 局部
11.7 组件和页面的区别
  1. 组件的 .json 文件中 需要声明 “component:true
  2. 组件的 .js 文件中 调用的是 Component()函数
  3. 组件的 事件处理函数 需要定义到 methods 节点中
11.8 组件的样式隔离特性
  • 组件A 的样式 不会影响 组件C的样式
  • 组件A 的样式 不会影响 小程序页面的样式
  • 小程序页面的样式 也不会影响 组件A\C 的样式
11.9 组件样式隔离的注意点
  1. app.wxss 中 的全局样式 对组件无效
  2. 只有 class 选择器才会有隔离的效果,比如 ID 选择器、属性选择器、标签选择器不受样式隔离的影响

在组件和引用组件的页面中,建议使用class选择器,不要使用ID、属性、标签选择器

11.9 修改组件的样式隔离选项

默认情况下,自定义组件的样式 隔离特性 能够 防止组件内外样式互相干扰的问题,但有时候,我们希望外界能够控制组件内容的样式,可以这样设置

# 在组件的 .js 文件中 新增如何配置
Component({
	options:{
		"styleIsolation":'isolated'
	}
})

# 或者 在 组件 的 .json 文件中 新增如何配置
{
	"styleIsolation":'isolated'
}
可选值 默认值 描述
isolated 启用样式隔离,外面的class样式不会影响组件
apply-shared 页面 wxss样式将会影响到自定义组件,但自定义组件wxss 不会影响页面
shared 页面 wxss 样式 可以影响 自定义组件,自定义组件 的wxss 也会影响页面 和 其他 设置 了 apply-shared 或者 shared 的 自定义组件

12、自定义组件 数据、方法、属性

12.1 自定义组件的data 数据
  /**
   * 组件的初始数据
   */
  data: {
    count:0
  },
12.2 自定义组件的 methods 节点
  /**
   * 组件的初始数据
   */
  data: {
    count: 0
  },

  /**
   * 组件的方法列表
   */
  methods: {
    // 定义 自定义 组件的方法
    addCount() {
      this.setData({
        count: this.data.count + 1
      })
      this._showCount()
    },
    // 自定义方法 建议用 _ 开头
    _showCount() {
      wx.showToast({
        title: 'count是' + this.data.count,
        icon: 'none'
      })
    }
  }
<view>count的值是:{{count}}view>
<button bindtap="addCount">点我+1button>
12.3 properties 属性

在小程序组件中,properties 是组件的对外属性,用来接收外界传递到组件中的数据

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    max: {
      type: Number, // 定义父组件传递过来的参数类型必须是 数字
      value: 10 // 定义默认值
    }
    // 简化的声明方式 就是 max:Number
  },
)}


<my-test1 max="10"></my-test1>
12.4 通过父组件传递的值,控制自定义组件的数据
      if (this.data.count >= this.properties.max) return
12.5 data 和 properties 的区别

在小程序的组件中,properties 属性 和 data 数据的用法相同,他们都是可读可写的,只不过

  • data 更倾向于 存储组件的私有数据
  • properties 更倾向于 存储 外界传递到组件中的数据
12.6 使用 setData 数据 修改 properties的值

由于data 数据 和 properties 属性 在本质上没有任何区别,因此 properties 属性的值,也可以用于页面渲染,或者使用 setData 为 properties 中的属性 重新赋值

Component({
	properties:{
		max:Number
	},
	methods:{
		addCount(){
			this.setData({ max: this.properties.max +1 })
			// 使用 setData 修改 properties 
		}
	}
})
12.7 什么是数据监听及其语法格式

数据监听器 用于 监听和响应任何属性和数据字段的变化,从而执行特定的操作 它的作用类似于 vue 中的 watch 侦听器。在小程序组件中,数据监听器的基本语法如下

Component({
	observers:{
		'字段A,字段B':function(字段A的新值,字段B的新值){
			// 操作
		}
	}
})
12.8 数据监听器的基本用法
<view>{{n1}} +{{n2}} = {{sum}}view>
<button size="mini" bindtap="addN1">n1自增button>
<button size="mini" bindtap="addN2">n2自增button>
// components/test1/test1.js
Component({
  /**
   * 组件的初始数据
   */
  data: {
    count: 0,
    n1:0,
    n2:0,
    sum:0
  },

  /**
   * 组件的方法列表
   */
  methods: {
    // n1 自增
    addN1(){this.setData({n1:this.data.n1+1})},
    addN2(){this.setData({n2:this.data.n2+1})},
  },
  observers:{
    'n1,n2':function(n1,n2){
      this.setData({sum:n1+n2})
    }
  }
})
12.9 监听 对象 属性的变化
Component({
	observers:{
		'对象.属性A,对象.属性B':function(属性A的新值,属性B的新值){
			// 触发此监听器的 3 种 情况
			// 为属性A赋值		使用 setData 设置 this.data.对象.属性A 的时候触发
			// 为属性B赋值 	使用 setData 设置 this.data.对象.属性B 的时候触发
			// 直接为对象赋值 使用 setData 设置 this.data.对象 的时候触发
			
			// do something
		}
	}
})

13、微信小程序自定义组件 监听器的案例

13.1 案例效果

有个三个按钮,分别是 R、G、B,还有 一个 view 设置它的背景颜色,背景颜色 为 我们设置的 RGB ,当我们点击 RGB 的时候,他会有 自增加 的效果

新建 test3 自定义组件

13.2 渲染组件的 ui 结构
13.3 定义 button 的事件
  methods: {
    changeR() {
      this.setData({
        'rgb.r': this.data.rgb.r + 5 > 255 ? 255 : this.data.rgb.r + 5
      })
    },
  }
13.4 监听对象的某个属性的变化
  observers: {
    'rgb.r,rgb.g,rgb.b': function (r, g, b) {
      this.setData({
        fullColor: `${r},${g},${b}`
      })
    }
  }
13.5 监听对象的所有属性的变化

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

  observers: {
    // 'rgb.r,rgb.g,rgb.b': function (r, g, b) {      
    //   this.setData({
    //     fullColor: `${r},${g},${b}`
    //   })
    // }
    // 监听 rgb 对象的 所有属性的变化
    'rgb.**':function(obj){
      console.log(obj);//{r: 0, g: 0, b: 5}
      
      this.setData({
        fullColor:`${obj.r},${obj.g},${obj.b}`
      })
    }
  }
13.6 什么是纯数据字段

不用于页面 渲染 的 data 字段
某些 data 种的字段,既不会展示在页面上,也不会传递给其他组件,仅仅在当前组件内部使用,带有这种特性的 data 字段适合被设置为纯数据字段

好处 有利于提升页面更新的性能

13.7 纯数据字段 使用规则
Component({
	options:{
		// 指定所有 _ 开头的数据字段为纯数据字段
		pureDataPattern: /^_/
	},
	data:{
		a:true, // 普通数据字段
		_b:true // 纯 数据字段
	}
})
13.8 使用纯数据字段-改造数据监听器
_rgb

14、自定义组件的生命周期和插槽

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

created、attached、detached

attached 是 刚刚被放到 组件U I 结构中,还没有渲染

渲染完成以后会 执行 ready

14.2 组件主要的生命周期函数

1、组件实例 刚刚 被创建好的时候,created 生命周期函数会触发
此时不能调用 setData
通常在这个生命周期函数中,只应该用于给 组件的 this 添加一些自定义的属性字段

2、在组件 完全初始化完毕,进入页面节点树后,attached 生命周期函数触发
此时 this.data 已经被 初始化完毕
一般 都是在 这个生命周期 函数 中 请求数据

3、在组件 里开页面节点树以后,detached 生命周期函数会触发
退出一个页面时,会触发页面内每个自定义组件的 detached 生命周期函数
此时适合做一些清理性质的工作

14.3 lifetimes 节点

再新版的小程序中,自定义组件的生命周期 会 放在这个节点下

Component({
	// 推荐写法
	lifetimes:{
		attached(){},// 组件实例进入页面节点,初始化完成
		detached(){},// 组件实例被从页面节点树 移除 时执行
	}
})
14.4 组件所在页面的生命周期

有时候 自定义 组件的行为 依赖于 页面状态的变化,此时需要用到组件所在页面的生命周期

例如: 每当 触发 页面的 show 生命周期函数的 时候,我们希望重新 生成一个新的 随机的 RGB 颜色值

生命周期函数 参数 说明
show 组件所在的页面被展示的时候执行
hide 组件所在的页面被隐藏的时候执行
resize Object Size 组件所在的页面尺寸变化的时候执行
14.5 组件所在的页面生命周期-pageLifetimes节点
Component({
  pageLifetimes: {
    show: function () {}, // 页面展示
    hide: function () {}, // 页面隐藏
    resize: function (size) {} // 页面尺寸发生变化
  },
14.6 再组件所在页面的生命周期中 随机获取颜色
// components/test3/test3.js
Component({
  pageLifetimes: {
    show: function () {
      this._randomColor()
    }, // 页面展示
    hide: function () {}, // 页面隐藏
    resize: function (size) {} // 页面尺寸发生变化
  },
  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {
    rgb: {
      r: 0,
      g: 0,
      b: 0
    },
    fullColor: '0,0,0'
  },

  /**
   * 组件的方法列表
   */
  methods: {
    _randomColor(){
      this.setData({
        rgb:{
          r:Math.floor(Math.random()*256),
          g:Math.floor(Math.random()*256),
          b:Math.floor(Math.random()*256),
        }
      })
    },
    changeR() {
      this.setData({
        'rgb.r': this.data.rgb.r + 5 > 255 ? 255 : this.data.rgb.r + 5
      })
    },
    changeG() {
      this.setData({
        'rgb.g': this.data.rgb.g + 5 > 255 ? 255 : this.data.rgb.g + 5
      })
    },
    changeB() {
      this.setData({
        'rgb.b': this.data.rgb.b + 5 > 255 ? 255 : this.data.rgb.b + 5
      })
    }
  },
  observers: {
    // 'rgb.r,rgb.g,rgb.b': function (r, g, b) {      
    //   this.setData({
    //     fullColor: `${r},${g},${b}`
    //   })
    // }
    // 监听 rgb 对象的 所有属性的变化
    'rgb.**': function (obj) {
      console.log(obj);

      this.setData({
        fullColor: `${obj.r},${obj.g},${obj.b}`
      })
    }
  }
})
14.7 什么是插槽

再自定义组件的 wxml 结构中 可以提供 一个 节点

就是一个占位符

14.8 单个插槽
自定义 组件的 wxml
<slot>slot>
// 使用者
<my-test2>
  <view>内不</view>
</my-test2>
14.9 开启多个插槽
Component({
  options:{
    multipleSlots:true,// 启用多个插槽
    pureDataPattern:/^_/,// 纯数据字段
  },
)}
14.10 定义多个插槽
自定义组件
  <slot name="before">slot>
  <view>固定文本view>
  <slot name="after">slot>
引用自定义组件
<my-test2>
  <view slot="before">第一个view>
  <view slot="after">第22个view>
my-test2>

15、父子组件通信和 behaviors

15.1 了解父子组件之间通信的 3种 方式
  1. 属性绑定 不同传递 方法
  2. 事件绑定 可以传递任意数据
  3. 获取组件实例

父组件可以 使用 this.selectComponent() 获取子组件实例对象
这样就可以访问子组件的任意数据和方法

15.2 属性绑定
// 父组件的 data 节点
data:{
	count:0
}


// 父组件的 结构
<my-test3 count="{{count}}"></my-test3>
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    count:Number
  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {

  }
})

<view> {{count}} </view>
15.3 实现子组件的 count 自增加 1
    countAdd(){
      this.setData({
        count:this.properties.count + 1
      })
    }
15.4 了解事件绑定的 4个核心步骤

子向父
1.在 父组件 的 .js 种,定义一个函数,这个函数 即将通过自定义事件的形式,传递给子组件
2.在 父组件 的 wxml 中 通过自定义事件的形式,将步骤1 中定义的函数引用,传递给子组件
3.在 子组件 的 js 中,通过调用 this.triggerEvent(‘自定义事件名称’,{/*参数对象 */}) 将数据发送到父组件
4.在父组件的 js 中 通过 e.detail 获取到子组件传递过来的数据

15.5 代码实现

第一步

# 父组件的 .js
syncCount(){
  console.log()
}

第二步

父组件的 wxml

<my-test4 count="{{count}}" bind:sync="syncCount">my-test4>


<my-test4 count="{{count}}" bindsync="syncCount">my-test4>

第三步

# 子组件的 .js
    countAdd(){
      this.setData({
        count:this.properties.count + 1
      })
      // 触发自定义事件,数值给父组件
      this.triggerEvent('sync',{value:this.properties.count})
    }

第四步

# 父组件
  syncCount(e){
    console.log(e.detail.value)
  },
15.6 实现
15.7 使用 this.selectComponent() 获取组件实例

可在父组件里 调用 this.selectComponent(“id或者class选择器”),获取子组件的实例对象,从而直接访问子组件的任意数据和方法。
注意 调用的时候 需要传入一个选择器

<my-test4 count="{{count}}" bind:sync="syncCount" class="customA" id="cA">my-test4>
<button bindtap="getChild">button>

getchild(){
	
	const child = this.selectComponent(".customA")
	child.setData({ count : child.properties.count + 1 })
	child.addCount() 调用子组件的 addCount 方法
}
15.8 了解什么是 behaviors

是小程序中,用于实现组件间代码共享的特性,类似于 vue.js 的 mixins
每个behavior可以包含以组属性、数据、生命周期和方法,当组件引用它的时候,它的属性、数据、和方法会被合并到组件中

15.9 创建 behavior

调用 Behavior() 就可以了

module.exports = Behavior({
	// 属性节点
	properties:{},
	// 私有数据节点
	data:{username:'zs'},
	// 事件处理函数
	methods:{},
	// 其他节点
})
15.10 导入并使用 behavior

在组件中,使用 require() 方法 导入 需要的 behavior ,挂在后即可访问 behavior 中的数据和方法

// components/test4/test4.js
const myBehavior = require('../../behaviors/my-behavior')
Component({
  // 挂在 混入 
  behaviors: [myBehavior],
  /**
   * 组件的属性列表
   */
)}
15.11 了解behavior 中 所有可用的节点

最常用的是 properties data methods behaviors

可用的节点 类型 是否必填 描述
properties Object Map 同组件的属性
data Object 同组件的数据
methods Object 同自定义组件的方法
behaviors String Array 引入其他的 behavior
created
attached
ready
moved
detached
15.12 同名字段的覆盖规则
  1. 同名的 data ,如果是对象类型,则合并
  2. 同名的 data不是对象, 组件 > 父 behavior >

16、vant 小程序UI 组件库 和 API 的promise 化

16.1 导入需要用到的小程序项目

导入 mp_05

16.2 小程序中队npm 的支持 和限制
  1. 不支持依赖于 node.js 内置库的 包 比如 fs path
  2. 不支持依赖于 浏览器内置对象的包 比如 jquery
  3. 不至于依赖于 c++ 插件的包
16.3 了解什么是 vant Weapp

vant weapp 是 有赞前端团队 开源 的一套 小程序 UI 组件库,助力于开发者快速搭建小程序应用

16.4 安装 vant 组件库
  1. 通过 npm 安装,建议使用 @1.3.3
  2. 构建 npm 包
  3. 修改 app.json

npm init -y
教程

16.5 使用 vant 组件

看文档

16.6 vant定义和使用 css 变量
:root {
	--main-bg-color:brown;
}
element {
	background-color: var(--main-bg-color);
}
16.7 使用 css 变量定制 vant 的主题样式
/* 在 app.wxss中 */
page {
	/* 定制 */
	--button-danger-background-color:#c0000;
	--button-danger-border-color:#d6000;
}

为什么使用 page 节点?

因为有 作用域,小程序的 根节点 就是 page

怎么知道的 代码 这么写 ?

主题颜色配置文件

16.8 什么是小程序api 的 promise 化

默认情况下,小程序的 官方 提供的 异步 api 都是基于回调函数 实现的
代码的可读性、维护性差

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

16.9 安装并购建 miniprogram-api-promise 这个第三方的 npm 包

npm install --save [email protected]
每次 npm 安装完成 建议 都要 删除 miniprogram_npm 这个文件夹,重新构建 npm 才可以使用

16.10 三个步骤
//app.js
import {
  promisifyAll
} from 'miniprogram-api-promise'
const wxp = wx.p = {}
promisifyAll(wx, wxp)
16.11 调用
<vant-button type="danger" bindtap="getInfo">var按钮</vant-button>

# 在页面的 .js 文件中,定义 tap 事件处理程序
async getInfo(){
  const { data:res } = await wx.p.request({
    method:'get',
    url:'https://www.escook.cn/api/get',
    data:{name:'zs',age:20}
  })
	console.log(res)
}

17、微信小程序全局数据共享

17.1 什么是共享数据?

又叫做 状态 管理,是 为了解决组件之间数据共享 的问题
常见的全局数据共享方案有 vuex redux mobX

17.2 小程序 全局数据共享方案

可以使用 mobx-miniprogram 配和 mobx-miniprogram-bindings 实现全局数据共享
mobx-miniprogram 用来 创建 store 实例对象
mobx-miniprogram-bindings 用来把 Store 中的共享 数据 或者方法,绑定到组件或者 页面中 使用

17.3 安装

npm install --save [email protected] [email protected]
别忘了 删了文件,重新构建 npm

17.4 创建 Store 实例对象

在跟目录下,创建 store 文件夹,创建 store.js 文件

// 这个 文件,专门用来创建 store 的实例对象
import {
  observable
} from 'mobx-miniprogram'
export const store = observable({
  // 数据字段
  numA: 1,
  numB: 2
})
17.5 定义计算属性
// 这个 文件,专门用来创建 store 的实例对象
import {
  observable
} from 'mobx-miniprogram'
export const store = observable({
  // 数据字段
  numA: 1,
  numB: 2,
  // 计算属性
  // get 表示 只读,不能被赋值
  get sum(){
    return this.numA + this.numB
  }
})
17.6 定义actions 方法
// 这个 文件,专门用来创建 store 的实例对象
import {
  observable,
  action
} from 'mobx-miniprogram'
export const store = observable({
  // 数据字段
  numA: 1,
  numB: 2,
  // 计算属性
  // get 表示 只读,不能被赋值
  get sum() {
    return this.numA + this.numB
  },
  // actions 用来 修改 store 中的数据
  updateNum1: action(function (step) {
    this.numA = this.numA + step
  }),
  updateNum2: action(function (step) {
    this.numB = this.numB + step
  }),
})
17.7 了解 store 中的成员 绑定到 页面上的实现思路
17.8 实现 store 中的成员 绑定到 页面上
// pages/message/message.js

import {
  createStoreBindings
} from 'mobx-miniprogram-bindings'
import {
  store
} from '../../store/store'
Page({

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

  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.storeBindings = createStoreBindings(this, {
      // this 表示的 要 把 store 挂在到那个页面上
      // fields 表示要把那些属性  绑定到 页面上
      // actions 表示要把那些 修改 store 属性的方法 绑定到页面上
      store,
      fields: ['numA','numB','sum'],
      actions: ['updateNum1']
    })
  },

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

  },

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

  },

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

  },

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

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

  },

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

  },

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

  }
})
17.9 在页面上使用 store 的成员
  btnHdandler1(e){
    this.updateNum1(e.target.dataset.step)
  },
  btnHdandler2(e){
    this.updateNum1(e.target.dataset.step)
  },
<view>{{numA}} +{{numB}} = {{sum}}view>
<button bindtap="btnHdandler1" data-step="{{1}}">+1button>
<button bindtap="btnHdandler2" data-step="{{-1}}">-1button>
17.10 绑定到组件上
// components/numbers/numbers.js
import {
  storeBindingsBehavior
} from 'mobx-miniprogram-bindings'
import {
  store
} from '../../store/store'
Component({
  // 通过 storeBindingsBehavior 来实现自动绑定
  behaviors: [storeBindingsBehavior],
  storeBindings: {
    store, // 指定要绑定的 store
    fields: {
      // 指定要绑定的字段数据
      numA: () => store.numA, // 绑定字段的 第一种方式
      numB: (store) => store.numB, // 绑定字段的 第二种方式
      sum: 'sum' // 绑定字段的第三种方式 也是最常用的
    },
    actions: {
      // 指定要绑定的方法
      updateNum2: 'updateNum2'
    }
  },
  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {

  }
})
17.11 在组件中 使用 store 成员
<view>{{numA}} +{{numB}} = {{sum}}view>
<button bindtap="btnHdandler1" data-step="{{1}}">+1button>
<button bindtap="btnHdandler2" data-step="{{-1}}">-1button>
  methods: {
    btnHdandler1(e) {
      this.updateNum2(e.target.dataset.step)
    },
    btnHdandler2(e) {
      this.updateNum2(e.target.dataset.step)
    },
  }

18、分包

18.1 了解分包的概念及好处

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

  1. 可以优化小程序首次启动的下载时间
  2. 在多团队共同开发时,可以更好的 解耦协作
18.2 分包前后项目的构成

前 只有一个包
后 主包 一般 只包含当前 项目的 启动页面 和 tabbar 页面,以及所有分包都需要的一些公共资源

分包: 只包含和当前分包有关的页面和私有资源

18.3 分包的加载规则

1.小程序启动的时候,默认会下载主包 并 启动 主包 内页面
tabbar 页面 必须放到主包种
2.当用户进入 分包 某个页面的时候,客户端会把对应的分包下载下来,下载完成后在进行展示
非 tabBar 页面可以按照功能的不同,划分为不同的分包之后,按需下载

18.4 分包的体积限制
  • 整个小程序所有分包大小不超过 16MB (主包+所有分包)
  • 单个分包/主包大小不能超过 2M
18.5 如何配置分包
|——app.js
|——app.json
|——apo.wxss
|——pages // 主包的所有页面
	|——index
	|——logs

|——packageA //第一个包
	|——pages // 第一个分包的所有页面
		|——cat
		|——dog

|——packageB //第2个包
	|——pages // 第2个分包的所有页面
		|——apple
		|——banana

|——utils
# app.json subpackages 节点中声明分包的结构
{
  "pages":[
    // 主包的所有页面
  ],
  "subpackages":[
    // 它通过 subpackages 节点,声明分包的结构
    {
      "root":"packageA",// 第一个分包的根目录
      "pages":[
        // 当前分包下,页面的相对存放路径
        "pages/cat/cat",
        "pages/dog/dog"
      ]
    },
    {
      "root":"packageB",// 第2个分包的根目录
      "name":"pack2",// 分包的别名
      "pages":[
        // 当前分包下,页面的相对存放路径
        "pages/apple/apple",
        "pages/banana/banana"
      ]
    }
  ]
}
18.6 演示在项目中如何配置分包
18.7 设置分包的别名,并查看体积

在 root 下面 加一个 name 属性即可
查看分包的体积: 详情=> 基本信息 =>

18.8 小程序打包的缘则
  1. 小程序会按照 subpackages 的配置进行分包,subpackages 之外的目录将被打包到主包中
  2. 主要 也可以有自己的 pages 即最外层的pages 字段
  3. tabBar 必须打包在主包内
  4. 分包之间不能互相嵌套。。 不能再分包里面嵌套分配
18.9 使用分包-引用原则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3pOBXbW7-1620460593899)(第一章原生微信小程序.assets/image-20210418161428783.png)]

1.主包 无法引用 分包内的私有资源
2.分包之间 不能相互引用 私有资源
3.分包 可以引用 主包的公共资源

18.10 独立分包

独立分包本质上也是分包,只不过他比较特殊,可以独立于主包和其他分包而单独运行

独立分包不依赖于 主包
普通分包 依赖于 主包

18.11 了解独立分包的应用场景

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

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

一个小程序可以有多个独立分包

18.12 如何设置独立分包
|——app.js
|——app.json
|——apo.wxss
|——pages // 主包的所有页面
	|——index
	|——logs

|——moduleA //第一个独立分包
	|——pages // 第一个独立分包的所有页面
		|——cat
		|——dog

|——moduleB //第2个 独立分包
	|——pages // 第2个独立分包的所有页面
		|——apple
		|——banana

|——utils
# app.json subpackages 节点中声明分包的结构
{
  "pages":[
    // 主包的所有页面
  ],
  "subpackages":[
    // 它通过 subpackages 节点,声明分包的结构
    {
      "root":"moduleA",// 第一个独立分包的根目录
      "independent":true,  // 声明当前 moduleA为独立分包
      "pages":[
        // 当前分包下,页面的相对存放路径
        "pages/cat/cat",
        "pages/dog/dog"
      ]
    },
    {
      "root":"packageB",// 第2个分包的根目录
      "name":"pack2",// 分包的别名
      "pages":[
        // 当前分包下,页面的相对存放路径
        "pages/apple/apple",
        "pages/banana/banana"
      ]
    }
  ]
}
18.13 独立分包的引用原则

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

  1. 主包 无法引用 独立分包内的私有资源
  2. 独立分包之间, 不能相互引用 私有资源
  3. 独立分包和普通分包之间,不能相互引用 私有资源
  4. 独立分包中不能引用主包内的公共资源
18.14 分包预下载

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

18.15 配置分包的预下载
# app.json   preloadRule
{
	"preloadRule":{
	// 分包 预下载的规则
    "pages/contact/contact":{
      // 触发 分包 预下载 的页面路径
      // networ 表示再 指定的网络模式下进行预下载
      // 可选值为 all wifi   ,默认值 wifi
      "network":"all",
      // packages 表示 进入页面后,预下载那些分包
      // 可以 通过 root 或者 name 指定预下载那些分包
      "packages":["pkgA"]
    }
  }
}
18.16 分包预下载的限制

同一分包中的页面 享有 共同的预下载大小限额是 2M

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wll4SooA-1620460593901)(第一章原生微信小程序.assets/image-20210418163813369.png)]

19、自定义 tabbar

19.1 tabbar和数字 和 页面 的数字同步
  1. 自定义组件
  2. 数据共享
  3. 等等
19.2 自定义 tabbar

参考文档

19.3 再 app.json 声明自定义tabbar

1、在 app.json 中的 tabBar 项指定 custom 字段,同时其余 tabBar 相关配置也补充完整。所有 tab 页的 json 里需声明 usingComponents 项,也可以在 app.json 全局开启。

19.4 添加 tabbar 的代码文件

2、在根目录中,新建 custom-tab-bar 文件夹
新建 index 自定义组件,注意 直接 新建就行,不用再新建文件夹了

19.5 基于 vant 组件渲染基本的 tabbar 效果

1、注册组件

# app.json 或者 index.json
"usingComponents": {
  "van-tabbar": "@vant/weapp/tabbar/index",
  "van-tabbar-item": "@vant/weapp/tabbar-item/index"
}

2、拷贝 js wxml

19.6 自定义 tabbar 的图标和文本

看文档

19.7 循环渲染 tabbar 的item
19.8 渲染美化数字徽标的样式

https://vant-contrib.gitee.io/vant-weapp/#/custom-style

19.9 按需渲染 数字徽标

再消息 item 里面定义即可

19.10 把store 的sum 渲染为 数字徽标

如何监听 sum 可以利用 sum
https://developers.weixin.qq.com/miniprogram/dev/extended/utils/mobx.html

19.11 实现tab 切换
19.12 使用 全局数据共享 解决 tabbar 选中项 不准确 问题

把 active 放在 store 里面

19.13 修改选中项文本颜色

你可能感兴趣的:(前端学习笔记)