小程序的前期学习

小程序

1.小程序简介

小程序和普通网页区别

  • 运行环境不同

    网页    远行在 浏览器环境上
    小程序  运行在   微信环境
  • 开发模式不同

    网页的开发模式  浏览器+代码编辑器
    小程序有自己的一套标准的开发模式
      申请小程序账号
      安装小程序开发者工具
      创建和配置小程序项目
  • API不同

    因为运行环境不同,小程序没有办法调用BOM和Dom的API
    小程序可以调用微信环境提供的各种API
    地理定位
    扫码
    支付

    项目构成

    • 项目的基本组成结构

      ① pages    用来存放所有小程序的页面  *
      ② utils    用来存放工具性质的模块(例如:格式化时间的自定义模块) *
      ③ app.js   小程序项目的入口文件   *
      ④ app.json  小程序项目的全局配置文件  *
      ⑤ app.wxss  小程序项目的全局样式文件  *
      ⑥ project.config.json 项目的配置文件
      ⑦ sitemap.json   用来配置小程序及其页面是否允许被微信索引

      2.小程序有几个文件

      页面

      1. wxml 小程序页面结构

      2. wxss 小程序页面样式文件

      3. json 小程序页面配置

      4. js 逻辑结构

      全局

      1. app.wxss 全局样式文件

      2. app.json 全局配置文件

      3. app.js 入口文件

3.Json配置文件

JSON 配置文件的作用

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

的 .json 配置文件,可以对小程序项目进行不同级别的配置。

小程序项目中有 4 种 json 配置文件,分别是: 
​
① 项目根目录中的 app.json 配置文件 
② 项目根目录中的 project.config.json 配置文件 
③ 项目根目录中的 sitemap.json 配置文件 
④ 每个页面文件夹中的 .json 配置文件

app.json 文件

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

简单了解下这 4 个配置项的作用:
① pages:用来记录当前小程序所有页面的路径
② window:全局定义小程序所有页面的背景色、文字颜色等
③ style:全局定义小程序组件所使用的样式版本
④ sitemapLocation:用来指明 sitemap.json 的位置

project.config.json 文件

project.config.json 是项目配置文件,用来记录我们对小程序开发工具所做的个性化配置,例如:
 setting 中保存了编译相关的配置
 projectname 中保存的是项目名称
 appid 中保存的是小程序的账号 ID

页面的 .json 配置文件

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

app.json 的 window 中相同的配置项

新建小程序页面

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

修改项目首页

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

4.WXML

什么是 WXML

WXML(WeiXin Markup Language)是小程序框架设计的一套标签语言,用来构建小程序页面的结构,其作

用类似于网页开发中的 HTML。

WXML 和 HTML 的区别

① 标签名称不同 
   HTML (div, span, img, a) 
   WXML(view, text, image, navigator) 
② 属性节点不同 
   <a href="#">超链接</a>
   <navigator url="/pages/home/home"></navigator> 
③ 提供了类似于 Vue 中的模板语法 
   数据绑定 
   列表渲染 
   条件渲染

5.WXSS 样式

什么是 WXSS

WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式,类似于网页开发中的 CSS。

6.小程序wxss和css的区别

wxss背景图⽚只能引⼊外链,不能使⽤本地图⽚

⼩程序样式使⽤@import引⼊外链样式⽂件,地址为相对路径

尺⼨单位为 rpx , rpx 是响应式像素,可以根据屏幕宽度进⾏⾃适应

7.JS 逻辑交互

小程序中的 .js 文件

一个项目仅仅提供界面展示是不够的,在小程序中,我们通过 .js 文件来处理用户的操作。例如:响应用户的

点击、获取用户的位置等等。

小程序中 .js 文件的分类

小程序中的 JS 文件分为三大类,分别是:
① app.js
   是整个小程序项目的入口文件,通过调用 App() 函数来启动整个小程序
② 页面的 .js 文件
  是页面的入口文件,通过调用 Page() 函数来创建并运行页面
③ 普通的 .js 文件
  是普通的功能模块文件,用来封装公共的函数或属性供页面使用

8.组件

1. 小程序中组件的分类

小程序中给我们提供了很多的组件,开发者可以基于组件快速搭建出漂亮的页面结构。官方把小程序的组

件分为了 9 大类,分别是:

视图容器

基础内容

表单组件

导航组件

⑤ 媒体组件

⑥ map 地图组件

⑦ canvas 画布组件

⑧ 开放能力

⑨ 无障碍访问

常用的视图容器类组件

① view

普通视图区域 
​
类似于 HTML 中的 div,是一个块级元素 
​
常用来实现页面的布局效果 

② scroll-view

 可滚动的视图区域 
​
 常用来实现滚动列表效果 

③ swiper 和 swiper-item

轮播图容器组件 和 轮播图 item 组件

swiper 组件的常用属性

