微信小程序

文档

开发指南

视频课程

代码构成

  • .json后缀的JSON配置文件
  • .wxml后缀的WXML模板文件,参考
  • .wxss后缀的WXSS样式文件,参考
  • .js后缀的JS脚本逻辑文件
  • .wxs后缀的WeiXin Script脚本语言,不能跟JS、微信API等交互,但是性能优于JS(一些纯前端的逻辑,如:format处理等可以使用wxs处理),参考详细文档

json配置

注意:JSON文件中无法使用注释,试图添加注释将会引发报错

全局配置 页面配置

app.json 是当前小程序的全局配置,包括了小程序的所有页面路径、界面表现、网络超时时间、底部tab等


{
  "pages": [
    "pages/index/index",
    "pages/logs/index"
  ],
  "window": {
    "navigationBarTitleText": "Demo"
  },
  "tabBar": {
    "list": [{
      "pagePath": "pages/index/index",
      "text": "首页"
    }, {
      "pagePath": "pages/logs/index",
      "text": "日志"
    }]
  },
  "networkTimeout": {
    "request": 10000,
    "downloadFile": 10000
  },
  "debug": true
}

project.config.json 是开发者工具相关配置

开发者工具

详情(右上)-> 本地设置 -> 不校验合法域名... -> 反勾选,看看能不能本地调试

快捷键

工具 -> 设置 -> 快捷键设置

  • 选择所有找到的查找匹配项 -> alt + q
  • 将下一个查找匹配项添加到选择 -> alt + d
  • 将上次选择移动到下一个查找匹配项 => alt + k + d

图标

iconfont

CSS样式

/* 方式1:矢量字体图标,需在iconfont网站设置字体对应的unicode编码 */
/* 尝试使用不同的字体源兼容不同的设备 */
/* 小程序中建议使用TTF和WOFF格式,WOFF2在低版本IOS上不兼容 */
@font-face {
  font-family: 'iconfont'; 
  src: url('//at.alicdn.com/t/font_1716930_3m30jvz589y.eot');
  src: url('//at.alicdn.com/t/font_1716930_3m30jvz589y.eot?#iefix') format('embedded-opentype'),
  url('//at.alicdn.com/t/font_1716930_3m30jvz589y.woff2') format('woff2'),
  url('//at.alicdn.com/t/font_1716930_3m30jvz589y.woff') format('woff'),
  url('//at.alicdn.com/t/font_1716930_3m30jvz589y.ttf') format('truetype'),
  url('//at.alicdn.com/t/font_1716930_3m30jvz589y.svg#iconfont') format('svg');
}
@font-face {
  font-family: 'iconfont'; 
  src: url('//at.alicdn.com/t/font_1716930_3m30jvz589y.svg#iconfont') format('svg');
}
.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.icon-sun:before {
  content: "\e603";
  color: red;
  font-size: 20px;
}

