“小”程序(1)

> 小?小怎么了?

简介

当一个吝啬的甲方提出,想做一款“很简单的”app。那么你可以劝他,不如做个小程序。这种情况下,无需养多两个大前端(ios和安卓),一个微信就能解决绝大多数的适配表现。另外,站在微信这个高频应用的肩膀上,你的小程序完全可以走得很远。所以当人说起"web前端的春天",一定会拿小程序作为例子。

个人对小程序的理解

尽管小程序拥有web前端开发者所艳羡的设备端操作功能。但是有的话必须说在前头:

小程序特点就是"小",不适合大型应用开发。如果你的甲方并不是那么吝啬,欲求也经常不满,那么小程序很可能不是最好的选择。

侧肘于微信,尽管号称有这样或那样能力(比如聊天,社区,区块链),但实际上微信一直很眼红他们拿不到但东西。或者说做的比他们好的东西。一般对这种应用最后结果是找个理由封杀。

一些显著但缺陷:不能主动推送消息给用户。只有在用户提交表单(或支付)一周内,才能发一次消息。或是通过客服在48小时内才能发。

小程序也从来不是什么web前端开发者的核心技能。小程序的那种抄袭着react和vue语法规范从来就不是业界的标准。事实上它的语法是非常嬗变的。当一个人说,自己很会做小程序,充其量也就是一个熟练的api调用工程师而已。

如果你写小程序,应该考虑用react或vue。

小程序发展史

小程序文档:https://developers.weixin.qq.com/miniprogram/dev/framework/

小程序从来就不是什么高深的东西。可以认为小程序就是一个增强版的微信的JS-SDK。本质都是通过微信赋予了网页更多的能力。然而传统的微信网页开发面临白屏的问题。能否将网页应用以离线资源的形式放到微信用户当中呢?鹅厂微信团队有了以下思考:

微信 Web 资源离线存储是面向 Web 开发者提供的基于微信内的 Web 加速方案。 通过使用微信离线存储,Web 开发者可借助微信提供的资源存储能力,直接从微信本地加载 Web 资源而不需要再从服务端拉取,从而减少网页加载时间,为微信用户提供更优质的网页浏览体验。每个公众号下所有 Web App 累计最多可缓存 5M 的资源。

小程序与普通网页开发的区别

小程序的主要开发语言是 JavaScript ,小程序的开发同普通的网页开发相比有很大的相似性。对于前端开发者而言,从网页开发迁移到小程序的开发成本并不高,但是二者还是有些许区别的。

网页开发渲染线程和脚本线程是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应,而在小程序中,二者是分开的,分别运行在不同的线程中。网页开发者可以使用到各种浏览器暴露出来的 DOM API,进行 DOM 选中和操作。而如上文所述,小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。这一区别导致了前端开发非常熟悉的一些库,例如 jQuery、 Zepto 等,在小程序中是无法运行的。同时 JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包在小程序中也是无法运行的。

网页开发者需要面对的环境是各式各样的浏览器,PC 端需要面对 IE、Chrome、QQ浏览器等,在移动端需要面对Safari、Chrome以及 iOS、Android 系统中的各式 WebView 。而小程序开发过程中需要面对的是两大操作系统 iOS 和 Android 的微信客户端。

注册一个自己的小程序

前往https://mp.weixin.qq.com/wxopen/waregister?action=step1注册。

作为登录帐号,请填写未被微信公众平台注册,未被微信开放平台注册,未被个人微信号绑定的邮箱

如果已经注册。可通过微信公众平台直接填写邮箱登录。

小程序的界面长这个样:

点击开发/开发设置有你的appid。请妥善保管。

打开微信开发者工具。切换到小程序

选择项目位置,填上你的appid。生成即可。

那么helloworld就生成了。

认识项目

app.js

全局的入口。

app.json

