连续复制
一键复制

FormData XMLHttpRequest Level 2 新增的一个对象,利用它来提交表单、模拟表单提交,当然最大的优势就是可以上传二进制文件!

复制代码
  1. <form action="" id="form">
  2. <!-- multiple 属性可选择多文件 -->
  3. <input type="file" name="" value="选择文件">
  4. <input type="text" name="username" value="jack ma">
  5. </form>
复制代码
  1. var form = document.getElementById("form"),
  2. formData = new FormData(form);
  3. /**
  4. * formData.get(name: string)
  5. *
  6. * 返回第一个属性为 name 的 值 || null
  7. */
  8. /**
  9. * formData.getAll(name: string)
  10. *
  11. * 获取所有属性名为 name 的值,以 数组 || [] 形式返回
  12. */
  13. /**
  14. * (同步操作)
  15. * formData.append(name: string, value: string|Blob, fileName: string)
  16. *
  17. * 可添加多个同名的值,不会覆盖,非唯一性
  18. */
  19. formData.append("username", "jackie");
  20. console.log("formData:", formData, "get:", formData.get("username"), "getAll:", formData.getAll("username"));
  21. /**
  22. * (同步操作)
  23. * formData.set(name: string, value: string|Blob, fileName: string)
  24. *
  25. * 有该属性则修改,无则添加该属性及值
  26. * 会将 name 属性的值全部改为 value,且 getAll 会返回 仅包含一个该value值 的数组
  27. */
  28. formData.set("username", "setted-name");
  29. console.log("formData:", formData, "get:", formData.get("username"), "getAll:", formData.getAll("username"));
  30. /**
  31. * has(name: string): Boolean
  32. */
  33. console.log("has:", formData.has("username"), formData.has("has-attr"));
  34. /**
  35. * delete(name: string)
  36. *
  37. * 删除所有 name 属性
  38. */
  39. formData.delete("username")
  40. console.log("deleted-has:", formData.has("username"), formData.get("username"), formData.getAll("username"));
  41. // ************************************************************************************************************************
  42. ### 多图上传
  43. // 通过 <input type="file" multiple >
  44. $.each($input[0].files, function (index, file) {
  45. formData.append("file" + index, file);
  46. });
  47. $.ajax({
  48. // ...
  49. // 直接将 formData 对象传递给后台
  50. data: formData,
  51. })

Base64、Blob、File 之间的相互转换

复制代码
  1. // 1、file、blob 转换为 base64
  2. function fileOrBlobToBase64 (fileOrBlob, callback) {
  3. var reader = new FileReader();
  4. reader.readAsDataURL(fileOrBlob);
  5. reader.onload = function(evt) {
  6. console.log(reader.result, this.result, evt.target.result); //获取到base64格式图片
  7. // callback(result);
  8. };
  9. }
  10. // 2、base64 转换为 blob
  11. function base64ToBlob(base64Data) {
  12. //console.log(base64Data);//data:image/png;base64,
  13. var byteString;
  14. if(base64Data.split(',')[0].indexOf('base64') >= 0)
  15. byteString = atob(base64Data.split(',')[1]);//base64 解码
  16. else{
  17. byteString = unescape(base64Data.split(',')[1]);
  18. }
  19. var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];//mime类型 -- image/png
  20. // var arrayBuffer = new ArrayBuffer(byteString.length); //创建缓冲数组
  21. // var ia = new Uint8Array(arrayBuffer);//创建视图
  22. var ia = new Uint8Array(byteString.length);//创建视图
  23. for(var i = 0; i < byteString.length; i++) {
  24. ia[i] = byteString.charCodeAt(i);
  25. }
  26. var blob = new Blob([ia], {
  27. type: mimeString
  28. });
  29. return blob;
  30. }
  31. // 3、base64 转换为 file
  32. function base64ToFile(base64, filename) {//将base64转换为文件
  33. var arr = base64.split(','), mime = arr[0].match(/:(.*?);/)[1],
  34. bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
  35. while(n--){
  36. u8arr[n] = bstr.charCodeAt(n);
  37. }
  38. return new File([u8arr], filename, {type:mime});
  39. }

