构建自己的开源项目

微信小程序

项目目录结构

  • components 目录:主要用来存放一些自定义组件相关的内容
  • libs 目录:主要用来存放项目中依赖的第三方库。例如 jquery、seajs、qrcode、echarts 等。
  • models 目录:主要用来封装与后台进行交互的 model 操作类。
  • utils 目录:主要用来存放项目开发过程中要使用到的各种工具类,避免重复代码。

过程

1、自定义 tabBar

使用官方小程序示例中的 自定义 tabBar

2、引入字体图标

使用 在线 url

将字体 url 转成 base64 的格式后使用出现问题……

3、API Promise化

使用官方 扩展能力 API Promise化 miniprogram-api-promise 工具

4、封装接口

参考下面文档接合下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 同时发送异步代码的次数
let ajaxTimes=0;
export const request=(params)=>{
// 判断 url中是否带有 /my/ 请求的是私有的路径 带上header token
let header={...params.header};
if(params.url.includes("/my/")){
// 拼接header 带上token
header["Authorization"]=wx.getStorageSync("token");
}
ajaxTimes++;
// 显示加载中 效果
wx.showLoading({
title: "加载中",
mask: true
});
// 定义公共的url
const baseUrl="https://api.zbztb.cn/api/public/v1";
return new Promise((resolve,reject)=>{
wx.request({
...params,
header:header,
url:baseUrl+params.url,
success:(result)=>{
resolve(result.data.message);
},
fail:(err)=>{
reject(err);
},
complete:()=>{
ajaxTimes--;
if(ajaxTimes===0){
// 关闭正在等待的图标
wx.hideLoading();
}
}
});
})
}
// 使用
import { request } from "../../request/index.js";
request({url:"/goods/search",data:this.QueryParams}).then(res=>{
console.log(res);
})
// 代码来源黑马

强烈推介的几个微信小程序开发小技巧,简单又实用

5、状态管理

用官方 扩展能力 架构扩展中的 mobx-miniprogram

6、开启开发者工具中 “开启上传代码时样式文件自动不全” 功能,这样小程序会自动不全其余一些样式兼容性写法。

7、封装组件库

参考 vant 封装 icon、官方指南中自定义组件

8、分包

9、引入事件管理工具 mitt 来作为时间管理中心,来处理组件、界面传值。

10、开启开发者工具中 “增强编译”,可以使用 async/await。

11、加入简单的防抖和节流

建议

利用场景值做数据统计

在模块里随便更改 exports 的指向会造成未知的错误。推荐开发者采用 module.exports 来暴露模块接口,除非你已经清晰地知道两者之间的关系。

1
2
3
4
5
// 例如
function sayHello (name) {
console.log(`Hello ${name}!`)
}
module.exports.sayHello = sayHello

scroll-view
在滚动 scroll-view 时会阻止页面回弹,所以在 scroll-view 中 滚动是无法触发 onPullDownRefresh 的。
若要使用下拉刷新,请使用页面的滚动,而不是 scroll-view,这样也能通过点击顶部状态栏回到页面顶部。

在特殊机型(例如 iphoneX、iphone 11)中,因为取消了物理按键,会出现手机底部区域被手机底部的小黑条遮挡的情况,此时可以使用 padding-bottom: env(safe-area-inset-bottom)来告诉微信进行自动适配。

优化

  1. 启动慢主要从优化代码包上下手:

    • 对静态资源进行优化,将非必要的静态资源文件上传到CDN
    • 对小程序的组件进行依赖分析,过滤掉未使用的组件
    • 对独立性比较强的页面进行独立分包,减少主包下载耗时
  2. 请求慢主要从预加载和缓存下手:

    • 冷启动开启数据预拉取
    • 页面路由切换时提前拉取数据
    • 对数据进行缓存
  3. 交互慢需要从发起请求和页面渲染下手:

    • 保障与用户体验相关的业务请求正常发送
    • 页面分步渲染

以上是我对下列视频及文章的归纳和总结

腾讯课堂小程序性能极致优化——独立分包和性能测速上报

腾讯课堂小程序性能极致优化——网络请求优化篇

腾讯课堂小程序性能极致优化——综合篇

关于反编译

我最早听说过类似“反编译”的词汇是在汽车、飞机等领域,通过反编译来仿制汽车、飞机等,昨天面试听到面试公司技术骨干提到这个反编译。我觉得很神奇。索性出一篇文章来了解反编译。

反编译

反编译指通过他人软件进行“逆向分析、研究”工作,推导出他人的软件产品所使用的思路、原理、结构、算法、处理过程、运行方式等设计要素,

某种特定情况下可能推导出源码。可以作为自己开发软件时的参考或直接用于自己的软件产品中。

这里我想到了,我在学校期间使用过一款扒网站的工具,跟反编译接近,工具是你输入一个网址然后通过这个网址来扒取网站的。我想大致原理是跟爬虫类似的,只不过爬虫抓取的是网站的数据,它抓取的是文件资源。

微信小程序反编译大致操作步骤,在模拟器中找到微信用微信打开某个小程序,小程序会被下载下来,然后找到下载下来的包,用ES 文件浏览器 把包复制到共享文件夹,然后通过 node 进行反编译,详细请看相关资料。


相关资料
科普:什么是编译与反编译
逆向反编译四大工具利器
知乎 反编译
反编译微信小程序
反编译获取任何微信小程序源码(完)
微信小程序反编译
如何将模拟器内的文件导出到电脑

关于微信小程序的书籍集合

《小程序开发原理与实战》

开发 app

1、不菲的开发成本

