前端开发-功能小片与经验总结

1.处理键盘事件,禁止后退键(Backspace)密码或单行、多行文本框除外,作用于IE、Chrome

 

document.onkeydown = function banBackSpace(e){
    var ev = e || window.event;//获取event对象
    var obj = ev.target || ev.srcElement;//获取事件源
    var t = obj.type || obj.getAttribute('type');//获取事件源类型
    //获取作为判断条件的事件类型
    var vReadOnly = obj.getAttribute('readonly');
    var vDisabled = obj.getAttribute('disabled');
    //处理null值情况
    vReadOnly = (vReadOnly == null) ? false : true;
    vDisabled = (vDisabled == null) ? false : true;

    //当敲Backspace键时,事件源类型为密码或单行、多行文本的,
    //并且readonly属性为true或enabled属性为false的,则退格键失效
    var flag1 = (ev.keyCode == 8 && (t=="password" || t=="text" || t=="textarea") && (vReadOnly==true || vDisabled==true)) ? true : false;

    //当敲Backspace键时,事件源类型非密码或单行、多行文本的,则退格键失效
    var flag2 = (ev.keyCode == 8 && t != "password" && t != "text" && t != "textarea") ? true : false;

    //判断
    if(flag1 || flag2){
        return false;
    }
}

 

2.滚动延时加载

 

$(window).scroll(function(){
    var scrollTop = $(this).scrollTop();
    var scrollHeight = $(document).height();
    var windowHeight = $(this).height();
    if(scrollTop + windowHeight == scrollHeight){
        HListApp.update(0, TempApps.get());  //0:追加
    }
});

 

 

 

3.图片居中显示缩略图

 

function fixThumImg(){
    var handle = $(this);
    var pHandle = handle.parent();
    var width = handle.width();
    var height = handle.height();
    var pWidth = pHandle.width();
    var pHeight = pHandle.height();
    
    if(width/height > pWidth/pHeight){
        handle.css("width", "100%");
        var cur_height = (height * pWidth) / width;
        handle.css("margin-top", (pHeight - cur_height)/2);
    }else {
        handle.css("height", "100%");
        var cur_width = (width * pHeight) / height;
        handle.css("margin-left", (pWidth - cur_width)/2);
     }
    
    handle.show();
}

 

4.检测页面是否含有frameset

 

if(top.document.getElementsByTagName("FRAME").length > 0){
    console.log("yes");
}

 

5.input的checked批量操作

 

//批量改变checked属性的话,直接用下面语句会有BUG:
$(".select").attr("checked", false);
//要用map来轮询操作:
$(".select").map(function(){
    $(this)[0].checked = false;
});

 

6.文件大小单位转换,保留最多两位小数

 

function sizeFormat(size)
{
    var unit = ["B", "K", "M", "G", "T"];
    var tmp = size;
    for(var i=0; i<unit.length-1; i++){
        if(tmp < 1024){
            tmp = Math.floor((tmp + 0.005) * 100)/100; //取最多两位小数点
            return tmp + unit[i];
        }
        tmp = tmp/1024;
    }
    tmp = Math.floor((tmp + 0.005) * 100)/100; //取最多两位小数点
    return tmp + unit[unit.length-1];
}

 

7.获取静态页面参数值

 

function getParameter (sProp )
{
    var re = new RegExp (sProp + "=([^\&]*)" , "i" );
    var a = re . exec (document . location . search );
    if (a == null )
        return null ;
    return a [ 1 ];
};


8.阻止滚动冒泡

 

 

//DIV的滚动冒泡不可用,只能阻止默认滚动,然后自己实现
document.getElementById("scroll_div").onmousewheel =(function(e){
    $(this)[0].scrollTop += e.wheelDelta > 0 ? -60 : 60;
	return false;
});

 

9.template变量替换函数

 

 

function replaceTplData(tpl, data){
	return tpl.replace(/\{([\w\.]*)\}/g, function(key, $1){
		return data[$1];
	})
}


10.时间戳格式化函数

 

/**
 * 和PHP一样的时间戳格式化函数
 * @example stampFormat2Date("Y-m-d H:i", new Date().getTime()/1000);
 * @param  {string} format    格式 如'Y-m-d H:i:s'
 * @param  {int}    timestamp 要格式化的时间 默认为当前时间(如:new Date().getTime()/1000)
 * @return {string}           格式化的时间字符串
 */