indicator-dots        boolean false                是否显示面板指示点
indicator-color        color     rgba(0, 0, 0, .3)  指示点颜色
indicator-active-color  color    #000000     当前选中的指示点颜色
autoplay        boolean false              是否自动切换
interval        number 5000                自动切换时间间隔
circular        boolean false              是否采用衔接滑动

常用的内容组件

① text

 文本组件 
 类似于 HTML 中的 span 标签,是一个行内元素 

② rich-text

富文本组件 
支持把 HTML 字符串渲染为 WXML 结构

其它常用组件

① button

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

② image

 图片组件 
 image 组件默认宽度约 300px、高度约 240px 

③ navigator(后面课程会专门讲解)

页面导航组件 
类似于 HTML 中的 a 链接

image 组件的 mode 属性

image 组件的 mode 属性用来指定图片的裁剪和缩放模式,常用的 mode 属性值如下:

scaleToFill  (默认值)缩放模式,不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素
aspectFit     缩放模式,保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。
aspectFill    缩放模式,保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。
widthFix      缩放模式,宽度不变,高度自动变化,保持原图宽高比不变
heightFix     缩放模式,高度不变,宽度自动变化,保持原图宽高比不变

9.API

小程序 API 概述

小程序中的 API 是由宿主环境提供的,通过这些丰富的小程序 API,开发者可以方便的调用微信提供的能力,

例如:获取用户信息、本地存储、支付功能等

小程序 API 的 3 大分类

小程序官方把 API 分为了如下 3 大类:

① 事件监听 API

特点:以 on 开头,用来监听某些事件的触发 
​
举例:wx.onWindowResize(function callback) 监听窗口尺寸变化的事件 

② 同步 API

特点1:以 Sync 结尾的 API 都是同步 API 
特点2:同步 API 的执行结果,可以通过函数返回值直接获取,如果执行出错会抛出异常 
举例:wx.setStorageSync('key', 'value') 向本地存储中写入内容 

③ 异步 API

 特点:类似于 jQuery 中的 $.ajax(options) 函数,需要通过 success、fail、complete 接收调用的结果 
 举例:wx.request() 发起网络数据请求,通过 success 回调函数接收数据

10.数据绑定

① 在 data 中定义数据

Page({
  data: {
     info:"hello ",
     list:[{msg:"122"},{msg:'333'}]
  },
})

② 在 WXML 中使用数据 Mustache 语法(双大括号)将

<text>{{info}}</text>

11.事件绑定

小程序常用的事件

tap    bindtap 或 bind:tap          手指触摸后马上离开,类似于 HTML 中的 click 事件
input   bindinput 或 bind:input     文本框的输入事件
change  bindchange 或 bind:change   状态改变时触发

事件对象的属性列表

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

type         String          事件类型
timeStamp    Integer    页面打开到触发事件所经过的毫秒数
target        Object          触发事件的组件的一些属性值集合
currentTarget Object    当前组件的一些属性值集合
detail      Object      额外的信息
touches     Array       触摸事件,当前停留在屏幕中的触摸点信息的数组
changedTouches  Array    触摸事件,当前变化的触摸点信息的数组

target 和 currentTarget 的区别

e.target 指向的是触发事件的源头组件,因此,e.target 是内部的按钮组件
e.currentTarget 指向的是当前正在触发事件的那个组件,因此,e.currentTarget 是当前的 view 组件

bindtap 的语法格式

  • 通过 bindtap,可以为组件绑定 tap 触摸事件

    <button type="primary" bindtap="btnHandler">按钮</button>
  • 在页面的 .js 文件中定义对应的事件处理函数,事件参数通过形参 event(一般简写成 e) 来接收

    btnHandler(e){
        console.log(e)
    }
  • 通过调用 this.setData(dataObject) 方法,可以给页面 data 中的数据重新赋值

    Page({
      data: {
         count:1
      },
      btnHandler(e){
        console.log(e)
        this.setData({
          count:this.data.count+1
        })
      }
     })

事件传参

  • 小程序中的事件传参比较特殊,不能在绑定事件的同时为事件处理函数传递参数

    <button type="primary" bindtap="btnHandler" data-info="{{123}}">按钮</button>
    ​
    info 会被解析为参数的名字
    数值 2 会被解析为参数的值
  • 在事件处理函数中,通过 event.target.dataset.参数名 即可获取到具体参数的值

     btnHandler(e){
        //  dataset是一个对象,包含了所有通过data-* 传递过来的参数项
        console.log(e.target.dataset)
        // 通过dataset可以访问到具体参数的值
        console.log(e.target.dataset.info)
      }

bindInput语法

在小程序中,通过 input 事件来响应文本框的输入事件

  • 通过 bindinput,可以为文本框绑定输入事件

    <input type="text" bindinput="btnHandler"/>
  • 在页面的 .js 文件中定义事件处理函数

    btnHandler(e){
        // e.detail.value  是变化过后,文本框最新的值
        console.log(e.detail.value)
    }

实现数据同步

12.条件渲染

wx:if

<!-- 在小程序中,使用 wx:if="{{condition}}" 来判断是否需要渲染该代码块 -->
<view wx:if="{{condition}}">True</view>

wx:elif 和 wx:else

<view wx:if="{{type===1}}">男</view>
<view wx:elif="{{type===2}}">女</view>
<view wx:else>保密</view>

结合 block 使用 wx:if

block 并不是一个组件,它只是一个包裹性质的容器,不会在页面中做任何渲染。

<block wx:if="{{true}}">
  <view>view1</view>
  <view>view2</view>
</block>

hidden

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

<view hidden="{{condition}}">条件为true隐藏,条件为false显示</view>

wx:if 与 hidden 的对比

① 运行方式不同
   wx:if 以动态创建和移除元素的方式,控制元素的展示与隐藏
   hidden 以切换样式的方式(display: none/block;),控制元素的显示与隐藏
② 使用建议
   频繁切换时,建议使用 hidden
   控制条件复杂时,建议使用 wx:if 搭配 wx:elif、wx:else 进行展示与隐藏的切换

13.循环渲染

wx:for

通过 wx:for 可以根据指定的数组,循环渲染重复的组件结构

当前循环项的索引用 index 表示;当前循环项用 item 表示

<view wx:for="{{array}}">
  索引是:{{index}} 当前项是{{item}}
</view>

手动指定索引和当前项的变量名

使用 wx:for-index 可以指定当前循环项的索引的变量名

使用 wx:for-item 可以指定当前项的变量名

<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
  索引是:{{idx}} 当前项是{{itemName}}
</view>

wx:key 的使用

类似于 Vue 列表渲染中的 :key,小程序在实现列表渲染时,也建议为渲染出来的列表项指定唯一的 key 值,

从而提高渲染的效率,

<view wx:for="{{array}}" wx:key="{{item.id}}">
  索引是:{{index}} 当前项是{{item}}
</view>

14.app.json全局配置文件

  1. pages:⽤于存放当前⼩程序的所有⻚⾯路径

  2. window:⼩程序所有⻚⾯的顶部背景颜⾊,⽂字颜⾊配置。

  3. tabBar:⼩程序底部的 Tab ,最少2个,最多5个

    15.页面配置

    页面配置文件的作用

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

    页面配置和全局配置的关系

    小程序中,app.json 中的 window 节点,可以全局配置小程序中每个页面的窗口表现。

    如果某些小程序页面想要拥有特殊的窗口表现,此时,“页面级别的 .json 配置文件”就可以实现这种需求。

    注意:当页面配置与全局配置冲突时,根据就近原则,最终的效果以页面配置为准

    16.小程序下拉刷新

    ⽅案 ⼀ :

    开启全局下拉刷新

    通过在 app.json 中, 将 "enablePullDownRefresh(哎耐薄 朴的瑞犯四)": true

    单组件下拉刷新

    通过在 组件 .json ,将 "enablePullDownRefresh": true

    ⽅案⼆:

    scroll-view 四扣楼:使⽤该滚动组件⾃定义刷新,通过 bindscrolltoupper 属性, 当滚动到顶部/左边会触发scrolltoupper事件,利⽤这个属性,实现下拉刷新功能。

    17.封装小程序的数据请求

    1. 在项目中新建http目录,在里面创建一个js文件封装get和post方法

    2. 在get方法中先用wx.showToast()提示数据加载,然后返回一个promise,在promise的回调函数中通过wx.request瑞快四特()来请求数据,在请求成功的回调中先关闭弹框,再调用promise的resolve方法,传递返回的数据

    3. export default返回封装的方法

    4. 在页面中通过import 导入方法,就可以直接使用了

18.⼩程序wx:if和 hidden的区别

<view wx:if="{{isShow}}">wx:if</view>
​
<view hidden="{{isShow}}">hidden</view>

wx:if 有更⾼的切换消耗。 hidden 有更⾼的初始渲染消耗。

使⽤

运⾏时条件变化使⽤wx: if,频繁切换使⽤hidden

19.网络请求

网络请求限制

出于安全考虑,小程序对数据接口的请求有要求:

  • 只能请求https类型的接口

  • 必须将接口的域名添加到信任列表中

配置合法域名

登录小程序公众平台--->开发管理---->开发设置--->服务器域名--->修改合法域名

发起GET请求

wx.request({ 
  url: 'example.php', //仅为示例,并非真实的接口地址
  method:'GET',
  data: {
    x: '',
    y: ''
  },
  header: {
    'content-type': 'application/json' // 默认值
  },
  success (res) {
    console.log(res.data)
  }
})

在页面刚加载时请求数据

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    this.getData()
  },
  getData(){
​
    wx.request({ 
      url: 'https://www.escook.cn/slides', //仅为示例,并非真实的接口地址
      method:'GET',
      header: {
        'content-type': 'application/json' // 默认值
      },
      success:(res)=>{
        // console.log(res.data)
        this.setData({
          banners:res.data
        })
      }
    })
    
​
   },

发起Post请求

