FormData
XMLHttpRequest Level 2 新增的一个对象,利用它来提交表单、模拟表单提交,当然最大的优势就是可以上传二进制文件!
复制代码-
- <form action="" id="form">
- <!-- multiple 属性可选择多文件 -->
- <input type="file" name="" value="选择文件">
- <input type="text" name="username" value="jack ma">
- </form>
-
复制代码-
- var form = document.getElementById("form"),
- formData = new FormData(form);
-
- /**
- * formData.get(name: string)
- *
- * 返回第一个属性为 name 的 值 || null
- */
-
- /**
- * formData.getAll(name: string)
- *
- * 获取所有属性名为 name 的值,以 数组 || [] 形式返回
- */
-
- /**
- * (同步操作)
- * formData.append(name: string, value: string|Blob, fileName: string)
- *
- * 可添加多个同名的值,不会覆盖,非唯一性
- */
- formData.append("username", "jackie");
- console.log("formData:", formData, "get:", formData.get("username"), "getAll:", formData.getAll("username"));
-
- /**
- * (同步操作)
- * formData.set(name: string, value: string|Blob, fileName: string)
- *
- * 有该属性则修改,无则添加该属性及值
- * 会将 name 属性的值全部改为 value,且 getAll 会返回 仅包含一个该value值 的数组
- */
- formData.set("username", "setted-name");
- console.log("formData:", formData, "get:", formData.get("username"), "getAll:", formData.getAll("username"));
-
-
- /**
- * has(name: string): Boolean
- */
- console.log("has:", formData.has("username"), formData.has("has-attr"));
-
- /**
- * delete(name: string)
- *
- * 删除所有 name 属性
- */
- formData.delete("username")
- console.log("deleted-has:", formData.has("username"), formData.get("username"), formData.getAll("username"));
-
- // ************************************************************************************************************************
-
- ### 多图上传
-
- // 通过 <input type="file" multiple >
- $.each($input[0].files, function (index, file) {
- formData.append("file" + index, file);
- });
-
- $.ajax({
- // ...
-
- // 直接将 formData 对象传递给后台
- data: formData,
- })
-
-
Base64、Blob、File 之间的相互转换
复制代码-
- // 1、file、blob 转换为 base64
- function fileOrBlobToBase64 (fileOrBlob, callback) {
- var reader = new FileReader();
- reader.readAsDataURL(fileOrBlob);
- reader.onload = function(evt) {
- console.log(reader.result, this.result, evt.target.result); //获取到base64格式图片
- // callback(result);
- };
- }
-
- // 2、base64 转换为 blob
- function base64ToBlob(base64Data) {
- //console.log(base64Data);//data:image/png;base64,
- var byteString;
- if(base64Data.split(',')[0].indexOf('base64') >= 0)
- byteString = atob(base64Data.split(',')[1]);//base64 解码
- else{
- byteString = unescape(base64Data.split(',')[1]);
- }
- var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];//mime类型 -- image/png
-
- // var arrayBuffer = new ArrayBuffer(byteString.length); //创建缓冲数组
- // var ia = new Uint8Array(arrayBuffer);//创建视图
- var ia = new Uint8Array(byteString.length);//创建视图
- for(var i = 0; i < byteString.length; i++) {
- ia[i] = byteString.charCodeAt(i);
- }
- var blob = new Blob([ia], {
- type: mimeString
- });
- return blob;
- }
-
- // 3、base64 转换为 file
- function base64ToFile(base64, filename) {//将base64转换为文件
- var arr = base64.split(','), mime = arr[0].match(/:(.*?);/)[1],
- bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
- while(n--){
- u8arr[n] = bstr.charCodeAt(n);
- }
- return new File([u8arr], filename, {type:mime});
- }
-
移动端调试控制台
复制代码- <script src="//cdn.bootcss.com/vConsole/3.3.3/vconsole.min.js"></script>
复制代码- // 实例化即可
- var VConsole = new VConsole();
IScroll 插件
iscroll.js
文件只包含基本功能iscroll-probe.js
文件方可监听scroll
事件。方便于添加上拉加载
和下拉刷新
功能
[[官方用例]] https://github.com/cubiq/iscroll/blob/master/demos/probe/index.html
复制代码- <div id="scroll-wrapper">
- <!-- 唯一子元素 为滚动内容 -->
- <div>
- <li>1</li>
- <li>2</li>
- <li>3</li>
- <!-- ... -->
- </div>
- </div>
复制代码- #scroll-wrapper {
- /* 需要知道容器(垂直滚动时)高度 或 (水平滚动时)宽度 */
- height: 800px;
- /* 必要 */
- overflow: hidden; /* 如垂直滑动,当与 IOS 滑动冲突时,可尝试 overflow-y: scroll */
-
- /* 可选,用于处理 IScroll 滚动区域不准确问题 */
- position: relative;
- /* 可选,解决谷歌浏览器下警告 */
- touch-action: none;
- }
-
- /* 当最后一条数据无法滑动到完整显示,可通过给滚动元素加 padding-bottom 解决 */
- #scroll-wrapper >div {
- padding-bottom: 20px;
- }
复制代码- var IScrollInstance = new IScroll("#scroll-wrapper", {
-
- });
-
- // request new data...
- $("#list").html(str);
- // 每次更新滑动列表内容后,记得手动刷新插件
- IScrollInstance && IScrollInstance.refresh();
-
-
- // iscroll-probe.js 才可监听到
- IScrollInstance.on("scroll", funciton () {
-
- });
-
- IScrollInstance.on("scrollEnd", _scrollEnd);
-
- function _scrollEnd(e) {
- /*
- 【this.maxScrollY】 页面最大滚动距离,若垂直滑动时为负数,其性质等同于 scrollHeight
- 【this.y】 已滚动距离
- 【this.pointY】 当前手指位置
- */
-
- // 手指滑出滚动区域后,使滑动内容回弹
- // if (this.pointY < 0)
- // _IScrollInstance.scrollTo(0, this.maxScrollY, 100);
-
- // 加载更多! maxScrollY 和 y 都为负数
- if (this.y < 0 && _IScrollInstance.maxScrollY >= _IScrollInstance.y) {
-
- }
- }
-
-
IScroll-pro 下拉刷新、上拉加载插件
插件源码及用例 地址:[[https://github.com/baiJiXianSheng/IScroll-pro]]
window.postMessage
H5 API:window.postMessage(message: any, targetOrigin: string)
;
当通过 iframe 嵌入页面时
父页面向 iframe 嵌套的子页面传递消息通知:
iframe.contentWindow.postMessage()
复制代码
- // 父页面
- document.querySelect("iframe").contentWindow.postMessage({ res: 1, evtType: "showNotice" }, "*");
- // 在子页面定义接收事件
- window.addEventListener("message", _postMessage);
- function _postMessage (evt) {
- if (evt.data.evtType === "showNotice") {
- // use evt.data.res to do something ...
- }
- }
iframe 包裹的子页面 向父页面传递消息:
window.parent.postMessage()
复制代码
- // 子页面
- // 若多层 iframe 嵌套时,可使用 window.top 取得最顶层页面window
- window.parent.postMessage({ res: 1, evtType: "showNotice" }, "*");
- // 父页面,定义接收消息事件处理函数
- window.addEventListener("message", _postMessage);
- function _postMessage (evt) {
- if (evt.data.evtType === "showNotice") {
- // use evt.data.res to do something ...
- }
- }
禁止 input
聚焦时调用第三方输入法(兼容性不高)
复制代码- <input style="ime-mode:disabled" />
禁止显示 input
历史输入
复制代码- <input autocomplete="off" />
IOS 下 input
聚焦时光标位置偏移。以input上边界开始到文本底部,IOS 下 input
默认行高100%?
(1)
该法可能会出现文字垂直居中效果不准确
复制代码- input {
- /* 如原本以 40px 垂直居中 */
- /* line-height: 40px; */
-
- /* 但通常 font-size 和 line-height值相同时,会出现文字被“裁剪”显示不全 */
- font-size: 20px;
-
- line-height: 20px;
- margin: 10px 0;
-
- /* 若使用 padding: 10px 0; 在ios的高版本如12,会出现bug,当你点击到padding-top的区间的时候,input的光标会移动到input默认文字的最前面,而不是我们希望的最后面 */
- }
(2)
复制代码
- .parentDom {
- display: flex;
- align-items: center;
- input {
- font-size: 20px;
- }
- }
IOS input 键盘 换行
-> 搜索
外面嵌套一层 form
复制代码- <form action="">
- <input type="search">
- </form>
IOS 原生滑动
复制代码- .box {
- height: 100%;
- overflow-y: scroll;
- -webkit-overflow-scrolling: touch;
- }
input[type=search]
时安卓或谷歌浏览器 输入框右侧蓝色x按钮
复制代码- input::-webkit-search-cancel-button {
- display: none;
- }
input
输入文本跳转搜索页面后,再次返回该页面时输入框自动聚焦
复制代码- // ...
-
- searchInput.value = "";
- if (document.activeElement instanceof HTMLElement) {
- document.activeElement.blur();
- }
-
- beforeRequest();
iPhone 设备 media 查询
样式适配
复制代码-
- /* iphoneX、iphoneXs */
- @media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) {
- div {
-
- }
- }
- /* iphone Xs Max */
- @media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio:3) {
- div {
-
- }
- }
- /* iphone XR */
- @media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio:2) {
- div {
-
- }
- }
-
CSS 伪元素 ::before
::after
复制代码-
- div::before {
- /* 默认为 inline 元素 */
- display: block;
-
- /*
- 值得类型可选:'文本'、url(xxx.png)、attr(节点的某个属性)、counter()序列
- **/
- content: '\0252';
- content: '内容';
- content: url(assets/xxx.png);
-
- /* <div data-index="1"></div> */
- /* 可通过js修改 data-index 的值,使得 伪元素的内容自动改变 */
- content: attr(data-index);
-
- }
-
BFC
float
的值不是none
position
的值不是static
或者relative
display
的值是inline-block
、table-cell
、flex
、table-caption
、inline-flex
overflow
的值不是visible
Input[type=file]
h5调用设备相机
手机QQ软件内置浏览器,需要添加 capture="camera" 属性方可调用相机。
html
复制代码- <!-- 若默认在 input 元素上添加 capture="camera" 属性,则某些浏览器(如safari?) 无法唤起相机 -->
-
- <input type="file" id="loadInput" hidden="" accept="image/*" />
js
复制代码-
- var u = navigator.userAgent;
- var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //g
- var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
-
- if (isIOS) {
- $("#loadInput").removeAttr("capture");
- } else {
- var browser = navigator.userAgent.toLowerCase();
- if (browser.match(/MicroMessenger/i) == 'micromessenger') {
- // 微信浏览器
- // 可直接调用相机
-
- } else if(browser.indexOf(' qq') != -1 && browser.indexOf('mqqbrowser') != -1){
- // 手机QQ软件 内置浏览器
- // 需要添加 capture="camera" 属性方可调用相机
- $("#loadInput").attr("capture","camera");
-
- } else if(browser.indexOf('mqqbrowser') != -1 && browser.indexOf(" qq") == -1){
- // QQ浏览器
- // alert("QQ浏览器");
- } else {
- // alert("以上都不是");
- }
- }
-
- // 主动触发 input-file 点击选择文件事件
- document.getElementById("loadInput").click();
-
IOS 下 当有 input 聚焦时,其他元素通过 click 绑定的点击事件,因 input 失去焦点阻止了 click 事件触发,需要二次点击方可触发
复制代码-
- var _isIphone = navigator.userAgent.toUpperCase().indexOf("IPHONE") > -1;
- // hack:IOS 上点击登录按钮时,若输入框聚焦,首先会触发 blur 事件,click事件无法触发,需再次点击触发
- if (_isIphone) {
- $("body").on("touchend", function(e) {
- // 当点击到 btn 上时,直接调用对应的方法
- if (e.target.id == "btn")
- dosomething();
- })
- } else {
- $("#btn").click(function () {
- dosomething0();
- });
- }
-
有 input
聚焦时,底部footer position: fixed
失效被键盘顶起。尝试解决方案:聚焦时 隐藏footer,失去焦点时 显示footer
复制代码-
- // 浏览器当前的高度
- var oHeight = $(document).height();
- $(window).resize(function () {
- var now = $(document).height();
- if (now < oHeight) {
- $(".footer").hide();
- } else {
- $(".footer").show();
- }
- });
-
h5 页面在 IOS 下返回,未重载
复制代码- // 解决 h5 在IOS 下返回,页面不重载问题
- var browserRule = /^.*((iPhone)|(iPad)|(Safari))+.*$/;
- if (browserRule.test(navigator.userAgent)) {
- window.onpageshow = function(event) {
- console.log("onpageshow!")
- if (event.persisted) {
- window.location.reload();
- }
- };
- }
-
h5 页面在 Android 下 window.history.go(-1)
无法返回上一页
复制代码-
- var u = navigator.userAgent;
- var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
-
- $("#cancel-btn").click(function () {
-
- if (isIOS)
- window.history.go(-1);
- else
- window.location.href = "lastPage.html";
-
- // 或者 无论IOS或Android,都直接通过 location.href = "lastPage.html"; 跳转到指定页面
- });
-
<video>
标签在 IOS 下点击无法播放
解决方案一:
复制代码-
- // 用一张播放按钮的图片,监听其点击事件,触发时动态生成 video 标签插入,并调用 video.play();
-
- ### 注:若在初始化加载html文档时,<video></video> 或 <source> 标签没有 src 属性及值,通过动态赋值(不会重新请求?)可能无法正常加载。
-
- $("#play-btn").click(function () {
-
- var $video = $("<video src='"+ url +"' controls></video>");
-
- // 可监听其 播放事件
- $video.on("play", function () { });
-
- $("#video-container").append($video);
-
- $video.get(0).play();
- });
-
iframe
在IOS下宽度变宽,产生左右滑动
复制代码-
- <div class="iframe-box">
- <iframe src=".." frameborder="0" height="100%"></iframe>
- </div>
-
复制代码-
- .iframe-box {
- overflow: auto; /* 或者 overflow-y: scroll */
- -webkit-overflow-scrolling:touch; /* IOS 顺滑 */
- width:100%;
- height:100%;
- }
-
- /* 关键步骤 */
- .iframe-box iframe {
- width: 1px;
- min-width: 100%;
- *width: 100%;
- }
-
复制代码-
- var u = navigator.userAgent;
- var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
-
- // 通过 js 设置 scrolling 属性
- $("iframe").attr("scrolling", isIOS ? "no" : "auto");
-
评论已关闭