小程序入门

437 阅读15分钟

01节 简介

小程序与普通网页的区别

1.线程

  • 网页开发是单线程的,js线程和渲染线程是互斥的。
  • 小程序有一条js逻辑线程和多条渲染线程两种线程。 2.DOM
  • 网页开发可以操作DOM。
  • 小程序中不能操作DOM。 3.运行环境
  • 网页是在PC 端和移动端的浏览器上运行
  • 小程序是在android、iOS、小程序开发者工具上运行

小程序的特色

用户:

  • 触手可及:可以通过扫描二维码、搜索、朋友的分享等方式打开。
  • 体验度优秀:小程序使得服务提供者的触达能力变得更强。 开发者:
  • 加载速度快
  • 渲染速度快
  • 开发速度快(云能力、运维能力和数据汇总能力)
  • 用户资源丰富

小程序的建立步骤

  1. 申请AppID
  2. 安装开发者工具
  3. 新建项目

02节 小程序代码组成

知识点
  1. JSON 配置
  2. WXML 模板
  3. WXSS 样式
  4. js 脚本 先粗略的阅读微信开发文档,用到的时候内容在仔细阅读
JSON 是什么

JSON 是一种数据格式,并不是编程语言,在小程序中,JSON扮演的静态配置的角色。 常见的json 配置文件有3种:

  • 小程序配置 app.json:做全局配置
  • 页面配置 page.json:对小程序具体页面的配置
  • 工具配置 project.config.json:对开发者工具的个性化配置,如域名校验、代码上传时自动压缩等
JSON 语法
  • JSON文件都是被包裹在一个大括号{} 中
  • JSON 中无法使用注释
  • 键名需要双引号” ” 包裹
  • 键值之间有冒号 : 分隔
  • 键值对之间用逗号 , 分隔
  • JSON的值只能是以下几种数据格式:
    • 数字,包含浮点数和整数
    • 字符串,需要包裹在双引号中
    • Bool值,true 或者 false
    • 数组,需要包裹在方括号中 []
    • 对象,需要包裹在大括号中 {}
    • Null
WXML 模板是什么

WXML 全称是 WeiXin Markup Language 微信标记语言,结合小程序的基础组件、事件系统,可以构建出页面的结构。
创建WXML 文件的方法:在app.json 中的“pages/index/index” 上新增一行 “pages/wxml/index” ,便会自动创建WXML 文件。
组件 <view></view>, <image></image>, <button></button>

组件

框架为开发者提供了一系列基础组件,开发者可以通过组合这些基础组件进行快速开发。

  • 组件是视图层的基本组成单元。
  • 组件自带一些功能与微信风格一致的样式。
  • 一个组件通常包括 开始标签 和 结束标签,属性 用来修饰这个组件,内容 在两个标签之内。 <button></button>
    type 按钮的样式类型
    open-type 微信开放能力
    contact 对话
    微信对话开放平台
    客服
数据绑定

WXML 通过 {{ 变量名 }} 来映射js里的 data 数据。
变量名是大小写敏感的,也就是说 {{name}} 和 {{NAME}} 是两个不同的变量。
没有被定义的变量的或者是被设置为 undefined 的变量不会被同步到 wxml 中。
<text id="{{id}}">{{msg}}</text>

data: {
    id:1,
    msg:'hello world’
},

{{}} 中的语法逻辑

{{}} 具有两种功能:动态渲染、逻辑运算。
{{}} 中除了变量名,还可以放置数字、字符串,并且做一些逻辑运算。
常见的逻辑运算的语法:

  • 算数运算
  • 字符串拼接
  • 三元运算
WXML 中的条件逻辑

在WXML 里有一套if、elif、else 组合。
就比如下面的例子:如果我附近有海底捞,选择火锅;否则如果有肯德基,就选择汉堡;否则,就回家做饭。

 <text wx:if="{{name==='海底捞'}}">……</text>
  <text wx:elif="{{name==='肯德基'}}">……</text>
  <text wx:else>……</text>

