微信客户端为原生微信小程序提供的底层生态支持

本文介绍了微信小程序的生态框架,包括响应式数据绑定、页面管理、基础组件、API接口和视图层与逻辑层的交互。小程序通过简单的数据绑定实现界面更新,管理页面路由,提供丰富组件和API,支持模块化开发,确保在不同环境下具备良好的兼容性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

在上一章节中,带大家解读了 微信小程序 的项目基本结构,以及各项目配置文件的作用和用法,目前大家都知道小程序是属于 寄生应用,而它的轻量化,及高效化的优势,让它一度成为主流的开发趋势。

但是,前台的便捷化,就意味着背后更多的事情,是由其他机制代完成了处理,那么作为微信小程序的 寄生宿主微信客户端基座生态环境,为微信小程序 提供了哪些支持以及优化呢?这个问题,也就是本章节 我要给大家带来分享的内容,谈谈,微信小程序的背后,微信为其做了些什么?


在这里插入图片描述

生态框架

小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。小程序可以调用很多宿主环境为其提供的微信客户端的能力,这就使得小程序比普通网页拥有更多的能力。

整个小程序框架系统主要围绕两部分展开:逻辑层(App Service)和 视图层(View)。小程序提供了自己的视图层描述语言 WXML 和 WXSS,以及基于 JavaScript 的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。

这也体现了,微信客户端在对小程序的生态适配支持上,已经形成了一套完善的框架思想体系。


这些框架生态的支持,主要体现在以下几个方面:

响应式数据绑定

微信小程序生态框架的核心是一个响应式的数据绑定系统,可以让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。

如下例:

<view> {{ title }}! </view>
<button bindtap="changeName"> Click me! </button>
Page({
  data: {
    title: "你好"
  },
  changeName() {
    this.setData({
      title: '微信小程序'
    })
  },
})
  • 开发者通过框架将逻辑层数据中的 title 与视图层的 title 进行了绑定,所以在页面一打开的时候会显示 “你好”;
  • 当点击按钮的时候,视图层会发送 changeName 的事件给逻辑层,逻辑层找到并执行对应的事件处理函数;
  • 回调函数触发后,逻辑层执行 setData 的操作,将 data 中的 title 从 “你好 ”变为 “微信小程序”,因为该数据和视图层已经绑定了,从而视图层会自动改变为 “微信小程序”。

页面管理

生态框架 管理了整个小程序的页面路由,可以做到页面间的无缝切换,并给以页面完整的生命周期。开发者需要做的只是将页面的数据、方法、生命周期函数注册到 生态框架 中,其他的一切复杂的操作都交由 生态框架 处理。

如图: 只需要在 app.json 中,配置好页面路径,框架则会自动接管页面的处理,以及路由视图的调配。
在这里插入图片描述

基础组件

一个小程序页面可以分解成多个部分组成,组件就是小程序页面的基本组成单元。
生态框架 提供了一套基础的组件,这些组件自带微信风格的样式以及特殊的逻辑,开发者可以通过组合基础组件,就可以构建出强大的 微信小程序 项目。

丰富的API 接口

生态框架 提供丰富的微信原生 API,可以方便快捷的调用起 微信底层 提供的能力,如获取用户信息,本地存储,支付功能等。


视图层与逻辑层

逻辑层 (App Service)

小程序开发框架的 逻辑层 使用 JavaScript 引擎为小程序提供开发 JavaScript 代码的运行环境以及微信小程序的特有功能。

逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。

开发者写的所有代码最终将会打包成一份 JavaScript 文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker,所以逻辑层也称之为 App Service

JavaScript 的基础上,微信小程序框架增加了一些功能,以方便小程序的开发:

  • 增加 App Page 方法,进行程序注册和页面注册
  • 增加 getApp getCurrentPages 方法,分别用来获取 App 实例和当前页面栈。
  • 提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
  • 提供模块化能力,每个页面有独立的作用域。

注意:
小程序框架的逻辑层并非运行在浏览器中,因此 JavaScript 在 web 中一些能力都无法使用,如 windowdocument 等 。

注册小程序

每个小程序都需要在 app.js 中调用 App 方法注册小程序实例,绑定生命周期回调函数、错误监听和页面不存在监听函数等。点击查看更多API配置

如下在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'
})

