网页的一般开发流程中,我们通常会通过JS操作DOM(对应的描述产生的树)

2024-05-12
来源:网络整理

在一般的网页开发过程中,我们通常会通过JS操作DOM(对应HTML的描述而生成的树),从而导致界面发生一些变化,以响应用户的行为。 例如,当用户点击某个按钮时,JS 会将一些状态记录到 JS 变量中,同时通过操作 DOM 的属性或行为来引起界面的一些变化。 当项目变大时,你的代码中会充满大量的界面交互逻辑和程序的各种状态变量。 显然这不是一个好的开发模式,于是就有了MVVM开发模式(例如Vue),主张渲染和逻辑分离。 简单来说,JS不再需要直接控制DOM。 JS只需要管理状态,然后使用模板语法来描述状态和界面结构之间的关系。

小程序的框架也采用了这个思路,如果需要在界面上显示一个字符串。

WXML是这样写的:

{{msg}}

JS 只需要管理状态:

this.setData({ msg: "Hello World" })

通过 {{ }} 语法将变量绑定到接口称为数据绑定。 单独的数据绑定不足以完全描述状态和接口之间的关系。 还需要 if/else 和 for 等控制功能。 在小程序中,这些控制能力是通过wx:开头的属性来表达的。

更详细的文档请参考WXML

3.WXSS风格

WXSS具备了CSS的大部分功能,小程序也在WXSS上做了一些扩展和修改。

添加了新的尺寸单位。 在编写CSS样式时,开发人员需要考虑到移动设备的屏幕会有不同的宽度和设备像素比例,并使用一些技术来转换一些像素单位。 WXSS底层支持新的尺寸单位rpx。 开发者可以免去转换的麻烦,让小程序底层来做转换即可。

提供全局样式和局部样式。 app.json 和 page.json 的概念与之前相同。 你可以将app.wxss编写为全局样式,该样式将应用于当前小程序的所有页面。 本地页面样式page.wxss仅在当前页面生效。 另外,WXSS仅支持部分CSS选择器。

更详细的文档请参考WXSS。

4.JS逻辑交互

一个服务仅仅有界面展示是不够的,还需要与用户进行交互:响应用户点击、获取用户位置等。在小程序中,可以通过编写JS脚本文件来处理用户操作。

{{ msg }} 点击我

当点击按钮的时候,我们希望在界面上显示的msg为“”,所以我们声明了一个属性on:,并在JS文件中声明了一个方法来响应这个点击操作:

Page({ clickMe: function() { this.setData({ msg: "Hello World" }) } })

响应用户操作就是这么简单。 有关更详细的事件,请参阅文档 WXML - 。

另外,你还可以在JS中调用小程序提供的丰富的API。 使用这些API,你可以轻松激活微信提供的能力,比如获取用户信息、本地存储、微信支付等。在前面的例子中,wx. 在//.js中调用获取微信用户的头像和昵称,最后将获取到的信息显示在界面上。 更多API请参考文档小程序的API。

2. 小程序托管环境

我们把微信客户端给小程序提供的环境称为托管环境。 借助宿主环境提供的能力,小程序可以完成许多普通网页无法完成的功能。

1.渲染层和逻辑层

首先我们简单了解一下小程序的运行环境。 小程序的运行环境分为渲染层和逻辑层。 WXML模板和WXSS样式工作在渲染层,JS脚本工作在逻辑层。

小程序的渲染层和逻辑层分别由两个线程管理:渲染层的界面使用Web视图进行渲染; 逻辑层使用Js核心线程来运行JS脚本。 一个小程序有多个接口,因此渲染层有多个Web视图线程。 这两个线程之间的通信会通过微信客户端进行中继(下文也会用本地来指代微信客户端),逻辑层将网络发送的请求也转发到本地。 小程序的通信模型如下图所示。

渲染层和逻辑层的详细文档可以参考框架。

2. 程序和页面

在打开小程序之前,微信客户端会将整个小程序代码包下载到本地。

然后通过app.json的字段就可以知道当前小程序的所有页面路径:

{ "pages":[ "pages/index/index", "pages/logs/logs" ] }

此配置描述定义了项目中的两个页面,位于 // 和 /logs/logs。 字段中写入的第一页是此小程序的主页(打开小程序时看到的第一页)。

所以微信客户端通过小程序的一些底层机制来加载首页的代码并渲染首页。

小程序启动后,会执行app.js中定义的App实例的回调:

App({ onLaunch() { // 展示本地存储能力 const logs = wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs', logs) // 登录 wx.login({ success: res => { // 发送 res.code 到后台换取 openId, sessionKey, unionId } }) }, globalData: { userInfo: null } })

整个小程序只有一个App实例,所有页面共享。 更多事件回调请参考文档注册程序App。

接下来我们简单看一下小程序的页面是如何写的。

可以观察到/logs/logs下实际上有4种类型的文件。 微信客户端首先会根据logs.json配置生成一个界面。 您可以在此 json 文件顶部定义颜色和文本。 然后客户端会加载该页面的WXML结构和WXSS样式。 最后,客户端将加载logs.js。 可以看到logs.js的大致内容是:

// logs.js const util = require('../../utils/util.js') Page({ data: { logs: [] }, onLoad() { this.setData({ logs: (wx.getStorageSync('logs') || []).map(log => { return { date: util.formatTime(new Date(log)), timeStamp: log } }) }) } })

Page是一个页面构造函数,这个构造函数生成一个页面。 在生成页面时,小程序框架会将数据data和.wxml一起渲染,生成最终的结构,这样你就得到了你所看到的小程序的外观。

渲染完界面后,页面实例会收到一个回调,你可以在这个回调中处理你的逻辑。

有关 Page 构造函数的更多详细文档,请参阅注册 Page 页面。

3.组件

小程序为开发者提供了丰富的基础组件。 开发者可以像搭积木一样,组合各种组件来构建自己的小程序。

就像HTML的div、p等标签一样,在小程序中,只需要在WXML中写入对应的组件标签名称,即可将组件显示在界面上。 比如你需要在界面上显示一张地图,你只需要这样写:

在使用组件时,还可以通过属性向组件传递值,从而使组件可以显示不同的状态。 例如,如果我们希望一开始的地图中心的经纬度是上海东方明珠塔,那么就需要声明(中心经度)和(中心纬度)两个属性:

组件的内部行为也将通过事件被开发人员感知。 例如,用户点击地图上的某个标记,可以在js中编写一个函数来处理:

当然,你也可以通过或来控制组件的外部样式,以适应你界面的宽度、高度等。

分享