1.必须搞懂的移动端适配UI像素概念
css里边px到底是什么?
是viewport像素,不是物理像素,不是逻辑像素,不是渲染像素。
pt逻辑像素/点(像素)
(device point / device pixel / point ),是为了调和距离不一样导致的差异,将所有设备根据距离,透视缩放到一个相等水平的观看距离之后得到的尺寸,是一个抽象的概念,这个单位就是ios开发的px,安卓开发的dp。对于pc,包括win(8+) linux,mac,由各自系统的或者对应软件(比如webview内部)提供的图像界面处理引擎处理进行缩放。例如iphone6的375 * 667的pt像素,但我们经常也会很恶心的叫他们为分辨率px物理像素
(physical pixel)就是反映显示屏的硬件条件,反映的就是显示屏内部led灯的数量,可以简单理解,一组三色led代表一个物理像素,当然根据屏幕物理属性以及处理led的方法不一样。强调这是物理的,因为这是一个纯硬件指标。比如我把屏幕锯了一半,物理像素就只有一半。所以我们一般说的分辨率/像素分辨率
就是物理像素
ppi
(pixel per inch) 每英寸像素,指的是屏幕在每英寸的物理像素,更高的ppi意味着屏幕的清晰度更佳。所谓视网膜屏,其实就是指在该观看距离内超出人类的辨认能力的屏幕。比如对于桌面设备,大于192ppi。对于移动设备大于326ppi。
假设一个ppi160,2寸x3寸的屏幕,物理像素应该是320x480。同理ppi320,同样尺寸的屏幕,物理像素是640x960。viewport像素
本质是DIP(Device Independent Pixels),中文意思设备无关像素,是与上述所有像素都无绝对逻辑关系的一个单位。其实是浏览器内部对逻辑像素进行再处理的结果,简单来理解就是调整逻辑像素的缩放来达到适应设备的一个中间层。dpr设备像素⽐
device pixel ratio,即物理像素和逻辑像素的⽐值。 在 web 中,浏览器为我们提供了window.devicePixelRatio
来帮助我们获取 dpr 。 在 css 中,可以使⽤媒体查询 min-device-pixel-ratio
,区分 dpr :@media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2){ }
。 在 React Native 中,我们也可以使⽤PixelRatio.get()
来获取 DPR 。
面向逻辑像素开发的基本开发流程
- 在head 设置width=device-width的viewport,其实就是让viewport的尺寸等于逻辑像素的尺寸
- 在css中使用px
- 在适当的场景使用flex布局,或者配合vw进行自适应
- 在跨设备类型的时候(pc <-> 手机 <-> 平板)使用媒体查询
- 在跨设备类型如果交互差异太大的情况,考虑分开项目开发
关于px的疑问
不同设备的物理像素是不一样的呀,我怎么实现不同物理像素的布局,如果设计师给你一张图,怎么将它转为我想要的在css里边的px。
首先,你要读懂设计师给你设计图的意图,一般国内的设计师,给出手机版的设计图,一般是750px,注意这里的px,并不是我们的px(逻辑像素),其实是物理像素,因为设计师是根据iphone6或者同等设备来进行设计的,那么要知道iphone6的逻辑像素其实是 375,dpr是2,那么拿到手的设计稿,转换为逻辑像素,就得除以2,我们叫这种设计图,叫两倍图。
同理,如果是375 + 375 + 375大小,那么我们就得除以3,叫三倍图。
如果设计团队有使用墨刀或者蓝湖,你可以在两者里边设置你的查看尺寸,得到我们需要的逻辑像素。
如果设计师不用蓝湖等工具,给你的并不是375的倍数怎么办,我先说办法,原因你们自己琢磨,我不细致分析。
最简单的方法,设计师给你的图的物理宽度w,除以一个数x,如果得的出来的商在360 - 414之间,那么你换算的公式为【你在设计图测量出来的物理像素数除以x】,那么dpr就是x,也就是x倍图。
web端开发
在写CSS时,我们⽤到最多的单位是px,即CSS像素 ,当⻚⾯缩放⽐例为100%时,⼀个CSS像素等于⼀个设备独⽴像素。但是CSS像素 是很容易被改变的,当⽤户对浏览器进⾏了放⼤,CSS像素会被放⼤,这时⼀个CSS像素会跨越更多的物理像素。
⻚⾯的缩放系数 = CSS像素 / 设备独⽴像素 。
移动端滚动问题!看一篇外文
2.export
和 export default
ES6 模块与 CommonJS 模块的差异
- CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。CommonJS 加载的是一个对象(即
module.exports
属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。- CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。
CommonJS 模块是 Node.js 专用的,与 ES6 模块不兼容。语法上面,两者最明显的差异是,CommonJS 模块使用require()
和module.exports
,ES6 模块使用import
和export
。
export
对外输出了指定名字的变量(变量也可以是函数或类)。import命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块的export对外接口的名称相同。export default
为模块指定默认输出。使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。
3.前后端联调跨域方案
Nginx反向代理方案
建议Nginx作为后端服务器代理
优点:nginx反向代理实现跨域,是最简单的跨域方式。只需要修改nginx的配置即可解决跨域问题,支持所有浏览器,支持session,只需保证ajax请求API Server与nginx设置一直,并且不会影响服务器性能。一台具有公网的Nginx服务器可以代理和它能进行内网通信的真实的服务器。让我们的服务器不直接对外暴露,增加其抗风险能力。我们只需要配置nginx,在一个服务器上配置多个前缀来转发http/https
请求到多个真实的服务器即可。原理类似Node中间件代理(两次跨域),同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求就无需遵循同源策略。
简单实现(前端项目axios设置为baseURL: '/api'
,服务器修改/etc/nginx/sites-available/default
如下,再重启nginx),然后具体访问您实际ip地址:80/dash
路径:
server {
listen 80 default_server;
listen [::]:80 default_server;
#root /home/marhoo_ubuntu2/www;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name localhost;
location /dash {
alias /home/marhoo_ubuntu2/web; #配置别名到静态页面源代码目录
}
location /api/ {
rewrite ^/api/(.*)$ /$1 break; #rewrite功能所有对后端的请求加一个api前缀方便区分,真正访问的时候移除这个前缀
proxy_pass http://192.168.31.104:7001;
#将真正的请求代理到真实的服务器地址,ajax的url为/api/xxx的请求将会访问http://192.168.31.104:7001/xxxx
}
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
}
CORS方案 服务器设置header :Access-Control-Allow-Origin
优点:开发阶段,后端可以把接口测试上线,允许所有Origin跨域,前端开发能够实时调用api。
简单实现:
后端设置CORS,以egg项目session保持会话的方案。保证
credentials: ture
,且允许所有Origin访问,改成origin: ctx => ctx.get('origin')
。前端项目ajax请求保证当跨域请求时带上cookies:
withCredentials: true
。
4. preload和prefetch
插件:preload-webpack-plugin
脚本块将预加载
使用资源提示(如预装)代替预加载,尤其在移动端需要考虑到用户流量消耗的问题
Chrome中的预加载、预装和优先级
Preload, Prefetch And Priorities in Chrome
游览器四个缓存的故事
5. box-sizing
box-sizing:主要用来计算一个元素中的宽度和高度的总和的值,而具体的计算方式将会根据box-sizing的属性值来决定,共有两个属性值:content-box和border-box,默认为content-box。
content-box:W3C的标准盒子模型,设置元素的height/width属性指的是content部分的高和宽。
border-box:IE传统盒子模型,设置元素的height/width属性指的是border+padding+content部分的高/宽
6. 微信支付
每个证书都是一个公钥一个私钥,私钥是自己生成签名的时候用的,公钥是给对方验证的时候用的。
比如调用统一下单接口,用商户的api证书私钥生成签名,然后微信用你的api证书的公钥验证你生成的签名是不是正确。
验签回调接口,同理。微信用他的平台的私钥生成签名,然后你用微信平台的公钥来验证这个签名的正确性,目的就是防篡改。
总之这是典型的非对称加密:证书验证私钥生成签名,公钥验证签名是否正确。
注:前后端交互http协议header中带上token,也是采用非对称加密解密的方式,但与签名是不同的概念,因为RSA签名和RSA加密是两个概念,下图做了解。
一、科普微信支付体系概念:
① 微信支付商户号(直联商户号)MCHID:
- 位置:【微信支付中心商户平台】-【账户中心】-【商户信息】-【基本账户信息】-【微信支付商户号】
- 作用:和appid成对绑定,收款资金会进入该MCHID。
② 微信支付关联商户号AppID:
- 位置:微信支付中心商户平台】-【产品中心】-【AppID账号管理】-【查看关联的AppID信息】
- 作用:请求下单接口时需要注意APPID的应用属性,例如公众号场景下的H5,需使用应用属性为公众号的APPID。
③ 商户API证书:
- 包含商户的商户号、公司名称、公钥信息的证书。是用来证实商户身份的, 证书中包含商户号、证书序列号、证书有效期等信息。
- 作用:技术开发人员在调用微信支付安全级别较高的接口(如:退款、企业红包、企业付款)时,会使用到商户API证书。
颁发证书的CA类型,可以将商户API证书分为两种:
- 微信支付颁发的API证书(被官方逐步废除中)——证书文件和私钥文件可从商户平台直接下载。
- 权威CA颁发的API证书——商家可自行生成或使用微信支付提供的证书工具生成证书请求串。证书请求串提交到商户平台后才能获得证书文件。如果是自行生成证书请求串,私钥文件请注意安全保存。如果是通过微信支付证书工具生成证书请求串,则私钥只能通过证书工具导出。
④ 微信平台证书
- 包含微信支付平台标识、公钥信息的证书。商户可以使用平台证书中的公钥进行验签。
- 接口:https://api.mch.weixin.qq.com...
调用“获取平台证书接口API” 获取。平台证书会周期性更换,商户应定时通过API下载新的证书。平台证书更新指引- 位置:平台证书
加密公钥
存在于response中的ciphertext字段中(需要APIv3对称解密,这是报文公钥敏感内容已加密),把它保存起来,最好生成pem文件。- 作用一:后续去验签任何微信支付接口返回的应答签名(在HTTP头Wechatpay-Signature中)和一个验签名串,确保返回信息没有被篡改。具体教程
- 作用二:开发者应当使用微信支付平台证书中的公钥,对上送的敏感参数信息进行加密。
⑤ 商户API私钥:
- 制作商户API证书时,会生成商户私钥,并保存在本地证书文件夹的文件apiclient_key.pem中。
- 作用一:开发者生成签名头必须要用到商户API私钥。
- 作用二:开发者应使用商户私钥对下行的敏感信息的密文进行解密。
⑥ API密钥(暂时可以不用,已逐步废弃,被微信支付平台公钥替代功能):
- 商户调用微信支付API时,要按照指定规则对请求数据进行签名。服务器收到请求后会进行签名验证,从而界定商户的身份并防止其他人恶意篡改请求数据。签名的计算规则中,使用到的key就是API密钥。
⑦ APIv3密钥
- 位置:【微信支付中心商户平台】-【账户中心】-【API安全】-【APIv3密钥】
- 应用:商户在开始微信支付体系前就需要在位置处设置APIv3密钥,这个密钥仅在用户侧对微信平台证书公钥加密报文(已在微信侧APIv3加密)对称解密时有用。
- 科普:
AES-GCM
是一种NIST标准的认证加密算法, 是一种能够同时保证数据的保密性、 完整性和真实性的一种加密模式。它最广泛的应用是在TLS中。APIv3就是一种NIST标准的密钥。
二、支付类型:
JSAPI支付
- 应用场景:通过使用微信浏览器里面H5网页中调用微信JSSDK执行JS调起支付。
- 统一下单:跟微信小程序支付一样,为JSAPI下单,拿到prepay_id
- 調起支付:調起支付参数根据规则签名(appID为公众号ID),网页可以调用WeixinJSBridge SDK来調起支付,JSAPI調起支付。
- 注意内容:为了微信侧回复的信息的准确性,需要调用平台证书拿到解密公钥完成verify验签。当然商户侧主动通信都需要带上各类标准的Authorization头部签名信息,让微信侧做验签。
小程序支付
- 应用场景:微信小程序,使用微信支付提供的SDK调起小程序支付。
- 统一下单:JSAPI下单,拿到prepay_id
- 調起支付:調起支付参数根据规则签名(appID为小程序ID),前端通过wx.requestPayment()特定API調起支付。
- 注意内容:为了微信侧回复的信息的准确性,需要调用平台证书拿到解密公钥完成verify验签。当然商户侧主动通信都需要带上各类标准的Authorization头部签名信息
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。