function stampFormat2Date(format, timestamp){
	var a, jsdate=((timestamp) ? new Date(timestamp*1000) : new Date());
	var pad = function(n, c){
		if((n = n + "").length < c){
			return new Array(++c - n.length).join("0") + n;
		} else {
			return n;
		}
	};
	var txt_weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
	var txt_ordin = {1:"st", 2:"nd", 3:"rd", 21:"st", 22:"nd", 23:"rd", 31:"st"};
	var txt_months = ["", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
	var f = {
		// Day
		d: function(){return pad(f.j(), 2)},
		D: function(){return f.l().substr(0,3)},
		j: function(){return jsdate.getDate()},
		l: function(){return txt_weekdays[f.w()]},
		N: function(){return f.w() + 1},
		S: function(){return txt_ordin[f.j()] ? txt_ordin[f.j()] : 'th'},
		w: function(){return jsdate.getDay()},
		z: function(){return (jsdate - new Date(jsdate.getFullYear() + "/1/1")) / 864e5 >> 0},

		// Week
		W: function(){
			var a = f.z(), b = 364 + f.L() - a;
			var nd2, nd = (new Date(jsdate.getFullYear() + "/1/1").getDay() || 7) - 1;
			if(b <= 2 && ((jsdate.getDay() || 7) - 1) <= 2 - b){
				return 1;
			} else{
				if(a <= 2 && nd >= 4 && a >= (6 - nd)){
					nd2 = new Date(jsdate.getFullYear() - 1 + "/12/31");
					return date("W", Math.round(nd2.getTime()/1000));
				} else{
					return (1 + (nd <= 3 ? ((a + nd) / 7) : (a - (7 - nd)) / 7) >> 0);
				}
			}
		},

		// Month
		F: function(){return txt_months[f.n()]},
		m: function(){return pad(f.n(), 2)},
		M: function(){return f.F().substr(0,3)},
		n: function(){return jsdate.getMonth() + 1},
		t: function(){
			var n;
			if( (n = jsdate.getMonth() + 1) == 2 ){
				return 28 + f.L();
			} else{
				if( n & 1 && n < 8 || !(n & 1) && n > 7 ){
					return 31;
				} else{
					return 30;
				}
			}
		},

		// Year
		L: function(){var y = f.Y();return (!(y & 3) && (y % 1e2 || !(y % 4e2))) ? 1 : 0},
		//o not supported yet
		Y: function(){return jsdate.getFullYear()},
		y: function(){return (jsdate.getFullYear() + "").slice(2)},

		// Time
		a: function(){return jsdate.getHours() > 11 ? "pm" : "am"},
		A: function(){return f.a().toUpperCase()},
		B: function(){
			// peter paul koch:
			var off = (jsdate.getTimezoneOffset() + 60)*60;
			var theSeconds = (jsdate.getHours() * 3600) + (jsdate.getMinutes() * 60) + jsdate.getSeconds() + off;
			var beat = Math.floor(theSeconds/86.4);
			if (beat > 1000) beat -= 1000;
			if (beat < 0) beat += 1000;
			if ((String(beat)).length == 1) beat = "00"+beat;
			if ((String(beat)).length == 2) beat = "0"+beat;
			return beat;
		},
		g: function(){return jsdate.getHours() % 12 || 12},
		G: function(){return jsdate.getHours()},
		h: function(){return pad(f.g(), 2)},
		H: function(){return pad(jsdate.getHours(), 2)},
		i: function(){return pad(jsdate.getMinutes(), 2)},
		s: function(){return pad(jsdate.getSeconds(), 2)},
		//u not supported yet

		// Timezone
		//e not supported yet
		//I not supported yet
		O: function(){
			var t = pad(Math.abs(jsdate.getTimezoneOffset()/60*100), 4);
			if (jsdate.getTimezoneOffset() > 0) t = "-" + t; else t = "+" + t;
			return t;
		},
		P: function(){var O = f.O();return (O.substr(0, 3) + ":" + O.substr(3, 2))},
		//T not supported yet
		//Z not supported yet

		// Full Date/Time
		c: function(){return f.Y() + "-" + f.m() + "-" + f.d() + "T" + f.h() + ":" + f.i() + ":" + f.s() + f.P()},
		//r not supported yet
		U: function(){return Math.round(jsdate.getTime()/1000)}
	};

	return format.replace(/[\\]?([a-zA-Z])/g, function(t, s){
		if( t!=s ){
			// escaped
			ret = s;
		} else if( f[s] ){
			// a date function exists
			ret = f[s]();
		} else{
			// nothing special
			ret = s;
		}
		return ret;
	});
}

 

11.JS中文拼音排序

 

var arr = ["中","华","人","民","共","和","国"]; 
console.log(arr.sort(function(a,b){return a.localeCompare(b)}));

注意到localeCompare方法是在当前区域中进行比较的,即比较的环境为当前操作系统设备的地理区域,比如数字、货币、日期时间等的表现方式(在”控制面板“中可以查看修改),如果设备排序的方式为笔划,那上面的结果则为:人,中,民,共,华,和,国(笔划升序)。

 

 

12.对象和数组的深拷贝

 

 

//对象和数组的深拷贝
Object.clone = function(sObj){
	if(typeof sObj !== "object"){	//数组和对象的type都是"object"
		return sObj;
	}
	var s = {};
	if(sObj.constructor == Array){
		s = [];
	}
	for(var i in sObj){
		s[i] = Object.clone(sObj[i]);	//递归复制所有属性,包括子对象属性
	}
	return s;
}

 

13.对象扩展

 

 

//对象扩展
//tObj被扩展对象,sObj扩展对象
Object.extend = function(tObj,sObj){
	for(var i in sObj){
		if(typeof sObj[i] !== "object"){
			tObj[i] = sObj[i];
		}else if (sObj[i].constructor == Array){
			tObj[i] = Object.clone(sObj[i]);
		}else{
			tObj[i] = tObj[i] || {};
			Object.extend(tObj[i],sObj[i]);
		}
	}
}
//测试用例
var a = {};
var b = {
	"a":1,
    "b":{
		"c":function(t){
			alert(t);
		}
	},
    "d":{
		"e":2,
        "f":[1,4,5,7,9]
    }
};
Object.extend(a,b);//a获得了b的所有属性


14. NaN解释

 

NaN(Not a Number,非数),是计算机科学中数值数据类型的一个值,表示未定义或不可表示的值
1)首先它是一个浮点数,所以不能用来比较,如:
alert(NaN==NaN)  // false 
2)类型为"number",如:
alert(typeof(NaN))  // "number"
alert(NaN==undefined)  // false 

 

 

