乐趣区

前端常用代码片段(五)

前端常用代码片段 (一) 点这里前端常用代码片段 (二) 点这里前端常用代码片段 (三) 点这里前端常用代码片段 (四) 点这里
1.tap 事件点透问题?
问题点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的 click 事件
zepto 的 tap 事件是绑定到 document 的,所以一般点击 tap 事件都会冒泡到 document 才会触发。当点击隐藏蒙层的时候默认也会手指触发到蒙层下面的元素 执行事件
1. github 上有个 fastclick 插件,用来规避 click 事件的延时执行
2. 用 touchend 代替 tap 事件并阻止掉 touchend 的默认行为 preventDefault()
//tap 事件出现点透问题
$(“#id”).on(“tap”, function (event) {
// 很多处理比如隐藏什么的
event.preventDefault();
});

//touchend 事件解决点头问题
$(“#id”).on(“touchend”, function (event) {
// 很多处理比如隐藏什么的
event.preventDefault();
});
3: 给 tap 事件里面的隐藏蒙层方法执行的方法 300 毫秒延迟
$(“#id”).on(‘tap’,function(ev){
setTimeout(function(){
$(“#id”).hide();
},320)
})
2. 固定定位布局 键盘挡住输入框内容?
1. 通过绑定窗口改变事件, 监听键盘的弹出。
然后去改变固定定位元素的位置。默认键盘的宽度应该是页面的 2 分之一。所以我们位移的距离改成键盘的二分之一就可以
window.onresize = function(){
//$(“.mian”) 就是固定定位的元素
if($(“.mian”).css(‘top’).replace(‘px’,”) != 0){
$(“.mian”).css(‘top’,0);
}else{
var winHeight = $(window).height();
$(“.mian”).css(‘top’,-(winHeight/4));
}
}
2. 通过定时器实时监听是否触发 input。
如果触发 input 框 就把固定定位,改变成静态定位。这样就会浏览器会总动把内容顶上去。
function fixedWatch(el) {
//activeElement 获取焦点元素
if(document.activeElement.nodeName == ‘INPUT’) {
el.css(‘position’, ‘static’);
} else {
el.css(‘position’, ‘fixed’);
}
}

setInterval(function() {
fixedWatch($(‘.mian’));
}, 500);
3. 去掉字符左右空格
export const trimLeOrRi=(str)=>{
// 删除左右两端的空格  
return str.replace(/(^\s*)|(\s*$)/g, “”);
}
4. 通过 JS 判断一个数组
4.1 instanceof 方法
instanceof 运算符是用来测试一个对象是否在其原型链原型构造函数的属性
var arr = [];
arr instanceof Array; // true
4.2.constructor 方法
constructor 属性返回对创建此对象的数组函数的引用,就是返回对象相对应的构造函数
var arr = [];
arr.constructor == Array; //true
4.3.toString.call
这种写法,是 jQuery 正在使用的
Object.prototype.toString.call(obj).slice(8,-1) == Array
4.4.ES5 新增方法 isArray()
var a = new Array(123);
var b = new Date();
console.log(Array.isArray(a)); //true
console.log(Array.isArray(b)); //false
字符串也是有 length 属性的
我们知道所有的 Array 都是有 length 属性的,就算是空数组,那么 length 为 0,那么字符串有没有呢?接下来我们来验证一下。
var str=”sdfsd5565s6dfsd65sd6+d5fd5″;
console.log(str.length) // 26
结果是有的,所以我们在判断类型时,不能单纯拿有没有 length 属性来判断是不是数组了,我们可以用下面的方法来判断是否是数组:
var obj=[1,2] ;
console.log(toString.call(obj) === ‘[object Array]’);
5. 删除数组尾部元素
一个简单的用来清空或则删除数组尾部元素的简单方法就是改变数组的 length 属性值。
const arr = [11, 22, 33, 44, 55, 66];
// truncanting
arr.length = 3;
console.log(arr); //=> [11, 22, 33]
// clearing
arr.length = 0;
console.log(arr); //=> []
console.log(arr[2]); //=> undefined
6. 使用对象解构来处理数组
可以使用对象解构的语法来获取数组的元素:
const csvFileLine = ‘1997,John Doe,US,john@doe.com,New York’;
const {2: country, 4: state} = csvFileLine.split(‘,’);
7. 在 switch 语句中用范围值
可以使用下面的技巧来写满足范围值的 switch 语句:
// 不推荐使用,只开阔眼界
function getWaterState(tempInCelsius) {
let state;

switch (true) {
case (tempInCelsius <= 0):
state = ‘Solid’;
break;
case (tempInCelsius > 0 && tempInCelsius < 100):
state = ‘Liquid’;
break;
default:
state = ‘Gas’;
}
return state;
}
// 推荐
function getWaterState2(tempInCelsius) {
if (tempInCelsius <= 0) {
return ‘Solid’;
}
if (tempInCelsius < 100) {
return ‘Liquid’;
}
return ‘Gas’;
}
8. 平铺多维数组
方法 1:es6 使用 Spread 操作,可以很容易去平铺嵌套多维数组:
const arr = [11, [22, 33], [44, 55], 66];
const flatArr = [].concat(…arr); //=> [11, 22, 33, 44, 55, 66]
可惜,上面的方法仅仅适用于二维数组。不过,通过递归,我们可以平铺任意维度的嵌套数组。

