小程序基础入门

小程序基础入门

一、课程介绍

image-20210906125844402

二、本章任务

  • 了解小程序的概念以及优势和劣势

  • 掌握小程序的申请和创建流程

  • 掌握小程序的基本模板语法

  • 掌握小程序代码组成

  • 了解小程序的渲染模型

  • 掌握小程序事件的使用

三、本章目标

  • 了解小程序是什么,以及小程序的优势和劣势

  • 能够申请并且创建小程序

  • 能够独立完成小程序界面的搭建和开发

  • 实现Todo List的功能

四、知识点

1. 小程序介绍

小程序是什么?

  • 小程序是一种新的开放能力,开发者可以快速地开发一个小程序。小程序可以在微信内被便捷地获取和传播,同时具有出色的使用体验。

  • 任何一个普通的开发者,经过简单的学习和练习后,都可以轻松地完成一个小程序的开发和发布。

小程序的发展史

  • 早年,随着微信越来越流行,微信逐渐成为移动互联网中一个主要的入口,越来越多的人会通过微信来分享和浏览网站。

  • 微信基于WebView实现了前端界面的渲染,为了丰富微信中H5页面的功能,微信提供了JS-SDK,开放了拍摄、录音、语音识别、二维码、地图、支付、分享、卡券等几十个API。给所有的 Web 开发者打开了一扇全新的窗户,让所有开发者都可以使用到微信的原生能力,去完成一些之前做不到或者难以做到的事情了。

  • JS-SDK 解决了移动网页能力不足的问题,通过暴露微信的接口使得 Web 开发者能够拥有更多的能力,然而在更多的能力之外,JS-SDK 的模式并没有解决使用移动网页遇到的体验不良的问题。

    • 用户在访问网页的时候,在浏览器开始显示之前都会有一个的白屏过程,在移动端,受限于设备性能和网络速度,白屏会更加明显。

    • 除了白屏,影响 Web 体验的问题还有缺少操作的反馈,主要表现在两个方面:页面切换的生硬和点击的迟滞感。

  • 为了提高用户体验和使用的流畅度,微信研发设计并且推出了微信小程序。

微信小程序的优势和劣势

优势

  • 微信助理,容易推广。在微信中,小程序拥有众多入口,例如附近的小程序、小程序码、分享、发现-小程序等五十多个的入口。这些入口有助于企业更好的获取流量,从而进行转化、变现。

  • 使用便捷。用户在使用小程序时,只需要轻轻点一下就可以使用,更加符合用户对使用方便、快捷的需求,所以小程序的用户数量不断增加。

  • 体验良好,有接近原生app的体验。在微信生态里,小程序在功能和体验上是可以秒杀掉 H5 页面的,H5 页面经常出现卡顿、延时、加载慢、权限不足等原因,而这些问题在小程序里都不会出现。

  • 成本更低,从开发成本到运营推广成本,小程序的花费仅为APP的十分之一,无论是对创业者还是传统商家来说都是一大优势。

不足

  • 单个包大小限制为2M,这导致无法开发大型的应用,采用分包最大是16M(这个值一直在变化,以官网为准)。

  • 需要像app一样审核上架,这点相对于H5的发布要麻烦一些。

  • 处处受微信限制。例如不能直接分享到朋友圈,涉及到积分,或者虚拟交易的时候,小程序也是不允许的。

如何学习微信小程序

  • 借助官方文档学习。 微信小程序有非常完善的官方文档,可以在官方文档上查到我们需要的所有东西。

https://developers.weixin.qq.com/miniprogram/dev/framework/

https://developers.weixin.qq.com/ebook?action=get_post_info&docid=0008aeea9a8978ab0086a685851c0a

  • 可以通过社区进行学习,社区提供了很多优质的资源,可以加快小程序的开发效率,提升小程序的开发体验。

https://github.com/justjavac/awesome-wechat-weapp

2. 小程序的申请和创建流程

账号的申请

开发小程序首先要进行小程序的账号申请。

https://mp.weixin.qq.com/wxopen/waregister?action=step1&token=&lang=zh_CN

