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。

    image.png
  • 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 。
面向逻辑像素开发的基本开发流程
  1. 在head 设置width=device-width的viewport,其实就是让viewport的尺寸等于逻辑像素的尺寸
  2. 在css中使用px
  3. 在适当的场景使用flex布局,或者配合vw进行自适应
  4. 在跨设备类型的时候(pc <-> 手机 <-> 平板)使用媒体查询
  5. 在跨设备类型如果交互差异太大的情况,考虑分开项目开发
关于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像素 / 设备独⽴像素 。

移动端滚动问题!看一篇外文

image.png

2.exportexport default

阮一峰Module 的加载实现

ES6 模块与 CommonJS 模块的差异
  • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
  • CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。
CommonJS 模块是 Node.js 专用的,与 ES6 模块不兼容。语法上面,两者最明显的差异是,CommonJS 模块使用require()module.exports,ES6 模块使用importexport

image.png

  • 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。
简单实现:

  1. 后端设置CORS,以egg项目session保持会话的方案。保证 credentials: ture ,且允许所有Origin访问,改成 origin: ctx => ctx.get('origin')

    image.png
  2. 前端项目ajax请求保证当跨域请求时带上cookies: withCredentials: true

    image.png

4. preload和prefetch

插件:preload-webpack-plugin
  1. 脚本块将预加载

    image.png
  2. 使用资源提示(如预装)代替预加载,尤其在移动端需要考虑到用户流量消耗的问题

    image.png
Chrome中的预加载、预装和优先级

Preload, Prefetch And Priorities in Chrome

游览器四个缓存的故事

A Tale of Four Caches

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加密是两个概念,下图做了解。
image.png

一、科普微信支付体系概念:

① 微信支付商户号(直联商户号)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支付
  1. 应用场景:通过使用微信浏览器里面H5网页中调用微信JSSDK执行JS调起支付。
  2. 统一下单:跟微信小程序支付一样,为JSAPI下单,拿到prepay_id
  3. 調起支付:調起支付参数根据规则签名(appID为公众号ID),网页可以调用WeixinJSBridge SDK来調起支付,JSAPI調起支付
  4. 注意内容:为了微信侧回复的信息的准确性,需要调用平台证书拿到解密公钥完成verify验签。当然商户侧主动通信都需要带上各类标准的Authorization头部签名信息,让微信侧做验签。
小程序支付
  1. 应用场景:微信小程序,使用微信支付提供的SDK调起小程序支付。
  2. 统一下单:JSAPI下单,拿到prepay_id
  3. 調起支付:調起支付参数根据规则签名(appID为小程序ID),前端通过wx.requestPayment()特定API調起支付。
  4. 注意内容:为了微信侧回复的信息的准确性,需要调用平台证书拿到解密公钥完成verify验签。当然商户侧主动通信都需要带上各类标准的Authorization头部签名信息image.png

Macrohoo
28 声望2 粉丝

half is wisdom!🤔