微信小程序面试题之理论篇

本文内容,来源于极客学院的分享,这里只做引用。

说说你对微信小程序的理解?优缺点?

2017年, 微信正式推出了小程序, 允许外部开发者在微信内部运行自己的代码, 开展业务。

截至目前,小程序已经成为国内前端的一个重要业务,跟 Web 和手机 App 有着同等的重要性

小程序是---种不需要下载安装即可使用的应用 , 它实现了应用"触手可及" 的梦想 , 用户扫-扫或者搜-下即可打开应用

也体现了 " 用完即走 " 的理念 , 用户不用关心是否安装太多应用的问题 。应用将无处不在 , 随时可用 , 但又无需安装卸载

注意的是, 除了微信小程序, 还有百度小程序 、微信小程序 、支付宝小程序 、抖音小程序 ,都是每个平台自己开发的 ,都是有针对性平台的应用程序

背景

小程序并非凭空冒出来的一个概念,当微信中的 WebView 逐渐成为移动 Web 的一个重要入口时 ,微信就有相关的 JS-SDK 。

JS-SDK 解决了移动网页能力不足的问题 ,通过暴露微信的接口使得 Web 开发者能够拥有更多的能 力 , 然而在更多的能力之外 JS-SDK 的模式并 没有解决使用移动网页遇到的体验不良 的问题。

因此需要设计 --- 个比较好的系统 , 使得所有开发者在微信中都能获得比较好的体验:

  • 快速的加载
  • 更强大的能力
  • 原生的体验
  • 易用且安全的微信数据开放
  • 高效和简单的开发

这些是 JS-SDK 做不到的, 需要设计一个全新的小程序系统。

对于小程序的开发,提供一个简单、高效的应用开发框架和丰富的组件及 API ,帮助开发者开发出具有原生体验的服务

小程序与H5

其中相比H5,小程序与其的区别有如下:

  • 运行环境: 小程序基于浏览器内核重构的内置解析器
  • 系统权限: 小程序能获得更多的系统权限 , 如网络通信状态 、数据缓存能力等
  • 渲染机制 :小程序的逻辑层和渲染层是分开的

小程序可以视为 只能用微信打开和浏览的H5

小程序和网页的技术模型是一样的,用到的 JavaScript 语言和 CSS 样式也是一样的,只是网页的 HTML 标签被稍微修改成了 WXML 标签

因此可以说,小程序页面本质上就是网页

优缺点

优点:
  • 随搜随用 , 用完即走: 使得小程序可以代替许多APP , 或是做APP的整体嫁接 , 或是作为阉割版功能的承载体
  • 流量大 , 易接受: 小程序借助自身平台更加容易引入更多的流量
  • 安全
  • 开发门槛低
  • 降低兼容性限制
缺点:
  • 用户留存 :及相关数据显示 , 小程序的平均次日留存在13%左右 , 但是双周留存骤降到仅有1%
  • 体积限制 :微信小程序只有2M的大小 , 这样导致无法开发大型-些的小程序
  • 受控微信 : 比起APP , 尤其是安卓版的高自由度 , 小程序要面对很多来自微信的限制 , 从功能接
    口 , 甚至到类别内容 , 都要接受微信的管控

说说微信小程序的生命周期函数有哪些?

跟vue 和 react 框架一样,微信小程序框架也存在生命周期, 实质也是 -堆会在特定时期执行的函数

小程序中 , 生命周期主要分成了三部分 :

  • 应用的生命周期
  • 页面的生命周期
  • 组件的生命周期

应用的生命周期

小程序的生命周期函数是在 app.j s 里面调用的 ,通过 App(Object) 函数用来注册-个小程序 ,指定其小程序的生命周期回调

官网地址:https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html#参数

页面的生命期

页面生命周期函数就是当你每进入/切换到一个新的页面的时候, 就会调用的生命周期函数 同样通过 App(Object) 函数用来注册 --- 个页面

组件的生命周期

组件的生命周期指的是 组件自身的 -些函数 , 这些函数在特殊的时间点或遇到 一些特殊的框架事件时被自动触发 ,通过 Component(Object) 进行注册组件

注意的是:

  • 组件实例刚刚被创建好时 , created 生命周期被触发 , 此时 , 组件数据 this. data 就是在component 构造器中定义的数据 data , 此时不能调用 setData

  • 在组件完全初始化完毕 、 进入页面节点树后 , attached 生命周期被触发 。此时 , this. data 已被初始化为组件的当前值 。这个生命周期很有用 , 绝大多数初始化工作可以在这个时机进行

  • 在组件离开页面节点树后 , detached 生命周期被触发 。退出 --- 个页面时 , 如果组件还在页面节点树中 , 则 detached 会被触发

