写点什么

uni-app 支持 PC 宽屏适配

用户头像
崔红保
关注
发布于: 2020 年 10 月 27 日

天下苦平台碎片化已久。


在移动互联网以前,开发者只需幸福的面对 web。进入移动互联网时代,iOS、Android、H5 以及各种小程序快应用层出不穷,开发者再也幸福不起来。

  • 学习 n 个技术

  • 开发 n 个版本

  • 各版迭代混乱,无法拉齐,用户茫然、内部痛苦

  • 开发测试成本 n 倍暴涨


结果就是工程师不停加班到头秃,但产品的需求仍然做不完、老板的预算一直压不下去,全都痛苦。


uni-app之前已经实现了手机端全覆盖,支持 iOS、Android、H5、微信小程序、阿里小程序、百度小程序、字节跳动小程序、QQ 小程序、快应用、360 小程序,并且在各端均有优异的运行性能。


从 2.9 版本起,uni-app 进一步提供了 PC 等宽屏的适配方案,完成了大统一。


开发者终于可以做到使用一个框架,一把撸掉所有项目。



不说虚的,先来个实际示例,大家直观感受一下:


如下是基于uni-appDCloud社区在 mobile 端的展示效果,列表、详情分为两个页面,点击列表中的帖子,打开详情页面:



如下是基于uni-appDCloud社区同一套代码,稍作配置后,在 pc 端的展示效果,列表、详情在同一个页面中左右分栏显示,点击左侧列表中的帖子,刷新右侧详情窗口的内容,这个 UI 更适合 pc 宽屏,也更有 pc 桌面 App 的体验。



*Tips:点击 DCloud社区演示系统,自己感受 PC 和 Mobile 的自适应。*


怎么样?有没有被酷到?


下面我们具体来讲讲uni-app的 pc 宽屏适配方案,总的来说,包括三个方面:

  • 窗体级适配:leftwindow、rightwindow、topwindow 等分栏

  • 组件级适配:match-media 组件

  • rpx 的宽屏响应


1. 窗体级适配:leftwindow 分栏


手机屏幕和 PC 显示器的设计不同。为了方便手持及接听电话,大多手机的设备高度大于设备宽度(即为窄屏设计),故 mobile App 多为竖屏/窄屏显示的 UI。


而 pc 显示器多为宽屏设计,即设备宽度大于设备高度,在 pc 上的桌面应用,很多会采用左右分栏的 UI 设计。


uni-app以目前手机屏幕为主窗体(window),在左/右/上三个方向,新扩展 leftWindowrightWindowtopWindow三个窗体,这三个窗体可设定在屏幕宽度大于某一阀值时自动出现(展现分栏的宽屏设计),屏幕宽度小于某一阀值后自动消失(恢复单窗口的窄屏设计)。


uni-app主窗体和扩展的三个窗体各自独立,支持互相通信,点击链接、切换页面时支持在相应的窗体内刷新,而不是整屏刷新。


我们以本文开头的DCloud社区为例,讲解如何在uni-app中快捷实现宽屏适配。


我们将社区的列表页作为主窗体,将详情内容扩展到rightWindow中,示意如下:



接下来分步说明,如何在uni-app项目中完成分栏实现。


step 1: 新建 right-window.vue 展现帖子详情


当然,rightWindow无需重写新闻详情页面,是可复用原有代码的,支持把已有详情页面当组件放到 rightWindow 页面中,如下:


<!-- responsive/right-window.vue --><template>  <view>    <!-- 将原来的详情页(/pages/detail/detail.vue),作为一个组件(pages-detail-detail)使用 -->    <pages-detail-detail ref="detailPage"></pages-detail-detail>  </view></template>
<script> export default { created(e) { //监听自定义事件,该事件由左侧列表页的点击触发 uni.$on('updateDetail', (e) => { // 执行 detailPage组件,即:/pages/detail/detail.vue 页面的load方法 this.$refs.detailPage.load(e.detail); }) } }</script>
复制代码


step 2: 在列表页面,处理点击列表后与 rightWindow 交互通信的逻辑。


// 列表页的改造goDetail(detail) {	if (this._isWidescreen) { 		//若为宽屏,则触发右侧分栏详情页的自定义事件,通知右侧窗体刷新新闻详情		uni.$emit('updateDetail', {			detail: encodeURIComponent(JSON.stringify(detail))		})	} else { 		// 若为窄评,则打开新窗体,在新窗体打开详情页面		uni.navigateTo({			url: '/pages/detail/detail?query=' + encodeURIComponent(JSON.stringify(detail))		});	}},
复制代码


step 3:pages.json中注册rightWindow,如下:


{  "rightWindow": {    "path": "responsive/right-window.vue", // 指定 rightWindow 页面文件    "style": {      "width": "calc(100vw - 400px)" // 页面宽度    },    "matchMedia": {      "minWidth": 768 //生效条件,当窗口宽度大于768px时显示    }  }}
复制代码


可以看到,无需太多工作量,就可以快速把一个为手机窄屏开发的应用,快速适配为 PC 宽屏应用。并且以后的代码维护,仍然是同一套,当业务迭代时不需要多处升级。


这套方案的实施,有如下特征:


  • 原先为手机窄屏开发的代码,基本无需修改,可完全适配到 pc 宽屏上;后续新增的业务模块,也是一套代码,同时兼容款窄屏。

  • 增加 pc 宽屏适配后,不影响原先 mobile 端的窄屏实现,窄屏上会自动隐藏 leftWindow/rightWindow 等扩展窗体。

  • rightWindow 里的页面是复用的,不需要重写新闻详情页面,支持把已有详情页面当组件放到 rightWindow 页面中。


更多配置细节,详见文档:https://uniapp.dcloud.net.cn/collocation/pages?id=topwindow


leftWindow 方案除了适用于将原有的 Mobile App 适配到大屏显示,也适用于新开发的 PC 应用,尤其是 PC Admin 管理控制台。


如下是基于leftwindowtopwindow构建的经典pc admin布局:



2. 组件级适配:match-media 组件


leftWindow等方案是页面窗体级适配方案,适用于多页面的组合分栏显示。


那么在同一个页面中,组件是否可以适配不同屏宽?当然可以,此时可以使用组件级适配方案。


除了传统的 css 媒体查询外,uni-app还提供了全平台兼容的 match-media组件 和配套的 [uni.createMediaQueryObserver](https://uniapp.dcloud.net.cn/api/ui/media-query-observer) 方法。


match-media是一个媒体查询适配组件,可以更简单的用于动态屏幕适配。


match-media组件中放置内容,并为该组件指定一组 media query 媒体查询规则,如屏幕宽度。运行时,如屏幕宽度满足查询条件,则这个组件就会被展示,反之则隐藏。


match-media组件的优势包括:

  1. 开发者能够更方便、显式地使用 Media Query 能力,而不是耦合在 CSS 文件中,难以复用。

  2. 能够在模板中结合数据绑定动态地使用,不仅能做到组件的显示或隐藏,在过程式 API 中可塑性也更高。

  3. 能够嵌套式地使用 Media Query 组件,即能够满足局部组件布局样式的改变。

  4. 组件化之后,封装性更强,能够隔离样式、模版以及绑定在模版上的交互事件,还能够提供更高的可复用性。


uni-app推荐采用运行时动态适配的方案,而不是为 PC 版单独编写条件编译(虽然你也可以通过自定义条件编译来实现单独的 PC 版)。这样设计的好处是在 ipad 等设备的浏览器上可以方便的横竖屏切换。


3. rpx 的宽屏响应


设计Mobile App时,设计师常会以 iPhone6 作为视觉稿的标准,即按照 750px 屏幕宽度出图;程序员以 750px 作为基准,根据设备实际尺寸,动态换算(缩放)出适合当前设备屏幕的元素宽高。


这就是 rpx(responsive pixel)的实现思路,只不过 rpx 由框架引擎动态换算元素尺寸,无需程序员写代码干预。


面向 mobile 端时,rpx 是一种很理想的解决方案,因为各种移动设备的屏幕宽度差异不是很大,相对于 750px 微调缩放后的效果,可最大化的还原设计师的设计。


但是,一旦脱离移动设备,在 pc 屏幕,或者 pad 横屏状态下,因为屏幕宽度远大于 750 了。此时 rpx 根据屏幕宽度变化的结果就严重脱离了预期,大的惨不忍睹。


假设一个图文列表的展现,我们针对左侧缩略图定义如下 css:

.uni-media-list-logo {	width: 180rpx;	height: 140rpx;411*(180/750)411*(180/750)411*(180/750)}
复制代码

在手机端,这个显示效果是比较理想的,如下:



当前选择 pixel 2作为模拟设备,屏幕宽度为 411px,故缩略图的宽度变为:180*(411/750) = 98px,高度变为:140*(411/750) = 76px,这个理论计算和实际运行相符,且效果较佳。


同样的代码,如果运行到 pc 端,假设屏幕宽度为 1920px,则缩略图的尺寸将变为:180*(1920/750) = 460px,高度变为:140*(1920/750) = 358px,这个惨不忍睹的大就出来了,一个1920*1080的显示器,只能显示 2 条记录(主要是缩略图高度放大导致的),效果如下:



为此,在uni-app 2.9+起,新增了 rpx 按 750px 做基准屏宽的生效范围控制,即屏幕宽度超过某阀值(默认为 960px)后,将不再以屏幕实际宽度换算元素宽高,而改以固定屏幕宽度(默认为 375px)计算元素宽高。


以上述图文列表为例,当屏幕宽度为 1920px(大于 960px)时,将采用固定的屏幕宽度(默认 375px)计算缩略图的宽高,即:180*(375/750) = 90px,高度变为:140*(375/750) = 70px,按照这个机制,pc 端运行效果如下,相比上图的放大变丑,展现更为理想优雅。



Tips:

  • 750px 生效的屏幕宽度阀值,及宽屏时计算所用的固定屏幕宽度,均支持自定义配置


{  "globalStyle": {    "rpxCalcMaxDeviceWidth": 960, // rpx 计算所支持的最大设备宽度,单位 px,默认值为 960    "rpxCalcBaseDeviceWidth": 375, // 设备实际宽度超出 rpx 计算所支持的最大宽度时,rpx计算所采用的固定屏幕宽度,单位 px,默认值为 375  }}
复制代码


  • 开发者可在 rpx 宽度管控的基础上,略作调整,实现更好的 pc 宽屏效果,如宽屏时,固定列表宽度且居中显示,如下图。当然,此处仅为了演示 rpx 在宽屏下的失控管理,实际应用中,可采用分栏窗口,将列表在左侧分栏中显示,如本文开篇示例截图。



4. 补充


4.1 通过 electron 打包为 windows、mac、linux 客户端


有了宽屏适配,uni-app 的应用就可以方便的通过electron打包为电脑客户端应用,windows、mac、linux 均支持。


开发者可以随意调用electron的 API,以调用更多操作系统的能力(为方便多端兼容,可以将这些特殊 API 写在自定义的条件编译里)


uni-app 插件市场有已经封装好的一些插件,详见:https://ext.dcloud.net.cn/search?q=electron


4.2 一个让手机版网页临时可用于 pc 浏览器的方案


如果你的 h5 版已经开发完毕,还没来得及适配 pc,但想在 pc 上先用起来。那么可以在 pc 网页里使用 iframe,约定好宽度,在里面套用 uni-app 的窄屏版。


当然还可以在 iframe 旁边放置二维码,提供手机版扫码地址,如下是一个实现示例:



5. 结语


uni-app 团队将 keep running,继续完善 uni-app 在 pc、pad 等宽屏设备上的更好适配,并会在 ssr、serverless 方向上重点投入,提供云端一体的更高效率的解决方案(详见uniCloud),帮助企业更高效,帮助开发者更轻松!


欢迎大家到https://github.com/dcloudio/uni-app上给我们 star 鼓励😄


发布于: 2020 年 10 月 27 日阅读数: 415
用户头像

崔红保

关注

中年人,很少写代码的CTO 2018.11.08 加入

还未添加个人简介

评论

发布
暂无评论
uni-app支持PC宽屏适配