对整个小程序做全局配置,包括路由,标题,色系等等。

  1. pages 字段 —— 用于描述当前小程序所有页面路径,这是为了让微信客户端知道当前你的小程序页面定义 在哪个目录。
  2. window 字段 —— 定义小程序所有页面的顶部背景颜色,文字颜色定义等。
  3. tabBarw 底部导航

尝试修改一下:

{
  "pages": [
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "一粒小麦",
    "navigationBarTextStyle": "black"
  },
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页",
        "iconPath": "./assets/tab-bar/home.png",
        "selectedIconPath": "/assets/tab-bar/home-active.png"
      },
      {
        "pagePath": "pages/logs/logs",
        "text": "日志",
        "iconPath": "./assets/tab-bar/user.png",
        "selectedIconPath": "/assets/tab-bar/user-active.png"
      }
    ]
  }
}

那么导航就生成了

底部导航2-5个是合法的范围。

你在app.json新定义一个页面,点击"编译",马上就会生成对应的页面文件子项目。相当智能。

page

小程序通过page文件夹管理页面。和现代的经典前端开发不一样的是,每个页面都有一个单页面作为配置。

wxml

可以理解为微信版的html。但这绝不是html。

<view> </view>可以理解为小程序的万能容器div。

基本语法包括数据绑定/条件/列表渲染等,跟vue高度类似。你甚至可以当vue来写。列举不同如下:

# 指令前缀全部换成`wx`,如 wx:if wx:else wx:for
# 指令内容为 "{{ js表达式 }}"
# 吐过绑定一个wxml标签属性可以 <view id="item-{{你的变量}}">

<template>标签则相当于一套自定义的,可复用的模板。

wxss

WXSS 具有 CSS 大部分的特性,小程序在 WXSS 也做了一些扩充和修改。归纳文档的要点就是:

  1. 新增了尺寸单位rpx
  2. 提供了全局的样式和局部样式。和前边 app.json, page.json 的概念相同,你可以写一个 app.wxss 作为全局样式,会作用于当前小程序的所有页面,局部页面样式 page.wxss 仅对当前页面生效。
  3. 此外 WXSS 仅支持部分 CSS 选择器
  4. 不建议css in js

建议使用iPhone6为标准设计稿。

关于rpx:rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。如果设备像素过低,不可避免会产生毛边。

正常来说用class选择器就没什么问题。

index.js

wxml默认的js入口文件。有一个全局的page方法。

核心逻辑都在js文件里,整体小程序开发起来的感觉,像是vue和react混合体,即有data和{{}} 以及wx:if ,又有

类似setState的setData,还有小程序特有的生命周期。

下面来实现一个页面。

const app = getApp()
Page({
  data: {
    name: '一Li小麦', todos: ['吃饭', '睡觉', '搬砖']
  },
  // 以下小程序自动触发。
  onLoad() {
    console.log('index页面加载')
  },
  onShow() {
    console.log('index页面显示')
  },
  onHide() {
    console.log('index页面隐藏')
  },
})
<view>
    <view class='title'>你好, {{name}}</view>
    <input placeholder="请输入想做的事" />
    <button>添加</button>
    <view wx:for="{{todos}}">
        <view>{{index}}: {{item}}</view>
    </view>
</view>

那么一个todo列表就出来了。

小程序入口可以看到onLaunch生命周期,那是首次加载。

事件绑定

目前页面有了界面,还需要添加事件绑定。

事件文档:https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html

事件处理通常是bind你的事件名

bindtap就是绑定点击事件。

事件绑定的形式和vue几乎一模一样。

<!-- wxml -->
<view>
    <view class='title'>你好, {{name}}</view>
    <input bindinput="input" placeholder="请输入想做的事" />
    <button bindtap="addTodo">添加</button>
    <view wx:for="{{todos}}">
        <view>{{index}}: {{item}}</view>
    </view>
</view>
Page({
  // ...
  input(e) {
    console.log(e)
    this.setData({
      val: e.detail.value
    })
  },
  addTodo() {
    this.setData({
      val: '',
      todos: [...this.data.todos, this.data.val]
    })
  }
})