2、高昂的推广成本

3、高昂的维系成本

开发小程序

1、计算能力不足

2、灵活性不足

3、有一定的局限性

三种运行载体的快速对比

运行载体 运行环境 功能性 便捷性 交互体验 开发成本 推广难度 消息推送
公众号 H5 简单 无需安装 一般 支持
小程序 微信 轻应用 无需安装 接近原生 App 受限
App 原生系统 丰富 需要安装 最流畅 支持

小程序的生命周期

场景值

利用场景值做数值统计

例如:场景 1129 (微信爬虫访问)可以用来对爬虫做一些优化,方便索引;场景 1038(从另一个小程序返回)可以用来对小程序免密签约的场景进行判断。

可以在 App 的 onLaunch 和 onShow 中 options.scene 或 wx.getLaunchOptionsSync 中获取上述场景值。

小程序生命周期的注册

(1)App() 必须在 app.js 中注册,不可以在 App()函数内或在定义 App() 函数前调用 getApp()方法;

(2)通过 getApp() 方法获取实例后,不可以私自调用生命周期函数。

Page 的 prototype 中还注册了 data 属性、route 属性、setData()方法。

1
2
this.route  //  获取当前所处的页面
getCurrentPage() // 获取当前页面的实例

data 会以 JSON 的形式由逻辑层传至渲染层,所以数据必须可以转换 JSON 的格式:字符串、数字、布尔值、对象、数组。

this.setData() 仅支持可 JSON 化的数据(即字符串、数字、布尔值、对象、数组)。单次设置的数据不能超过 1024 KB,尽量避免一次设置过多的数据。

全局变量使用

1
2
3
4
5
6
7
8
//  app.js
App({
globalData : 1
})

// a.js
var app = getAppp()
app.globalData++

小程序页面栈的表现形式

路由方式 页面栈变化 老页面生命周期变化 新页面生命周期变化
初始化 新页面入栈 onLoad()、onShow()
打开新页面 新页面入栈 onHide() onLoad()、onShow()
页面重定向 当前页面出栈,新页面入栈 onUnload() onLoad()、onShow()
页面返回 页面不断出栈,直到目标返回页 onUnload() onShow()
tab 切换 页面全部出栈,只留下新的 tab 页面 视具体情况而定 视具体情况而定
重加载 页面全部出栈,只留下新的页面 onUnload() onLoad()、onShow()

注意事项

(1)navigateTo、redirectTo 只能打开非 tabBar 页面。

(2)switchTab 只能打开 tabBar 页面,但是不能传递参数。

(3)reLaunch 可以打开任意页面

(4)页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。

(5)调用页面路由带的参数可以在目标页面的 onLoad 中获取。

1
2
3
4
5
6
7
8
9
10
//  common.js
function sayHello (name) {
console.log(`Hello ${name}!`)
}
function sayGoodbye (name) {
console.log(`Goodbye ${name}!`)
}

module.exports.sayHello = sayHello
exports.sayGoodbye = sayGoodbye
1
2
3
4
5
6
7
8
9
var common = require('common.js')
Page({
helloMINA: function(){
common.sayHello('MINA')
},
goodbyeMINA: function(){
common.sayGoodbye('MINA')
}
})

注意事项

(1)exports 是 module.exports 的一个引用,在模块里随便更改 exports 的指向会造成未知的错误。推荐开发者采用 module.exports 来暴露模块接口,除非你已经清晰地知道两者之间的关系。

(2)小程序目前不支持直接引入 node_modules ,建议开发者在需要使用 node_modules 时复制相关的代码到小程序的目录中,或者使用小程序支持的 npm 功能。

api 分为事件监听类、同步执行类、异步执行类。

封装 api 接口

1
2
3
4
5
6
7
8
let getImageInfoPromise = new Promise(function(resole,reject){
wx.getImageInfo({
src: '',
success: function(res) {
resolve(res);
}
})
})

组件

scroll-view

在滚动 scroll-view 时会阻止页面回弹,所以在 scroll-view 中 滚动是无法触发 onPullDownRefresh 的。

若要使用下拉刷新,请使用页面的滚动,而不是 scroll-view,这样也能通过点击顶部状态栏回到页面顶部。

WXSS

在特殊机型(例如 iphoneX、iphone 11)中,因为取消了物理按键,会出现手机底部区域被手机底部的小黑条遮挡的情况,此时可以使用 padding-bottom: env(safe-area-inset-bottom)来告诉微信进行自动适配。

1、清除浮动的元素本身不能为浮动元素

2、清除浮动的元素本身必须是块级元素。

相对定位,相对的是原来的位置,但原来所占的空间仍然保留。

实战:商城类项目开发

典型的电商交互闭环

项目目录结构

  • components 目录:主要用来存放一些自定义组件相关的内容
  • images 目录:主要用来存放商城用到的图片信息等
  • libs 目录:主要用来存放商城项目中依赖的第三方库。
  • models 目录:主要用来封装与后台进行交互的 model 操作类。
  • pages 目录:主要用来存放商城要用到的各个具体页面,里面的每个不同的子目录都代表一个独立页面,分别包含与目录同名的 wxml、wxss、js、和 json 文件。
  • utils 目录:主要用来存放商城开发过程中要使用到的各种工具类,避免重复代码。
  • app.js:小程序主逻辑入口。
  • app.json:小程序全局配置文件。
  • app.wxss:小程序公共样式表。

wxss 文件不支持使用本地图片作为资源

双列效果