移动端调试控制台

复制代码
  1. <script src="//cdn.bootcss.com/vConsole/3.3.3/vconsole.min.js"></script>
复制代码
  1. // 实例化即可
  2. var VConsole = new VConsole();

IScroll 插件

复制代码
  1. <div id="scroll-wrapper">
  2. <!-- 唯一子元素 为滚动内容 -->
  3. <div>
  4. <li>1</li>
  5. <li>2</li>
  6. <li>3</li>
  7. <!-- ... -->
  8. </div>
  9. </div>
复制代码
  1. #scroll-wrapper {
  2. /* 需要知道容器(垂直滚动时)高度 或 (水平滚动时)宽度 */
  3. height: 800px;
  4. /* 必要 */
  5. overflow: hidden; /* 如垂直滑动,当与 IOS 滑动冲突时,可尝试 overflow-y: scroll */
  6. /* 可选,用于处理 IScroll 滚动区域不准确问题 */
  7. position: relative;
  8. /* 可选,解决谷歌浏览器下警告 */
  9. touch-action: none;
  10. }
  11. /* 当最后一条数据无法滑动到完整显示,可通过给滚动元素加 padding-bottom 解决 */
  12. #scroll-wrapper >div {
  13. padding-bottom: 20px;
  14. }
复制代码
  1. var IScrollInstance = new IScroll("#scroll-wrapper", {
  2. });
  3. // request new data...
  4. $("#list").html(str);
  5. // 每次更新滑动列表内容后,记得手动刷新插件
  6. IScrollInstance && IScrollInstance.refresh();
  7. // iscroll-probe.js 才可监听到
  8. IScrollInstance.on("scroll", funciton () {
  9. });
  10. IScrollInstance.on("scrollEnd", _scrollEnd);
  11. function _scrollEnd(e) {
  12. /*
  13. 【this.maxScrollY】 页面最大滚动距离,若垂直滑动时为负数,其性质等同于 scrollHeight
  14. 【this.y】 已滚动距离
  15. 【this.pointY】 当前手指位置
  16. */
  17. // 手指滑出滚动区域后,使滑动内容回弹
  18. // if (this.pointY < 0)
  19. // _IScrollInstance.scrollTo(0, this.maxScrollY, 100);
  20. // 加载更多! maxScrollY 和 y 都为负数
  21. if (this.y < 0 && _IScrollInstance.maxScrollY >= _IScrollInstance.y) {
  22. }
  23. }

IScroll-pro 下拉刷新、上拉加载插件