那么这个功能就实现了。

网络请求

你在本地起一个服务,小程序请求是很简单的。

wx.request({
  url:'http//localhost:8000',
  success:(res)=>{
    console.log(res)
  }
})

小程序是不用担心跨域的。

如果是线上,必须是https。上线时得在合法环境下配置校验。

路由

  • 微信路由接口有三个,分别是 wx.redirectTo 、 wx.navigateTo 和 wx.switchTab
  • wx.navigateTo 全局最多调用5次
  • 如果某页面设置为 tab 页,则只支持 wx.switchTab ,不支持其他两种路由方式访问

能力举例

wxml有一套自己的标签(组件)系统。

https://developers.weixin.qq.com/miniprogram/dev/component/functional-page-navigator.html

比如说,有了地图组件(Map)你只要告诉经纬度,就实现了腾讯地图。有比如说富文本编辑器(editor)。

多媒体

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

image

在小程序中多媒体写作:

<image src="xxx.jpg"></image>

而且只支持jpg,png和svg。

image有很多模式。

audio

audio对象经过了微信团队的封装,当然如果不喜欢样式,也可以通过this.audioCtx = wx.createAudioContext('你audio的id')获取到这个对象。然后进行操作。

现在来实现一款播放器。

<view>
    <audio poster="{{poster}}" name="{{name}}" author="{{author}}" src="{{src}}" id="myAudio" controls loop></audio>
    <button type="primary" bindtap="audioPlay">播放</button>
    <button type="primary" bindtap="audioPause">暂停</button>
    <button type="primary" bindtap="audio14">设置当前播放时间为14秒</button>
    <button type="primary" bindtap="audioStart">回到开头</button>
</view>
const app = getApp()
// audio.js
Page({
  onReady(e) {
    // 使用 wx.createAudioContext 获取 audio 上下文 context
    this.audioCtx = wx.createAudioContext('myAudio')
  },
  data: {
    poster: 'http://y.gtimg.cn/music/photo_new/T002R300x300M000003rsKF44GyaSk.jpg?max_age=2592000',
    name: '此时此刻',
    author: '许巍',
    src: 'http://ws.stream.qqmusic.qq.com/M500001VfvsJ21xFqb.mp3?guid=ffffffff82def4af4b12b3cd9337d5e7&uin=346897220&vkey=6292F51E1E384E06DCBDC9AB7C49FD713D632D313AC4858BACB8DDD29067D3C601481D36E62053BF8DFEAF74C0A5CCFADD6471160CAF3E6A&fromtag=46'
  },
  audioPlay() {
    this.audioCtx.play()
  },
  audioPause() {
    this.audioCtx.pause()
  },
  audio14() {
    this.audioCtx.seek(14)
  },
  audioStart() {
    this.audioCtx.seek(0)
  }
})

那么页面就出来了。

camera

调用相机对传统前端来说也是很不错的功能。

<camera device-position="back" flash="off" binderror="error" style="width: 100%; height: 300px;"></camera>
<button type="primary" bindtap="takePhoto">拍照</button>
<view>预览</view>
<image mode="widthFix" src="{{src}}"></image>
Page({
  takePhoto() {
    const ctx = wx.createCameraContext()
    ctx.takePhoto({
      quality: 'high',
      success: (res) => {
        this.setData({
          src: res.tempImagePath
        })
      }
    })
  },
  error(e) {
    console.log(e.detail)
  }
})

那么你还可以给自己拍个照。适用于上传头像等场景

弹窗

Wx.showToast

wx.showshow

Loading wx.showModal

其他能力

  1. 视频
  2. 下拉刷新
  3. 触底加载
  4. 文件上传下载
  5. 数据缓存
  6. 录音
  7. 位置
  8. 转发
  9. 登录
  10. 支付

搬运api什么的最烦了。以后用到再说。

原文发布于微信公众号 - 一Li小麦(gh_c88159ec1309)

原文发表时间:2019-08-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券