15.判断变量是否为undefined

 

alert(typeof a == "undefined");

不能直接用以下方法:

 

alert(a == undefined);

因为当变量a未声明时,则会导致JS错误
 

16.JS数组格式化

很多时候我们会想通过一个存有数据的数组来组成一个特定格式的列表,比如数组["aaa","bbb","ccc"],要把它输出到列表1)aaa, 2)bbb, 3)ccc形式,

我们可以通过map函数来简单实现:

1)通过map来格式化一个新数组:

 

var arr = ["aaa","bbb","ccc"];
var tmp = arr.map(function(item, i){
    return i + ")" + item;
});
//此时tmp数组为["1)aaa","2)bbb","3)ccc"]

2)通过join把新数组转换到string

 

 

var str = tmp.join('\n');
//此时str为"1)aaa\n2)bbb\n3)ccc"

当然,我们也可以一步到位:

 

 

var arr = ["aaa","bbb","ccc"];
var str = arr.map(function(item, i){
    return i + ")" + item;
).join('\n');

 

17.可配置函数-闭包用法

 

//如Nodejs里Connect的中间件函数,是指定了req,res和next三个参数的,如:
require('connect')().use(function(req, res, next){
	//middleware logic
	console.log(req.url);
	next();
});
//要想把参数传递给中间件函数,可用闭包的方法,如:
function setup(options) {
	// setup logic
	
	return function (req, res, next) {
		// middleware logic
		//options still accessible even though outer function has returned
		console.log(req.url);
		next();
	}
}

require('connect')().use(setup{name: "Eric"}) //成功把name="Eric"传递到中间件函数

 

18.图像置灰

 

 

.filter_gray{
    -webkit-filter: grayscale(100%);
    -moz-filter: grayscale(100%);
    -ms-filter: grayscale(100%);
    -o-filter: grayscale(100%);

    filter: grayscale(100%);

    filter: gray;
}

 

19.字符串的实际长度

 

平时很多时候要获取字符串的实际长度,但是string.length是不分中英文的,也就是说单双字节的字都算是长度1.

要想获取字符串的实际长度,可以先把双字节的替换成两个单字节的再获取长度,如下

 

function getRealLength(str) {
    return str.replace(/[^\x00-\xff]/g,"aa").length;
};
alert(getRealLength('测试测试ceshiceshi'));


20.禁止页面右键菜单

 

 

 

document.oncontextmenu = function(event) {
	event.returnValue = false;
}

 

21.限制input标签只能输入数字

 

$(".digit-only").keydown(function(e){
	var k = window.event ? e.keyCode : e.which;
	if((k >= 48 && k <=57) || (k >= 96 && k <=105) || k == 8 || k == 0 || (k >= 37 && k <= 40)) {
	}else {
		if((k==67 || k == 86) && e.ctrlKey){	//ctrl + (v/c)
		}else {
			return false;
		}
	}
});

 

22.$(document).ready() 与window.onload的区别

 

  (1).执行时间 
        window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行。 
        $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕。 

  (2).编写个数不同 
         window.onload不能同时编写多个,如果有多个window.onload方法,只会执行一个 
         $(document).ready()可以同时编写多个,并且都可以得到执行 

  (3).简化写法 
         window.onload没有简化写法 
         $(document).ready(function(){})可以简写成$(function(){});

 

23.JS数组根据下标删除元素

 

Array.prototype.remove = function(from, to) {
            var rest = this.slice((to || from) + 1 || this.length);
            this.length = from < 0 ? this.length + from : from;
            return this.push.apply(this, rest);
        };

 

24.在数组指定位置插入元素

 

//在数组(arr)指定位置(i)插入元素(item)
    function insertArray (arr, i, item) { arr.splice(i, 0, item); }

 

25.压缩稀疏数组(ES5)

 

function(arr) {
    //filter方法会跳过稀疏数组中缺少的元素,比如delete a[i]后,可调用该函数去重新压缩成稠密的
    return arr.filter(function() { return true; });
}

压缩空缺并删除undefined和null元素

 

 

function(arr) {
    return arr.filter(function(x) { return x != undefined && x != null;});
}

 

 

 

 

26.富文本

 

function encodeHTML(a) {
	if (a.length == 0) {
		return ""
	}
	a = a.replace(/&/g, "&");
	a = a.replace(/</g, "<");
	a = a.replace(/>/g, ">");
	a = a.replace(/\'/g, "´");
	a = a.replace(/\"/g, """);
	a = a.replace(/\n/g, "<br>");
	return a
}
function decodeHTML(a) {
	if (a.length == 0) {
		return ""
	}
	a = a.replace(/&/g, "&");
	a = a.replace(/</g, "<");
	a = a.replace(/>/g, ">");
	a = a.replace(/´/g, "'");
	a = a.replace(/"/g, '"');
	a = a.replace(/<br>/g, "\n");
	return a
}

 

27.用Ajax请求的时候,怎么才能捕捉到因为跨域限制而导致的失败?

 

网上查了好久,找到了这句话:

If you end up with an XMLHttpRequest having status=0 and statusText=null, it means that the request was not allowed to be performed.

再看看Ajax源码,看到以下:

ajaxError(xhr.statusText || null, xhr.status ? 'error' : 'abort', xhr, settings, deferred)

再看看Ajax的error函数的触发:

settings.error.call(context, xhr, type, error)

第一个参数是xhr;第二个是type,由xhr.status转换过来,0为'error', 1为'abort';第三个参数是error代表xhr.statusText。

综上所述,只要判断type==='abort' && error === null就可以了,如下:

 

$.ajax({
	type: 'get',
	url: 'http://xxxxxxx',
	dataType: 'json',
	data: {},
	success: function(ret){
		console.log(ret);
	},
	error: function(xhr, type, error) {
		if(type === 'abort' && error === null) {
			// 因跨域请求被拦截
			console.log('type:' + type + ', error:' + error);
		}
	}
});

 

28.怎么也记不住但又最常用的CSS代码

 

1)单行显示,超过显示点点点

 

    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;

2)多行显示,超过最近显示点点点

 

    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    text-overflow: ellipsis;
    -webkit-box-orient: vertical;

3)去除移动端点击出现的蓝色背景

 

