工作总结3.0

一、通用

  • ajax

原生ajax封装

ajax({
      url: bms_api + '/member/getPayResultCycle',
      type: 'POST',
      header: {
        Authorization: token, // 用户token,过期重新登录
        tenant: tenant, // 租户区分渠道
      }
}

function ajax(opt) {
  // console.log(opt.api.api)
  !opt.type ? opt.type = 'get' : null; // 默认get请求
  !opt.async ? opt.async = true : null; // 异步会阻断程序

  var xmlHttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('microsoft.XMLHTTP');
  // xmlHttp.timeout = opt.timeout ? opt.timeout : 5000;
  var API = opt.api;

  var url = IPCONFIG.base + PORTCONFIG[API['class']] + API['class'] + '_api' + API.api;

  if (!opt.params["timestamp"]) {
    opt.params["timestamp"] = new Date().getTime();
  }
  var postData = setURLparams(opt.params);

  // console.log(opt.api)

  if (opt.type.toUpperCase() === 'POST') {
    xmlHttp.open(opt.type, url, opt.async);
    xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
    if (opt.header) {
      for (var item in opt.header) {
        xmlHttp.setRequestHeader(item, opt.header[item]);
      }
    }
    xmlHttp.setRequestHeader('tenant',tenant);
    xmlHttp.send(postData);
  } else if (opt.type.toUpperCase() === 'GET') {
    url = url + '?' + postData;
    xmlHttp.open(opt.type, url, opt.async);
    // 只有需要token的接口传自定义header
    if (API['class'] == 'urm' || API['class'] == 'crm') {
      // console_log("API['class'] "+API['class']+' '+API.api);
      if (opt.header) {
        for (var item in opt.header) {
          xmlHttp.setRequestHeader(item, opt.header[item]);
        }
      }
      xmlHttp.setRequestHeader('tenant',tenant);
    }
    xmlHttp.send(null);
  }
  xmlHttp.onreadystatechange = function () {
    if (xmlHttp.readyState == 4) {
      dataHandler(xmlHttp, opt);
    } else {
      // 请求中。。。
      // console.log(url, xmlHttp.readyState, xmlHttp.status)
    }
  };
  // xmlHttp.ontimeout = function () {
  //   console_log('ontimeout: '+opt.api.errorCode+' '+xmlHttp.status);
  //   if (typeof opt.error != 'undefined') {
  //     opt.error(xmlHttp);
  //   } else if (opt.api.errorCode) {
  //     // 请求失败
  //     BadGateWay({
  //       code: opt.api.errorCode,
  //       status: xmlHttp.status,
  //     });
  //   }
  // }
}
  • ajax自定义header跨域问题

问题原因
添加自定义header会导致发送ajax后浏览器自动先发送一个预检请求(OPTIONS),预检请求中的内容是空的,所有后端的拦截器不需要对预检请求中的数据进行校验,此时的校验肯定是不通过的,导致拦截器无法放行,后续的实际请求就无法发送了,浏览器就会认为跨域出现了问题,所以就产生了跨域问题.

在设置了自定义header后,浏览器到后端请求将分为两步进行

1.发送预请求 OPTIONS 请求
浏览器将先发送一个预请求OPTIONS到后端,这里后端需要对OPTIONS请求做出正确响应,可以直接返回200(我司是204)状态码,不用返回内容信息。

2.发送真正的数据请求
浏览器接收到OPTIONS正确响应后会自动执行发送get或post请求。可此时依旧没有请求到后端数据,F12查看控制台输出,会发现报错了。这就是接下来要处理的跨域问题。

  • 跨域的处理主要是服务器端设置响应头

Access-Control-Allow-Origin; //支持全域名访问,不安全,部署后需要固定限制为客户端网址
Access-Control-Allow-Methods; //支持的http 动作
Access-Control-Allow-Headers; //响应头 请按照自己需求添加

header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, tenant");
lQLPJxZiSE3YHfXNAQ3NA4mw3V4s90wBVnkCohedpcDWAA_905_269.png
  • ie浏览器兼容问题
    Access-Control-Allow-Headers多行设置或者配的值有空格就会报错请求不通
lQLPJxZi8-lynFHMts0EzrAWsA3ei8QOZQKjMMfLgPgA_1230_182.png
  • 尺寸适配

    1. rem

rem是CSS3新增的一个相对单位(root em,根em)
1rem=根元素html的font-size值。当页面中所有元素都使用rem单位时,你只需要改变根元素font-size值,所有元素就会按比例放大或者缩小。因此我们只需要写一小段js代码,根据屏幕宽度改变html的font-size值,就可以做到弹性布局。这种方法确实便捷,兼容性也很好,是目前非常主流的弹性布局方案。
rem布局的本质是等比缩放,一般是基于宽度

弊端与优点
弊端之一:和根元素font-size值强耦合,系统字体放大或缩小时,会导致布局错乱
弊端之二:html文件头部需插入一段js代码
rem的优点:移动端rem布局比vw主流的原因 兼容性
vw单位兼容性比rem稍差,ios8、安卓4.4及以上才完全支持。

2. vw

w3c的官方解释
viewpoint width,视窗宽度,1vw=视窗宽度的1%
viewpoint height,视窗高度,1vh=视窗高度的1%

viewport即浏览器可视区域大小
我们可以这样理解 100vw = window.innerwidth, 100vh = window.innerheight
在移动端我们一般都可以认为,100vw就是屏幕宽度。若使用vw布局,就不需要再像rem那样,在js中去动态设置根元素的font-size了,sass中只需要使用这个函数做转换即可

//以iphone7尺寸@2x 750像素宽的视觉稿为例
@function vw($px) {
    @return ($px / 750) * 100vw;
}
 
//假设一个div元素在视觉稿中,宽度为120px,字体大小为12px
div {
    width: vw(120);
    font-size: vw(12);
}

vw单位和百分比%单位对比
百分比%是根据父元素宽度或者高度进行计算,而vw vh固定按照viewport来计算,不会受父元素宽高度影响。
100vw包括了页面滚动条宽度(页面滚动条属于viewport范围内,100vw当然包括了页面滚动条宽度)。但把body或者html设置为width:100%时,是不包括页面滚动条的宽度的。也就是说100vw在有纵向滚动条的情况下,会比100%宽

3. 媒体查询

@media是css3的新属性,它的原理是监控移动端设备的宽度,然后根据不同的宽度,适配不同的css样式,来实现移动端适配

应用场景:
部分pad屏幕高度较小,单独调整垂直间距
小米小爱pad新设备-6寸屏 960x480

@media screen and (max-height: 540px) {
    .content .title .title2 {
        margin-top: -0.7rem;
    }
    .content .durationArea {
        top: 1.8rem;
    }
    .explanation {
        top: 7.24rem;
    }
}
  • android ios交互

    1. android

  // 获取参数
  var params = android.getData();
  var paramsObj = JSON.parse(params);
  var versionName = android.getVersionName();
  packageName = android.getPackageName()
// 方法调用
// 按返回-关闭h5
android.isFinish(true);
// 按返回-上一页h5
android.isFinish(false);

2. ios

DSBridge

DSBridge是目前地球上最好的IOS/Android javascript bridge. DSBridge有四大特点: 支持同步调用、跨平台、三端皆易用。

bridge.call(method,[args,callback])
功能:调用Native api
method: api函数名
args:参数,类型:json, 可选参数
callback(String returnValue):仅调用异步api时需要

html
<script src="./dsbridge.js"></script>

js
// 接收参数 同步
    if (isIOS) {
        var res = dsBridge.call("getParam","getData");
        var params = JSON.parse(res);
        paramObj = params;
    } else if (typeof android === 'object') {
        var params = android.getParam();
        paramObj = JSON.parse(params);
    }
// 异步
// 对于一些比较耗时的api, DSBridge提供了异步支持,正如上面代码所示,此时你需要传一个回调(如果没有参数,回调可作为第二个参数),当api完成时回调将会被调用,结果以字符串的形式传递。
    dsBridge.call("getParam","getData", function (res) {
        console.log(res);
    })

// 回传
    if (isIOS) {
        dsBridge.call("setOrderNum", code, function (res) {
           console.log(res);
        });
    } else if (typeof android === 'object') {
        android.setOrderNum(code);
    }
  • h5支付

场景:app内嵌页 支付宝、微信支付
ios上线审核

function wechatPay() { // 微信支付
    selects.payType = 2;
    console.log(selects);
    $('.pay1').addClass('select');
    $('.pay2').removeClass('select');
}

function aliPay() { //支付宝支付
    selects.payType = 1;
    console.log(selects);
    $('.pay2').addClass('select');
    $('.pay1').removeClass('select');
}

function goPay(code) {
    var timestamp = Date.parse(new Date());
    console.log('timestamp:'+timestamp);
    ajax({
        url: bms_api+'/member/createPrePayOrder',
        type: 'post',
        header: {
            'Authorization': paramObj.token 
        },
        params: {
            preOrderCode: code,
            ip: IP,
            requestTime: timestamp,
            payType: selects.payType,
            tradeType: 'MWEB',
        },
        success: function (data) {
            if(data.retCode == '00000000') {
                console.log(data);
                if (data.retMsg.form) { // 支付宝
                    var content = $('.confirm');
                    var div = creatDom('div', content);
                    div.innerHTML = (data.retMsg.form);  //res.data是返回的表单
                    var forms = document.getElementsByTagName('form');
                    console.log(forms);
                    document.forms[0].submit();
                } else if (data.retMsg.mweb_url) {// 微信
                    location.href = data.retMsg.mweb_url;
                    payResult();
                }
            } else {
                var toast = data.retMsg;
                showToast(toast);
            }
            isClick = true;
        },
        error: function (err) {
            console.log(err);
            isClick = true;
            var toast = '服务器开小差';
            showToast(toast);
        }
    })
}

二、微信小程序

  • ios显示时间为NaN

小程序中的时间数据在安卓上能正常显示,但在ios系统上会显示NaN
原因是ios不支持在数据库中传递 2019-07-02这种格式的日期,必须转换为2019/07/02这种格式才会显示正常;

      data.retInfo.activityList.forEach((item,index) => {
            // console.log(new Date(item.expireTime.replace(/-/g, "/")).getTime());
            // console.log(Number(new Date(item.expireTime.replace(/-/g, "/")))); 
            if(new Date(item.expireTime.replace(/-/g, "/")).getTime() < new Date(data.retInfo.serverTime.replace(/-/g, "/")).getTime()) {
              item.isEnd = 1
            } else {
              item.isEnd = 0
            }
      })
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容