还有一些特殊的生命周期, 它们并非与组件有很强的关联 ,但有时组件需要获知, 以便组件内部处理。

这样的生命周期称为 "组件所在页面的生命周期 " ,在 pageLifetimes 定义段中定义 ,如下:

js 复制代码
Component({
    pageLifetimes: {
        show: function() {
            // 页面被展示
        },
        hide: function() {
            // 页面被隐藏
        },
    }
})

执行过程

应用的生命周期执行过程:
  • 用户首次打开小程序,触发 onLaunch (全局只触发一次)
  • 小程序初始化完成后,触发onShow方法,监听小程序显示
  • 小程序从前台进入后台,触发 onHide方法
  • 小程序从后台进入前台显示,触发 onShow方法
  • 小程序后台运行一定时间,或系统资源占用过高,会被销毁
页面生命周期的执行过程:
  • 小程序注册完成后,加载页面,触发onLoad方法
  • 页面载入后触发onShow方法,显示页面
  • 首次显示页面,会触发onReady方法,渲染页面元素和样式,一个页面只会调用一次
  • 当小程序后台运行或跳转到其他页面时,触发onHide方法
  • 当小程序有后台进入到前台运行或重新进入页面时,触发onShow方法
  • 当使用重定向方法 wx.redirectTo()或关闭当前页返回上一页wx.navigateBack(),触发onUnload
当存在应用生命周期和页面周期的时候,相关的执行顺序如下:
  • 打开小程序:(App)onLaunch -->(App)onShow --> (Pages)onLoad-->(Pages)onShow-->(pages)onRead
  • 进入下一个页面:(Pages)onHide -->(Next)onLoad -->(Next)onShow -->(Next)onReady
  • 返回上一个页面:(curr)onUnload -->(pre)onShow
  • 离开小程序:(App)onHide
  • 再次进入:小程序未销毁 -->(App)onShow(执行上面的顺序) ,小程序被销毁(App)onLaunch重新开始执行

说说微信小程序中路由跳转的方式有哪些?区别?

是什么

微信小程序拥有 web 网页和 Application 共同的特征

我们的页面都不是孤立存在的,而是通过和其他页面进行交互,来共同完成系统的功能

在微信小程序中,每个页面可以看成是一个 pageModelpageModel 全部以 的形式进行管理

有哪些

常见的微信小程序页面跳转方式有如下 :

  • wx.navigateTo(Object)
  • wx.redirectTo(Object)
  • wx.switchTab(Object)
  • wx.navigateBack(Object)
  • wx.reLaunch(Object)

wx.navigateTo(object)

wx.navigateTo() 用于保留当前页面 、跳转到应用内的某个页面 使用 wx.navigateBack 可以返回到原页面。

对于页面不是特别多的小程序 ,通常推荐使用 wx.navigateTo 进行跳转,以便返回原页面 , 以提高加载速度 。当页面特别多时 ,则不推荐使用

参数表如下所示:

js 复制代码
wx.navigateTo({
  url: 'test?id=1',
  events: {
    // 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
    acceptDataFromOpenedPage: function(data) {
      console.log(data)
    },
    someEvent: function(data) {
      console.log(data)
    }
    ...
  },
  success: function(res) {
    // 通过eventChannel向被打开页面传送数据
    res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' })
  }
})

流程图如下:

wx.redirectTo(object)

重定向 ,当页面过多时,被保留页面会挤占微信分配给小程序的内存 ,或是达到 微信所限制的 10 层页面栈 的情况下, 我们应该考虑选择 wx.redirectTo

wx.redirectTo() 用于关闭当前页面 ,跳转到应用内的某个页面

这样的跳转 , 可以避免跳转前页面占据运行内存 , 但返回时页面需要重新加载 , 增加了返回页面的显示时间

参数表如下所示:

js 复制代码
wx.redirectTo({
  url: 'test?id=1'
})

流程图如下:

wx.switchTab(object)

跳转到 tabBar 页面 ,并关闭其他所有非 tabBar 页面

参数表如下所示 :

wx.navigateBack(object)

wx.navigateBack() 用于关闭当前页面, 并 返回上---页面或多级页面