1
2
3
4
5
6
7
8
9
10
11
12
13
.djbox {
float: left;
margin: 0 0 1%;
width: 49.5%;
box-sizing: border-box;
min-height: 240px;
postion: relative;
background: #fff;
}

.djbox:nth-child(odd){
margin-right: 1%;
}

自定义模板

1
2
3
4
//  cart.wxml
<template name = "cart">
<view class="cart-dialog slideInUp"></view>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//  cart.js
// 模板调用页面的 page 对象缓存


// 模板内部方法,主要是需要满足小程序的事件绑定机制
// 事件方法必须绑定在当前 page 对象上

let methods = {
/**
* 显示添加购物车组件
*/
showShoppingCart(){
// 略
},

hideShoppingCart(){
// 略
},
}

module.exports = {
async init(curPage,goodsId, mode = 3){
page = curPage;
page.setData({
shoppingCart: {
buyNum: 1,
}
})
}
}
1
2
3
//  index.wxml
<import src="../../template/cart/cart.wxml"></import>
<template is="cart" data = "{{shoppingCart}}"></template>

《小程序,巧应用:微信小程序开发实战(第2版)》


《微信小程序:开发入门及案例详解》

第 2 章 小程序开发核心

小程序 js 模块化机制遵循 CommonJS 规范,跟 node 遵循的规范一样。

引用

一个 WXML 可以通过 import 或 include 引入其他 WXML 文件,

两种方式都能引入 WXML 文件,区别在于

import 引入 WXML 文件后只接受模板的定义,忽略模板定义之外的所有内容,而且使用过程中有作用域的概念。

include 则是引入文件中除 <template/> 以外的代码直接拷贝到 <include/>位置

整体来说 import 是引入模板定义,include 是引入组件。

1
2
3
4
5
6
7
8
<import src="b.wxml">
<template is="bTemplate" data=""></template> <!-- 使用b.wxml中定义的模板 -->

<view>内容</view> <!-- import 引用时会被忽略 -->
<template name="bTemplate">
<view>b template content</view>
</template>
<template is="bTemplate"/> <!-- import 引用时会被忽略 -->

import 引用有作用域概念,只能直接使用引用的定义模板,而不能使用间接引入的定义模板。

例如:在 a.wxml 中引入 b.wxml,b.wxml 在引入 c.wxml,a 能直接使用 b 中定义的模板,b 能使用 c 中定义的模板,但 a 不能使用 c 中的模板。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<import src="b.wxml">
<template is="bTemplate"/>
<template is="cTemplate"/> <!-- 不能直接用 c.wxml 中的模板 -->

<import src="c.wxml"/>
<view> b content </view> <!-- import时被忽略 -->
<template name="bTemplate">
<template is="cTemplate" />
<view>b template content</view>
</template>

<template is="cTempalte"/> <!-- import 时被忽略 -->
<template name="cTempalte">
<view>c template content</view>
</template>

include 引入会将模板定义标签外的内容(含模板使用标签)直接赋值替换 <include/>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<include  src="b.wxml">
<template is="bTemplate"/> <!-- 不能调用 b.wxml 中的模板 -->
<template is="cTemplate"/> <!-- 不能调用 c.wxml 中的模板 -->

<include src="c.wxml"/>
<view> b content </view> <!-- 不会忽略 -->
<template name="bTemplate">
<template is="cTemplate" /> <!-- 不会调用 c.wxml 中的模板,引用时被忽略 -->
<view>b template content</view>
</template>
<template is="bTempalte" data="{{name}}"/> <!-- 没有被忽略,能正常调用自己文件中的模板 -->
<template name="cTempalte">
<view>c template content</view>
</template>
Page({
data: {
name: '2' / * 能将数据注入到 b.wxml 中 */
}
})

通过对比发现,import 更适合引用模板定义文件,include 更适合引入组件文件。

在开发过程中一定要开启开发者工具中 “ 开启上传代码时样式文件自动不全 ” 功能,这样小程序会自动不全其余一些样式兼容性写法,

保证在不同终端达到统一视觉效果。

模块的使用

通过 exports 暴露接口。

通过 require(path) 引入依赖,path 是需要引入的模块文件的相对路径。

注意:

exports 是 module.exports 的一个引用,因此在模块里面随意更改 exports 的指向会造成未知的错误。所以更推荐开发者采用

module.exports 来暴露模板接口,除非你已经很清晰地知道这两者的关系

小程序目前不支持直接引入 node_modules,开发者需要使用 node_modules 时建议拷贝出相关代码到小程序目录中。

JavaScript 运行环境

微信小程序逻辑代码运行在三端, iOS、Android、开发者工具,这三端是各自不同的三个解析引擎:

在 iOS 上,小程序的 JavaScript 代码是运行在 JavaScriptCore 中。

在 Android 上,小程序的 JavaScript 代码是通过 X5 内核来解析。

第 6 章案例分析:豆瓣电影

开放平台:淘宝开放平台、腾讯开发者平台、高德 API、百度 API 等。

主要使用正在热映、即将上映、电影条目信息这 3 个 API 接口:

正在热映 API:https://api.douban.com/v2/movie/in_theaters? city=北京
即将上映 API: https://api.douban.com/v2/movie/in_theaters?start=0&count=20
电影条目信息 API:https://api.douban.com/v2/movie/subject/1324043

由于豆瓣 API 不能支持非浏览器客户端发起的请求,非浏览器客户端需要下载对应的 SDK 来请求 API,
所以小程序在微信中打开时不能直接调用豆瓣 API 接口,所以我们利用自己的服务器做了一次请求跳转。

技术架构

借用服务端三层架构模式,一个项目可分为表现层、业务逻辑层、数据访问层。

