但图片过大的时候,网速慢的时候,图片会呈现断片式加载一截一截的显示,显的比较难看。可以先显示压缩过的模糊的预览图片,在通过new Image() 的方式加载图片,当图片加载好后在替换页面上的图片
.div1{ width:100%; height:50px; overflow:hidden; }
.div1:hover{ overflow-y:auto }
.div2{ width:100%; margin-left:20px; height:2000px; }
隐藏滚动条
隐藏竖直滚动条,但页面依然可以滚动 兼容性:兼容 IE9及以上
html,body {height: 100%;}
html {overflow: hidden;}
body {overflow: auto;width: calc(100vw + 20px);}
::-webkit-scrollbar { display: none; }
弹窗滚动条不滚动
兼容:兼容 IE8 及以上
通过点击出现弹窗后,通过js设置外部滚动条为隐藏
<div class="buttom" style="width:100%;height:1500px;"></div>
<div class="shadow_box">
<div class="shadow"></div>
<div class="text_box"></div>
</div>
$('.buttom').click(function(){
$('.shadow_box').show()
$(document.body).css({"overflow-x":"hidden","overflow-y":"hidden"});
})
$('.shadow').click(function(){
$('.shadow_box').hide()
$(document.body).css({"overflow-x":"auto","overflow-y":"auto"});
})
通过禁止滚动条响应事件,在关闭弹窗后再响应
function handleStopWheel(e) {
e.preventDefault();
}
$('.buttom').click(()=>{
window.addEventListener("wheel",handleStopWheel,{passive: false})
})
$('#site-toLogin').click(() => {
window.removeEventListener("wheel",handleStopWheel)
});
5:设备分类的参考
关于手机和 PC 的判断
window.location.href = /Android|webOS|iPhone|ipod|ipad|BlackBerry/i.test(navigator.userAgent) ? "https://www.baidu.com/" : "http://news.baidu.com/";
关于屏幕大小属性参考
# 浏览器窗口大小(包括工具栏)
window.outerHeight
window.outerWidth
# 窗口文档显示区(不包含滚动条)
window.innerWidth
window.innerHeight
# 元素级内部大小(不包含滚动条)
clientWidth
clientHeight
关于手机横竖屏的判断
通过 window.orientation
属性进行判断, PC 端为 undefined,90或-90为横屏幕,剩下则是竖屏
手机和电脑长按的混合处理
let isAndroid=/Android|webOS|iPhone|ipod|ipad|BlackBerry/i.test(navigator.userAgent)
let set1,set2,isLong=0,start=false
let dom=document.getElementById('aaa')
dom.removeEventListener('touchstart',a)
dom.removeEventListener('touchmove',b)
dom.removeEventListener('touchend',c)
dom.removeEventListener('mousedown',a)
dom.removeEventListener('mousemove',b)
dom.removeEventListener('mouseup',c)
if(isAndroid){
dom.addEventListener('touchstart',a)
dom.addEventListener('touchmove',b)
dom.addEventListener('touchend',c)
}else{
dom.addEventListener('mousedown',a)
dom.addEventListener('mousemove',b)
dom.addEventListener('mouseup',c)
}
function a(){
start=true
set1=setTimeout(function(){
console.log('这次是长按')
isLong=1
},800)
}
function b(){
if(start){
isLong=2
clearTimeout(set1)
}
}
function c(){
if(isLong==0){
clearTimeout(set1)
console.log('这次是单击')
}
isLong=0
start=false
}
6:功能的相关参考
禁止使用页面后退
兼容性:不支持IE
不支持IE
history.pushState(null, null, document.URL);
window.addEventListener('popstate', function () {
history.pushState(null, null, document.URL);
});
点击关闭当前页面
浏览器出于安全策略的考虑,只允许Javascript 关闭由Javascript 打开的页面,所以当我们需要关闭当前页面的时候,你可以这样
<a onClick="window.opener=null;window.open('','_self');window.close();">关闭</a>
window.opener是一个可读可写的属性,返回对创建该窗口的 Window 对象的引用
window.opener.lose()可以关闭父级窗口
思路,先设置opener为空,当打开一个空的新窗口,关闭父级窗口,因为打开的是空,所有新的子页面不会出现
表单自动填入功能
在部分浏览器中,会默认开启自动完成功能。注意 属性 name 和 id 会影响改功能;
<input type="text"/>
// 当不存在name 或 id 的时候,自动完成不会开启,只有当其中一个出现的时候才会启动。
<form>
<input type="email" name="email" autocomplete="off" />
// 也可以通过 autocomplate 进行控制。
// 自动填写功能默认为黄色,下面的样式会重置它
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
textarea:-webkit-autofill:hover,
textarea:-webkit-autofill:focus,
select:-webkit-autofill,
select:-webkit-autofill:hover,
select:-webkit-autofill:focus {
border: 1px solid green;
-webkit-text-fill-color: green;
-webkit-box-shadow: 0 0 0px 1000px #000 inset;
transition: background-color 5000s ease-in-out 0s;
}
html动态加载 js文件
function loadScript(url,callback){
var script=document.createElement("script");
script.type="text/javascript";
if(script.readyState){
script.onreadystatechange=function(){
if(script.readyState=="load"||script.readyState=="complete"){
script.onreadystatechange=null;
callback();
};
}
}else{
script.onload=function(){
callback();
}
}
script.src=url;
}
loadScript("jquery.js",function(){
console.log('加载完成')
})
prototype 原型改造
var a=document.getElementById("en")
a.addClass=function(name){
var a=this.getAttribute("class")
if(a){
a=a+" "+name;
this.setAttribute("class",a)
}else{
console.log(this)
}
}
a.addClass("name")
String.prototype.lengths=function(name){
console.log(this.length)
}
"lenght".lengths()
页面打印及4A大小的设置
let dom="<!DOCTYPE html>...</html>"
function doPrint3(dom){
var iframe=document.getElementById("print-iframe");
if(!iframe){
var el = document.getElementById("printcontent");
iframe = document.createElement('IFRAME');
iframe.setAttribute("id", "print-iframe");
iframe.setAttribute('style', 'width:794px;height:1090px;');
document.body.appendChild(iframe);
iframe.contentWindow.document.documentElement.innerHTML=dom
var doc = iframe.contentWindow.document;
doc.write("<LINK rel="stylesheet" type="text/css" href="css/print.css">");
}
iframe.contentWindow.print();
if (navigator.userAgent.indexOf("MSIE") > 0){
document.body.removeChild(iframe);
}
}
doPrint3(dom){
var iframe=document.getElementById("print-iframe");
if(!iframe){
iframe = document.createElement('IFRAME');
iframe.setAttribute("id", "print-iframe");
iframe.setAttribute('style', 'width:794px;height:1090px;');
document.body.appendChild(iframe);
iframe.contentWindow.document.documentElement.innerHTML=dom
}
setTimeout(function(){
iframe.contentWindow.print();
var doc = iframe.contentWindow.document;
doc.close();
iframe.contentWindow.focus();
document.body.removeChild(iframe);
},10)
},
数据表格和固定头部的样式
React 代码
import * as React from 'react'
var $ = require('jquery')
export class LTable extends React.Component<any,any>{
constructor(props:any) {
super(props);
this.resize=this.resize.bind(this)
this.state = {
id:this.props.id||'l_'+new Date().getTime(),
clas:this.props.className||'',
height:this.props.height||'300px',
}
}
static contextTypes={
router: function(){
return null
}
}
mounted = false;
componentWillMount(){
this.mounted = true;
}
componentDidMount() {
window.addEventListener('resize', this.resize)
this.resize()
}
componentDidUpdate(){
this.resize()
}
componentWillUnmount(){
window.removeEventListener('resize',this.resize);
this.mounted = false;
}
resize(){
let id=this.state.id
let tbody=this.props.tbody
if(tbody.length>0){
let ltable=document.getElementById(id)!.getElementsByTagName('table')
let thead0=ltable[0].getElementsByTagName('thead')[0]
let thead1=ltable[1].getElementsByTagName('thead')[0]
let ltbody=document.getElementById(id)!.getElementsByClassName('l_table_body')[0]
let th0=thead0.getElementsByTagName('th')
let th1=thead1.getElementsByTagName('th')
thead0.style.minWidth=thead1.offsetWidth+'px'
ltable[0].style.width=ltable[1].offsetWidth+'px'
for(let i=0;i<th1.length;i++){
th0[i].style.width=th1[i].offsetWidth+'px'
}
$(ltbody).scroll(function(e:any){
let div=document.getElementById(id)!.getElementsByClassName('l_table_head')[0]
div.scrollLeft=e.target.scrollLeft
})
}
}
render(){
let thead=this.props.thead,tbody=this.props.tbody
return (
<div id={this.state.id} className={"l_table "+this.state.clas}>
{this.props.title?
<h3 className="l_table_title">{this.props.title}</h3>:''
}
<div className="l_table_head l_scroll_hide">
<table>
<thead>
<tr>
{thead.map((e:any,i:any)=>
<th key={i}>{e.title}</th>
)}
</tr>
</thead>
</table>
</div>
<div className="l_table_body" style={{height:this.state.height}}>
{tbody.length>0?
<table>
<thead>
<tr>
{thead.map((e:any,i:any)=>
<th key={i}>{e.title}</th>
)}
</tr>
</thead>
<tbody>
{tbody.map((tr:any,a:any)=>
<tr key={a}>
{thead.map((td:any,b:any)=>{
if(td.render){
return <td key={b}>{td.render(tr)}</td>
}else{
return <td key={b}>{td.title}</td>
}
})}
</tr>
)}
</tbody>
</table>:
<div className="l_nodata">
<span>No Date</span>
</div>
}
</div>
</div>
)
}
}
.l_table{border: 1px solid #c3c3c3;background: #fff;margin-bottom:20px;}
.l_table table{width:100%}
.l_table th,.l_table td{word-break:keep-all;overflow:hidden;white-space:nowrap;-o-text-overflow:ellipsis;text-overflow:ellipsis;}
.l_table table,.l_table th,.l_table td{border:0;border-spacing:0;}
.l_table td{padding: 6px 10px;max-width: 150px;}
.l_table_title{text-align:center;font-weight:700;margin:0;padding:16px 0;position:relative;top:1px;font-size:14px;color:rgba(0,0,0,0.65);padding-right:17px;}
.l_scroll_hide::-webkit-scrollbar{background:transparent}
.l_scroll_hide{scrollbar-color: transparent transparent;}
.l_table th{background:#fafafa;position:relative;z-index:1;box-sizing:border-box;padding:0px 10px;text-align:left}
.l_table .l_table_head{border-top:1px solid #e8e8e8;}
.l_table .l_table_body td,.l_table_head th,.l_table .l_table_body th{border-right: 1px solid #e8e8e8;border-bottom: 1px solid #e8e8e8}
.l_table .l_table_head{overflow-x:hidden;overflow-y:scroll;}
.l_table .l_table_body{overflow-y:scroll;margin-top: -35px;}
.l_table_head,.l_table_body thead{line-height:34px}
.l_table_body thead{visibility:hidden;}
.l_nodata{position:relative;height:100%}
.l_nodata span{position:absolute;top:calc(50% + 10px);left:50%;transform:translate(-25%);}
自动化填充的样式修改
无论浏览器的元素默认样式设置的再怎么绚丽,我们都希望有足够的自由(修改所有的一切);更何况自动填写那一块黄色的背景和我们设置的风格完全无法融合;
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
textarea:-webkit-autofill:hover,
textarea:-webkit-autofill:focus,
select:-webkit-autofill,
select:-webkit-autofill:hover,
select:-webkit-autofill:focus {
border: 1px solid green;
-webkit-text-fill-color: green;
-webkit-box-shadow: 0 0 0px 1000px #000 inset;
transition: background-color 5000s ease-in-out 0s;
}
7:浏览器开发调试
CONSOLE 各种提示信息的集合
console.log('文字信息');
console.info('提示信息');
console.warn('警告信息');
console.error('错误信息');
throw new Error('这是一个错误提示');
throw { name: '参数错误', message: 'data[0]不存在'}
console.assert(false,'看不见')
console.log("%c我要变色了","color:blue;font-size:20px")
console.group('第一个组');
console.log("1-1");
console.log("1-2");
console.log("1-3");
console.groupEnd();
console.group('第一个组');
console.group("1-1");
console.group("1-1-1");
console.log('内容');
console.groupEnd();
console.groupEnd();
console.group("1-2");
console.log('内容');
console.log('内容');
console.log('内容');
console.groupEnd();
console.groupEnd();
var Obj = {
Obj1: {
a: "aaa",
b: "bbb",
c: "ccc"
},
Obj2: {
a: "aaa",
b: "bbb",
c: "ccc"
}
}
var Arr = [
["aa","bb","cc"],
["dd","ee","ff"],
["gg","hh","ii"],
]
console.table(Obj);
console.table(Arr);
console.trace('调用')
console.time("Chrome中循环1000次的时间");
for(var i = 0; i < 1000; i++){ }
console.timeEnd("Chrome中循环1000次的时间");
8:加密方案
AES对称加密
一般现在的项目,为了通信安全,会考虑信息加密的方案,通过使用AES对传输的内容进行加密,再通过RSA对AES的秘钥进行加密。最后将AES密文和RSA密文传输到后端。
像AES对称加密,是通过一个秘钥进行的加密和解密的,所以这个秘钥的安全性极为重要。
import CryptoJS from "crypto-js"
const AesString=(SymmetricKey,ivString,text)=>{、
const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
const iv = CryptoJS.enc.Utf8.parse(ivString);
let encrypted = CryptoJS.AES.encrypt(text, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
let ciphertext = encrypted.toString();
return ciphertext
}
const AesDcString=(SymmetricKey,ivString,text)=>{
const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
const iv = CryptoJS.enc.Utf8.parse(ivString);
let encrypted = CryptoJS.AES.decrypt(text, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
let message = decrypted.toString(CryptoJS.enc.Utf8);
return message
}
import CryptoJS from "crypto-js"
const AesFile=(SymmetricKey,ivString,file)=>{
const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
const iv = CryptoJS.enc.Utf8.parse(ivString);
let reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onloadend = function () {
let buffer = reader.result;
let wordArray = CryptoJS.lib.WordArray.create(buffer);
let encrypted = CryptoJS.AES.encrypt(wordArray, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
});
let ciphertext = encrypted.toString();
return ciphertext
};
}
const AesDcFile=(SymmetricKey,ivString,fileText,filename)=>{
const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
const iv = CryptoJS.enc.Utf8.parse(ivString);
var decrypted = CryptoJS.AES.decrypt(fileText, key,{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
var buffer = new ArrayBuffer(decrypted.sigBytes);
var view = new Uint8Array(buffer);
for (var i = 0; i < decrypted.sigBytes; i++) {
view[i] = decrypted.words[i >>> 2] >>> (24 - (i % 4) * 8) & 0xff;
}
var blob = new Blob([buffer]);
saveAs(blob,filename);
}
import { saveAs } from "file-saver";
import CryptoJS from "crypto-js"
import JSZip from 'jszip'
const AesFileZip=(SymmetricKey,ivString,fileList,save=false,name='encryption.txt')=>{
const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
const iv = CryptoJS.enc.Utf8.parse(ivString);
const zip = new JSZip()
for(let i in fileList){
zip.file(fileList[i].name, fileList[i].raw)
}
zip.generateAsync({type:"uint8array"}).then(function(zipData) {
const encryptedData = CryptoJS.AES.encrypt(CryptoJS.lib.WordArray.create(zipData), key, {
iv:iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
});
const encryptedBase64 = encryptedData.toString();
if(save){
let str = new Blob([encryptedBase64], {type: 'text/plain;charset=utf-8'});
saveAs(str,encryption.txt);
}
return encryptedBase64
});
}
const AesDcStrToZip=(SymmetricKey,ivString,text,save=true,name='deciphering.zip')=>{
const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
const iv = CryptoJS.enc.Utf8.parse(ivString);
var decrypted = CryptoJS.AES.decrypt(text, key,{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
if(save){
var buffer = new ArrayBuffer(decrypted.sigBytes);
var view = new Uint8Array(buffer);
for (var i = 0; i < decrypted.sigBytes; i++) {
view[i] = decrypted.words[i >>> 2] >>> (24 - (i % 4) * 8) & 0xff;
}
var blob = new Blob([buffer], {type: "text/plain"});
saveAs(blob,name);
}
return decrypted
}
const AesDcStrFileToZip=(SymmetricKey,ivString,file,save=true,name='deciphering.zip')=>{
const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
const iv = CryptoJS.enc.Utf8.parse(ivString);
let reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function() {
let ciphertext = this.result;
var decrypted = CryptoJS.AES.decrypt(ciphertext, key,{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
if(save){
var buffer = new ArrayBuffer(decrypted.sigBytes);
var view = new Uint8Array(buffer);
for (var i = 0; i < decrypted.sigBytes; i++) {
view[i] = decrypted.words[i >>> 2] >>> (24 - (i % 4) * 8) & 0xff;
}
var blob = new Blob([buffer], {type: "text/plain"});
saveAs(blob,name);
}
return decrypted
};
}
RSA非对称加密
非对称加密
import forge from 'node-forge';
const encrypt=(key,text)=>{
var privateKey = forge.pki.publicKeyFromPem(key);
var encrypted = privateKey.encrypt(text, 'RSA-OAEP', {
md: forge.md.sha256.create(),
mgf1: {
md: forge.md.sha1.create()
}
})
return btoa(encrypted)
}
const decrypt=(key,text)=>{
var privateKey = forge.pki.privateKeyFromPem(key);
var encrypted = privateKey.decrypt(atob(text), 'RSA-OAEP', {
md: forge.md.sha256.create(),
mgf1: {
md: forge.md.sha1.create()
}
})
return encrypted
}
const decryptFile=(file,text)=>{
return new Promise(function(resolve, reject) {
let reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function() {
let ciphertext = this.result;
console.log(ciphertext)
let privateKey = forge.pki.privateKeyFromPem(ciphertext);
try{
let encrypted = privateKey.decrypt(atob(text), 'RSA-OAEP', {
md: forge.md.sha256.create(),
mgf1: {
md: forge.md.sha1.create()
}
});
resolve(encrypted);
}catch(err){
reject(err)
}
}
})
}
9:数据处理
数组去除符合条件的子元素
如果直接使用 for 循环去除,那么会出现错误,原因是函数在不断的去除,而索引没变
var arr = [0,1,2,3,4,5,1,2,3]
for (let i=0;i<arr.length;i++) {
if(arr[i] == 2){
arr.splice(i--,1)
}
}
JS 浮点数精确度问题
当js进行浮点型计算的时候,会导致计算出错。例:0.6910=6.8999999999999995,因为js作为解释性语言,同其他语言一样在计算小数的时候将小数转二进制不好转换
解决办法:将小数转换成整数,计算完成后转换成小数。0.69100*10/100
5.324.toFixed(2)==5.32
数字转成每隔3位加逗号
var num_s = "1232134456.546 ";
var num=parseFloat(num_s).toLocaleString();
本地时间规则化
new Date.toLocaleTimeString()
获取当前时间及前半个小时
var a= new Date();
var y=a.getFullYear();
var m=a.getMonth()+1;
var d=a.getDate();
var h=a.getHours();
var f=a.getMinutes();
h<10?h="0"+h:h=h;
f<10?f="0"+f:f=f;
$scope.end_time=y+"-"+m+"-"+d+" "+h+":"+f
var b= new Date(a.getTime()-1000*60*30);
y=b.getFullYear();
m=b.getMonth()+1;
d=b.getDate();
h=b.getHours();
f=b.getMinutes();
$scope.start_time=y+"-"+m+"-"+d+" "+h+":"+f
10:网络请求
AJax停止网络请求 abort()
var currentAjax = null;
function startAjax(){
if(currentAjax) {currentAjax.abort();}
currentAjax = $.ajax({
type:'POST',
beforeSend:function(){},
url:'test.php',
data:'username=xxx',
dataType:'JSON',
error:function(){alert('error')},
success:function(data){alert(data)}
});
}
angular.js $http停止请求
通过注入 $q
服务,使用$q.defer
来停止
var _enj;
$scope.clconversations=function(){
if(_enj){_enj.resolve()};
_enj = $q.defer();
$http.get('/Iridium/public/tcpanalysis/getconversations',{
params:{
start_time: $scope.start_time,
end_time:$scope.end_time,
},
timeout:_enj.promise
}).then(function(response){
console.log('')
});
}
Rem布局
1:网易的rem布局
1:设置viewport
<!--viewport 如果页面不允许缩放请加上 user-scalable=no-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,minimal-ui">
2:根据750px设计稿计算比例
//750px/100=7.5 在页面加载后:需要动态设置font-size
document.documentElement.style.fontSize = document.documentElement.clientWidth /7.5 + 'px';
// 也可以设置成百分比 页面中默认100%=16px
// {w/(750/100)}/16
// (w/7.5)/16
// w/120
document.documentElement.style.fontSize = document.documentElement.clientWidth /1.2 + '%';
2:淘宝rem 布局
<head>
<script>!function(e){function t(a){if(i[a])return i[a].exports;var n=i[a]={exports:{},id:a,loaded:!1};return e[a].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var i={};return t.m=e,t.c=i,t.p="",t(0)}([function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=window;t["default"]=i.flex=function(normal,e,t){var a=e||100,n=t||1,r=i.document,o=navigator.userAgent,d=o.match(/Android[\S\s]+AppleWebkit\/(\d{3})/i),l=o.match(/U3\/((\d+|\.){5,})/i),c=l&&parseInt(l[1].split(".").join(""),10)>=80,p=navigator.appVersion.match(/(iphone|ipad|ipod)/gi),s=i.devicePixelRatio||1;p||d&&d[1]>534||c||(s=1);var u=normal?1:1/s,m=r.querySelector('meta[name="viewport"]');m||(m=r.createElement("meta"),m.setAttribute("name","viewport"),r.head.appendChild(m)),m.setAttribute("content","width=device-width,user-scalable=no,initial-scale="+u+",maximum-scale="+u+",minimum-scale="+u),r.documentElement.style.fontSize=normal?"50px": a/2*s*n+"px"},e.exports=t["default"]}]); flex(false,100, 1);</script>
</head>
此方案默认1rem=100px,如需更改,在代码代码最后更改flex(false,100, 1),此代码仅适用手机,设计稿按屏幕分辨率设计,
在相当数量的布局情境中(比如底部导航元素平分屏幕宽,大尺寸元素),你必须使用百分比或者flex才能完美布局!
Flex布局
Flex布局(弹性布局)在未来将成为主流,目前推荐在手机端使用,React native系列官方建议项目使用flex布局; IE10+
// 设为 Flex 后,子元素的float、clear和vertical-align属性将失效
// Webkit 内核的浏览器,必须加上-webkit前缀
.box{
display: -webkit-flex;
display: flex;
}