下载开发工具

这里大家可以从官方网站下载最新版的开发工具。因为这个开发工具一直在更新,所以建议大家直接从官网下载。

https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

获取AppId

登录后台管理系统获取AppId。

image-20210906125928650

https://mp.weixin.qq.com/

创建项目

image-20210906125941278

image-20210906125947132

3. 项目的目录结构

  • pages:

    • wxml: 编写小程序界面结构的地方

    • wxss: 编写小程序样式的地方

    • json:编写界面配置的地方

    • js:编写界面逻辑的地方

  • utils: 编写工具类的地方

  • app.js:创建程序实例的位置

  • app.json: 编写全局配置地方

  • app.wxss: 编写全局样式的地方

  • project.config.json: 项目的配置文件

  • sitemap.json:配置哪些页面可以被检索到

4. 小程序常用配置

https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html

配置导航窗口

https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#window

配置页面

一般情况下我们会给每个页面创建一个文件夹,所以我们首先在pages下创建一个文件夹。

小程序直接给我们提供了创建页面的功能,右键这个文件夹,点击创建新建Page即可直接生成页面所需的文件。

生成文件之后,所有的页面都需要在app.json的pages属性中声明之后,才可以访问,小程序会默认先加载pages属性中第一个页面。如果开发过程如果我们需要调试别的页面,我们可以添加一个新的编译模式。

image-20210906130123495

配置tabbar

https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#tabBar

在移动端经常会涉及到tabbar的使用,小程序直接给我们提供了配置tabbar的方法。

这里需要注意的是,tabbar的图标不能是线上的地址,需要提前准备好放到项目里,一般情况下,这些静态资源可以放在assets文件夹下。这些图标大家可以从阿里矢量图标库中进行下载https://www.iconfont.cn/

"tabBar": {

"list": [{

"pagePath": "pages/index/index",

"text": "首页",

"iconPath": "assets/icons/index.png",

"selectedIconPath": "assets/icons/index-active.png"

},{

"pagePath": "pages/my/index",

"text": "我的",

"iconPath": "assets/icons/wode.png",

"selectedIconPath": "assets/icons/wode-active.png"

}]

},

总结

小程序中的配置还有很多,大家也不用全部记住,需要的时候在查就可以了,大家需要掌握的是如何查阅文档。

5. 小程序模板语法WXML

WXML 全称是 WeiXin Markup Language,是小程序框架设计的一套标签语言,结合小程序的基础组件、事件系统,可以构建出页面的结构。

标签的使用

在小程序中没有H5提供的那些标签了,这里我们需要使用小程序给我们提供的组件。小程序给我们提供的标签很多,这里我们就介绍几个常用的,剩下的大家可以结合文档使用。

view标签是我们开发过程中最常用的标签了,这个就相当于Html中的div。

text标签也是我们开发中常用的,这个相当于Html中的span

image标签相当于我们Html中的img。

...

剩下的大家可以结合官方文档使用

https://developers.weixin.qq.com/miniprogram/dev/component/

数据绑定

用户界面呈现会因为当前时刻数据不同而有所不同,或者是因为用户的操作发生动态改变,这就要求程序的运行过程中,要有动态的去改变渲染界面的能力。

在 Web 开发中,开发者使用 JavaScript 通过Dom 接口来完成界面的实时更新。在小程序中,使用 WXML 语言所提供的数据绑定功能,来完成此项功能。

数据定义

在界面对应的JS文件中的data属性上定义数据

   data: {
     msg:\"hello world\",
     num: 18,
   },

引用数据

通过{{}}的方式可以引用数据。

除了引用数据之外,这里还可以进行一些计算,最终显示的结果是计算之后得到的结果。

<view>{{msg}},{{num + 10}}</view>

小程序中任何需要获取数据的地方都需要用{{}},包括标签内的属性。

逻辑渲染

WXML 中,使用 wx:if="{{condition}}" 来判断是否需要渲染该代码块:

<view wx:if="{{condition}}"> True </view>

使用 wx:elif 和 wx:else 来添加一个 else 块:

<view wx:if="{{length > 5}}"> 1 </view>

<view wx:elif="{{length > 2}}"> 2 </view>

<view wx:else> 3 </view>

因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 <block/> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。

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

除此之外微信小程序还可以通过hidden属性进行条件渲染。wx:if在不满足条件的时候会删除掉对应的DOM,hidden属性则是通过display属性设置为none来进行条件渲染。

<view hidden="{{condition}}">

隐藏

</view>

列表渲染

在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item。

<!-- array 是一个数组 -->
<view wx:for="{{array}}">
  {{index}}: {{item.name}}
</view>

<!-- 对应的脚本文件
Page({
  data: {
      array: [{
      name: '天亮教育',
    }, {
      name: '尚云科技'
    }]
  }
})
-->

使用 wx:for-item 指定数组当前元素的变量名,使用 wx:for-index 指定数组当前下标的变量名。

<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">

{{idx}}: {{itemName.name}}

</view>

Key

如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 <input/> 中的输入内容, <switch/> 的选中状态),需要使用 wx:key 来指定列表中项目的唯一的标识符。

wx:key 的值以两种形式提供:

  1. 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。

  2. 保留关键字 this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。

当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。

这里大家可以先体会一下key的概念,等到我们介绍到数据变化的时候在演示key作用。

6. 小程序样式wxss

WXSS(WeiXin Style Sheets)是一套用于小程序的样式语言,用于描述WXML的组件样式,也就是视觉上的效果。

WXSS与Web开发中的CSS类似。为了更适合小程序开发,WXSS对CSS做了一些补充以及修改。

尺寸单位

在WXSS中,引入了rpx(responsive pixel)尺寸单位。引用新尺寸单位的目的是,适配不同宽度的屏幕,开发起来更简单。

在小程序中,规定所有手机的屏幕宽度都是750rpx,所以在不同尺寸的屏幕下1rpx的宽度都不同。

1rpx = (屏幕宽度/750)px

在iphone6手机下,屏幕宽度是375px,所以1rpx=0.5px。

样式的导入

在小程序中,样式引用是这样写:

@import './test_0.wxss'

由于WXSS最终会被编译打包到目标文件中,用户只需要下载一次,在使用过程中不会因为样式的引用而产生多余的文件请求。

小程序中的样式选择器

目前支持的选择器。

小程序中会大量使用flex布局。多用一用flex布局。

7. 小程序中的JS

小程序中的js和浏览器中和node中的区别

浏览器中JS:

  • ES

  • DOM

  • BOM

Node中的JS:

  • ES

  • NPM

  • Native

小程序中的JS:

  • ES

  • 小程序框架

  • 小程序API

小程序中js的模块化

在小程序中实现JS模块化,和node中、ES6中是一致的,大家还可以使用之前的方式进行JS的模块化编程。

小程序中js的加载执行顺序

小程序的执行的入口文件是 app.js 。并且会根据其中 require 的模块顺序决定文件的运行顺序。

案例:JS文件模块化

小程序中js的执行环境

小程序目前可以运行在三大平台:

  1. iOS平台,包括iOS9、iOS10、iOS11

  2. Android平台

  3. 小程序IDE

8. 小程序中的数据渲染

小程序和浏览器中有什么不同

浏览器中渲染是单线程的。

而在小程序中的运行环境分成渲染层和逻辑层,第2章提到过 WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。

小程序中如何渲染

我们看看小程序是如何把脚本里边的数据渲染在界面上的。

WXML模板使用 view 标签,其子节点用 {{ }} 的语法绑定一个 msg 的变量。

<view>{{ msg }}</view>

在 JS 脚本使用 this.setData 方法把 msg 字段设置成 "Hello World"。

Page({

onLoad: function () {

this.setData({ msg: 'Hello World' })

}

})

从这个例子我们可以看到3个点:

1.渲染层和数据相关。

2.逻辑层负责产生、处理数据。

3.逻辑层通过 Page 实例的 setData 方法传递数据到渲染层。

小程序中通讯模型

小程序的渲染层和逻辑层分别由2个线程管理:

渲染层的界面使用了WebView 进行渲染;

逻辑层采用JsCore线程运行JS脚本。

一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端(下文中也会采用Native来代指微信客户端)做中转,逻辑层发送网络请求也经由Native转发。

image-20210906130224831

生命周期示意图

数据驱动的思想

在开发UI的过程中,程序需要维护很多变量状态,同时要操作对应的UI元素。随着页面越来越复杂,我们需要维护的变量越来越多,同时要处理的界面上的交互也越来越多,整个程序会变的越来越复杂。

通常情况下视图和变量的状态是相关联的,如果有某种方法可以让状态和视图绑定在一起,那就可以让我们省去修改视图的工作,这个方法就叫做数据驱动。

在有了框架之后,我们一般很少会采用直接去修改视图的方式,更新界面了,绝大多数情况,都会通过操作数据的方式,来更新视图。通过数据去驱动视图渲染。

9. 程序和界面

程序

"小程序"指的是产品层面的程序,而"程序"指的是代码层面的程序实例,为了避免误解,下文采用App来代替代码层面的"程序"概念。

App({

onLaunch: function(options) {},

onShow: function(options) {},

onHide: function() {},

onError: function(msg) {},

globalData: 'I am global data'

})

宿主环境提供了 App() 构造器用来注册一个程序App,需要留意的是App() 构造器必须写在项目根目录的app.js里,App实例是单例对象,在其他JS脚本中可以使用宿主环境提供的 getApp() 来获取程序实例。

  • onLaunch: 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)

  • onShow:当小程序启动,或从后台进入前台显示,会触发 onShow

  • onHide:当小程序从前台进入后台,会触发 onHide

  • onError:当小程序发生脚本错误,或者 API 调用失败时,会触发 onError 并带上错误信息。

  • 其他字段:可以添加任意的函数或数据到 Object 参数中,在App实例回调用 this 可以访问。

小程序全局数据

我们在前面说到小程序的JS脚本是运行在JsCore的线程里,小程序的每个页面各自有一个WebView线程进行渲染,所以小程序切换页面时,小程序逻辑层的JS脚本运行上下文依旧在同一个JsCore线程中。

在上文中说道App实例是单例的,因此不同页面直接可以通过App实例下的属性来共享数据。App构造器可以传递其他参数作为全局属性以达到全局共享数据的目的。

在其他JS中可以通过getApp()获取App实例,之后可以获取到定义在App实例上的数据。

Page

一个小程序可以有很多页面,每个页面承载不同的功能,页面之间可以互相跳转。

页面构造器

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() { }

})

生命周期

onLoad:生命周期函数--监听页面加载,触发时机早于onShow和onReady

onReady:生命周期函数--监听页面初次渲染完成

onShow:生命周期函数--监听页面显示,触发事件早于onReady

onHide:生命周期函数--监听页面隐藏

onUnload:生命周期函数--监听页面卸载

数据

WXML可以通过数据绑定的语法绑定从逻辑层传递过来的数据字段,这里所说的数据其实就是来自于页面Page构造器的data字段,data参数是页面第一次渲染时从逻辑层传递到渲染层的数据。

在JS脚本中如果需要获取到data上的数据,需要通过this.data获取。

<!-- page.wxml -->

<view>{{text}}</view>

// page.js

Page({

data: {

text: '天亮教育',

},

onLoad(){

console.log(this.data.text)

}

})

如果涉及到更新,这里可以调用Page实例提供的setData把数据传递给渲染层,从而达到更新界面的目的。由于小程序的渲染层和逻辑层分别在两个线程中运行,所以setData传递数据实际是一个异步的过程,所以setData的第二个参数是一个callback回调,在这次setData对界面渲染完毕后触发。

setData其一般调用格式是 setData(data, callback),其中data是由多个key: value构成的Object对象。

// page.js

Page({

onLoad: function(){

this.setData({

text: 'change data'

}, function(){

// 在这次setData对界面渲染完毕后触发

})

}

})

