手记

NOW直播和微信小程序那些事

本文作者:ivweb yangkevin 原文出处:ivweb社区 未经同意,禁止转载

微信小程序从发布开始,可谓赚足了眼球,一度引发了开发界“全民学JavaScript”的梗。

为了跟上时代步伐,我们NOW直播团队也在发布后第一时间尝鲜,本文就来扒一扒这几天试水小程序开发的那些事。

入门

准备工作

想要开发微信小程序,首先必须要有一个微信公众平台小程序的帐号(目前帐号只有内测邀请唯一途径),此帐号用于获取app id、secret id、添加开发者等管理后台操作。

然后你需要下载官方提供的微信web开发者工具,这是一个集成了编码、调试、预览、发布功能的一个IDE。

编码功能:

调试功能,集成了chrome开发者工具,可以实现样式预览、JS断点调试等:

发布、预览功能,可以在此上传你的程序,预览生成二维码,提供在手机微信上预览小程序的功能;另外,开发者工具还集成了ES6编译、代码压缩等基础代码构建功能:

开发入门

对于哪怕是只有一点点web前端经验的开发者来说,微信小程序的入门门槛简直是低到不能再低了。

一个小程序的主要文件目录简洁到如下:

├─ app.json 
├─ app.wxss
├─ app.js
└── pages
    ├─ index
    │   ├─ index.wxml
    │   ├─ index.wxss
    │   └─ index.js
    └─ my-page
        ├─ my-page.json
        ├─ my-page.wxml
        ├─ my-page.wxss
        └─ my-page.js

一个小程序大体上分为两大块:

  • 应用实例app

  • 页面pages

应用实例

小程序会读取根目录的app.jsonapp.jsapp.wxss生成程序实例,当然样式文件不是必需的。

程序配置app.json

// app.json
{
  "pages":[
    "pages/index/index"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle":"black"
  }
}

在这个文件里可以针对以下内容作小程序的全局配置:

  • 页面文件的路径

  • 网络超时时间

  • 程序级tab配置

  • 窗口颜色

  • 手机导航栏、小程序标题栏的背景色、字体色,下图是设置了导航栏颜色为绿色的效果:

  • 下拉刷新行为(禁用下拉、下拉文字、图标、颜色),下图是典型的下拉刷新效果:

逻辑脚本app.js

每一个小程序都是通过App({/*configs*/})这样一个App方法来注册的,在其具体的配置中,我们可以监听并处理程序级的生命周期函数、声明全局变量。比如,需要设置程序启动、显示时的一些操作,设置一些程序全局的数据、变量、方法,都可以在这里完成。

//app.js
App({
  onLaunch: function () {
    // do something
  },
  global: {
    data: null
  }
})

app.js里声明的属性及方法,都可以在小程序的任意页面里访问到:

// page.js

//获取应用实例
var app = getApp()
Page({
  doSth: function() {
    console.log(app.globalData);
  }
})

app.js里支持的的程序级的生命周期回调包括:

  • onLaunch 小程序初始化完成时触发

  • onShow 启动,从后台进入前台显示时触发

  • onHide 从前台进入后台时触发

页面

一个页面简单讲可以理解成小程序的一个完整界面单元,每一次完整的界面切换就是page之间的跳转,下图演示一个典型的页面切换、回退过程:

一个页面的组成部分包括:

  • 视图层

    • WXML(WeiXin Markup language) 用于描述页面的结构

    • WXSS(WeiXin Style Sheet) 用于描述页面的样式,非必需
  • 逻辑层

    • JS 控制页面行为及数据变化

    • JSON 页面级配置,非必需

视图层与逻辑层的关系:数据驱动 + 事件绑定

视图层与逻辑层统一通过数据事件相互联系起来,用一句话描述就是:数据驱动。

如果你有使用过React、Vue(或其他MVVM框架)等,对于“数据驱动”肯定一点都不陌生了,没错,小程序毫无疑问吸收了这一开发理念。

来看看一个简单页面的代码:

<!--index.wxml-->

<view bindtap="bindViewTap" class="userinfo">
  <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}"></image>
  <text class="userinfo-nickname">
    {{userInfo.nickName}}
  </text>
</view>
//index.js

Page({
  data: {
    userInfo: {
        nickName: 'test',
        avatarUrl: 'https://a.com/test.png'
    }
  },
  //事件处理函数
  bindViewTap: function() {
    console.log('触发了tap');
  }
})

这段代码实现的是一个简单的页面效果:

可以看到出:

每一个“页面”,都是通过JS逻辑层的Page({/*configs*/})方法来注册的;