插件源码及用例 地址:[[https://github.com/baiJiXianSheng/IScroll-pro]]


window.postMessage

H5 API:window.postMessage(message: any, targetOrigin: string);

当通过 iframe 嵌入页面时

  • 父页面向 iframe 嵌套的子页面传递消息通知:iframe.contentWindow.postMessage()

复制代码
  1. // 父页面
  2. document.querySelect("iframe").contentWindow.postMessage({ res: 1, evtType: "showNotice" }, "*");
  3. // 在子页面定义接收事件
  4. window.addEventListener("message", _postMessage);
  5. function _postMessage (evt) {
  6. if (evt.data.evtType === "showNotice") {
  7. // use evt.data.res to do something ...
  8. }
  9. }
  • iframe 包裹的子页面 向父页面传递消息:window.parent.postMessage()

复制代码
  1. // 子页面
  2. // 若多层 iframe 嵌套时,可使用 window.top 取得最顶层页面window
  3. window.parent.postMessage({ res: 1, evtType: "showNotice" }, "*");
  4. // 父页面,定义接收消息事件处理函数
  5. window.addEventListener("message", _postMessage);
  6. function _postMessage (evt) {
  7. if (evt.data.evtType === "showNotice") {
  8. // use evt.data.res to do something ...
  9. }
  10. }

禁止 input 聚焦时调用第三方输入法(兼容性不高)

复制代码
  1. <input style="ime-mode:disabled" />

禁止显示 input 历史输入

复制代码
  1. <input autocomplete="off" />

IOS 下 input 聚焦时光标位置偏移。以input上边界开始到文本底部,IOS 下 input 默认行高100%?

  • (1)
    该法可能会出现文字垂直居中效果不准确

复制代码
  1. input {
  2. /* 如原本以 40px 垂直居中 */
  3. /* line-height: 40px; */
  4. /* 但通常 font-size 和 line-height值相同时,会出现文字被“裁剪”显示不全 */
  5. font-size: 20px;
  6. line-height: 20px;
  7. margin: 10px 0;
  8. /* 若使用 padding: 10px 0; 在ios的高版本如12,会出现bug,当你点击到padding-top的区间的时候,input的光标会移动到input默认文字的最前面,而不是我们希望的最后面 */
  9. }
  • (2)

复制代码
  1. .parentDom {
  2. display: flex;
  3. align-items: center;
  4. input {
  5. font-size: 20px;
  6. }
  7. }

IOS input 键盘 换行 -> 搜索

外面嵌套一层 form

复制代码
  1. <form action="">
  2. <input type="search">
  3. </form>

IOS 原生滑动

复制代码
  1. .box {
  2. height: 100%;
  3. overflow-y: scroll;
  4. -webkit-overflow-scrolling: touch;
  5. }

input[type=search] 时安卓或谷歌浏览器 输入框右侧蓝色x按钮

复制代码
  1. input::-webkit-search-cancel-button {
  2. display: none;
  3. }

input 输入文本跳转搜索页面后,再次返回该页面时输入框自动聚焦

复制代码
  1. // ...
  2. searchInput.value = "";
  3. if (document.activeElement instanceof HTMLElement) {
  4. document.activeElement.blur();
  5. }
  6. beforeRequest();

iPhone 设备 media 查询 样式适配

复制代码
  1. /* iphoneX、iphoneXs */
  2. @media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) {
  3. div {
  4. }
  5. }
  6. /* iphone Xs Max */
  7. @media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio:3) {
  8. div {
  9. }
  10. }
  11. /* iphone XR */
  12. @media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio:2) {
  13. div {
  14. }
  15. }

CSS 伪元素 ::before::after

复制代码
  1. div::before {
  2. /* 默认为 inline 元素 */
  3. display: block;
  4. /*
  5. 值得类型可选:'文本'、url(xxx.png)、attr(节点的某个属性)、counter()序列
  6. **/
  7. content: '\0252';
  8. content: '内容';
  9. content: url(assets/xxx.png);
  10. /* <div data-index="1"></div> */
  11. /* 可通过js修改 data-index 的值,使得 伪元素的内容自动改变 */
  12. content: attr(data-index);
  13. }

BFC

  • float 的值不是 none

  • position 的值不是 static或者relative

  • display 的值是 inline-blocktable-cellflextable-captioninline-flex

  • overflow 的值不是 visible


Input[type=file]

  • h5调用设备相机

手机QQ软件内置浏览器,需要添加 capture="camera" 属性方可调用相机。

html

复制代码
  1. <!-- 若默认在 input 元素上添加 capture="camera" 属性,则某些浏览器(如safari?) 无法唤起相机 -->
  2. <input type="file" id="loadInput" hidden="" accept="image/*" />

js

复制代码
  1. var u = navigator.userAgent;
  2. var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //g
  3. var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
  4. if (isIOS) {
  5. $("#loadInput").removeAttr("capture");
  6. } else {
  7. var browser = navigator.userAgent.toLowerCase();
  8. if (browser.match(/MicroMessenger/i) == 'micromessenger') {
  9. // 微信浏览器
  10. // 可直接调用相机
  11. } else if(browser.indexOf(' qq') != -1 && browser.indexOf('mqqbrowser') != -1){
  12. // 手机QQ软件 内置浏览器
  13. // 需要添加 capture="camera" 属性方可调用相机
  14. $("#loadInput").attr("capture","camera");
  15. } else if(browser.indexOf('mqqbrowser') != -1 && browser.indexOf(" qq") == -1){
  16. // QQ浏览器
  17. // alert("QQ浏览器");
  18. } else {
  19. // alert("以上都不是");
  20. }
  21. }
  22. // 主动触发 input-file 点击选择文件事件
  23. document.getElementById("loadInput").click();

