连续复制
一键复制
一键打包
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");
评论已关闭