开发问题

移动端

移动端各种禁用

  • 禁止长按图片弹出菜单、vivo手机的坑-禁止微信浏览器网页点击图片,图片会自动放大
img {
  pointer-events: none; 
  -webkit-user-select: none;
  -moz-user-select: none;
  -webkit-user-select:none;  
  -o-user-select:none;  
  user-select:none;  
}

如果想要在微信中识别二维码,将 pointer-events 改为 auto 即可!

  • 禁止文本选择
p {
  -webkit-user-select: none;
  -moz-user-select: none;
  -webkit-user-select:none;  
  -o-user-select:none;  
  user-select:none;  
}
  • 禁止显示在浏览器打开:
document.oncontextmenu=function(e){
  // 或者return false;
  e.preventDefault();
};

css

font-weight

font-weight:属性设置文本的粗细。100、200、300。。。900。定义由粗到细的字符。400 等同于 normal,而 700 等同于 bold。mac系统下大于等于950失效,Windows有效。

css ios H5页面web页面 上下滑动卡顿问题解决方案

  • 原因1:
html,body {
  height: 100%;
}

删除上述代码即可

  • 其他原因
* {
  -webkit-overflow-scrolling: touch;
}

增加上述代码。

微信公众号开发

微信JS-SDK拍照

拍照或从手机相册中选图接口

当指定来源只有相机时,部分Android机会直接退出,解决办法将来源设置相机和相册两者都有。

安全

获取两个对象不同部分 或 对象对比方法(表单提交只提交修改部分)

/**
* @description 判断变量是不是引用类型
* @param {*} variable - 待判定的变量。接受任意类型
* @returns {Boolean} 如果返回true则表示是引用类型,反之则不是
*/
function variableIsReference(variable) {
  return (
    variable !== null &&
    variable !== undefined &&
    typeof variable !== "string" &&
    typeof variable !== "number" &&
    typeof variable !== "boolean" &&
    typeof variable !== "symbol"
  );
}

/**
 * @description 两个对象字面量比较  注意,如果obj1 = {a:"123",b:456}, ob2 = {b:456,a:"123"};本方法也会判定他们完全相等
 * @param {Object} o1 - 必填。要比较的对象
 * @param {Object} o2 - 必填。被比较的对象
 * @param {Array<String>} keys - 选填。仅检查指定的keys
 * @returns {Object} 返回的结果 包含两个属性
 *          {Boolean} isAllSame 表明是否完全相同
 *          {Object} diffObj 被检查出来不相同的项
 */
function diff(o1, o2, keys = null, __isRecursion__ = false) {
  let isAllSame = true,
    diffObj = {};
  let list = Object.entries(o1);
  let list2 = Object.entries(o2);
  if (Array.isArray(keys) && keys.length > 0) {
    list = list.filter(([k, v]) => keys.includes(k));
    list2 = list2.filter(([k, v]) => keys.includes(k));
  }
  if (__isRecursion__ && list.length !== list2.length) {
    isAllSame = false;
    //递归模式下,上一级只读取isAllSame
    //参见下面的那句 const { isAllSame: _isAllSame } = diff(v1, v2);
    return {
      isAllSame,
    };
  }
  // 递归模式下,有一项不同则终止循环,所以有every
  if (__isRecursion__) {
    list.every(__fetchDiff__);
  } else {
    list.forEach(__fetchDiff__);
  }

  function __fetchDiff__([key, v1]) {
    const v2 = o2[key];
    let isSame = v1 == v2;
    //区分其是基本类型还是引用类型,如果是引用类型还需要进一步判断(递归本方法)
    // v2也要校验,否则v1为引用类型 v2为基本类型则无需diff就可判定isSame一定为false
    const isReference = variableIsReference(v1) && variableIsReference(v2);
    if (isReference) {
      // 递归的时候要传入第四参数表明是递归
      const { isAllSame: _isAllSame } = diff(v1, v2, null, true);
      isSame = _isAllSame;
    }

    if (!isSame) {
      isAllSame = false;
      diffObj[key] = v1;
    }
    return v1 == v2;
  }
  return {
    isAllSame,
    diffObj,
  };
}
const obj1 = {
  a: 123,
  c: {
    d: 2,
    e: {
      f: 2
    }
  },
  b: 456,
  h: 10,
  g: {
    a: 2
  }
};
const ob2 = {
  b: 456, 
  a: "123",
  c: {
    d: 2,
    e: {
      f: 2
    }
  },
  g: {
    a: 1
  }
};
const res = diff(obj1, ob2);
console.log(res);

前后端数据通信参数加密

技术:crypto-js

加密代码实现:

项目中需要将所有传到后台的参数分5个步骤处理:

第一步:排序

第二步:将排序好的参数进行MD5加密作为接口的签名

第三步:将排序好的参数和接口签名拼接上进行AES加密

第四部:将AES加密后的密文Base64加密

第五步:将最终的密文encodeURIComponent;

代码如下:

function encryption(data) {
    let strs=[];
    for(let i in data){
        strs.push(i+'='+data[i]);
    }
    strs.sort();  // 数组排序
    strs=strs.join('&'); // 数组变字符串
    let endData=strs+'&sign='+CryptoJS.MD5(strs+'ADfj3kcadc2349akvm1CPFFCD84f').toString(); // MD5加密
    let key = CryptoJS.enc.Utf8.parse("0880076B18D7EE81"); // 加密秘钥
    let iv = CryptoJS.enc.Utf8.parse("CB3EC842D7C69578");  //  矢量
    let encryptResult = CryptoJS.AES.encrypt(endData,key, {   //  AES加密
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7  // 后台用的是pad.Pkcs5,前台对应为Pkcs7
    });
    return encodeURIComponent(CryptoJS.enc.Base64.stringify(encryptResult.ciphertext));  // Base64加密encode;
}

加密最终的密文拼接在接口地址后面,请求接口。后台返回的数据也是密文;解密方法如下:

function decryption(data) {
    let key = CryptoJS.enc.Utf8.parse("0880076B18D7EE81");  // 加密秘钥
    let iv = CryptoJS.enc.Utf8.parse("CB3EC842D7C69578");   //  矢量
    let baseResult=CryptoJS.enc.Base64.parse(data);   // Base64解密
    let ciphertext=CryptoJS.enc.Base64.stringify(baseResult);     // Base64解密
    let decryptResult = CryptoJS.AES.decrypt(ciphertext,key, {    //  AES解密
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    let resData=decryptResult.toString(CryptoJS.enc.Utf8).toString();

    return JSON.parse(resData);

}

备注:因为后台返回的数据是json格式;所以做种return的时候使用JSON.parse();如果解密的目标为字符串,比如说需要解密的是一个加密的token值。那就要做相应的改动:

function decryption(data) {
    let key = CryptoJS.enc.Utf8.parse("0880076B18D7EE81");  // 加密秘钥
    let iv = CryptoJS.enc.Utf8.parse("CB3EC842D7C69578");   //  矢量
    let baseResult=CryptoJS.enc.Base64.parse(data);   // Base64解密
    let ciphertext=CryptoJS.enc.Base64.stringify(baseResult);     // Base64解密
    let decryptResult = CryptoJS.AES.decrypt(ciphertext,key, {    //  AES解密
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    return CryptoJS.enc.Utf8.stringify(decryptResult)

}

Token、JWT、OAuth、SAML、SSO

  • Token

web性能优化

离线缓存

参考:PWA

关键渲染路径以及优化策略

《Designing for Performance》的作者 Lara Swanson 在2014年写过一篇文章《Web性能即用户体验》,她在文中提到“网站页面的快速加载,能够建立用户对网站的信任,增加回访率,大部分的用户其实都期待页面能够在2秒内加载完成,而当超过3秒以后,就会有接近40%的用户离开你的网站”。

Google和亚马逊的研究表明,Google页面加载的时间从0.4秒提升到0.9秒导致丢失了20%流量和广告收入,对于亚马逊,页面加载时间每增加100毫秒就意味着1%的销售额损失。可见,页面的加载速度对于用户可能的下一步操作是多么的举足轻重。

想一想,如果你希望你的网站在一秒钟之内呈现用户想看的关键信息,有哪些可行的手段?Minify,压缩,雪碧图等等。

项目管理

自动化测试、自动化构建

  • Travis CI

参考:持续集成服务 Travis CI 教程

代码规范

ESLint Prettier

前端工程的三个阶段

  • 第一阶段:库/框架选型

前端工程建设的第一项任务就是根据项目特征进行技术选型。

基本上现在没有人完全从0开始做网站,哪怕是政府项目用个jquery都很正常吧,React/Angularjs等框架横空出世,解放了不少生产力,合理的技术选型可以为项目节省许多工程量这点毋庸置疑。

  • 第二阶段:简单构建优化

选型之后基本上就可以开始敲码了,不过光解决开发效率还不够,必须要兼顾运行性能。前端工程进行到第二阶段会选型一种构建工具,对代码进行压缩,校验,之后再以页面为单位进行简单的资源合并。

  • 第三阶段:JS/CSS模块化开发

分而治之是软件工程中的重要思想,是复杂系统开发和维护的基石,这点放在前端开发中同样适用。在解决了基本开发效率运行效率问题之后,前端团队开始思考维护效率,模块化是目前前端最流行的分治手段。

  • 第四阶段 组件化开发与资源管理

前端是一种技术问题较少、工程问题较多的软件开发领域。

当我们要开发一款完整的Web应用时,前端将面临更多的工程问题,比如:

大体量:多功能、多页面、多状态、多系统; 大规模:多人甚至多团队合作开发; 高性能:CDN部署、缓存控制、文件指纹、缓存复用、请求合并、按需加载、同步/异步加载、移动端首屏CSS内嵌、HTTP 2.0服务端资源推送。

谷歌浏览器

插件

Chrome扩展下载器

  • 网站性能测试插件 Lighthouse

限制端口

  • 1: // tcpmux

  • 7: // echo

  • 9: // discard

  • 11: // systat

  • 13: // daytime

  • 15: // netstat

  • 17: // qotd

  • 19: // chargen

  • 20: // ftp data

  • 21: // ftp access

  • 22: // ssh

  • 23: // telnet

  • 25: // smtp

  • 37: // time

  • 42: // name

  • 43: // nicname

  • 53: // domain

  • 77: // priv-rjs

  • 79: // finger

  • 87: // ttylink

  • 95: // supdup

  • 101: // hostriame

  • 102: // iso-tsap

  • 103: // gppitnp

  • 104: // acr-nema

  • 109: // pop2

  • 110: // pop3

  • 111: // sunrpc

  • 113: // auth

  • 115: // sftp

  • 117: // uucp-path

  • 119: // nntp

  • 123: // NTP

  • 135: // loc-srv /epmap

  • 139: // netbios

  • 143: // imap2

  • 179: // BGP

  • 389: // ldap

  • 465: // smtp+ssl

  • 512: // print / exec

  • 513: // login

  • 514: // shell

  • 515: // printer

  • 526: // tempo

  • 530: // courier

  • 531: // chat

  • 532: // netnews

  • 540: // uucp

  • 556: // remotefs

  • 563: // nntp+ssl

  • 587: // stmp?

  • 601: // ??

  • 636: // ldap+ssl

  • 993: // ldap+ssl

  • 995: // pop3+ssl

  • 2049: // nfs

  • 3659: // apple-sasl / PasswordServer

  • 4045: // lockd

  • 6000: // X11

  • 6665: // Alternate IRC [Apple addition]

  • 6666: // Alternate IRC [Apple addition]

  • 6667: // Standard IRC [Apple addition]

  • 6668: // Alternate IRC [Apple addition]

  • 6669: // Alternate IRC [Apple addition]

Github 相关知识

Github 徽章

参考:玩转 Github 徽章

Gitlab 相关知识

参考:Gitlab 登录(Username or email: weich Password: p7)

vscode

代码格式化功能

插件:Prettier formatter for Visual Studio Code

经典文章

项目部署

大公司里怎样开发和部署前端代码?

项目架构

百姓网的前端架构

开发工具

processon:免费在线作图,实时协作

typora: 免费极简 Markdown 编辑器

上次更新: 2018-7-16 19:16:47