lib:放置一些最底层、第三方库,如 jquery、seajs、qrcode、echarts 等,通常 lib 层是全公司共用一套。豆瓣电影中由于没有第三方库文件,或者说小程序框架本身就是一个第三方库,所以没有 lib 层。

common:放置和项目相关的一些公共代码,如转码、工具包、公共样式设置等。根据业务需要可以将 widgets 和 common 合并为一个目录。

service:业务逻辑层,按业务类型整合相关的方法,向上暴露需要的接口方法,比如 a 页面需要调用登录和列表信息,b 页面需要调用登录和详情信息,那么这两个页面中的登录接口就会被调用两次,这时我们便可以将这种和业务紧密相关的接口调用方法封装起来,作为一个服务暴露给上层应用。业务逻辑层能降低表现层对业务的关注,让更多精力关注在页面渲染、页面交互等功能上。

widgets:一些通用的带 UI 的小组件,如 pop、header、购物车图标等等,它和 common 层有些类似,但是相对 common 层,widgets 具备 UI 界面和一个闭环的交互功能。由于业务问题,在豆瓣电影实例中没有 widgets 目录。

pages:表现层,一般表现层中一个文件夹对应一个页面所涉及的所有资源。

这种分层方式是前端项目常见的架构分层方式,适用于任何原则,同时按照组件化原则我们通常会把一个组件、包、页面所涉及的所有资源放置在一个目录中。

basestlye:一些项目公共的基本样式,被 app.wxss 引入,当前项目中没有公共样式,内容为空。

utils:基础工具包,项目中我们把系统 toast 进行了一层代理,封装到对应方法中,如果以后需要改变 toast 行为,我们便可以直接修改代码,而不用在每个调用页面进行修改。

detail:详情页相关资源。
home:首页相关资源。
douban:请求豆瓣接口的相关逻辑代码。

公共模块开发

在 JavaScript 整体编码中一般 handle 是需要对外暴露的公共方法的句柄,写在模块前面,
_fn 是私有方法,写在后面,这样便于他人阅读代码。


《 微信小程序项目开发实战:用WePY、mpvue、Taro打造高效的小程序》

第 11 章实战:使用 Taro 实现星座测试小程序

Taro 是一套遵循 React 语法规范的多端开发解决方案。

Taro 遵循 React 语法规范,它采用与 React 一致的组件化思想,组件生命周期与 React 保持一致,同时支持 JSX 语法,让代码具有更丰富的表现力,使用 Taro 进行开发可以获得和 React 一致的开发体验。

采用 Taro 开发小程序具有以下的优秀特效:

  • 支持使用 npm/yarn 安装管理第三方依赖。
  • 支持使用 ES7/ES8 甚至更新的 ES 规范,一切都可自行配置。
  • 支持使用 CSS 预编译器,例如 Sass 等。
  • 支持使用 Redux 进行状态管理。
  • 支持使用 Mobx 进行状态管理。
  • 小程序 API 优化、异步 API Promise 化等。

Taro 项目的编写采用 React 语法,所以引入本地静态文件应当使用 import 语句

1
2
import bg from '../../public/bg.jpeg'
import './index.less'

Taro 提供的 Image 组件可完成图片内容的显示

1
<Image src={bg} mode="widthFix" className="bg" />

在组件中绑定的监听事件,需要使用.bind 的方式声明事件。

1
onClick={this.onTap.bind(this,item)}

该方法要执行的事件,需要在组件中声明。

1
2
3
4
5
onTap(name){
Taro.navigateTo({
url:''
})
}

URL 地址传参

1
2
3
Taro.navigateTo({
url: '/pages/page/path/name?id=2&type=test'
})

在 componentWillMount 方法里通过 this.$router.params 获取到传入的参数。

1
2
3
componentWillMount () {
console.log(this.$router.params) // 输出 { id: 2, type: 'test' }
}

发起网络请求,支持 Promise 化使用。
Taro.request()

赋值
setState()

项目编译与生成
Taro 并不是所有的内容都被各类小程序所支持的,不同小程序也因为平台的不同对部分 API 的支持不同,所以开发者为了开发全平台支持的小程序,需要尽可能地使用 Taro 提供的通用组件。

编译为微信小程序

1
npm run build:weap

编译为百度小程序

1
npm run build:swan

需要下载安装百度开发者工具

编译为支付宝小程序

1
npm run build:alipay

需要下载安装支付宝开发者工具

编译为字节跳动小程序

1
npm run build:tt

编译为 H5

1
npm run build:h5

《微信小程序开发入门与实践》

整本书围绕着 Orange Can 项目展开,讲解 API、组件用法、技巧以及常见的误区说明并附带一些小程序开发的经验。

Orange Can 项目分为

  • 文章阅读
    • 文章列表
    • 文章详情
    • 评论
  • 电影资讯
  • 设置

通过 Orange Can 你将学会

  • swiper组件的裁剪模式
  • image组件的裁剪模式
  • 缓存的使用技巧
  • 列表渲染
  • 数据绑定
  • 模板
  • 对小程序页面的生命周期有大致了解
  • 如何调用服务器数据
  • template 模板的使用技巧
  • 获取硬件设备信息、罗盘与重力感应的应用
  • 扫描二维码
  • 用户登录、用户信息校验、解析用户加密数据、获取用户openId、发送模板消息、微信支付
  • 音乐播放、录音、分享等

通过 Orange Can 你将有能力构建出一个内容型的小程序应用。
本书还提供部分服务器的PHP代码,主要供用户登录、校验、解析加密数据、模板消息、微信支付等功能调用。