整个小程序只有一个 App 实例,是全部页面共享的。开发者可以通过 getApp 方法获取到全局唯一的 App 实例,获取App上的数据或调用开发者注册在 App 上的函数。

const appInstance = getApp()// 获取 app 实例。
console.log(appInstance.globalData) // I am global data

注意:

  • 不要在定义于 App() 内的函数中,或调用 App 前调用 getApp() ,使用 this 就可以拿到 app 实例。
  • 通过 getApp() 获取实例之后,不要私自调用生命周期函数。
注册页面

对于小程序中的每个页面,都需要在页面对应的 js 文件中进行注册,指定页面的初始数据、生命周期回调、事件处理函数等。

使用 Page 构造器注册页面:查看 Page 构造器配置

还可以使用 Component (自定义组件) 构造器构造页面 :

Page 构造器适用于简单的页面。但对于复杂的页面, Page 构造器可能并不好用。
此时,可以使用 Component 构造器来构造页面。 Component 构造器的主要区别是:方法需要放在 methods: { } 里面。

点击查看有关更多 Component 构造器配置详情

页面路由

在小程序中所有页面的路由全部由生态框架进行管理

页面栈

框架以栈的形式维护了当前的所有页面。 当发生路由切换的时候,页面栈的表现如下:

路由方式页面栈表现
初始化新页面入栈
打开新页面新页面入栈
页面重定向当前页面出栈,新页面入栈
页面返回页面不断出栈,直到目标返回页
Tab 切换页面全部出栈,只留下新的 Tab 页面
重加载页面全部出栈,只留下新的页面

开发者可以使用 getCurrentPages() 函数获取当前页面栈。数组中第一个元素为首页,最后一个元素为当前页面。

注意

  • 不要尝试修改页面栈,会导致路由以及页面状态错误。
  • 不要在 App.onLaunch 的时候调用 getCurrentPages(),此时 page 还没有生成。

页面路由器对象。可以通过 this.pageRouter 或 this.router 获得当前页面或自定义组件的路由器对象。

路由的相对路径

页面路由器有 switchTab reLaunch redirectTo navigateTo navigateBack 五个方法,与 wx 对象向同名的五个方法 switchTab reLaunch redirectTo navigateTo navigateBack 功能相同;唯一的区别是,页面路由器中的方法调用时,相对路径永远相对于 this 指代的页面或自定义组件。
如下:

Page({
  wxNavAction: function () {
    wx.navigateTo({
      url: './new-page'
    })
  },
  routerNavAction: function () {
    this.pageRouter.navigateTo({
      url: './new-page'
    })
  }
})
switchTabwx. switchTab
reLaunchwx.reLaunch
redirectTowx.redirectTo
navigateTowx.navigateTo
navigateBackwx.navigateBack

在这里插入图片描述

注意事项

  • navigateTo, redirectTo 只能打开非 tabBar 页面。
  • switchTab 只能打开 tabBar 页面。
  • reLaunch 可以打开任意页面。
  • 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
  • 调用页面路由带的参数可以在目标页面的onLoad中获取。
模块化

可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports 才能对外暴露接口。

注意

  • exports 是 module.exports 的一个引用,因此在模块里边随意更改 exports 的指向会造成未知的错误。所以更推荐开发者采用 module.exports 来暴露模块接口,除非你已经清晰知道这两者的关系。
  • 小程序目前不支持直接引入 node_modules , 开发者需要使用到 node_modules 时候建议拷贝出相关的代码到小程序的目录中,或者使用小程序支持的 npm 功能。

如:

// common.js
function sayHello(name) {
  console.log(`Hello ${name} !`)
}
function sayGoodbye(name) {
  console.log(`Goodbye ${name} !`)
}

module.exports.sayHello = sayHello
exports.sayGoodbye = sayGoodbye

在需要使用这些模块的文件中,使用 require 将公共代码引入

let common = require('common.js')
Page({
  helloMINA: function() {
    common.sayHello('MINA')
  },
  goodbyeMINA: function() {
    common.sayGoodbye('MINA')
  }
})

文件作用域
在 JavaScript 文件中声明的变量和函数只在该文件中有效;不同的文件中可以声明相同名字的变量和函数,不会互相影响。
通过全局函数 getApp 可以获取全局的应用实例,如果需要全局的数据可以在 App() 中设置,

API 支持