/* 方式2:在iconfont网站下载svg图标,然后转成base64后使用 */
.svg-icon{
  display: block;
  width: 200px;
  height: 200px;  
  background-repeat: no-repeat;
  background: url("data:image/svg+xml;base64,PHN2ZyB0PSIxNTg5MjEzNjE0NDc2IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjggMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjEzMDEiIHdpZHRoPSIyMDAiIGhlaWdodD0iMjAwIj48cGF0aCBkPSJNNTE0LjEzMzMzMyA1MDkuODY2NjY3bS0yNTYgMGEyNTYgMjU2IDAgMSAwIDUxMiAwIDI1NiAyNTYgMCAxIDAtNTEyIDBaIiBmaWxsPSIjZDQyMzdhIiBwLWlkPSIxMzAyIj48L3BhdGg+PHBhdGggZD0iTTUxNC4xMzMzMzMgMTcwLjY2NjY2N2MtMTkuMiAwLTMyLTE0LjkzMzMzMy0zMi0zMlYyOS44NjY2NjdjMC0xNy4wNjY2NjcgMTIuOC0yOS44NjY2NjcgMjkuODY2NjY3LTI5Ljg2NjY2N2gyLjEzMzMzM2MxNy4wNjY2NjcgMCAzMiAxNC45MzMzMzMgMzIgMzJ2MTA4LjhjMCAxNC45MzMzMzMtMTQuOTMzMzMzIDI5Ljg2NjY2Ny0zMiAyOS44NjY2Njd6TTUxNC4xMzMzMzMgMTAyNGMtMTkuMiAwLTMyLTE0LjkzMzMzMy0zMi0zMnYtMTA4LjhjMC0xNy4wNjY2NjcgMTQuOTMzMzMzLTMyIDMyLTMyaDIuMTMzMzM0YzE3LjA2NjY2NyAwIDMyIDE0LjkzMzMzMyAzMiAzMnYxMDguOGMtMi4xMzMzMzMgMTcuMDY2NjY3LTE3LjA2NjY2NyAzMi0zNC4xMzMzMzQgMzJ6TTg1My4zMzMzMzMgNTA5Ljg2NjY2N2MwLTE5LjIgMTQuOTMzMzMzLTMyIDMyLTMyaDEwOC44YzE3LjA2NjY2NyAwIDMyIDE0LjkzMzMzMyAzMiAzMnYyLjEzMzMzM2MwIDE3LjA2NjY2Ny0xNC45MzMzMzMgMzItMzIgMzJoLTEwOC44Yy0xNy4wNjY2NjctMi4xMzMzMzMtMzItMTcuMDY2NjY3LTMyLTM0LjEzMzMzM3pNMCA1MDkuODY2NjY3YzAtMTkuMiAxNC45MzMzMzMtMzIgMzItMzJoMTA4LjhjMTcuMDY2NjY3IDAgMzIgMTQuOTMzMzMzIDMyIDMydjIuMTMzMzMzYzAgMTcuMDY2NjY3LTE0LjkzMzMzMyAzMi0zMiAzMkgzMmMtMTcuMDY2NjY3LTIuMTMzMzMzLTMyLTE3LjA2NjY2Ny0zMi0zNC4xMzMzMzN6TTc0Mi40IDI0Ny40NjY2NjdjLTEyLjgtMTIuOC0xMi44LTMyLTIuMTMzMzMzLTQ0LjhsNzYuOC03Ni44YzEyLjgtMTIuOCAzMi0xMi44IDQ0LjggMFYxMjhjMTIuOCAxMi44IDEyLjggMzIgMCA0NC44bC03Ni44IDc2LjhjLTEwLjY2NjY2NyAxMC42NjY2NjctMzIgMTAuNjY2NjY3LTQyLjY2NjY2Ny0yLjEzMzMzM3pNMTM4LjY2NjY2NyA4NTEuMmMtMTIuOC0xMi44LTEyLjgtMzQuMTMzMzMzLTIuMTMzMzM0LTQ0LjhsNzYuOC03Ni44YzEyLjgtMTIuOCAzMi0xMi44IDQ0LjggMGwyLjEzMzMzNCAyLjEzMzMzM2MxMi44IDEyLjggMTIuOCAzMiAwIDQ0LjhMMTgzLjQ2NjY2NyA4NTMuMzMzMzMzYy0xMi44IDEwLjY2NjY2Ny0zMiAxMC42NjY2NjctNDQuOC0yLjEzMzMzM3pNNzQwLjI2NjY2NyA3MjcuNDY2NjY3YzEyLjgtMTIuOCAzNC4xMzMzMzMtMTIuOCA0NC44LTIuMTMzMzM0bDc2LjggNzYuOGMxMi44IDEyLjggMTIuOCAzMiAwIDQ0LjhsLTIuMTMzMzM0IDIuMTMzMzM0Yy0xMi44IDEyLjgtMzIgMTIuOC00NC44IDBsLTc2LjgtNzYuOGMtMTAuNjY2NjY3LTEyLjgtMTAuNjY2NjY3LTMyIDIuMTMzMzM0LTQ0Ljh6TTEzNi41MzMzMzMgMTIzLjczMzMzM2MxMi44LTEyLjggMzQuMTMzMzMzLTEyLjggNDQuOC0yLjEzMzMzM2w3Ni44IDc2LjhjMTIuOCAxMi44IDEyLjggMzIgMCA0NC44bC0yLjEzMzMzMyAyLjEzMzMzM2MtMTIuOCAxMi44LTMyIDEyLjgtNDQuOCAwTDEzNi41MzMzMzMgMTY4LjUzMzMzM2MtMTAuNjY2NjY3LTEyLjgtMTAuNjY2NjY3LTMyIDAtNDQuOHoiIGZpbGw9IiNGRkM0NDUiIHAtaWQ9IjEzMDMiPjwvcGF0aD48L3N2Zz4=");
}

