小程序技术|青训营笔记

150 阅读5分钟

这是我参与「第四届青训营」笔记创作活动的的第1天

对小程序的初步了解

小程序是一种近些年新兴的前端业务。现如今,小程序已经在我们的手机中随处可见。无论你想要在微信中和朋友家人分享来自其他APP上的信息,还是想要在抖音中用小程序来玩一玩简单轻松的小游戏,都会使用到小程序。这个神奇的小东西以其异于传统应用商店APP的“无需下载,点开即用"的巧妙优势,成功从已经接近饱和的应用市场中杀出一条血路。同时小程序易于开发的优点,也让越来越多的从业人员和爱好者投入这个行业。

从2017年1月微信小程序正式发布;2019年全网小程序的数量就已经赶超APP;到2020年小程序的数量甚至近乎APP的两倍(数据来源:阿拉丁)。而随着一场席卷全球的疫情,部门也投入到了小程序的开发当中,让小程序的推广步入一个更为崭新的阶段。

综合来看,小程序的发展前景十分可观,这个也让各行各业对于小程序的开发逐渐重视起来。

深入了解小程序

第三方开发应用最简单最方便的方式:WebView + JSBridge

这里就需要简单说明什么是WebView和JSBridge了。WebView顾名思义,就像这个名字本身所描述的那样,WebView可以让开发者展示Web页面。使用起来也非常简便,只需创建一个实例,然后调用loadUrl方法就可以进行网页页面的展示。在小程序开发中的用途也十分相似,开发者可以用WebView在APP内展示网页。

JSBridge也同样通俗易懂。其全名为”JavaScript Bridge“,本身是由JavaScript构建的桥梁。它提供给开发者API,用于实现Web和Native彼此的双向调用。

小程序开发过程中的常见问题

  1. 无网络的情况体验不佳
  2. 网页切换体验不佳
  3. 保证网页监控和安全

针对这些问题,我们思考出三个设计目标来解决上述存在的问题:

  1. 开发门槛低:HTML + CSS + JS 作为前端开发最基础,也涉及最先被介绍的三个工具,无疑给广大开发者提供了知识背景上的便捷。
  2. 接近原生的使用体验:资源加载 + 渲染 + 页面切换 (WebView和JSBridge)
  3. 能够保证安全可控:独立JS沙箱 在说明这个之前,我们首先要了解什么是沙箱。 简单来说,沙箱就是一个与外界隔离的独立环境。这样的设计可以保证内外环境互相不干扰,以此来保证不受信任的代码不会对沙箱以外的代码造成影响。 而为了上述目的的JS沙箱,则是通过禁用DOM的API来实现的。但是禁用DOM又会为我们渲染页面这方面带来困难。可选的解决办法是:使用React等不需要操作DOM的方式来渲染页面。

小程序开发方案

经过上述的提问以及解决方法的思考,我们可以整合出来一个大体的思路,具体如下图所示:

屏幕截图 2022-08-19 091538.png

从上图我们不难看出,小程序的开发是双线程架构,主要分为渲染层和逻辑层,然后由Native进行中转(也可以理解为我们经常说的“微信客户端”)

小程序语法

我们用一个简短的例子来简要说明:

TTML:

<view
  tt: for="{{list}}"
  tt: if="{{isOpen}}"
  bindtap="onTap"
/>

TTSS:

view {
  background-color: "red";
  width: 750rpx;
}

JS:

Page({
  data: {
    list: ["a", "b", "c"],
    isOpen: true
  }
  onTap: function() {
    console.log('tap me!')
  }
})

虽然名字不一样,但是我们可以从一些语法和结构上看出,上面三段代码分别对应了HTML、CSS以及JS。接下来我们通过实现一个简单的番茄闹钟小程序,来应用上述的小程序语法。

实现简单的番茄闹钟小程序

屏幕截图 2022-08-19 100150.png

TTML

<view class = "container">
    <view class = "clock">
        {{ timeText }} <!--填充时间-->
    </view>
    <!--重置按钮-->
    <button tt:if="{{ running }}" class="button" bindtap="onRest">重置</button>
    <!--开始按钮,要保持和“重置按钮”是互斥关系(if else)-->
    <button tt:else class="button" bindtap="onStart">开始</button>
 </view>

JS

\\ 格式化时间
const DEFAULT_TIME = 25*60:

function formatTime(time) {
    const minutes = Math.floor(time/60);
    const seconds = time % 60;
    const mText = '0${minutes}'.slice(-2);
    const sText = '0${seconds}'.slice(-2);
    return '${mText}: ${sText}'
}
Page({
    data: {
        timeText: formatTime(DEFAULT_TIME),
        running: false;
    },
    setTimer: function() {
        this.timer = setInterval(() => {
            // 每秒钟时间都减一
            this.time = this.time - 1;
            // 时间减到0之后,清除历史
            if(this.time < 0) {
                clearInterval(this.timer);
                return;
            }
            this.setData({
                // 时间未到达0之前,格式化时间并显示
                timeText: formatTime(this.time),
             })
        }, 1000
     },
     // 开始按钮实现
     onStart: function() {
         if(!this.timer) {
             this.time = DEFAULT_TIME
             this.setTimer()
             this.setData({
                 running: true
             })
         }
     },
     // 重置按钮实现
     onRest: function() {
         clearInterval(this.timer)
         this.timer = null
         this.time = DEFAULT_TIME
         this.setData({
             timeText: formatTime(this.time),
             running: false
          })
      }
})

以上就是实现部分,css不是很重要所以在这里不多赘述。

延伸拓展(摘自张晓伟老师的PPT)

跨端框架

remaxtaromegalompvueuni-app
语法ReactReact/VueVueVueVue
厂家蚂蚁金服京东网易美团Hbuilder

跨端框架原理

从实现原理上分,我们可以分为

  1. 编译时方案 有“无法完全抹平差异”的缺陷。因为小程序在转化过程中很多特性没有办法进行转换,所以一般都选择运行时方案。
  2. 运行时方案 主要依赖虚拟DOM和一个template组件。