WXML统一通过{{data}}花括号的方式来引用逻辑层的数据;

视图层通过bind+event key来和逻辑层的事件回调实现绑定;

当逻辑层需要控制视图层变化时,统一通过关键函数setData来驱动数据变化,间接改变视图,如:

//index.js

Page({
  data: {
    userInfo: {
        nickName: 'test',
        avatarUrl: 'https://a.com/test.png'
    }
  },
  //事件处理函数
  bindViewTap: function() {
    console.log('触发了tap');
    this.setData({
        userInfo: {
            nickName: 'test',
            avatarUrl: 'https://a.com/change.png'
        }
    });
  }
})

上述代码中,setData调用后,页面图片就变化了。setData与React中的setState真的是有相当的相似之处。

其实,微信小程序是完全不支持DOM操作的,千万不要想着手动去控制DOM结构。简单的说,HTML5开发中BOM的那一整套API都没法使用,包括window、document......

WXML在近似于HTML外,吸收了很多其他模板标记语言的优点,例如支持:

  • 条件渲染:
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
  • 循环列表:
<view wx:for="{{items}}">
  {{index}}: {{item.message}}
</view>

事件绑定(交互回调)

前面已经提到过事件绑定,前端人对于事件还是非常熟悉的,事件是视图层到逻辑层的通讯方式。

小程序支持的事件类型包括有:

  • touchstart 手指触摸
  • touchmove 手指触摸后移动
  • touchcancel 手指触摸动作被打断,如来电提醒,弹窗
  • touchend 手指触摸动作结束
  • tap 手指触摸后离开
  • longtap 手指触摸后,超过350ms再离开

和web事件类似,小程序也支持冒泡事件和非冒泡事件,在绑定过程中通过bind(冒泡)和catch(非冒泡)区分:

<!--page.wxml-->

<view id="outter" bindtap="handleTap1">
  outer view
  <view id="middle" catchtap="handleTap2">
    middle view
    <view id="inner" bindtap="handleTap3">
      inner view
      <view id="inner-inner" bindtap="handleTap4">
        inner-inner view
      </view>
    </view>
  </view>
</view>
//page.js

Page({
  data: {
  },
  handleTap1: function () {
    console.log(1);
  },
  handleTap2: function () {
    console.log(2);
  },
  handleTap3: function () {
    console.log(3);
  },
  handleTap4: function () {
    console.log(4);
  }
})

上述程序中,middle view是关键分割点,点击inner-inner view,将会依次显示4,3,2,因为middle view中使用了catch来绑定事件并阻止事件往上层冒泡,middle view及其子组件的tap冒泡事件都会在它这一层被截断。

丰富的组件

WXML文件中,组件是视图的基本组成单元,类似HTML的提供的各种标签,小程序提供了非常全面的组件:

  • UI容器

  • 滚动UI容器

  • 轮播组件

  • 文本容器

  • 视屏、音频

  • 表单组件 (输入框、单/复选、滑动选择等等navtive表单组件),下图示例是一个在HTML环境中不好实现的picker组件,通过调用native,来实现丝般顺滑的体验:

  • 弹窗

  • loading

  • 地图展示

  • 画布(canvas)

......

样式

关于样式,其实没有什么好说的,作为小程序的UI描述语言,几乎与CSS无异,写法、支持的属性也一样。不过,样式文件不是必需的,并且,页面级的样式会优先于全局样式,即index.wxss的样式声明优先级会高于app.wxss

页面的切换和生存周期

前面有说到,页面作为小程序的界面单元,那么肯定就有页面间的切换、跳转、后退等。

以下程序是一个简单的通过tap动作触发页面切换程序:

<!--index.wxml-->
<view class="container">
  <text class="a">index</text>
  <text>go to </text>
  <text class="link" bindtap="bindViewTap">my-page</text>
</view>
// index.js
Page({
  data: {
  },
  //事件处理函数
  bindViewTap: function() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  }
})

除了使用wx.navigateTo方法外,还可以使用wx. redirectTo,这两者的区别是,前者打开的页面中,可以直接返回原来页面切换前的状态;而后者则是完全关闭当前页面打开新页面,返回时,原来的页面只能“重新渲染”。

区别于HTML5应用,小程序为每个页面提供了一些更强大的生命周期和用户操作回调函数:

  • onLoad 监听页面加载
  • onReady 监听页面初次渲染完成
  • onShow 监听页面显示
  • onHide 监听页面隐藏
  • onUnload 监听页面卸载
  • onPullDownRefreash 监听用户下拉刷新动作
为HTML5带来的惊喜