前沿

作者的平台信息
微信公众号:小楼昨夜又秋风
知乎专栏:小楼昨夜又秋风
知乎ID:七月在夏天

本书源码
开发者社区

第1章 微信小程序简介

1.1 什么是微信小程序

小程序的特性

  • 小程序没有“官方的”应用市场
  • 小程序不能被关注,小程序没有粉丝这个概念。
  • 小程序没有群发消息和主动推送消息的能力。
  • 微信中没有明显的小程序入口,但是发现有一个【小程序】栏,它会记录用户曾经用过的历史小程序

获取和使用小程序的途径

  • 扫描二维码、有限能力的搜索、群聊分享、小程序栏
  • 长按进入小程序
  • 小程序名称不能和公众号相同
  • 有一定的分享能力,可以分享给朋友和群聊,但不能分享到朋友圈
  • 同一个公司的公众号和小程序可以相互发现。公众号里可以看到该公司的小程序,同时,小程序里也可以看到该公司的公众号。

1.2 什么类型的应用适合用小程序开发

“简单的”、“低频的”、“对性能要求不高的”应用适合用小程序来开发。
小程序特别适合做线下的场景化应用,官方的一切措施都是为了将小程序导向线下。

1.3 小程序与原生App(iOS、Android)的优劣对比

Web App
相对于其他两种App,Web App具有开发简单、高效,更新灵活、跨平台,大量的网页应用稍作调整即可放在移动端运行。但缺点与优点并存,Web App性能、体验极差(对,是极差),无法使用照相机、系统通知、本地缓存等原生特性。

Native App
Native App具有性能、体验非常良好,组件支持完善、接口丰富等特点。但Native App最大的缺点在于,不能跨平台,有多少个平台就要开发多少个版本,现在主要有iOS和Android两个主流平台。

Hybrid App
Hybrid App具有接近于Native App的体验、开发效率高、跨平台等特性。

相比于Native App,小程序具有Hybrid App的一些优势:
跨平台(对于iOS和Android两个平台只需要开发一套程序)。
具备接近于Native App的体验(注意只是接近)。
对原生组件有访问能力。
具备缓存能力。
上手容易,开发逻辑较为简单。

小程序独有的特点

  • 小程序在设计时就做了很多约定式的规范:比如简单的文件结构、默认的文件命名、内置好的Tab栏与导航栏等,这让小程序的初学者更容易上手和理解。
  • 开发环境很干净,你无须安装任何除开发工具外的其他软件。当然现在这个工具简陋的可怕,很多常见的IDE功能都不具备,但相比于其他Hybrid App的环境要求,小程序这点真的很棒。
  • 发布和部署流程非常简单,几乎是“傻瓜式”,点击几下就可以将应用发布到腾讯云。
  • 小程序之所以在公布后引起了互联网圈儿和开发者们极高的关注度,原因并不在技术上,无数开发者、创业者看中的是微信天然的关系链与获客能力。这也是小程序最大的优势。

小程序独有的缺点:

  • 小程序为了简化复杂性,做了一些UI上的设计规范,确实方便了很多对UI要求不高的应用。但这也限制了那些对UI要求极高的产品发挥。
  • 小程序很遗憾地不支持现有的HTML DOM结构,而是自己给出了一系列的组件,造就了一个封闭的开发环境,这直接导致了现有的经典JavaScript框架、类库都无法使用。小程序现在的生态几乎是荒芜一片,等待着开发者们去耕耘(挑战与机遇并存,正因为没有,才有机会)。如果你想用小程序实现一组图形来展现股票或者天气的曲线,目前来看,相当烦琐。你无法使用经典的echart或者highchart,你只能自己用Canvas来一点点地绘制。
  • 截止到笔者编写本书时,小程序还不支持WebView,这是相当头疼的一个问题。
  • 小程序只实现了模板化并没有实现自定义组件。通常希望把这个组件的标签、样式以及业务逻辑打包在一起,然后可以放在项目中多个地方使用。外部客户端调用组件时,只需要传入组件所需要的参数,由组件自己来完成数据获取、转化、绑定并和UI层通信等操作。

小程序和现在主流App的优劣对比

1.4 小程序会淘汰原生App吗

不会。小程序的定位也非常明确——做低频和业务逻辑不复杂的应用,原生App与小程序之间更多地将是一种互补的关系,绝对谈不上取代。

1.5 Web前端的未来

从信息的角度讲,移动端主要负责信息的输出,而PC端主要负责信息的输入。

不可或缺的 Web前端开发者:

  • 混合式App是现在的主流App,一个App很难只用Objective-C或者Java来开发,必然会有Web技术介入。
  • 大多数移动端应用也都有一个对应的Web网站。
  • 现在的公司做营销和推广都离不开微信,无论是H5页面还是做微信服务号、企业号都是纯粹的Web技术。

1.6 Web前端开发者与小程序

微信小程序更多的是App或者Web网页的另一个流量入口,但绝不会替代原生App或者Web网页(至少很长一段时间内是这样,未来小程序怎么发展还有待观察)。正如我们描述的微信对现在公司营销的重要性,小程序也将成为Web前端开发者应该掌握的一门技术。

1.7 MINA框架与微信小程序

信小程序并不是一项技术或者一个框架,微信小程序是一个生态,与之对应的应该是iOS生态和Android生态,其中微信小程序又与iOS生态极为相似,它们都非常封闭,而且审核非常严格(微信小程序的审核比苹果还要严格)。而MINA是小程序的一个框架,它提供了小程序运行所需要的接口、模型和机制。