小程序开发框架提供丰富的微信原生 API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。
几乎所有小程序的API都挂载在wx对象底下(除了Page/App等特殊的构造器),所以讲述到API概念时,通常指的是wx对象底下的方法详细介绍请参考 API配置文档

微信小程序中,不同的 API 所实现的功能也不一样,所以,这里把API 按照同类型,可以大致分为以下几类:

事件监听API

以 on 开头的 API 用来监听某个事件是否触发,如:wx.onSocketOpen,wx.onCompassChange 等。
这类 API 接受一个回调函数作为参数,当事件触发时会调用这个回调函数,并将相关数据以参数形式传入。

同步API

以 Sync 结尾的 API 都是同步 API, 如 wx.setStorageSync,wx.getSystemInfoSync 等。此外,也有一些其他的同步 API,如 wx.createWorker,wx.getBackgroundAudioManager 等,

同步 API 的执行结果可以通过函数返回值直接获取,如果执行出错会抛出异常。

异步API

大多数 API 都是异步 API,如 wx.request,wx.login 等。这类 API 接口通常都接受一个 Object 类型的参数,这个参数都支持按需指定以下字段来接收接口调用结果:

在这里插入图片描述
回调参数

在这里插入图片描述

异步API 返回 Promise

基础库 2.10.2 版本起,异步 API 支持 callback & promise 两种调用方式。当接口参数 Object 对象中不包含 success/fail/complete 时将默认返回 promise,否则仍按回调方式执行,无返回值。

云开发API

开通并使用微信云开发,即可使用云开发API,在小程序端直接调用服务端的云函数。

通信模型

小程序的渲染层和逻辑层分别由2个线程管理:渲染层的界面使用了WebView 进行渲染;逻辑层采用JsCore 线程运行JS脚本。一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端(下图中采用Native来代指微信客户端)做中转,逻辑层发送网络请求也经由Native转发,小程序的通信模型如图:

在这里插入图片描述

数据驱动

在开发UI界面过程中,程序需要维护很多变量状态,同时要操作对应的UI元素。随着界面越来越复杂,我们需要维护很多变量状态,同时要处理很多界面上的交互事件,整个程序变得越来越复杂。通常界面视图和变量状态是相关联的,如果有某种“方法”可以让状态和视图绑定在一起(视图变,数据变,数据变,视图变),那我们就可以省去手动修改视图的工作。
这个方法就是“数据驱动”,下边我们来介绍一下小程序的数据驱动基本原理。
WXML结构实际上等价于一棵Dom树,通过一个JS对象也可以来表达Dom树的结构,如图:
在这里插入图片描述
WXML可以先转成虚拟Dom,而虚拟Dom 本质上就是一个JS对象,然后再渲染出真正的Dom树,这和 Vue 的思想很像,我们可以看到转换的过程案例如图:
在这里插入图片描述
通过setData 把msg数据从“Hello World”变成“Goodbye”,产生的JS对象对应的节点就会发生变化,此时可以对比前后两个JS对象得到变化的部分(同 Vue diff 虚拟Dom 匹对算法),然后把这个差异应用到原来的Dom树上,从而达到更新UI的目的,这就是“数据驱动”的原理,如图:
在这里插入图片描述

双线程下的界面渲染

小程序的逻辑层和渲染层是分开的两个线程。在渲染层,宿主环境会把WXML转化成对应的JS对象,在逻辑层发生数据变更的时候,我们需要通过宿主环境提供的setData方法把数据从逻辑层传递到渲染层,再经过对比前后差异,把差异应用在原来的Dom树上,渲染出正确的UI界面,大致流程如下图:
在这里插入图片描述


视图层 (View)

小程序的运行环境分成视图层和逻辑层,在前面提到过 WXML 模板和 WXSS 样式就工作在视图层,JS 脚本则工作在逻辑层。小程序的视图层和逻辑层分离是经过很多考虑得出来的模型。

  • 框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。
  • 将逻辑层的数据反映成视图,同时将视图层的事件发送给逻辑层。
  • WXML(WeiXin Markup language) 用于描述页面的结构。
  • WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。
  • WXSS(WeiXin Style Sheet) 用于描述页面的样式。
  • 组件(Component)是视图的基本组成单元。
WXS

注意事项

  • WXS 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行。
  • WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致。
  • WXS 的运行环境和其他 JavaScript 代码是隔离的,WXS 中不能调用其他 JavaScript 文件中定义的函数,也不能调用小程序提供的API。
  • 由于运行环境的差异,在 iOS 设备上小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍。在 android 设备上二者运行效率无差异。
    查看更多WXS 语法配置