<block>可以一次性判断多个组件标签。

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

列表渲染

WXML 使用wx:for 渲染列表,默认数组的当前项的变量名为item,下标名为index。

<view wx:for="{{food}}" wx:key="id">
  <text>{{item.name}}</text>
</view>
food:[{id:1,name:'西红柿鸡蛋面'},{id:2,name:'香菜蛋花汤'},{id:3,name:'白菜炖粉条'}]

列表渲染-唯一标志符
  1. wx:key 是列表中每一个项目的唯一的标识符。
    这个标志符可以提高wxml 动态渲染的效率。比如列表数据中的某一项数据发生改变时,微信会根据唯一标志符,找找到wxml 列表中与此条数据对应的项目,然后只对此项目进行渲染。 这和vue、react 里的diff 算法是一个原理。 wx:key 是列表中每一个项目的唯一的标识符。 这个标志符可以提高wxml 动态渲染的效率。比如列表数据中的某一项数据发生改变时,微信会根据唯一标志符,找找到wxml 列表中与此条数据对应的项目,然后只对此项目进行渲染。 这和vue、react 里的diff 算法是一个原理。
  2. wx:key 的赋值方式:
  • 列表项目的属性, <view wx:for="{{objectArray}}" wx:key=“attr" > {{……}} </view>
  • 列表项目自身,如 <view wx:for="{{numberArray}}" wx:key="*this" > {{……}} </view>
模板

wxml 中的重复性元素,可以制作成模板,从而方便批量修改。

<!-- template 模板需要设置name -->
<template name="hotel">
  <text>{{name}}:</text>
  <text wx:for="{{food}}" wx:key="id">{{index?'、':''}}{{item.name}}</text>
</template>
<!-- 使用模板时,is 指定其使用的模板,data 指定模板数据 -->
<template is=“hotel” data=“{{name:'呷哺',food}}"></template>  

共同属性

所有wxml 标签都支持的属性称之为共同属性

image.png

wxss 是什么

WXSS(WeiXin Style Sheets)是小程序的样式语言,用于描述WXML的组件的视觉效果。WXSS 就相当于网页里的css
rpx自配
参考微信官方文档 developers.weixin.qq.com/miniprogram…

wxss和css 不一样的地方
  • wxss拥有相对的尺寸单位rpx,一个单位的rpx 是手机宽度的1/750
  • 外联样式可用@import 导入
  • background-image 里的图片为网络图片时,其图片所在网络的域名要经过微信许可。
  • position 为absolute 的元素,需要position 为fixed 的容器。(这是由小程序的文档流中不存在window、document对象导致的)

WeUI.wxss

  • WeUI 是一套与微信原生视觉体验一致的基础样式库
  • WeUI 由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一。
  • WeUI 包含button、cell、dialog、progress、toast、article、actionsheet、icon等各式原生组件的样式。
npm init -y
npm install weui-miniprogram

初次使用npm需要在“工具”里构建npm;

作用域

小程序的作用域同 NodeJS 比较相似。
在一个文件中声明的变量和函数只在该文件中有效。
因此,在不同的文件中可以声明相同名字的变量和函数,不会互相影响。

模块化

es6 中模块化语法可以应用于小程序中。
A.js 中建立A 模块


export default class A{
	constructor(name){
		this.name = name
	}
}

在index.js 中引入A 模块

import A from './A.js'
Page({
	data: {
		fruit:new A('苹果')
	},
})

03篇 宿主环境

前言

宿主环境是微信客户端给小程序提供的一种环境 。
宿主指的就是微信客户端,也就是官方API里的wx 对象。

宿主环境的作用是什么?
宿主环境会把我们写的各种文件整合到一起,进行解析,然后在微信APP 里显示出我们所看到的样子。 宿主环境可以为小程序提供微信客户端的能力,比如微信扫码,这是普通网页不具备的。

image.png

App