1.8 微信小程序beta测试版

测试版本的概念非常重要,可以让开发者预先知道下个版本的更新内容,建议开发者应该第一时间使用测试版本测试一下自己的小程序。

第2章 小程序环境搭建与开发工具介绍

2.1 微信Web开发者工具下载及安装

微信Web开发者工具

AppID代表微信小程序的ID号,必须拥有微信小程序账号才可以申请这个ID号。

2.3.1 编辑选项卡

wifi 一栏,可以选择不同的网络环境。

2.3.2 调试选项卡

【区域1】模拟器同编辑选项卡功能一样。
【区域2】展示了小程序经编译后生成的文件和文件结构。
【区域3】是编译后的文件内容查看区,可以在这个区域的文件里设置调试断点。
【区域4】调试功能区,可以在这里查看变量状态与数值、断点设置情况、变量作用域等。这个区域和Chrome浏览器里的调试工具几乎一样,调试的方法和快捷键也是相同的。
【区域5】信息输出区域,这个区域会显示程序运行的错误信息、警告信息以及用户自己打印的相关信息(通过console.log()输出的信息)。

如何在小程序中调试?
可以在【区域3】中点击每行代码前的行号设置断点。当代码运行到断点处后,将停止。常用快捷键有【F10】单步执行,【F11】进入方法,【F8】继续运行到下一个断点。更多快捷键可自行在【区域4】中查看。

在整个调试选项卡中,最重要的部分还是【区域2】和【区域3】顶部的6个功能模块儿。
调试选项卡的6个功能Panel
【Sources】Sources Panel是默认的panel,用于显示当前项目的脚本文件。
Sources Panel
【Console】Console Panel用于调试和输出信息,开发者也可以在这里输入代码。
panel在【Sources】模块中同样存在。
当点击【Console】后,consolePanel将变大,使开发者可以浏览到更多信息。
Console panel
【Network】Network Panel主要用于观察和显示网络连接的相关情况。这里的NetworkPanel和Chrome浏览器里的Network Panel几乎一样。
Network Panel
【Storage】Storage Panel用于显示当前项目的数据缓存情况。
【AppData】AppData Panel用于显示项目中被激活的所有页面的数据情况,这些数据主要是用来做数据绑定。
【Wxml】Wxml Panel是非常重要的一个功能模块,这个模块类似于Chrome调试工具下的Elements模块,主要用于调试Wxml标签和相关CSS样式,调试方法同Chrome一样。如果你是一个前端新手,那么建议好好地摸索一下这个功能模块的调试技巧,绝大多数和样式、标签相关的问题,都需要依靠这个Panel来调试。
Wxml Panel

2.3.3 项目选项卡

项目选项卡主要用来管理和设置项目。
项目选项卡

项目选项卡主要有3大功能:显示当前项目细节、预览及上传项目以及项目配置。

显示项目细节
顶部显示了项目名称和App ID。如果我们新建项目时选择的是“无AppID”,则这里将会固定地显示一个“touristappid”;如果你设置了项目的AppID,则这里会显示项目的AppID。

预览及上传项目
预览按钮可以实现在真机上运行小程序,但前提条件是你必须有一个微信小程序账号。

项目配置
开启ES6转ES5
小程序支持使用ES6来编写代码。如果使用ES6来编写代码,框架会默认使用babel将开发者的代码转换为ES5代码(这样做的主要原因是为了保持对三端:iOS、Android和开发工具模拟器的良好兼容性)。

开启上传代码时样式自动补全
开启此选项,开发工具会自动检测并补全缺失样式,保证在iOS 8上的正常显示。

开启代码压缩上传
开启此选项,开发工具在上传代码时将会帮助开发者压缩JavaScript代码,减小代码包体积。

监听文件变化,自动刷新开发者工具
开启此选项后,如果代码发生了改变(需要Ctrl+S先保存),小程序开发工具会自动帮助开发者刷新调试模拟器,从而提高开发效率。也就是说,开发者不再需要手动地点击编译按键即可实时预览小程序运行效果。

开发环境不校验请求域名以及TLS版本
开启此选项,开发工具将不会校验安全域名以及TLS版本,帮助在开发过程中更好地完成调试工作。在开发工具里如果选取了“无AppID”模式,那么开发工具的安全限制级别非常低,不需要使用https访问服务器,也不会校验TLS版本。但如果我们填入了“AppID”,那么默认情况下开发工具的校验行为会和真机环境保持一致,比如,必须使用https访问服务器且服务器域名必须加入到微信小程序账号中的可信任域名列表中。如果我们不想接受这样的限制,又想使用“AppID模式”,那么需要把“开发环境不校验请求域名以及TLS版本”这一项给勾选上。

ES6转ES5的转换,只会帮助开发者处理语法上的问题,新的ES6的API例如Promise等需要开发者自行引入Polyfill或者别的类库。同时,为了提高代码质量,在开启ES6转换功能的情况下,默认启用JavaScript严格模式。开发者可以自己查阅资料了解什么是JavaScript的严格模式。

2.3.8 快速打开官方API文档

小程序提供了一个快速打开官方文档的方法,即点击开发工具左上角的【帮助】→【关于】,在弹出的“关于”对话框中点击【点击打开文档】,即可马上进入官方API文档。

官方API文档除了用于经常查阅API外,推荐大家在版本更新后第一时间去查看更新内容。最新的更新内容对我们开发者来说尤其重要,更新内容通常会出现在官方API文档的【工具】→【下载】以及【历史更新日志】里。

2.3.9 开发工具的更新