事件系统

什么是“事件系统”?

UI界面的程序需要和用户互动,例如用户可能会点击你界面上某个按钮,又或者长按某个区域,这类反馈应该通知给开发者的逻辑层,需要将对应的处理状态呈现给用户。
有些时候程序上的“行为反馈”不一定是用户主动触发的,例如我们在视频video播放的过程中,播放进度是会一直变化的,这种反馈也应该通知给开发者做相应的逻辑处理。
在小程序里边,我们把这种“用户在渲染层的行为反馈”以及“组件的部分状态反馈”抽象为渲染层传递给逻辑层的“事件行为过程”,如图:
在这里插入图片描述
事件描述还可以概述为以下几点:

  • 事件是视图层到逻辑层的通讯方式。
  • 事件可以将用户的行为反馈到逻辑层进行处理。
  • 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
  • 事件对象可以携带额外信息,如 id, dataset, touches。
事件分类
  1. 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
  2. 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。

查看更多事件相关


兼容支持

小程序的宿主环境一直在迭代更新,提供更多的能力给开发者去完成更多的事情,所以你的小程序会运行在不同版本的宿主环境下。为了让你的小程序在不同环境下都能提供相应的服务,我们需要来了解一下在小程序中如何实现兼容办法。
我们可能需要针对不同手机进行程序上的兼容,此时可以使用 wx.getSystemInfo 或者 wx.getSystemInfoSync 来获取手机品牌、操作系统版本号、微信版本号以及小程序基础库版本号等,通过这个信息,我们可以针对不同平台做差异化的服务。

例如:通过wx.getSystemInfoSync获取宿主环境信息

    wx.getSystemInfoAsync({
      success (res) {
        console.log(res.brand) //获取到设备品牌
      }
    })
    brand: "iPhone",      // 手机品牌
    model: "iPhone 6",    // 手机型号
    platform: "ios",      // 客户端平台
    system: "iOS 9.3.4",  // 操作系统版本
    version: "6.5.23",    // 微信版本号
    SDKVersion: "1.7.0",  // 小程序基础库版本
    language: "zh_CN",    // 微信设置的语言
    pixelRatio: 2,        // 设备像素比
    screenWidth: 667,    // 屏幕宽度
    screenHeight: 375,     // 屏幕高度
    windowWidth: 667,    // 可使用窗口宽度
    windowHeight: 375,     // 可使用窗口高度
    fontSizeSetting: 16   // 用户字体大小设置

随着宿主环境的更新,新版本的宿主环境会提供一些新的API,你可以通过判断此API是否存在来做程序上的兼容。

if (wx.openBluetoothAdapter) {
  wx.openBluetoothAdapter()
} else {
  // 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示
  wx.showModal({
    title: '提示',
    content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
  })
}

我们可以选择合适的判断方法来做小程序的向前兼容,以保证我们的小程序在旧版本的微信客户端也能工作正常。在不得已的情况下(小程序强依赖某个新的API或者组件时),还可以通过在小程序管理后台设置“基础库最低版本设置”来达到不向前兼容的目的。例如你选择设置你的小程序只支持1.5.0版本以上的宿主环境,那么当运行着1.4.0版本宿主环境的微信用户打开你的小程序的时候,微信客户端会显示当前小程序不可用,并且提示用户应该去升级微信客户端。


总结

在本章节中,给大家分享介绍了 微信客户端 的宿主环境的基本运行机制以及它所提供的各种能力,组合这些能力可以完成一个体验非常流畅的小程序,同时也了解到如何对小程序在不同环境下兼容的办法,以便给不同环境下的的微信用户提供可靠或者降级的服务。

总览全局,就会发现,微信客户端 提供的生态框架支持,已相当完善,这将助力于我们开发者更加高效化的打造一款小程序。后续,我相信在这些方面会越来越生态体系化。


🚵‍♂️ 博主座右铭:向阳而生,我还在路上!
——————————————————————————————
🚴博主想说:将持续性为社区输出自己的资源,同时也见证自己的进步!
——————————————————————————————
🤼‍♂️ 如果都看到这了,博主希望留下你的足迹!【📂收藏!👍点赞!✍️评论!】
——————————————————————————————

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旧梦星轨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值