图标使用

<icon class="iconfont icon-sun"></icon>

<icon class="svg-icon"></icon>

wxml模板

跟vue的模板类似,具体参考:wxml模板

wxss样式

wxss具有css大部分的特性,小程序在wxss也做了一些扩充和修改,具体参考:wxss样式

跟app.json类似,可以写一个app.wxss作为全局样式

wxss在底层支持新的尺寸单位rpx(responsive pixel)来兼容不同尺寸的设备,由于换算采用的浮点数运算,所以运算结果会和预期结果有一点点偏差

rpx把屏幕分成750个单位,每个单位是1/750。iPhone6上屏幕宽度是350px,那么每个RPX约等于0.5px,此时60rpx = 30px

wxss变量使用

/* app.wxss 中定义全局变量*/
Page {
  --txf-main-color: #1aad19;
}

/* test.wxss 中使用变量 */
.title {
  color: var(--txf-main-color, 'red');
}

/* 计算 */
.test {
  height:calc(100vh - 170rpx);
}

常用伪类选择器


/* 当用户将鼠标悬停在元素上时应用样式 */
button:hover {
  background-color: blue;
}

/* 当用户点击元素时应用样式 */
button:active {
  background-color: red;
}

/* 当元素获得焦点时应用样式,通常用于表单元素 */
input:focus {
  border: 1px solid blue;
}

/* 选择作为某个元素的第一个子元素的元素 */
div > p:first-child {
  color: green;
}

/* 选择作为某个元素的最后一个子元素的元素 */
ul > li:last-child {
  border-bottom: none;
}

/* 选择作为某个元素的特定序号的子元素的元素 */
tr:nth-child(even) {
  background-color: #f2f2f2;
}

/* 选择被选中的单选按钮或复选框 */
input[type="checkbox"]:checked {
  background-color: yellow;
}

/* 选择不符合特定条件的元素 */
div:not(.highlight) {
  color: grey;
}

/* 选择文档的根元素,通常用于定义全局变量
   小程序中使用:root无效,使用Page{--main-color: #ff0000;}代替
*/
:root {
  --main-color: #ff0000;
}

wxss命名规范

wxss: 模块__模块元素-描述符

weui-cell__radio

weui-cell__radio-selected

全局

txf__input

具体页面

覆盖: txf__input

不覆盖: txf-login__input

指定字段: txf-login__input-password

指定字段聚焦: txf-login__input-password:focus

js逻辑

跟vue的写法类似,可以调用微信封装的一些API,具体参考:事件 API

小程序宿主环境

小程序的运行环境分成渲染层和逻辑层,其中WXML模板和WXSS样式工作在渲染层,JS脚本工作在逻辑层

小程序的渲染层和逻辑层分别由2个线程管理:渲染层的界面使用了WebView进行渲染;逻辑层采用JsCore线程运行JS脚本

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

微信客户端在打开小程序之前,会把整个小程序的代码包下载到本地,app.json的pages字段的第一个页面就是这个小程序的首页

小程序启动之后,在app.js定义的App实例的onLaunch回调会被执行,整个小程序只有一个App实例,是全部页面共享的

注册小程序


// app.js
App({
  onLaunch (options) {
    // Do something initial when launch.
  },
  onShow (options) {
    // Do something when show.
  },
  onHide () {
    // Do something when hide.
  },
  onError (msg) {
    console.log(msg)
  },
  globalData: 'I am global data'
})

获取全局实例


// xxx.js
const appInstance = getApp()
console.log(appInstance.globalData) // I am global data

注册页面


//index.js
Page({
  data: {
    text: "This is page data."
  },
  onLoad: function(options) {
    // 页面创建时执行
  },
  onShow: function() {
    // 页面出现在前台时执行
  },
  onReady: function() {
    // 页面首次渲染完毕时执行
  },
  onHide: function() {
    // 页面从前台变为后台时执行
  },
  onUnload: function() {
    // 页面销毁时执行
  },
  onPullDownRefresh: function() {
    // 触发下拉刷新时执行
  },
  onReachBottom: function() {
    // 页面触底时执行
  },
  onShareAppMessage: function () {
    // 页面被用户分享时执行
  },
  onPageScroll: function() {
    // 页面滚动时执行
  },
  onResize: function() {
    // 页面尺寸变化时执行
  },
  onTabItemTap(item) {
    // tab 点击时执行
    console.log(item.index)
    console.log(item.pagePath)
    console.log(item.text)
  },
  // 事件响应函数
  viewTap: function() {
    this.setData({
      text: 'Set some data for updating view.'
    }, function() {
      // this is setData callback
    })
  },
  // 自由数据
  customData: {
    hi: 'MINA'
  }
})