微信小程序开发者工具将自动更新,无须开发者手动更新。每次启动开发工具后,如果有新版本则会自动提示下载。
在Windows下,如果开发者重启开发工具后依然没有自动更新,请退出开发工具,右键点击开发工具图标,选择【以管理员身份运行】。以上解决方案在Windows 10下测试可行。如果以上方案都不可用,请前往官网下载并安装最新版本的开发工具。

2.3.10 常用小程序快捷键

1、格式调整
Ctrl+S:保存文件
Ctrl+[,Ctrl+]:代码行缩进
Ctrl+Shift+[,Ctrl+Shift+]:折叠打开代码块
Ctrl+C Ctrl+V:复制粘贴,如果没有选中任何文字则复制粘贴一行
Shift+Alt+F:代码格式化
Alt+Up,Alt+Down:上下移动一行
Shift+Alt+Up,Shift+Alt+Down:向上向下复制一行
Ctrl+Shift+Enter:在当前行上方插入一行
Ctrl+Shift+F:全局搜索

2、光标相关
Ctrl+End:移动到文件结尾
Ctrl+Home:移动到文件开头
Ctrl+i:选中当前行
Shift+End:选择从光标到行尾
Shift+Home:选择从行首到光标处
Ctrl+Shift+L:选中所有匹配
Ctrl+D:选中匹配
Ctrl+U:光标回退

3、界面相关
Ctrl+\:隐藏侧边栏
Ctrl+m:打开或者隐藏模拟器

第3章 从第一个简单的“Welcome”页面开始小程序之旅

本章涉及内容:
小程序的基本文件结构
CSS的使用限制
自适应单位rpx
全局样式
App.json配置文件
Flex布局

3.1 认识小程序的基本文件结构

官方示例项目的文件及文件结构

根目录下面有3个文件:app.js、app.json和app.wxss。一个小程序项目必须有这3个描述App的文件,它们必须放在应用程序的根目录下,否则小程序会提示找不到app.json文件。

app.js、app.json和app.wxss的含义
这3个文件是应用程序级别的文件。
接着是和这3个应用程序级别文件平行的pages文件夹。一个小程序由若干个页面文件构成。
.js、.wxml、.wxss和.json文件的含义

wxml文件类似于我们熟悉的HTML文件,用来编写页面的标签和骨架,不同的是wxml文件里的标签元素不可以使用HTML标签,只能使用小程序自己封装的一些组件,这些组件也是我们后面要重点学习的知识。
wxss文件的作用类似于我们熟悉的CSS文件,用于编写小程序的样式,实际上小程序的样式编写语言就是CSS,只是把.css文件换成了.wxss文件。
json文件用来配置页面的样式与行为。
js文件类似于我们前端编程中的JavaScript文件,用来编写小程序的页面逻辑。
以上4种类型的页面文件的文件名称必须相同,这是要注意的一个地方。
utils文件夹,这个文件夹用来存放一些公共的js文件。

3.2 开始动手编写第一个小程序页面

在app.json 中注册 welcome 页面
注册welcome页面

如果有多个页面,需要将每个页面的路径加入到pages这个数组下,否则小程序不会加载这些页面。
多页面
页面的添加或者删除都需要在pages数组下面增减对应的页面路径,否则小程序会报错。

即使welcome.js文件是一个空文件,依然需要在welcome.js中主动调用一下Page()方法。即使你目前不想在.json文件中配置任何属性,也需要加入一个空的{},以保证小程序能正确执行。

如果app.json文件下pages数组里的页面路径,指向的是一个不存在的文件,那么MINA框架会自动创建这个页面的4个文件。

3.3 构建welcome页面的元素和样式

welcome.wxml

这段代码总共使用了3个微信小程序的组件,分别是
view、text和image组件。
view组件通常作为容器来使用,类似于HTML中的div标签;
text组件用来显示一段文本,类似于HTML中的span标签;
image组件用来显示一张图片,类似于HTML中的img标签。

图片默认宽度300px、高度225px

相对路径与绝对路径在小程序中同样有相对路径和绝对路径的区别。
它以“/”开头,“/”代表根目录。

1
<image src="../../images/avatar/avatar-1.png"></image>

路径中的“..”表示向上一级。

真实项目中,图片资源尽量不要存储在小程序的目录中,因为小程序的大小不能超过1MB,超过则无法真机运行和发布项目。应该将图片都存放在服务器上,让小程序通过网络来加载图片资源。

3.4 小程序所支持的CSS选择器

CSS选择器描述

同时需要注意的是,本地资源在wxss中是无法使用的。比如background-image,如果使用的是本地图片,则无法显示,可以使用网络图片来代替本地图片。

3.5 Flex布局

Flex布局是W3C组织在2009年提出的一个新的布局方案,其宗旨是让页面的样式布局更加简单,并且可以很好地支持响应式布局。这并不是小程序所独有的技术,它本身是CSS语法的一部分。只不过早期时候,主流的浏览器对Flex布局的支持并不完善,造成了很多开发者不知道有这种布局的存在或者使用非常少,我们还是习惯使用传统的position和float属性来布局。但传统的布局方式有它的缺陷,比如像垂直居中就不是那么容易实现,Flex可以很好地解决这些问题。