开发者可通过 getCurrentPages()获取当前的页面栈 ,决定需要返回几层则设置对象的 delta 属性 即可

参数表如下:

js 复制代码
// 在C页面内 navigateBack,将返回A页面
wx.navigateBack({
  delta: 2
})

wx.reLaunch(object)

关闭所有页面 , 打开到应用内的某个页面 , 返回的时候跳到首页

参数表如下所示:

js 复制代码
wx.reLaunch({
  url: 'test?id=1'
})

总结

关于上述五种跳转方式 ,做下总结
  • navigateTo 保留当前页面 , 跳转到应用内的某个页面 , 使用 wx.navigateBack 可以返回到原页
  • redirectTo 关闭当前页面 , 跳转到应用内的某个页面
  • switchTab 跳转到 tabBar 页面 , 同时关闭其他非 tabBar 页面
  • navigateBack 返回上 --- 页面
  • reLanch 关闭所有页面 , 打开到应用内的某个页面
其中关于它们的页面栈的关系如下 :
  • navigateTo 新页面入栈
  • redirectTo 当前页面出栈 , 新页面入栈
  • navigateBack 页面不断出栈 , 直到目标返回页 , 新页面入栈
  • switchTab 页面全部出栈 , 只留下新的 Tab 页面
  • reLanch 页面全部出栈 , 只留下新的页面

说说微信小程序的实现原理?

背景

网页开发 , 渲染线程和脚本是互斥的 , 这也是为什么长时间的脚本运行可能会导致页面失去响应的原因 , 本质就是我们常说的 JS是单线程的

而在小程序中 , 选择了 Hybrid 的渲染方式 ,将视图层和逻辑层是分开的, 双线程同时运行 :

  • 视图层的界面使用 WebView 进行渲染,
  • 逻辑层运行在 JsCore
  • 渲染层 : 界面渲染相关的任务全都在 webview 线程里执行 。-个小程序存在多个界面 , 所以渲染层存在多个 webview 线程

  • 逻辑层 : 采用 JsCore 线程运行 JS 脚本 , 在这个环境下执行的都是有关小程序业务逻辑的代码

通信

小程序在渲染层, 宿主环境会 把wxml 转化成对应的JS对象

在逻辑层发生数据变更的时候,通过宿主环境提供的 setData 方法 把数据从逻辑层传递到染层,再经过对比前后差异,把差异应用在原来的 Dom 树上,染出正确的视图

当视图存在交互的时候,例如用户点击你界面上某个按钮,这类反馈应该通知给开发者的逻辑层,需要将对应的处理状态呈现给用户

对于事件的分发处理,微信进行了特殊的处理将所有的事件拦截后,丢到逻辑层交给 JavaScript 进行处理

由于小程序是基于双线程的 ,也就是任何在视图层和逻辑层之间的数据传递都是线程间的通信, 会有-

定的延时, 因此在小程序中 ,页面更新成了异步操作

异步会使得各部分的运行时序变得复杂-些, 比如在渲染首屏的时候 ,逻辑层与渲染层会同时开始初始

化工作 , 但是渲染层需要有逻辑层的数据才能把界面渲染出来

如果渲染层初始化工作较快完成 , 就要等逻辑层的指令才能进行下-步工作

因此逻辑层与渲染层需要有一定的机制保证时序正确 , 在每个小程序页面的生命周期中 , 存在着若干次

页面数据通信

运行机制

小程序启动运行两种情况:

  • 冷启动 (重新开始) :用户首次打开或者小程序被微信主动销毁后再次打开的情况 , 此时小程序需

    要重新加载启动, 即为冷启动

  • 热启动 : 用户已经打开过小程序 , 然后在-定时间内再次打开该小程序 , 此时无需重新启动 , 只需

    要将后台态的小程序切换到前台, 这个过程就是热启动

需要注意
  • 小程序没有重启的概念
  • 当小程序进入后台, 客户端会维持 ---段时间的运行状态 ,超过 --- 定时间后会被微信主动销毁
  • 短时间内收到系统两次以上内存警告 , 也会对小程序进行销毁 , 这也就为什么-旦页面内存溢出 , 页面会奔溃的本质原因了

开发者在后台发布新版本之后 , 无法立刻影响到所有现网用户 , 但最差情况下 , 也在发布之后 24 小时之

内下发新版本信息到用户

每次冷启动时 ,都会检查是否有更新版本 ,如果发现有新版本 , 将会异步下载新版本的代码包, 并同时