.tapNone{
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

 

 

 

29.判断div是否在可视区域

 

$(window).scroll(function () {
	var a = document.getElementById("eq").offsetTop;
	if (a >= $(window).scrollTop() && a < ($(window).scrollTop()+$(window).height())) {
		alert("div在可视范围");
	}
});

 

30.JS实现异或加/解密

 

 

var Xor = (function() {
	var _e = {},
		_seed = 7;

	_e.encode = function(str, seed) {
		seed = seed || _seed;

		var ret = '';
		for(var i=0; i<str.length; i++) {
			ret += String.fromCharCode(str.charCodeAt(i) ^ seed);
		}
		return ret;
	};

	_e.decode = function(str, seed) {
		str = str;
		seed = seed || _seed;

		var ret = '';
		for(var i=0; i<str.length; i++) {
			ret += String.fromCharCode(str.charCodeAt(i) ^ seed);
		}
		return ret;
	};

	return _e;
})();

再进化一下,加密的seed不只是一个数字,而是支持一串字符串,按顺序一个一个异或,解密的时候再反序来一个一个异或,另外加密后再通过base64加密

 

// 异或加/解密(base64)
var Xor = (function() {
	var _e = {},
		_seed = 'diamont1001@163.com';

	_e.encode = function(str, seed) {
		seed = seed || _seed;

		var ret = '';
		for(var i=0; i<str.length; i++) {
			var ret1 = String.fromCharCode(str.charCodeAt(i) ^ seed.charCodeAt(0));
			for(var j=1; j<seed.length; j++) {
				ret1 = String.fromCharCode(ret1.charCodeAt(0) ^ seed.charCodeAt(j));
			}
			ret += ret1;
		}
		return base64encode(ret);
	};

	_e.decode = function(str, seed) {
		str = base64decode(str);
		seed = seed || _seed;

		var ret = '';
		for(var i=0; i<str.length; i++) {
			var ret1 = String.fromCharCode(str.charCodeAt(i) ^ seed.charCodeAt(0));
			for(var j=seed.length-1; j>0; j--) {
				ret1 = String.fromCharCode(ret1.charCodeAt(0) ^ seed.charCodeAt(j));
			}
			ret += ret1;
		}

		return ret;
	};

	return _e;
})();

 

31. new Event() 报错 "Uncaught Type Error: Illegal constructor**"

在安卓自带的浏览器,系统版本<5.0,会有可能报以上错误。

解决方法:

 

try {
    event = new Event(eventName, {
        bubbles: true
    });
} catch(e){
    event = document.createEvent('Event');
    event.initEvent(eventName, true, false);
}

参考:https://github.com/silviomoreto/bootstrap-select/issues/1286

 

32. 动画优化

1) 用requestAnimationFrame代替setTimeout

 

const raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame || (f) => setTimeout(f, 1000 / 60);


2) 尽快的调用下一帧

 

 

requestAnimationFrame(function tick() {
  requestAnimationFrame(tick);
  // do something
});

 

 

3) 用translateZ代替z-index

z-index会形成不再预期内的复合层。
 

 

33. 图片上传前预览

图片上传,很多时候需要做下预览,这时就需要用到 FileReader 类来读取图片了。

<input id="userAvatar" type="file"> 编辑头像
$('#userAvatar').change(function(ev) {
		var file = this.files[0];

		if(file) {
			var reader = new FileReader();
			reader.readAsDataURL(file);
			reader.onload = function(e){
				$('#avatarImg').attr('src', this.result);
			};
		}
	});

 

34. 文章关键词标红(源数据为html)

var str = '<p data="123你好啊123">213你好啊123你好你好啊</p>';
str.replace(/(你好)(?=[^>]*(<|$))/gmi, '<span style="background-color: red">$1</span>');

出来的结果是:

<p data="123你好啊123">213<span style="background-color: red">你好</span>啊123<span style="background-color: red">你好</span><span style="background-color: red">你好</span>啊</p>

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值