这里推荐一个学习方法。编程里的知识点是非常细小而琐碎的,学习不同的知识应该掌握不同的方法。对于学习CSS这类知识,笔者认为较好的学习方法应该是在实践中学习。比如Flex布局的学习,我们首先应当大致浏览一下整个Flex的知识树,知道Flex解决了什么问题,有什么特点,大致有几类属性就够了。当我们在做项目遇到布局问题时,脑海里就能意识到Flex可能可以解决这个问题。接着我们抱着试试看的心态,带着目的去查找Flex布局的相关资料,即解决了问题,又能在实践中加深对Flex布局的理解,这比单纯死记硬背效果要好很多。人脑总是对形象化的东西记忆特别深刻,所以我们应当尽量在实践中学习知识。当然,也有可能Flex不能解决问题,但你查找和尝试解决问题的这个过程本身就是很好的学习手段。

小程序自适应单位rpx简介

在小程序里,长度单位既可以使用rpx,也可以使用px。使用rpx可以使组件自适应屏幕的高度和宽度,但使用px不会。要透彻地理解rpx需要对移动端分辨率有一定的了解,比如物理分辨率px、逻辑分辨率pt等概念。

建议以iPhone 6的宽度750个物理像素作为标准,来做设计图。在此宽度下,这张设计图里每个元素的尺寸转换到小程序样式时,转换比例为1物理像素=1rpx=0.5px。rpx和px就是小程序样式里可以使用的两种长度单位。

最后,我们为什么要强调最好是在iPhone 6的尺寸下做设计图呢?因为只有在iPhone 6的尺寸下,设计图里的1个像素才满足下面的转换关系:1物理像素=1rpx=0.5px如果不以iPhone 6的标准来做设计图,也是可以的。但非iPhone 6的尺寸下,设计图与rpx、px的转换关系就不是整数倍的,计算起来比较麻烦,所以建议设计图最好以iPhone 6的尺寸标准来设计,这样换算起来很方便。这也是官方建议的一个设计标准。

如果我们足够细心,可以看到小程序的模拟器选择项下,给出了每种机型的分辨率。要强调的是,这里的分辨率指的是逻辑分辨率pt,而非物理分辨率。以iPhone 6为例,模拟器里给出的分辨率是:375×667;Dpr:2它的意思是:iPhone 6的水平方向有375个逻辑像素点,而竖直方向有667个逻辑像素点,每个逻辑像素点包含2个物理像素点。开发者一定要注意逻辑像素和物理像素的区别。我们通常在PS里做的设计图,它的像素可以简单理解为物理像素。再次提醒开发者,1物理像素不等于1px。假设有一张图片在操作系统下显示宽度为750个像素,我们现在想让这个图片水平方向充满整个页面。如果你直接在页面里(iPhone 6模拟机型下)将图片宽度设置为750px,这是不对的。正确的设置方法为750rpx或者375px,才能让图片水平填满小程序。因为,iPhone 6下:1物理像素=1rpx=0.5px。

3.7 全局样式文件 app.wxss

把公共样式放在 app.wxss 文件内。

3.8 页面的根元素page

page代表着整个页面的容器,如果想对页面整体做样式或者属性设置,那么应该考虑page这个页面的根元素。

3.9 app.json中的window配置项

设置window的属性navigationBarBackgroundColor值为#ECC0A8

第4章 文章列表页面

本章涉及内容:
swiper组件构建banner轮播图以及swiper组件的其他属性
详细介绍image组件的4种缩放模式与9种裁剪模式
数据绑定
常用事件

4.1 文章列表页面元素分析及准备工作

文章页面主体部分由两部分构成,上半部分是一个轮播图,下半部分是文章列表。

轮播图效果,小程序已经提供了一个现成的组件——swiper。
小程序启动后显示的首页,由app.json文件里pages数组的第一个元素决定。

4.2 swiper组件

同时,需要注意的是,swiper组件的直接子元素只可以是swiper-item,如果放置其他组件,则会被自动删除。但swiper-item下是可以放置其他组件或者元素的。

4.3 Boolean值的陷阱

vertical=”false”
vertical=”true”
vertical=”aaa”
vertical=”bbb”
从上面的属性举例中找出原因了:
false并不是Boolean类型,而是一个字符串。只要不是空字符串,那么在JavaScript里都会认为这是一个true。

不加入vertical属性
vertical=” “
vertical=”false“
以上小程序都会认为vertical属性设置成了false

4.4 构建文章列表的骨架和样式

4.5 image组件的4种缩放模式与9种裁剪模式

4种缩放模式和9种裁剪模式如果从理论上完全精确理解,还是有稍许的难度的。但这里笔者建议各位开发者,没有必要完全从理论上搞清楚这些模式。当遇到具体问题时,尝试多去更换几个属性,找到最适合自己需求的属性即可。



相关资料

小程序开发原理与实战

Flex 布局教程:语法篇
页面配置
全局配置
swiper
image
sitemap 配置

微信小程序 从入门到实践开发

微信小程序介绍

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

微信小程序的特点:免安装、操作更接近原生 APP、必须在微信中使用
开放注册范围:个人、企业、政府、媒体、其他组织。

微信小程序和微信的原生功能应用在本质上是一样的 —— 都是 Web App。 Web App 就是一种通过 H5 页面技术实现的,和 Native App 的功能和界面几乎一样的手机 App 形态。

微信小程序的优势

1、微信有海量用户,而且粘性很高,在微信里开发产品更容易触达用户;
2、推广 App 或 公众号的成本太高。
3、开发适配成本低。
4、容易小规模试错,然后快速迭代。
5、跨平台。

微信小程序对于创业者的优势

1、App 流量成本的急剧攀上
2、移动互联网格局基本已定,用户主要需求场景已被巨头把持
3、面向所有产品对用户时间的竞争

开发支持:

阅读更多
You need to set client_id and slot_id to show this AD unit. Please set it in _config.yml.