unction flattenArray(arr) {
const flattened = [].concat(…arr);
return flattened.some(item => Array.isArray(item)) ?
flattenArray(flattened) : flattened;
}

const arr = [11, [22, 33], [44, [55, 66, [77, [88]], 99]]];
const flatArr = flattenArray(arr);
//=> [11, 22, 33, 44, 55, 66, 77, 88, 99]
方法 2:递归
function flatten(arr){
var res = [];
for(var i=0;i<arr.length;i++){
if(Array.isArray(arr[i])){
res = res.concat(flatten(arr[i]));
}else{
res.push(arr[i]);
}
}
return res;
}
方法 3:reduce
function flatten(arr){
return arr.reduce(function(prev,item){
return prev.concat(Array.isArray(item)?flatten(item):item);
},[]);
}
本节参考文章:5 分钟掌握 JavaScript 小技巧
9. 如果数组列表太大,以下递归代码将导致堆栈溢出。你如何解决这个问题,仍然保留递归模式?
var list = readHugeList();

var nextListItem = function() {
var item = list.pop();

if (item) {
// process the list item…
nextListItem();
}
};
通过修改 nextListItem 函数可以避免潜在的堆栈溢出,如下所示:
var list = readHugeList();

var nextListItem = function() {
var item = list.pop();

if (item) {
// process the list item…
setTimeout(nextListItem, 0);
}
};
堆栈溢出被消除,因为事件循环处理递归,而不是调用堆栈。当 nextListItem 运行时,如果 item 不为 null,则将超时函数(nextListItem)推送到事件队列,并且函数退出,从而使调用堆栈清零。当事件队列运行超时事件时,将处理下一个项目,并设置一个计时器以再次调用 nextListItem。因此,该方法从头到尾不经过直接递归调用即可处理,因此调用堆栈保持清晰,无论迭代次数如何。
10.10!
function f(n){
return (n > 1) ? n * f(n-1) : n
}
11. 移动端底部 input 被弹出的键盘遮挡
Element.scrollIntoView(): 方法让当前的元素滚动到浏览器窗口的可视区域内。
document.querySelector(‘#inputId’).scrollIntoView();
// 只要在 input 的点击事件,或者获取焦点的事件中,加入这个 api 就好了
这个 api 还可以设置对齐方法,选择将 input 放在屏幕的上方 / 下方,类似的 api 还有: Element.scrollIntoViewIfNeeded(),这两个是解决同一个问题的,选择一个用就可以了。
window.addEventListener(‘resize’, function() {
if(
document.activeElement.tagName === ‘INPUT’ ||
document.activeElement.tagName === ‘TEXTAREA’
) {
window.setTimeout(function() {
if(‘scrollIntoView’ in document.activeElement) {
document.activeElement.scrollIntoView();
} else {
document.activeElement.scrollIntoViewIfNeeded();
}
}, 0);
}
});
本节参考文章:关于 input 的一些问题解决方法分享及评论
12. 控制 input 显 / 隐密码
这个就很简单了,只需更改 input 的 type 属性值就可以了。可以看一下 codepen 的 demo
// 点击函数,获取 dom,判断更改属性。
show(){
let input=document.getElementById(“inputId”);
if(input.type==”password”){
input.type=’text’;
}else{
input.type=’password’;
}
}
本节参考文章:关于 input 的一些问题解决方法分享
13.input 多行输入显示换行
在使用 textarea 标签输入多行文本的时候,如果没有对多行文本显示处理,会导致没有换行的情况, 如果用户需要换行 …
解决方法:只要在显示内容的地方将该属性设置为 white-space: pre-line 或者 white-space:pre-wrap,多行文本就可以换行了。
备注:white-space 属性用于设置如何处理元素内的空白,其中包括空白符和换行符。

14. 输入框首尾清除空格 -trim()
输入框清除首尾空格是 input 较为常见的需求,通常在上传的时候将首尾空格去除掉。
原生清除方法:
// 原生方法获取值,清除首尾空格返回一个新的字符串
var str2 = document.getElementById(“inputId”).trim();
Vue 清除方法:
<input v-model.trim=”msg”>
15. 在 input 中监听键盘事件
在用户登录或者搜索框的时候,一般都会监听键盘事件绑定回车按键,来执行登录 / 搜索 等操作。
原生绑定:
<input onkeydown=”keydownMsg(event)” type=”text” />
function keydownMsg(key) {
keyCode = key.keyCode; // 获取按键代码
if (keyCode == 13) {// 判断按下的是否为回车键
// 在 input 上监听到回车 do something
}
}
Vue 按键修饰符 Vue 为监听键盘事件,提供了按键修饰符,并且为常用的按键提供了别名,使用方法如下: 当回车按键在 input 中被按下的时候,会触发里面的函数。
<input @keyup.enter=”enterActive”>
16. 元素滚动到浏览器窗口的可视区域

Element.scrollIntoView() 方法让当前的元素滚动到浏览器窗口的可视区域内。Element.scrollIntoViewIfNeeded() 方法也是用来将不在浏览器窗口的可见区域内的元素滚动到浏览器窗口的可见区域。但如果该元素已经在浏览器窗口的可见区域内,则不会发生滚动。
因而再有什么回到顶部、去到置顶位置和键盘弹出挡住输入框之类的需求,都可以简单解决了。
scrollIntoView
scrollIntoView 只接受一个参数,但接受两种类型的参数,分别是 Boolean 型参数和 Object 型参数。

先说 Boolean 型参数,参数可以使 true 和 false。如果为 true,元素的顶端将和其所在滚动区的可视区域的顶端对齐。若为 false,元素的底端将和其所在滚动区的可视区域的底端对齐。
<body>
<div class=”chunk”></div>
<div class=”btn-top”>up</div>
<div class=”btn-bottom”>down</div>
<script>
const up = document.querySelector(‘.btn-top’);
const down = document.querySelector(‘.btn-bottom’);
const test = document.querySelector(‘.chunk’);
up.addEventListener(‘click’, function() {
test.scrollIntoView(true);
});
down.addEventListener(‘click’, function() {
test.scrollIntoView(false);
});
</script>
</body>

Object 型参数, 这个对象有两个属性,属性 block 值可以是 start 和 end;属性 behavior 值 auto、instant 和 smooth
up.addEventListener(‘click’, function() {
test.scrollIntoView({
block: ‘start’,
behavior: ‘smooth’
});
});
down.addEventListener(‘click’, function() {
test.scrollIntoView({
block: ‘end’,
behavior: ‘smooth’
});
});

scrollIntoViewIfNeeded
scrollIntoViewIfNeeded 可以接受一个 Boolean 型参数,和 scrollIntoView 不同,true 为默认值,但不是滚动到顶部,而是让元素在可视区域中居中对齐;false 时元素可能顶部或底部对齐,视乎元素靠哪边更近。
两者主要区别有两个。首先是 scrollIntoViewIfNeeded 是比较懒散的,如果元素在可视区域,那么调用它的时候,页面是不会发生滚动的。其次是 scrollIntoViewIfNeeded 只有 Boolean 型参数,也就是说,都是瞬间滚动,没有动画的可能了。
兼容性的话
scrollIntoView:Boolean 型参数几乎随便用了 scrollIntoViewIfNeeded:IE 和 FireFox 全红,移动端基本都 OK
详细见原文
本节参考文章:scrollIntoView…
17.ES6 中的 解构运算符 …
… 每次只能展开最外层的数组,被 [].concat 后,arr 就扁平化一次。
function flatten(arr){
while(arr.some(item => Array.isArray(item))){
arr = [].concat(…arr);
}
return arr;
}

const arr = [1, [2, [3, 4]]];
console.log(flatten(arr));
本节参考文章:数组扁平化
18.reverse 数组
const reverse = xs => {
if (xs.length === 1) return xs;
const [head, …tail] = xs;
return reverse(tail).concat(head);
};

reverse([1,2,3,4,5,6]) // [6,5,4,3,2,1]
19. 正则实现 trim() 功能
function myTrim(str) {
let reg = /^\s+|\s+$/g;
return str.replace(reg, “”);
}
console.log(myTrim(‘ asdf ‘));
本节参考文章:2018 前端面试总结 …
20.js 数组每一项去除空格
var s = “222 , 3334, 3666 ”

s.replace(/\s/g,””) // “222,3334,3666”

退出移动版