这里说的App 是宿主环境提供的一个 App() 构造器,用于注册一个程序App。

  • App() 构造器必须写在项目根目录的app.js里。如:App({…})
  • App实例是单例对象,也是一个全局对象,就像网页里的window一样。
  • 在其他JS脚本中可以使用宿主环境提供的 getApp() 方法来获取App 实例。利用getApp() 我们可以将数据写入全局,或者从全局读取数据。 如:
const app = getApp()
app.globalData.motto=‘好好学习’
点开微信小程序的一瞬间,微信客户端做了些什么

image.png

小程序的后台状态和前台状态
  • 后台状态:用户点击小程序右上角关闭按钮,或手机的home 键时,会离开小程序,但小程序并不会被销毁,而是进入后台状态。此时,APP构造器参数里的onHide 方法会被调用。
  • 前台状态:用户再次小程序时,微信用户端会唤醒后台状态的微信小程序,微信小程序就进入了前台状态,onShow 方法会被调用。

注意:App的生命周期是由用户操作主动触发的,开发者不能在代码里主动调用

页面构造器Page()

页面的js 里的所有代码都是写在Page()构造器里的。 Page构造器接受一个Object参数,在Object中可以绑定数据,监听页面事件。

Page({
  data: { text: "This is page data." },
  onLoad: function(options) { },
  onReady: function() { },
  onShow: function() { },
  onHide: function() { },
  onUnload: function() { },
  onPullDownRefresh: function() { },
  onReachBottom: function() { },
  onShareAppMessage: function () { },
  onPageScroll: function() { }
})
页面的生命周期

页面的生命周期首先要考虑三个事件:

  1. 页面初次加载时:onLoad,在页面没被销毁之前只会触发1次。
  2. 页面显示时:onShow ,从别的页面返回到当前页面时,都会被调用。
  3. 页面初次渲染完成时:onReady,在页面没被销毁前只会触发1次,在逻辑层可以和视图层进行交互。 页面显示后,随着用户的操作,还会触发其它的事件:
  • 页面不可见时:onHide,wx.navigateTo切换到其他页面、底部tab切换时触发。
  • 返回到其它页时:onUnload,wx.redirectTo或wx.navigateBack使当前页面会被微信客户端销毁回收时触发。
页面的用户行为
  • 下拉刷新 onPullDownRefresh:监听用户下拉刷新事件,需要在全局或具体页面的json 文件中配置enablePullDownRefresh为true。
  • 上拉触底 onReachBottom:监听用户上拉触底事件。可以在app.json的window选项中或页面配置page.json中设置触发距离onReachBottomDistance。在触发距离内滑动期间,本事件只会被触发一次。
  • 页面滚动 onPageScroll:监听用户滑动页面事件,参数为 Object,包含 scrollTop 字段,表示页面在垂直方向已滚动的距离(单位px)。
  • 用户转发 onShareAppMessage:只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮,在用户点击转发按钮的时候会调用,此事件需要return一个Object,包含title和path两个字段,用于自定义转发内容
页面数据的注意事项
  • 用数据驱动视图渲染要用this.setData(),而不要用this.data,这不仅无法驱动视图,还会造成数据不一致。
  • 由于setData是两个线程间的通信,为了提高性能,每次设置的数据不应超过1024KB 。
  • 不要把data中的任意一项的value设为undefined,否则可能会有引起一些不可预料的bug。
页面跳转

页面跳转的方式有很多种:

  • 在app.json 中用tabBar 属性设置跳转方式
  • 在wxml 页使用导航组件 <navigator> 跳转页面
<view class="btn-area">
  <navigator url="/page/navigate/navigate?title=navigate" hover-class="navigator-hover">跳转到新页面</navigator>
  <navigator url="../../redirect/redirect/redirect?title=redirect" open-type="redirect" hover-class="other-navigator-hover">在当前页打开</navigator>
  <navigator url="/page/index/index" open-type="switchTab" hover-class="other-navigator-hover">切换 Tab</navigator>
  <navigator target="miniProgram" open-type="navigate" app-id="" path="" extra-data="" version="release">打开绑定的小程序</navigator>
