但图片过大的时候,网速慢的时候,图片会呈现断片式加载一截一截的显示,显的比较难看。可以先显示压缩过的模糊的预览图片,在通过new Image() 的方式加载图片,当图片加载好后在替换页面上的图片
.div1{ width:100%; height:50px; overflow:hidden; }
.div1:hover{ overflow-y:auto }
.div2{ width:100%; margin-left:20px; height:2000px; }
通过overflow:hidden
隐藏滚动条
隐藏竖直滚动条,但页面依然可以滚动 兼容性:兼容 IE9及以上
html,body {height: 100%;}
html {overflow: hidden;}
body {overflow: auto;width: calc(100vw + 20px);}
::-webkit-scrollbar { display: none; }
蒙版弹窗滚动条不滚动
通过点击出现弹窗后,通过js设置外部滚动条为隐藏
$('.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)
});
设备分类的参考
关于手机和 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为横屏幕,剩下则是竖屏
功能的相关参考
禁止用户使用页面后退
不支持IE
history.pushState(null, null, document.URL);
window.addEventListener('popstate', function () {
history.pushState(null, null, document.URL);
});
js控制点击关闭当前页面
浏览器出于安全策略的考虑,只允许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)
},
手机和电脑长按的混合处理
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
}
数据表格和固定头部的样式
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;
}
浏览器开发调试
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次的时间");
通信数据的加密
一般现在的项目,为了通信安全,会考虑信息加密的方案,通过使用AES对传输的内容进行加密,再通过RSA对AES的秘钥进行加密。最后将AES密文和RSA密文传输到后端。
AES对称加密
像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)
}
}
})
}
数据的处理参考
数组去除符合条件的子元素
如果直接使用 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
请求的处理参考
同请求关闭重复请求