wx.request({ 
  url: 'example.php', //仅为示例,并非真实的接口地址
  method:'POST',
  data: {
    x: '',
    y: ''
  },
  header: {
    'content-type': 'application/json' // 默认值
  },
  success (res) {
    console.log(res.data)
  }
})

跳过request合法域名校验

后端程序员仅仅提供了http协议的接口,需要不校验合法域名

微信开发者工具---->详情---->不校验合法域名

没有跨域

跨域只存在于浏览器的web开发中,小程序是运行在微信环境中,小程序不存在跨域问题

Ajax技术的核心是依赖于浏览器的 XMLHttpRequest 对象,小程序是运行在微信环境中没有这个对象,小程序不能叫做ajax请求 叫做发起网络数据请求

网络请求

网络请求限制

出于安全考虑,小程序对数据接口的请求有要求:

  • 只能请求https类型的接口

  • 必须将接口的域名添加到信任列表中

配置合法域名

登录小程序公众平台--->开发管理---->开发设置--->服务器域名--->修改合法域名

发起GET请求

wx.request({ 
  url: 'example.php', //仅为示例,并非真实的接口地址
  method:'GET',
  data: {
    x: '',
    y: ''
  },
  header: {
    'content-type': 'application/json' // 默认值
  },
  success (res) {
    console.log(res.data)
  }
})

在页面刚加载时请求数据

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    this.getData()
  },
  getData(){
​
    wx.request({ 
      url: 'https://www.escook.cn/slides', //仅为示例,并非真实的接口地址
      method:'GET',
      header: {
        'content-type': 'application/json' // 默认值
      },
      success:(res)=>{
        // console.log(res.data)
        this.setData({
          banners:res.data
        })
      }
    })
    
​
   },

发起Post请求

wx.request({ 
  url: 'example.php', //仅为示例,并非真实的接口地址
  method:'POST',
  data: {
    x: '',
    y: ''
  },
  header: {
    'content-type': 'application/json' // 默认值
  },
  success (res) {
    console.log(res.data)
  }
})

跳过request合法域名校验

后端程序员仅仅提供了http协议的接口,需要不校验合法域名

微信开发者工具---->详情---->不校验合法域名

没有跨域

跨域只存在于浏览器的web开发中,小程序是运行在微信环境中,小程序不存在跨域问题

Ajax技术的核心是依赖于浏览器的 XMLHttpRequest 对象,小程序是运行在微信环境中没有这个对象,小程序不能叫做ajax请求 叫做发起网络数据请求

页面导航

页面导航的两种方式

  • 声明式导航

    在页面上声明 <navigator>导航组件,url属性是导航地址

  • 编程式导航

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

声明式导航

导航到tabBar页面

tabBar页面是被配置为tabBar的页面

navigator组件,需要指定url属性和open-type属性

url: 跳转页面的地址 必须以 / 开头

open-type 跳转的方式 值为switchTab

<navigator url="/pages/home/home" open-type="switchTab">跳转到home</navigator>

导航到非tabBar页面

tabBar页面是被配置为tabBar的页面

navigator组件,需要指定url属性和open-type属性

url: 跳转页面的地址 必须以 / 开头

open-type 跳转的方式 值为navigate

<navigator url="/pages/cart/cart" open-type="navigate">cart</navigator>

导航到非tabBar页面时,open-type="navigate" 可以省略

后退导航

如果要后退到上一页面或多级页面,需要指定open-type和delta属性

open-type 的值必须是navigateBack ,表示要进行后退导航

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

<navigator open-type="navigateBack" delta="1">返回</navigator>

如果只是返回到上一页面,可以省略delta=“1”,因为默认值为1

传参

/pages/cart/cart?id=2&name=zs

  • 参数和路径直接使用?分割

  • 参数名和参数值之间用 =

  • 不同参数用 & 分割

<navigator url="/pages/cart/cart?id=2&name=zs" open-type="navigate">跳转到home</navigator>
<navigator url="/pages/cart/cart?id={{num}}&name=zs" open-type="navigate">跳转到home</navigator>

编程式导航

导航到tabBar

wx.switchTab({
      url: '/pages/home/home',
})

导航到非tabBar

wx.navigateTo({
      url: '/pages/cart/cart',
    })

后退导航

wx.navigateBack({
      delta:1
})

传参

wx.switchTab({
      url: '/pages/cart/cart?id=23&name=zs',
    })
​
wx.switchTab({
url: `/pages/cart/cart?id=${this.data.num}&name=zs`,
})

在onLoad中接收参数

  onLoad(options) {
    console.log(options,"options")  //{id: "23", name: "zs"}
  },

页面事件

下拉刷新

手指在屏幕上下拉滑动操作,重新加载页面数据

步骤

1启动下拉刷新

  • 全局开启下拉刷新

    在app.json 的window节点中,enablePullDownRefresh:true

  • 局部开启下拉刷新

    在页面的.json文件中,enablePullDownRefresh:true

2配置下拉刷新窗口样式

backgroundTextStyle:dark 下拉的loading的效果

backgroundColor 窗口的背景颜色

3监听下拉刷新事件

通过onPullDownRefresh()监听用户下拉事件

4停止下拉刷新动作

 // 数据重置成功,调用该函数,关闭下拉刷新的效果
    wx.stopPullDownRefresh()

上拉加载

手指在屏幕上上拉滑动操作,加载更多数据

步骤

配置上拉触底距离

  • 全局配置 onReachBottomDistance:60

  • 局部配置 onReachBottomDistance :60

监听页面的上拉触底事件

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

小程序生命周期函数

小程序生命周期

  1. onLaunch() 小程序初始化的生命周期钩子函数

  2. onShow () 小程序启动或者从后台切换到前台

  3. onHide() 切换到后台

页面生命周期

  1. onLoad 监听页面加载 只执行一次

  2. onReady 监听页面初次渲染完成 只执行一次

  3. onShow 监听页面显示 可以执行n次

  4. onHide 监听页面隐藏 可以执行n次

  5. onUnload 生命周期回调—监听页面卸载

wxs

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

WXML中无法调用页面的js中定义的函数,但是wxml可以调用wxs中定义的函数,所以wxs的应用场景就是过滤器

wxs和JavaScript的关系

wxs类似于JavaScript,但是wxs和JavaScript是完全不同的两种语言

  • wxs有自己的数据类型

    number数值类型 string 字符串 boolean布尔 function 函数 array 数组 date日期 object 对象 regexp 正则

  • wxs不支持ES6以上的语法

    不支持let const 解构赋值 展开运算符就 箭头函数 对象属性的简写

    支持var定义的遍历 普通的function

  • wxs遵循CommJS规范

    module 对象

    module.exports

    require 导入

内嵌wxs脚本

WXS 代码可以编写在 wxml 文件中的 <wxs> 标签内

<wxs>标签必须提供module属性,用来指定当前wxs的模块名称,wxml中访问模块中的成员

<view>{{m1.toUpper(username)}}</view>
<view>{{username}}</view>
​
​
​
<wxs module="m1">
  module.exports.toUpper=function(str){
    return str.toUpperCase()
  }
 
</wxs>

外联的wxs

.wxs 为后缀名的文件内。

utils/tool.wxs

var toFix=function (val){
  return val.toFixed(2)
}
​
module.exports.toFix = toFix
<view>{{tools.toFix(price)}}</view>
​
​
​
<wxs src="../../utils/tool.wxs"  module="tools" />

wxs

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

WXML中无法调用页面的js中定义的函数,但是wxml可以调用wxs中定义的函数,所以wxs的应用场景就是过滤器

wxs和JavaScript的关系

wxs类似于JavaScript,但是wxs和JavaScript是完全不同的两种语言

  • wxs有自己的数据类型

    number数值类型 string 字符串 boolean布尔 function 函数 array 数组 date日期 object 对象 regexp 正则

  • wxs不支持ES6以上的语法

    不支持let const 解构赋值 展开运算符就 箭头函数 对象属性的简写

    支持var定义的遍历 普通的function

  • wxs遵循CommJS规范

    module 对象

    module.exports

    require 导入

内嵌wxs脚本

WXS 代码可以编写在 wxml 文件中的 <wxs> 标签内

<wxs>标签必须提供module属性,用来指定当前wxs的模块名称,wxml中访问模块中的成员

<view>{{m1.toUpper(username)}}</view>
<view>{{username}}</view>
​
​
​
<wxs module="m1">
  module.exports.toUpper=function(str){
    return str.toUpperCase()
  }
 
</wxs>

外联的wxs

.wxs 为后缀名的文件内。

utils/tool.wxs

var toFix=function (val){
  return val.toFixed(2)
}
​
module.exports.toFix = toFix
<view>{{tools.toFix(price)}}</view>
​
​
​
<wxs src="../../utils/tool.wxs"  module="tools" />

组件

复用性强

创建组件

  • 项目根目录下,新建components

  • components---->新建文件夹 mycom--->myCom文件夹右击 新建component 输入组件的名称回车自动生成4个文件

引入组件

全局引入

组件可以在每个小程序页面中使用

多个页面都会用到该组件使用 全局

app.json

注册组件

"usingComponents":{
     "my-com":"/components/myCom/myCom"
},

使用组件

<my-com></my-com>

局部引入

组件只能在当前被引入的页面中使用

页面的json中

{
  "usingComponents": {
    "my-text":"/components/myText/myTest"
  }
}

使用组件

<my-text></my-text>

组件和页面的区别

都是由4个文件组成 .js .json .wxml .wxss

组件

组件的json文件中需要声明 "component": true,

组件的 .js文件中调用Component() 函数

组件的事件处理函数需要定义到methods中

页面

页面的 .js中调用 Page()方法

样式