页面生命周期

![](http://img.fengfengphp.com/wechat2.png)

Hello World

hover-class属性,单击变样式

hover-start-time属性,触发单击变样式的默认时间,默认50毫秒

bindtap会向父组件冒泡,catchtap不会向父组件冒泡


<!-- This is our View -->
<view> Hello {{name}}! </view>
<button hover-class="bg_red" bindtap="changeName"> Click me! </button>

// This is our App Service.
// This is our data.
var helloData = {
  name: 'Weixin'
}

// Register a Page.
Page({
  data: helloData,
  changeName: function(e) {
    // sent data change to view
    this.setData({
      name: 'MINA'
    })
  }
})

Component构造器

Page构造器适用于简单的页面。但对于复杂的页面,更建议使用Component构造器,参考

类似于自定义组件

详情


Component({
  data: {
    text: "This is page data."
  },
  methods: {
    onLoad: function(options) {
      // 页面创建时执行
    },
    onPullDownRefresh: function() {
      // 下拉刷新时执行
    },
    // 事件响应函数
    viewTap: function() {
      // ...
    }
  }
})

路由相关

参考

模块化

可以将一些公共的代码抽离成为一个单独的js文件,作为一个模块

参考

微信API

参考

详情

其他

事件相关

事件

内置组件可以使用wxs来处理事件(前提是纯前端逻辑,可以提升性能)

网络

参考

api.weixin.qq.com不能用wx.request请求,需要在服务器请求

app.json可配置超时时间,默认是60s


"networkTimeout": {
  "request": 10000,
  "downloadFile": 10000
}

只要成功接收到服务器返回,无论statusCode是多少,都会进入success回调。请开发者根据业务逻辑对返回值进行判断

sitemap配置

可以理解成小程序SEO,参考:sitemap配置

场景值

场景值用来描述用户进入小程序的路径。完整场景值的含义请查看场景值列表,参考 详细配置

第三方组件

weui样式库、weui组件库,可以使用扩展声明的方式直接在小程序中使用。app.json -> useExtendedLib中添加对weui的引用。开发者工具 -> 工具 -> 构建npm

weui滑动删除举例:usingComponents中添加mp-slideview的引用

parser: 渲染HTML

painter、wxml-to-canvas:视图生成为图片

文档阅读顺序

开发前,看一看

指南

框架

使用组件时,找一找

组件 WeUI

使用前端API时,找一找

前端API

使用后端API时,找一找

后端API

指南细分

  • 调试
  • Skyline渲染引擎
  • glass-easel组件框架
  • 性能与体验
  • 等等

npm包

npm

示例

npm init

npm install @vant/weapp -S --production

详情 -> 工具 -> 勾选使用npm模块

工具 -> 构建npm

app.json

{
  // 去掉
  "style": "v2",
  "usingComponents": {
    "van-button": "@vant/weapp/button/index",
    "van-area": "@vant/weapp/area/index",
    ...
  }
}

app.wxss

/* 引入全局样式 */
@import '/miniprogram_npm/@vant/weapp/common/index.wxss'

骨架屏

骨架屏是页面的一个空白版本,通常会在页面完全渲染之前,通过一些灰色的区块大致勾勒出轮廓,待数据加载完成后,再替换成真实的内容

骨架屏

setData

// [] 动态指定属性名称
this.setData({
  [`formData.${field}`]: e.detail.value
});

自定义导航栏

{
  "navigationStyle": "custom",
  "styleIsolation": "apply-shared"    // isolated | apply-shared | shared
}

其他

    wx.getSystemInfo({
      success: (res) => {
        // 如果能找到ios肯定在最左,如:ios 10.0.1。0 + 1 = 1
        // 如果找不到,-1 + 1 = 0
        // !!快速转bool
        // IOS工具栏高度:44  Android工具栏高度:48
        var ios = !!(res.system.toLowerCase().search('ios') + 1)
        console.log(ios)
      }
    })

results matching ""

    No results matching ""