注意事项:

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

  • 由于setData是需要两个线程的一些通信消耗,为了提高性能,每次设置的数据不应超过1024kB。

  • 不要把data中的任意一项的value设为undefined,否则可能会有引起一些不可预料的bug。

页面的用户行为:

onPullDownRefresh 下拉刷新

监听用户下拉刷新事件,需要在app.json的window选项中或页面配置page.json中设置enablePullDownRefresh为true。当处理完数据刷新后,wx.stopPullDownRefresh可以停止当前页面的下拉刷新。

onReachBottom 上拉触底

监听用户上拉触底事件。可以在app.json的window选项中或页面配置page.json中设置触发距离onReachBottomDistance。在触发距离内滑动期间,本事件只会被触发一次。

onPageScroll 页面滚动

监听用户滑动页面事件,参数为 Object,包含 scrollTop 字段,表示页面在垂直方向已滚动的距离(单位px)。

onShareAppMessage 用户转发

只有定义了此事件处理函数,右上角菜单才会显示"转发"按钮,在用户点击转发按钮的时候会调用,此事件需要return一个Object,包含title和path两个字段,用于自定义转发内容,如代码清单3-13所示。

// page.js

Page({

onShareAppMessage: function () {

return {

title: '自定义转发标题',

// 自定义点击链接需要跳转的页面,默认当前页面

path: '/page/user?id=123'

}

}

})

10. 事件

事件定义

在小程序中绑定事件可以以bind开头然后跟上事件的类型,如bindtap绑定一个点击事件,对应的值是一个字符串,需要在page构造器中定义同名函数,每次触发事件之后就会执行对应函数的内容。

<view bindtap="handleTap">点击事件</view>

<view bind:tap="handleTap">另一种写法</view>

// pages/my/index.js

Page({

handleTap(){

console.log("执行了点击事件");

}

})

常见的事件类型

  • touchstart 手指触摸动作开始

  • touchmove 手指触摸后移动

  • touchcancel 手指触摸动作被打断,如来电提醒,弹窗

  • touchend 手指触摸动作结束

  • tap 手指触摸后马上离开

  • longpress 手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发

  • longtap 手指触摸后,超过350ms再离开(推荐使用longpress事件代替)

  • transitionend 会在 WXSS transition 或 wx.createAnimation 动画结束后触发

  • animationstart 会在一个 WXSS animation 动画开始时触发

  • animationiteration 会在一个 WXSS animation 一次迭代结束时触发

  • animationend 会在一个 WXSS animation 动画完成时触发

事件传参

在小程序中进行事件传参不能像传统的Web项目中一样,在括号里写参数。在小程序中需要在标签上通过data-方式定义事件所需的参数。

<!-- data-参数名='参数值' -->

<view bindtap="handleTap" data-msg="我是事件的参数">点击事件</view>

每个事件回调触发时,都会收到一个事件对象,通过这个对象可以获取路由传递的参数。

handleTap(e){

console.log("执行了点击事件");

// 通过currentTarget中的dataset属性可以获取时间参数

console.log(e.currentTarget.dataset.msg);

}

关于这个事件对象其他属性

  • type 事件类型

  • timeStamp 页面打开到触发事件所经过的毫秒数

  • target 触发事件的组件的一些属性值集合

  • currentTarget 当前组件的一些属性值集合

  • detail 额外的信息

  • touches 触摸事件,当前停留在屏幕中的触摸点信息的数组

  • changedTouches 触摸事件,当前变化的触摸点信息的数组

这里需要注意的是target和currentTarget的区别,currentTarget为当前事件所绑定的组件,而target则是触发该事件的源头组件。

阻止事件冒泡

在小程序中除了通过bind之外,还可以通过catch进行事件绑定,通过catch绑定的事件不会触发事件冒泡。

事件捕获

事件的触发分为两个阶段,首先是捕获阶段,其次是冒泡阶段。默认情况下事件都是在冒泡阶段触发。如果希望事件可以在捕获阶段触发,可以通过capture-bind进行事件绑定。

posted @ 2021-09-06 13:09  星空与沧海  阅读(362)  评论(0编辑  收藏  举报