一般情况下,自定义组件的样式只对当前组件生效,不会影响到组件之外的ui结构

  • 组件myCom的样式不会影响组件myText

  • 组件myCom的样式不会影响小程序页面

  • 小程序页面的样式不会影响组件myCom和组件myText

app.wxss中的全局样式对组件无效

只有class选择器有样式隔离的影响,id,标签,属性选择器不受样式隔离的影响

建议使用class选择器

data数据

定义组件的数据

  data: {
    count:0
  },

methods方法

事件处理函数 和自定义方法定义到methods中

methods: {
    addCount(){
      this.setData({
        count:this.data.count+1
      })
      this.showCount()
    },
    showCount(){
      wx.showToast({
        title: 'count值为'+this.data.count,
      })
    }
​
  }

properties

父传子

properties是组件的对外属性,用来接收外界传递给组件中的数据

//父组件
<my-com tit="2202A大哥们好" num="{{20}}"></my-com>
 properties: {
    tit:{
      type:String,   //数据类型
      value:'hello'   //默认值
    },
    num:Number
  },

properties和data的区别

  • 小程序的组件中,properties属性和data属性用法相同,都是可读可写的但是:

    • data更倾向于存储组件的私有数据

    • properties 存储外界传递给组件的私有数据

methods: {
    addCount(){
      console.log(this.data)   //{count: 0, tit: "2202A大哥们好", num: 20}
      console.log(this.properties)
      // 本质上一样的,都是可读可写的
      console.log(this.properties===this.data)   //true
    }
 }
​

使用setData修改properties的值

this.setData({
          num:this.properties.num+2
})

数据监听器

监听和响应任何属性和数据字段的变化,从而执行特定的操作

Component({
    observers:{
        '字段A,字段B':function(字段A的新值,字段B的新值){
            //代码
        }
    }
})

组件生命周期

组件全部生命周期

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

组件主要生命周期

在小程序组件中,最重要的生命周期函数有3个,分别是created,attached,detached

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

  • 不能调用setData

  • 用于给组件的this添加一些自定义的属性字段

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

  • this.data已被初始化完毕

  • 初始化工作,比如发请求

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

  • 退出一个页面时,会触发页面内每个自定义组件的detached生命周期函数

  • 清理性质的工作

lifetimes节点

Component({
  lifetimes: {
    attached: function() {
      // 在组件实例进入页面节点树时执行
    },
    detached: function() {
      // 在组件实例被从页面节点树移除时执行
    },
  },
  // 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
  attached: function() {
    // 在组件实例进入页面节点树时执行
  },
  detached: function() {
    // 在组件实例被从页面节点树移除时执行
  },
  // ...
})

组件所在页面的生命周期

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

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

生命周期函数参数描述
show组件所在页面被展示时执行
hide组件所在页面被隐藏时执行
resizeObject Size组件所在页面尺寸变化时执行
Component({
  pageLifetimes: {
    show: function() {
      // 页面被展示
    },
    hide: function() {
      // 页面被隐藏
    },
    resize: function(size) {
      // 页面尺寸变化
    }
  }
})

页面展示的时候,重新生成一个随机的RGB颜色值

Component({
 pageLifetimes:{
    show(){
      this._randomColor()
    }
  },
  methods:{
    _randomColor(){
      this.setData({
        _rgb:{
          r:Math.floor(Math.random()*256),
          g:Math.floor(Math.random()*256),
          b:Math.floor(Math.random()*256)
        }
      })
    }
  }
})

插槽

什么是插槽

组件的wxml中可以提供一个<slot>节点,用于承载组件引用时提供的子节点。

传递单个slot

需要使用多 slot 时,可以在组件 js 中声明启用。

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

组件

<text>components/myTest/myTest.wxml</text>
<view>hello</view>
​
<slot name="one"></slot>
<view>good</view>
<slot name="two"></slot>

页面

<my-test>
  <view slot="one"> 
    <text>123</text>
  </view>
  <view slot="two"> 
    <text>345</text>
  </view>
</my-test>

父子组件通信

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

① 属性绑定

  • 用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容的数据

② 事件绑定

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

③ 获取组件实例

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

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

小程序组件通信

  1. 父传子

    1. 在子组件标签绑定属性 传递要传输的变量

    2. 在子组件中用properties来接收数据 可以直接使用

    3. 修改本组件的properties数据使用this.setData()

  2. 子传父

    1. 在子组件标签上定义一个事件,绑定要执行的方法

    2. 在子组件中通过 this.triggerEvent来触发自定义事件

    3. 父组件中通过事件对象e来接收传递的数据

  3. 、获取其他组件数据

    this.selectComponent色来可特肯破嫩特(".类名") 就获取到组件的数据

npm

js脚本语言,不能单独运行,嵌套在html中使用,在浏览器中运行

浏览器有js引擎,解析js代码的,逐行解析

ECMAScript,BOM,DOM

node

让js运行在服务端的开发环境

node使用的js的语法 ECMAScript 有自己的api ,fs,http,path

模块化开发