</view>
  • 在js 中用路由API跳转
运行js时要留心异步事件

小程序只有一个JSCode 线程,页面有多个。
小程序切换页面时,小程序的逻辑层依旧运行在同一个JsCore线程中。
页面使用了setTimeout或者setInterval的定时器后,跳转到其他页面时,这些定时器并没有被清除,需要开发者自己在页面离开的时候进行清理。

自定义组件

自定义组件的方法:

  1. 在主项目下建立components 文件夹,在其中建立floatball 文件夹,在此文件夹上右击“新建 Component”,这样就可以建立出json、wxml、wxss、js 四个文件。
  2. 组件的json中设置 "component": true
  3. 组件的wxml、wxss可以正常写。
  4. 组件的js中的properties 可以接受父组件属性。
  5. 父组件在调用子组件时要在其json 文件中设置usingComponents,如:
  "usingComponents": {
    "floatball":"/components/floatball/floatball"
  }
父子组件的数据传递
  1. 父组件向子组件传递数据:属性
  2. 子组件向父组件传递数据:事件在父组件调用子组件时,为其绑定事件, 父组件 wxml:
    `<floatball text="helloWorld" bind:tapBall="tapBall"> 点击这个按钮将触发“myevent”事件

`

子组件 js:This.triggerEvent("函数名称","参数","是否冒泡")

Component({
  properties: {},
  methods: {
    tapBall: function(){
      var myEventDetail = {} // detail对象,提供给事件监听函数
      var myEventOption = {} // 触发事件的选项
      this.triggerEvent('tapBall', myEventDetail, myEventOption)
    }
  }
})

建议onClickBall 的属性名和属性值都写成一样,免得把“在父组件中使用属性值,在子组件中触发属性名”记混了。

插槽
  1. 匿名插槽
<!-- 组件模板 -->
<view class="wrapper">
  <view>这里是组件的内部节点</view>
  <slot></slot>
</view>
<!-- 引用组件的页面模板 -->
<view>
  <component-tag-name>
    <!-- 这部分内容将被放置在组件 <slot> 的位置上 -->
    <view>这里是插入到组件slot中的内容</view>
  </component-tag-name>
</view>

2.具名插槽以及多插槽


Component({
  options: {
    multipleSlots: true // 在组件定义时的选项中启用多slot支持
  },
  properties: { /* ... */ },
  methods: { /* ... */ }
})
<!-- 组件模板 -->
<view class="wrapper">
  <slot name="before"></slot>
  <view>这里是组件的内部细节</view>
  <slot name="after"></slot>
</view>
<!-- 引用组件的页面模板 -->
<view>
  <component-tag-name>
    <!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 -->
    <view slot="before">这里是插入到组件slot name="before"中的内容</view>
    <!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 -->
    <view slot="after">这里是插入到组件slot name="after"中的内容</view>
  </component-tag-name>
</view>

04篇 应用场景

知识点
  • 开发流程
  • 界面常见的交互反馈
  • 发起https 网络通信
  • 微信登录
  • 本地数据缓存
  • 设备能力
开发流程

在开发前,首先要有原型图和UI视觉图。
我们开发者要做的,就是基于UI视觉图和原型图的交互逻辑开发小程序。
我们可以按照以下三步走:

  1. WXML+WXSS还原设计稿。
  2. 按照页面交互,梳理出每个页面的data部分,填充WXML的模板语法。
  3. 完成JS逻辑部分。
交互反馈

用户在小程序上进行交互的时候,某些操作可能比较耗时,需要我们予以及时的反馈,去舒缓用户等待的不良情绪,这样的反馈就是交互反馈。

常见的交互反馈有:

  • 触摸反馈 wx.showloading
  • Toast和模态对话框 wx.showToast wx.showModal wx.showActionSheet
  • 界面滚动
触摸反馈