IOS 下 当有 input 聚焦时,其他元素通过 click 绑定的点击事件,因 input 失去焦点阻止了 click 事件触发,需要二次点击方可触发

复制代码
  1. var _isIphone = navigator.userAgent.toUpperCase().indexOf("IPHONE") > -1;
  2. // hack:IOS 上点击登录按钮时,若输入框聚焦,首先会触发 blur 事件,click事件无法触发,需再次点击触发
  3. if (_isIphone) {
  4. $("body").on("touchend", function(e) {
  5. // 当点击到 btn 上时,直接调用对应的方法
  6. if (e.target.id == "btn")
  7. dosomething();
  8. })
  9. } else {
  10. $("#btn").click(function () {
  11. dosomething0();
  12. });
  13. }

input 聚焦时,底部footer position: fixed 失效被键盘顶起。尝试解决方案:聚焦时 隐藏footer,失去焦点时 显示footer

复制代码
  1. // 浏览器当前的高度
  2. var oHeight = $(document).height();
  3. $(window).resize(function () {
  4. var now = $(document).height();
  5. if (now < oHeight) {
  6. $(".footer").hide();
  7. } else {
  8. $(".footer").show();
  9. }
  10. });

h5 页面在 IOS 下返回,未重载

复制代码
  1. // 解决 h5 在IOS 下返回,页面不重载问题
  2. var browserRule = /^.*((iPhone)|(iPad)|(Safari))+.*$/;
  3. if (browserRule.test(navigator.userAgent)) {
  4. window.onpageshow = function(event) {
  5. console.log("onpageshow!")
  6. if (event.persisted) {
  7. window.location.reload();
  8. }
  9. };
  10. }

h5 页面在 Android 下 window.history.go(-1) 无法返回上一页

复制代码
  1. var u = navigator.userAgent;
  2. var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
  3. $("#cancel-btn").click(function () {
  4. if (isIOS)
  5. window.history.go(-1);
  6. else
  7. window.location.href = "lastPage.html";
  8. // 或者 无论IOS或Android,都直接通过 location.href = "lastPage.html"; 跳转到指定页面
  9. });

<video> 标签在 IOS 下点击无法播放

  • 解决方案一:

复制代码
  1. // 用一张播放按钮的图片,监听其点击事件,触发时动态生成 video 标签插入,并调用 video.play();
  2. ### 注:若在初始化加载html文档时,<video></video> 或 <source> 标签没有 src 属性及值,通过动态赋值(不会重新请求?)可能无法正常加载。
  3. $("#play-btn").click(function () {
  4. var $video = $("<video src='"+ url +"' controls></video>");
  5. // 可监听其 播放事件
  6. $video.on("play", function () { });
  7. $("#video-container").append($video);
  8. $video.get(0).play();
  9. });

iframe 在IOS下宽度变宽,产生左右滑动

复制代码
  1. <div class="iframe-box">
  2. <iframe src=".." frameborder="0" height="100%"></iframe>
  3. </div>
复制代码
  1. .iframe-box {
  2. overflow: auto; /* 或者 overflow-y: scroll */
  3. -webkit-overflow-scrolling:touch; /* IOS 顺滑 */
  4. width:100%;
  5. height:100%;
  6. }
  7. /* 关键步骤 */
  8. .iframe-box iframe {
  9. width: 1px;
  10. min-width: 100%;
  11. *width: 100%;
  12. }
复制代码
  1. var u = navigator.userAgent;
  2. var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
  3. // 通过 js 设置 scrolling 属性
  4. $("iframe").attr("scrolling", isIOS ? "no" : "auto");