一个js文件就是一个模块 每个模块之间是相互独立的 互不影响

模块中定义的内容 必须暴露出去

使用模块 必须引入

module.exports={} require 该导入导出遵循COmmonJS规范,只能应用于服务端

export default import 该导入导出是遵循ES6规范,可以用在前端也可以用在服务端

node的模块

系统模块

按照完node后就自动有的模块 fs,path,http

自定义模块

自己定义的模块

第三方模块

别人写的模块

npm 这个地方可以查询有哪些第三方模块

https://www.npmjs.com/  网站上搜索自己所需要的包
https://registry.npmjs.org/  服务器上下载自己需要的包

怎么下载第三方模块

包管理工具 npm cnpm

yarn

下载

npm install --global yarn
​
yarn --version

使用方法 | Yarn 中文文档

小程序中对npm的支持

小程序一级开始支持npm按照第三方包,可以提高小程序的开发效率

  • 不支持nodeJS内置的包

  • 不支持浏览器内置对象的包

  • 不支持c++插件的包

原生小程序中使用vant

  • npm安装(@1.3.3)

npm i @vant/weapp@1.3.3
  • 去掉app.json 中的"style":"v2"

  • 修改 project.config.json

    {
      ...
      "setting": {
        ...
        "packNpmManually": true,
        "packNpmRelationList": [
          {
            "packageJsonPath": "./package.json",
            "miniprogramNpmDistDir": "./"
          }
        ]
      }
    }
  • 构建npm

  • 把nodemodules中的@vant拿到项目目录中

  • 引入组件 app.json

    "usingComponents": {
      "van-button": "@vant/weapp/dist/button/index"
    }

    全局数据共享

    全局数据共享(又叫做:状态管理)是为了解决组件之间数据共享的问题。开发中常用的全局数据共享方案有:Vuex、Redux、MobX 等。而我们微信小程序常用的全局共享方案是:MobX

    使用

    在小程序中,可使用 mobx-miniprogram 配合 mobx-miniprogram-bindings 实现全局数据共享。其中:

    mobx-miniprogram 用来 创建 Store 实例对象 mobx-miniprogram-bindings 用来 把 Store 中的共享数据或方法 , 绑定到组件或页面中使用

    安装Mobx相关的包

    npm i --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1

    mobx相关的包安装完后,删除mini-program-npm ,重新构建npm(工具---构建npm)

    创建store实例

    根目录下新建store/index.js

    import {observable,action} from 'mobx-miniprogram'
    ​
    ​
    // 创建store实例
    export const store = observable({
      // 定义共享数据  数据字段
      numA:1,
      numB:1,
      // 计算属性
      get sum(){
        return this.numA+this.numB
      },
      // actions 方法  用来修改state中的数据
      updateNuma:action(function(n){
        this.numA+=n
      }),
      updateNumb:action(function(n){
        this.numB+=n
      })
    })

    把store中的成员绑定到页面中

    使用store的手工绑定方式 应用于页面或者组件, 使用createStoreBindings 创建绑定,会返回一个清理函数的对象用于取消绑定

    在页面的onUnload(组件detached) 调用清理函数,否则会导致内存泄露

    页面的wxml

    <view>
    {{ numA}}+{{numB}}={{sum}}
    </view>
    <button data-n="{{4}}" bindtap="handClick">numA</button>

    页面的js文件

    import {createStoreBindings}  from 'mobx-miniprogram-bindings'
    import {store}  from '../../store'
    Page({
        handClick(e){
        this.updateNuma(e.target.dataset.n)
      },
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad(options) {
        // 返回一个清理函数的对象用于取消绑定
      this.storeBinds=createStoreBindings(this,{
          // 绑定store实例  指定要绑定的store
          store,
          // fields:['numA','numB','sum'],   //数组形式  把store中的数据拿来
          // fields:{                        //映射形式
          //    a:'numA',   //this.data.a=store.numA   
          //    b:'numB'    //this.data.b=store.numB
          // },
          // 函数形式
          fields:{
            numA:()=>store.numA,
            numB:()=>store.numB,
            sum:'sum'
          },
          actions:['updateNuma','updateNumb']
        })
      },
      
       onUnload() {
        // 调用清理函数  否则将造成内容泄露
        this.handClick.destroyStoreBindings()
      },
    })

    behavior

    behavior绑定适用于Component构造器,使用storeBindingsBehavior和storeBindings定义数据段

    语法

    import {storeBindingsBehavior} from 'mobx-miniprogram-bindings'
    Component({
        behaviors:[storeBindingsBehavior],
        storeBindings:{
            //配置项
            store,
            fields:['numA','numB'],
            actions:{
               buttonTap:'updateNuma'
            }
        }
    })

    组件的wxml

    <view>{{numA}}+{{numB}}={{sum}}</view>
    <button data-n="{{5}}" bindtap="handClick">numA</button>

    组件的js

    // components/myNumber/myNumber.js
    ​
    import {storeBindingsBehavior} from 'mobx-miniprogram-bindings'
    import {store} from '../../store'
    Component({
      behaviors:[storeBindingsBehavior],
      storeBindings:{
        // 配置项
        store,
        fields:['numA','numB','sum'],
        actions:['updateNuma']
      },
      methods: {
        handClick(e){
          console.log(123)
          this.updateNuma(e.target.dataset.n)
        }
      }
    })
    ​

    behaviors

  • behaviors 是用于组件间代码共享的特性

    分包

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

    好处:

    优化小程序首次启动的下载时间

    分包后项目构成

    分包后小程序由1个主包和多个分包组成

    • 主包:一般只包含项目的启动页面或Tabbar页面

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

    分包体积限制

    • 整个小程序所有包大小不超过16M(主包+分包)

    • 单个分包/主包大小不能超过2M

    app.json中声明分包的结构

    //声明分包的结构
    "subPackages": [
        {
           "root":"packageA",   //第一个分包的根目录
           "pages": [   //分包下所有页面的存放路径
             "pages/detail/detail"
           ]
        },
        {
          "root":"packageB",
          "pages": [
            "pages/goods/goods"
          ]
       }
      ],

    自定义tabBar

    根目录下自定义组件新建custom-tab-bar/index

    把点击的active定义为共享的数据

    store.js

    // 创建store实例  
    export  const store = observable({
      // 定义共享数据  数据字段
      activeTabBarIndex:0,   //点击的下标
    ​
      updateActiveIndex:action(function(index){
        this.activeTabBarIndex = index
      })
    })

    wxml

    <van-tabbar active="{{ active }}" bind:change="onChange">
      <van-tabbar-item  info="{{item.info?item.info:''}}" wx:for="{{list}}" wx:key="index">
      <image slot="icon" src="{{item.iconPath}}" style="width: 25px; height: 25px;"  mode="aspectFit"></image>
      <image slot="icon-active" src="{{item.selectedIconPath}}" style="width: 25px; height: 25px;"  mode="aspectFit"></image>
      {{item.text}}
      </van-tabbar-item>
    </van-tabbar>

    js

    import {storeBindingsBehavior} from  "mobx-miniprogram-bindings"
    import {store} from '../store'
    ​
    Component({
    ​
      behaviors:[storeBindingsBehavior],
      storeBindings:{
        store,
        fields:{
          sum:'sum',
          active:'activeTabBarIndex'
        },
        actions:{
          updateActive:"updateActiveIndex"
        }
      },
       
      observers:{
        'sum':function(val){
          this.setData({
            'list[1].info':val
          })
        }
      },
    ​
      /**
       * 组件的初始数据
       */
      data: {
       
        "list": [
            {
              "pagePath": "/pages/home/home",
              "text": "首页",
              "iconPath": "/images/tabs/home.png",
              "selectedIconPath": "/images/tabs/home-active.png"
            },
            {
              "pagePath": "/pages/message/message",
              "text": "消息",
              "iconPath": "/images/tabs/message.png",
              "selectedIconPath": "/images/tabs/message-active.png",
              "info":1
            },
            {
              "pagePath": "/pages/contact/contact",
              "text": "联系我们",
              "iconPath": "/images/tabs/contact.png",
              "selectedIconPath": "/images/tabs/contact-active.png"
            },
            {
              "pagePath": "/pages/contact/contact",
              "text": "联系我们",
              "iconPath": "/images/tabs/contact.png",
              "selectedIconPath": "/images/tabs/contact-active.png"
            }
        ]
      },
    ​
      /**
       * 组件的方法列表
       */
      methods: {
        onChange(event) {
          // event.detail 的值为当前选中项的索引
          // this.setData({ active: event.detail });
          this.updateActive(event.detail)
          wx.switchTab({
            url: this.data.list[event.detail].pagePath,
          })
          
        },
      }
    })
    ​

    配置信息

    • app.json 中的 tabBar 项指定 custom 字段,同时其余 tabBar 相关配置也补充完整。

    • 所有 tab 页的 json 里需声明 usingComponents 项,也可以在 app.json 全局开启

      "tabBar":{
          "custom":true,
          "list":[]
      }

      小程序的双向绑定和vue哪里不一样

      ⼩程序直接使⽤ this.data.key = value 是不能更新到视图中的。必须使⽤ this.setData来更新值。

bindtap和catchtap

都是点击事件,bindtap不能阻止冒泡,catchtap能阻止冒泡

小程序路由函数

  1. wx.redirectTo() 关闭当前页面,跳转到非tabbar页面。

  2. wx.navigateTo() 保留当前页面,跳转到非tabbar页面。

  3. wx.navigateBack() 关闭当前页面 通过 getCurrentPages卡瑞特()

    获取前的⻚⾯栈,定需要返回⼏层

  4. wx.switchTab() 关闭所有的非tabbar页面 跳转到tabbar页面

  5. wx.relaunch瑞拉吃() 关闭所有页面 跳转到某一页面

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值