native应用热更新

以往的产品开发中,如果选用HTML5来开发,性能上一般会比native要差一些,而选用native开发,则一般有比较长的版本发布周期。

微信小程序的出现,使得我们在开发native应用的同时,再也不用忍受漫长的版本发布,只要我们编写好了小程序上传,微信就可以通过后台实现客户端的热更新,在产品性能、发布体验上,都达到了质的提升。

强大的API,强大的native功能

虽然开发小程序非常接近于HTML5开发,但是本质上,它已经不再是web,它更像是React Native这样的native开发框架,通过JSBridge,串联起native底层和上层的JS、WXML逻辑。

它通过封装微信客户端提供的文件系统、网络通信、任务管理、数据安全等基础功能,对上层提供了一套完整的API,使得开发者能够非常方便的使用到微信客户端提供的各种基础功能,快速构建一个应用。

所以,在以前HTML5阶段无法实现或实现起来相当困难的一些功能,在小程序时代将会变得非常简单。

小程序为我们提供了丰富、简单的微信原生API,可以方便的调起微信提供的能力或一些系统原生能力:

  • http请求(ajax)

  • 文件上传、下载

  • websocket

  • 本地图片、音频、视频的预览、播放

  • 本地音频的暂停、进度等控制

  • 视频、音频录制、预览、上传

  • 设备网络状态

  • 系统信息(手机型号、设备像素比等)

  • 设备重力感应

  • 罗盘

  • 地理位置信息

  • 动画、绘图

  • 数据缓存,类似HTML5的localstorage,同样有5M的数据存储限制

  • 微信支付

  • 模板消息(服务通知)

......

开发成本低

小程序严格限定了代码的文件、目录结构,即同名依赖识别:

    ├ pages
    ├─ index
    │   ├─ index.wxml
    │   ├─ index.wxss
    │   └─ index.js
    └─ my-page
        ├─ my-page.json
        ├─ my-page.wxml
        ├─ my-page.wxss
        └─ my-page.js

至少在应用、页面的核心代码这一块,开发者没有必要也不允许自定义自己的目录结构;

另外,结合官方提供的开发者工具,无需操心ES6的编译、代码压缩等构建问题。

还没有那么完美

微信小程序的出现,给我们带来了接近HTML5、跨平台的开发体验,带来了接近原生应用的产品体验,然而在我们的实践中,还是品尝到了一些不是那么完美的体验。

关于视频

小程序确实提供了类似HTML5的video组件,用于视频播放,然而把它远远还没达到HTML5的video那么强大:

  • 视频内容无法被覆盖

个人直播业务,基本所有的主播信息、点赞、评论、礼物等等展示都是覆盖于视频之上,如下图:

可是目前的小程序里提供的video组件,会强制所有其他元素必须在其之下,类似CSS中的z-index值,它永远是最高的,这样想通过absolute定位等方式实现漂浮礼物动效等业务需求,变得不可行。

关于后台接口

  • referer限制

小程序提供了一个HTTP请求接口wx.request({/*configs*/}),可以实现类似Ajax的功能,然而当我们使用现有的业务接口时,却遇到了困难。

在浏览器环境下,我们的后台接口作了很多安全限制,最基本的一项就是请求的referer限制,必须是本域请求才能通过。然而,微信小程序明确规定,wx.request这个方法中不允许设置Referer。所以,如果你们的业务有类似我们的这样的后台接口时,会面临一些接口改造。

  • 鉴权

我们正常的web业务,前后端通信中,对cookie的依赖是无处不在的,但是,小程序作为本质上的native应用,请求是没有cookie的,我们的程序中,也没有办法拿到cookie,所以,对于很多现有的业务接口,直接兼容微信小程序,恐怕没那么简单。

小程序提供的唯一鉴权方案需要通过小程序客户端、业务服务端、微信平台服务器三方沟通来实现,具体可以看微信官方文档架构图:

其实,以上就是目前大部分开发平台使用的OAuth 2.0标准鉴权方案。

相对封闭

可能是小程序出于战略考虑,设计上还是相对封闭的,想通过小程序打通现有的业务,包括APP、HTML5网站等等,甚至微信公众号,都会受到一些限制。

我们曾想过在小程序里提供常见的长按公众号二维码识别进入关注界面的功能,目前是无法实现的;另外,想通过小程序打开现有的web页面、调起系统现有的APP等,目前也是不支持的。

</div>

7人推荐
随时随地看视频
慕课网APP

热门评论

cover-view 并不支持touch事件,你是怎么做到上滑下滑切换视频的?求解?谢谢

查看全部评论