用客户端本地的包进行启动, 即 新版本的小程序需要等下一次冷启动才会应用上

说说提高微信小程序的应用速度的手段有哪些?

加载白屏

小程序启动会常常遇到如下图场景 :

这是因为 ,小程序首次启动前 ,微信会在小程序启动前为小程序准备好通用的运行环境 ,如运行中的线程和 一些基础库的初始化

然后才开始进入启动状态 ,展示一个固定的启动界面 ,界面内包含小程序的图标名称和加载提示图标 。

此时 , 微信会在背后完成几项工作 :

  • 下载小程序代码包
  • 加载小程序代码包
  • 初始化小程序首页

下载到的小程序代码包不是小程序的源代码 , 而是编译 、压缩 、打包之后的代码包

整体流程如下图:

解决方案

围绕上图小程序的启动流程我们可以从:

  • 加载
  • 渲染

两个纬度进行切入。

加载

提升体验最直接的方法是 控制小程序包的大小 , 常见手段有如下:

  • 代码包的体积压缩可以通过勾选开发者工具中" 上传代码时 , 压缩代码 "选项
  • 及时清理无用的代码和资源文件
  • 减少资源包中的图片等资源的数量和大小 (理论上除了小icon , 其他图片资源从网络下载) , 图片资源压缩率有限
  • 分包

采取分包加载的操作, 将用户访问率高的页面放在主包里 ,将访问率低的页面放入子包里 ,按需加载

当用户点击到子包的目录时 , 还是有一个代码包下载的过程 , 这会感觉到明显的卡顿 , 所以 子包也不建议拆的太大

当然我们可以采用 子包预加载技术 , 并不需要等到用户点击到子包页面后在下载子包

渲染

关于微信小程序首屏渲染优化的手段如下:

  • 请求可以在页面onLoad就加载 , 不需要等页面ready后在异步请求数据
  • 尽量减少不必要的https请求 , 可使用 getStorageSync() 及 setStorageSync() 方法将数据存储在本地
  • 可以在前置页面将 --- 些有用的字段带到当前页 , 进行首次渲染 (列表页的某些数据--> 详情页) ,没有数据的模块可以进行骨架屏的占位

在微信小程序中 ,提高页面的多次渲染效率主要在于 正确使用setData

  • 不要过于频繁调用setData , 应考虑将多次setData合并成-次setData调用
  • 数据通信的性能与数据量正相关 , 因而如果有-些数据字段不在界面中展示且数据结构比较复杂或包含长字符串 ,则不应使用 setData 来设置这些数据
  • 与界面渲染无关的数据最好不要设置在data中 , 可以考虑设置在page对象的其他字段下

除此之外 , 对于 -些独立的模块我们尽可能抽离出来 ,这是因为 自定义组件的更新并不会影响页面上其他元素的更新

各个组件也将具有各自独立的逻辑空间 。每个组件都分别拥有自己的独立的数据 、 setData 调用

总结

小程序启动加载性能:
  • 控制代码包的大小
  • 分包加载
  • 首屏体验 (预请求, 利用缓存 ,避免白屏, 及时反馈
小程序渲染性能:
  • 避免不当的使用setData
  • 使用自定义组件
相关推荐
幽络源小助理35 分钟前
美食推荐系统微信小程序
微信小程序·小程序·美食
帅次1 小时前
Flutter Container 组件详解
android·flutter·ios·小程序·kotlin·iphone·xcode
深空数字孪生2 小时前
小程序 UI 设计,怎样在方寸间实现高效交互
ui·小程序·交互
幽络源小助理3 小时前
超市售货管理平台小程序
小程序
帅次5 小时前
Flutter setState() 状态管理详细使用指南
android·flutter·ios·小程序·kotlin·android studio·iphone
浩宇软件开发6 小时前
基于微信小程序的天气预报app
微信小程序·小程序·天气app
用户6120414922137 小时前
小程序做的超市商品管理系统
微信小程序·敏捷开发·小程序·云开发
说私域8 小时前
基于开源AI智能名片链动2+1模式S2B2C商城小程序的项目投资保障研究
人工智能·小程序·开源·零售
程序员小刘8 小时前
基于鸿蒙 HarmonyOS 5 打车小程序案例
华为·小程序·harmonyos
顽强d石头8 小时前
【uniapp】小程序中input输入框的placeholder-class不生效
前端·小程序·uni-app