《微信小程序七日谈》- 第二天:你可能要抛弃原来的响应式开发思维
《微信小程序七日谈》系列文章:
- 第一天:人生若只如初见;
- 第二天:你可能要抛弃原来的响应式开发思维;
- 第三天:玩转Page组件的生命周期;
- 第四天:页面路径最多五层?导航可以这么玩;
- 第五天:你可能要在登录功能上花费大力气;
- 第六天:小程序devtool隐藏的秘密;
- 第七天:不要捡了芝麻丢了西瓜
本系列的文章并非初学教程,而是笔者在具体开发过程中遇到的问题以及部分解决方案。
上篇文章第一天:人生若只如初见简单记录了笔者初步上手开发微信小程序遇到的一些问题,其中提到了wxss的部分细节问题。这篇文章以笔者在开发小程序响应式UI当中遇到的一些问题为例,简单记录一下使用wxss为响应式开发带来的一些模式和思维上的改变。
rem的重定义
前端工程师对rem非常熟悉,rem是以html元素的font-size为基准的尺寸计量单位。rem方便了开发者对响应式UI的尺寸进行统筹管理。
wxss中的rem与css中的rem的含义完全不同,下面是微信官方文档中对rem的定义:
rem(root em): 规定屏幕宽度为20rem;1rem = (750/20)rpx
其中的750这个数值是wxss将设备屏幕的宽统一定义为750rpx,对此,下文会讲解。
各位读到这里是否脑海里浮现了一个想法:wxss的rem怎么听起来有点像bootstrap的栅格系统呢?
wxss将屏幕宽分为20rem,bootstrap将设备屏幕宽度分为12列。初看起来确实有点类似。但其实wxss的rem和bootstrap的栅格系统并不相同。虽然wxss和bootstrap都是讲屏幕尺寸分割为单元格,但rem和栅格的定位不同。
bootstrap的开发者使用指定的classname进行元素间的比例分配,这其实接近为css3中的flexbox;而wxss的rem是一个尺寸单位,你可以在合理的场景下将任何以px为单位的属性值替换为rem。
所以,开发小程序UI时,需要抛弃思维中对rem的常规认知。截止目前,笔者还未遇到必须使用小程序rem的需求,希望大家踊跃探讨。
rpx的奇妙之处
上文提到wxss将设备屏幕的宽统一定义为750rpx,其中的rpx是wxss带来的新的尺寸单位。rpx的定义如下:
rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
css中的px与设备的物理像素并非绝对的一比一关系。尤其是在移动设备上,px与物理像素的比例与设备的dpr(devicePixelRadio)有关,详细的对应关系各位可自行查阅。
rpx称为相对像素值,rpx与物理像素也并非绝对的一比一关系。wxss将设备宽定义为750rpx,是以iPhone6的分辨率(750x1334)为基准划分的。也就是说,在iPhone6上,1rpx=1物理像素=0.5px。官方文档列出了几种屏幕的rpx对应关系如下:

大家可以从中得到rpx和px的换算公式:
1rpx = 1px/dpr
其中iPhone6的dpr=2。
那么rpx带给响应式UI什么改变呢?
目前大部分UI工程师在制作UI稿的时候是按照iPhone6的尺寸设计,然后前端工程师按照UI稿尺寸的一半进行UI的还原开发。这样在iPhone6以及接近iPhone6尺寸的设备上是没有任何问题的。但是移动设备的尺寸多种多样,我们的产品不可能只应对iPhone6(况且iPhone7已经来了哈哈...),所以通常的做法是使用css的媒体查询根据设备的尺寸再进行适配微调。
如果使用rpx是不是就可以解决这个问题呢?笔者在开发过程中尝试使用rpx代替px,使用UI稿的原始尺寸还原UI,截止到目前体验非常好。rpx本身代表的是相对像素,所以不论多大尺寸的屏幕,rpx的UI占据的屏幕比例是绝对固定的,是等比缩放的。
但是rpx并非万能的,比如使用css sprites的图标。请看下文。
sprites图标的响应式处理
使用css sprites作为图标背景时,每个图标的尺寸是以px为单位固定的,比如:
.icon{
background-image: url('//image.daojia.com/icon.png');
display: inline-block;
vertical-align: middle;
}
.icon__circle{
background-position: 0 0;
width: 40px;
height: 40px;
}
如果图标的尺寸不符合UI设计,则进行一定比例的缩放:
.icon__circle{
transform: scale(0.5);
}
也就是说,使用sprites图标不可避免地会用到px,如果与rpx结合使用,是不能保证同rpx一样等比缩放效果的。那么怎么去解决这个问题呢?
根据上文总结出的rpx与px的换算公式,如果想要将以px规定的UI达到同rpx一样的响应式缩放效果,必须将px与设备的dpr进行计算。但是css作为一种标记语言,并不具备动态特性,无法动态地获取设备dpr并计算。所以,单纯使用wxss并不能解决上文提到的问题。
好消息是小程序提供了获取设备信息的API,并且支持CommonJS模块化方案。有了这些功能,我们可以在封装组件时加入动态的逻辑配置。
还是以上文的代码为例,sprites图的icon__circle尺寸为40px*40px,我们的目标是将其适配为20rpx,以下是笔者的开发方案。
比如项目中有一个user组件,包含了一些sprites图标节点。user组件的文件目录如下:
user.wxml- 组件模板;user.wxss- 组件样式;user.js- 组件逻辑。
首先给user.wxml中icon对应的element设置动态的transform:
<view class='icon icon__circle' style="transform: scale({{iconScale}})"></view>
其中iconScale是引用user的外部组件index传递给user组件的:
<import src='user.wxml'/>
<template is='product-user' data="{{iconScale: userIconScale}}"/>
userIconScale是index组件的一个data,userIconScale的值并非index组件规定的,而是由index组件的js调用user.js动态获取的。以下代码是user.js暴露的API:
const ORIGIN_ICON_PX = 40;
const TARGET_ICON_RPX = 20;
module.exports = {
getIconScale() {
let result = 1;
wx.getSystemInfo({
success: function(res) {
let _dpr = res.pixelRatio;
result = TARGET_ICON_RPX/(ORIGIN_ICON_PX * _dpr);
}
});
return result;
}
}
然后在index组件的js中调用以上API:
let getIconScale = require('user.js').getIconScale;
Page({
data: {
userIconScale: 1
},
onLoad(){
this.setData({
userIconScale: getIconScale()
});
}
});
以上只是初步的方案,很多地方需要再仔细琢磨。不过以上方案基本上具备了一个组件的逻辑封装,并且达到了我们对响应式的开发需求。
总结
第二天的开发经历还是颇有收获的,不仅仅是对小程序开发模式的熟悉,而且对一些综合方案也有一定的深入。期待后续吧。
《微信小程序七日谈》- 第二天:你可能要抛弃原来的响应式开发思维的更多相关文章
- 《微信小程序七日谈》- 第四天:页面路径最多五层?导航可以这么玩
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 微信小 ...
- 《微信小程序七日谈》- 第三天:玩转Page组件的生命周期
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 前两篇 ...
- 《微信小程序七日谈》- 第一天:人生若只如初见
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 微信小 ...
- 《微信小程序七日谈》- 第五天:你可能要在登录功能上花费大力气
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...
- 《微信小程序七日谈》- 第六天:小程序devtool隐藏的秘密
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...
- 《微信小程序七日谈》- 第七天:不要捡了芝麻丢了西瓜
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...
- 使用wepy开发微信小程序商城第二篇:路由配置和页面结构
使用wepy开发微信小程序商城 第二篇:路由配置和页面结构 前言: 最近公司在做一个微信小程序的项目,用的是类似于vue的wepy框架.我也借此机会学习和实践一下. 小程序官方文档:https://d ...
- 如何在微信小程序定义全局变量、全局函数、如何实现 函数复用 模块化开发等问题详解
1.如何定义全局数据 在app.js的App({})中定义的数据或函数都是全局的,在页面中可以通过var app = getApp(); app.function/key的方式调用,不过我们没有必要 ...
- 微信小程序自学第二课:app及页面的生命周期、使用setData绑定数据
一.App声明周期 1.App() app.js中的App() 函数用来注册一个小程序.接受一个 object 参数,其指定小程序的生命周期函数等. 示例代码: App({ onLaunch: fun ...
随机推荐
- MVC视图中处理Json
/// <summary> /// 登录 /// </summary> /// <param name="value"></param&g ...
- MRBS, meeting room manager system,会议预定管理系统
MRBS,会议管理软件,新增权限控制,周期性例会管理等. 下载地址 http://www.dotnetcms.org/mrbs/mrbs.rar
- iOS Vuforia:TextReco 增加自己的单词库
Vuforia的文字识别引擎提供了很好的文字识别功能.引擎依赖于UTF-8字符编码,现支持的字符有A-Z a-z,换行符.空格.单引号.短斜杠.Note:不支持中文及数字.能识别的字体是: ...
- FTP客户端上传下载Demo实现
1.第一次感觉MS也有这么难用的MFC类: 2.CFtpFileFind类只能实例化一个,多个实例同时查找会出错(因此下载时不能递归),采用队列存储目录再依次下载: 3.本程序支持文件夹嵌套上传下载: ...
- Win C盘扩容
最近C盘真的空间越来越小了,记下简单的几个操作步骤以便以后用到. 参考文档: http://jingyan.baidu.com/article/90808022a6c6b7fd91c80fc8.htm ...
- 用node开发repl应用
前言 每次看到一些库npm -g install xx然后,执行xx就可以跑起来,这不就是一个shell工具了吗,那么我不就可以不用学习shell语法,直接用js写命令行脚本了吗! 什么是REPL应用 ...
- Asp.net Core 使用Redis存储Session
前言 Asp.net Core 改变了之前的封闭,现在开源且开放,下面我们来用Redis存储Session来做一个简单的测试,或者叫做中间件(middleware). 对于Session来说褒贬不一, ...
- WPF TextBlock 绑定 换行
最近有个小需求 需要在textblock中换行 其实textblock换行有很多写法,比如: Xaml: <TextBlock Text="AAAAA BBBBB" /> ...
- 《objective-c基础教程》学习笔记(十一)—— 类别
在编写面向对象程序的时候,我们经常想为现有的类添加一些新的行为.有些时候,我们可以创建这个类的子类.但是,如果我们用到工具集或者类库的时候,无法处理新建的子类.这时,Objective-C就给我们提供 ...
- session和jsessionid有什么关系
首先,并不是说你一打开一个页面就会产生一个session. 所谓session你可以这样理解:当你与服务端进行会话时,比如说登陆成功后,服务端会为你开壁一块内存区间,用以存放你这次会话的一些内容,比如 ...