通常页面会摆放一些button按钮或者view区域,用户触摸按钮之后会给按钮换个颜色。

  • 用户触摸后的样式设置可用通过组件的hover-class属性实现,如: 如果按钮是要加载数据的,按钮要显示一个loading的状态。
  • 按钮loading 状态的显示,可以通过<button> 组件的loading 属性实现:

image.png

Toast 提示

在某个操作成功之后,我们希望提示用户这次操作成功,并且不打断用户接下来的操作。这就需要使用弹出式提示Toast,Toast提示默认1.5秒后自动消失。更多

 // 显示Toast
    wx.showToast({ 
      title: '已发送',
      icon: 'success',
      duration: 1500
    })
    // 隐藏Toast
    wx.hideToast()

模态框

在做错误提示的时候,Toast 是不合适的,因为错误提示需要明确告知用户具体原因,因此不适合一闪而过的Toast。 错误提示需要使用模态框,模态框可以让用户明确知晓自己的操作结果,同时附带下一步操作的指引。更多

wx.showModal({
      title: '标题',
      content: '告知当前状态,信息和解决方法',
      confirmText: '主操作',
      cancelText: '次要操作',
      success: function(res) {
        if (res.confirm) {
          console.log('用户点击主操作')
        } else if (res.cancel) {
          console.log('用户点击次要操作')
        }
      }
    })

image.png

界面滚动

往往手机屏幕是承载不了所有信息的,所以就有了界面滚动。
常见的界面滚动有:下拉刷新、上拉加载。
下拉刷新:用户下拉整个界面时,可以刷新当前页面。
上拉加载:用户上拉整个界面,触底时,加载更多信息。这种交互操作叫为上拉触底。
注:scroll-view 滚动视图组件,提供了提供了丰富的滚动回调触发事件,可以实现界面中某一区域的滚动。

HTTPS网络通信
  1. wx.request() 的作用:往服务器传递数据,从服务器拉取信息。
  2. request() :
  • get请求:通过url传递参数,如 url:'test.com/getinfo?id=…'
  • post 请求:通过data传递参数,如:data: { id:1, version:'1.0.0’ }, 3.建议使用post 传递数据,因为url 的最大长度是1024字节,url上的参数需要拼接到字符串里,参数的值还要urlEncode。
    4.开发中的小程序的request 请求可以任意写,而正式版的小程序则必须遵循以下条件:
  • 遵循https 协议。
  • 在管理平台注册了。
微信登录

微信登录面对的问题:

  • 怎么获取用户在微信的信息
  • 怎么获取小程序用户的唯一身份标志 我们要用openid 来判断用户的唯一性。
openid 的获取方法
  1. wx.login() 方法可以获取微信登录凭证code
  2. 使用code 可以向微信服务器换取微信用户的唯一识别标志openid
  • 微信服务器提供的接口地址: api.weixin.qq.com/sns/jscode2…
  • AppId和AppSecret 是为了确保用code换openid的人是当前小程序的开发者

wx.getUserProfile(); 可以获取用户头像,昵称,性别,地区等信息 AppId 是公开信息,泄露AppId不会带来安全风险 AppSecret 是小程序秘钥,不能泄露,如果发现泄露需要到小程序管理平台进行重置。

本地数据缓存的概念

本地数据缓存:就是将小程序的数据存储在当前设备硬盘上。 本地数据缓存的作用:

  • 存储用户在小程序上产生的操作,在用户关闭小程序重新打开时可以恢复之前的状态。
  • 缓存一些服务端非实时的数据,从而提高小程序获取数据的速度。
写入缓存
// 异步写入
wx.setStorage({
  key:"key",
  data:"value1"
  success: function() {
    console.log('写入value1成功')
  },
  fail: function() {
    console.log('写入value1发生错误')
  }
})
// 同步写入
try{
  wx.setStorageSync('key', 'value2')
  console.log('写入value2成功')
}catch (e) {
  console.log('写入value2发生错误')
}

设备能力

小程序的宿主环境提供了很多的操作设备的能力,可以让我们提高开发效率,增强用户体验。
常见的设备能力: