[TOC]

常用代码片段

1. document

1.1 自动点击按钮

<div id="one">1234</div>
<script>
  var div = document.getElementById('one');   //获取元素div
  div.onclick = function(){   //给元素增加点击事件
    console.log('我被点击了')
  };
  div.click();
</script>

1.2 HTML加载完毕再执行JS

window.onload=function (){
  console.log("页面加载完毕");
}

1.3 JS设置div高度、最小高度

<style>
  .one { border: 1px solid red; }
</style>
<div class="one"> 1111 </div>
<script>
  var one = document.querySelector(".one")
  one.style.height = "100px";
  one.style.minHeight = "200px"
</script>

1.4 JS实现页面跳转

<input type="button" onclick="new_page()" value="在新窗口打开s"/> 
<input type="button" onclick="old_page()" value="跳转后有后退功能"/> 
<input type="button" onclick="replace()" value="跳转后没有后退功能"/> 
<script language="javascript">
  function old_page()  {  window.location = "about.html" } 
  function replace()  {  window.location.replace("about.html")  } 
  function new_page()  {  window.open("about.html")  } 
  // window.history.back(-1);	返回上一页 返回两个页面: history.go(-2); 
  // window.history.go(-1);
  // window.navigate("xx.jsp"); 
  // self.location='xx.htm';  self:当前窗口对象(如果是在iframe里,则为该框架的窗口对象)
  // 第一种:直接跳转加参数
  // window.location.href="login.jsp?backurl="+window.location.href; 
  // 
</script> 
<script>window.location.href='http://www.baidu.com';</script>

window.location 属性是兼容所有浏览器的。因此在实现页面跳转的时候这个比较常用。

window.navigate("http://xx.html/") 这个方法是只针对IE的,不适用于火狐等其他浏览器,在HTML DOM Window Object中,根本没有列出window.navigate这个方法,所以这个方法尽量少用。

1.5 事件委托指定子节点才出发事件

现在给一个场景 ul > li > div > p,div占满li,p占满div,给ul绑定时间,需要判断点击的是不是li标签。

<ul id="test">
  <li>
    <p>11111111111</p>
  </li>
  <li>
    <div><p>11111111111</p></div>
  </li>
  <li>
    <span>3333333333</span>
  </li>
  <li>4444444</li>
</ul>

如上列表,有4个li,里面的内容各不相同,点击li,event对象肯定是当前点击的对象,怎么指定到li上,下面我直接给解决方案:

var oUl = document.getElementById('test');
oUl.addEventListener('click',function(ev){
  var target = ev.target;
  while(target !== oUl ){
    if(target.tagName.toLowerCase() == 'li'){
      console.log('li click~');
      break;
    }
    target = target.parentNode;
  }
})

参考资料:https://www.cnblogs.com/liugang-vip/p/5616484.html

1.6 获取浏览器窗口宽度

// 浏览器窗口的宽度
getClientWidth(){
  var clientWidth = 0, bodyClientWidth = 0, documentClientWidth = 0;
  if(document.body){ bodyClientWidth = document.body.clientWidth; }
  if(document.documentElement){
    documentClientWidth = document.documentElement.clientWidth;
  }
  clientWidth = (bodyClientWidth - documentClientWidth > 0) ? bodyClientWidth : documentClientWidth;
  return clientWidth;
}

1.7 文档的总高度(页面内容的总高度)

//文档的总高度
getScrollHeight: function(){
  var scrollHeight = 0, bodyScrollHeight = 0, documentScrollHeight = 0;
  if(document.body){ bodyScrollHeight = document.body.scrollHeight; }
  if(document.documentElement){
    documentScrollHeight = document.documentElement.scrollHeight;
  }
  scrollHeight = (bodyScrollHeight - documentScrollHeight > 0) ? bodyScrollHeight : documentScrollHeight;
  return scrollHeight;
}

1.8 获取浏览器可见部分的高度

// 获取浏览器可见部分的高度
getWindowHeight: function() {
  var windowHeight = 0;
  if(document.compatMode == "CSS1Compat"){
    windowHeight = document.documentElement.clientHeight;
  }else{ 
    windowHeight = document.body.clientHeight; 
  }
  return windowHeight;
}

1.9 获取URL上的参数,解决参数中文乱码

function getParams(name) {
  var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
  // decodeURI就是解决中文乱码问题的
  var r = decodeURI(window.location.search).substr(1).match(reg);
  if (r != null) {
    return unescape(r[2]);
  }
  return null;
}
var message = getParams('message');

// chrome浏览器调试工具
// https://www.baidu.com/?aa=baladadasjj%E5%B7%B4%E6%8B%89&bb=dsadadada

1.10 使用JS页面跳转

// 当前页面跳转
window.location.href = window.location.origin + '/#/' + targetLink;
window.location.href = "http://www.baidu.com";
// 在新窗口中打开页面
window.open("http://www.baidu.com");

1.11 元素懒加载:滚动到底部触发事件

<div class="father">
  <div class="son">son</div>
  <div class="son">son</div>
  <div class="son">son</div>
</div>
.father {
  width: 200px; height: 500px; border: 1px solid;
  overflow: auto;
}
.son {
  height: 200px;
  background: rgba(100, 200, 100, 0.5)
}
var father = document.querySelector('.father');
var i = 0;
father.onscroll = function() {
  var clientHeight = father.clientHeight; // 可视区域高度
  var scrollHeight = father.scrollHeight; // 滚动的总高度
  var scrollTop = father.scrollTop; // 已经滚动的高度
  if (scrollTop + clientHeight === scrollHeight) {
    console.log('已经滚动到底部了');
    var div = document.createElement("div");
    div.innerHTML = "<p class=co>这是p标签</p>" + i++;
    father.appendChild(div);
  }
};

http://js.jirengu.com/yahec/1/edit?html,css,js

别的参考链接:https://blog.csdn.net/u011215669/article/details/84947036

1.12 scroll:页面已经滚动了多少距离

getScrollTop: function (){
  var scrollTop = 0, bodyScrollTop = 0, documentScrollTop = 0;
  if(document.body){ bodyScrollTop = document.body.scrollTop; }
  if(document.documentElement){
    documentScrollTop = document.documentElement.scrollTop;
  }
  scrollTop = (bodyScrollTop - documentScrollTop > 0) ? bodyScrollTop : documentScrollTop;
  return scrollTop;
}

1.13 scroll:设置滚动到顶部

const clickBackTop = () => {
  // 执行动画间隔时间,毫秒
  const spacingTime = 20;
  // 运动轨迹
  let space = [50, 40, 30, 20, 1, 0, 0, 0];
  let i = 0;
  let scrollTimer = setInterval(() => {
    const scrollTop =  document.body.scrollTop || document.documentElement.scrollTop;
    if (scrollTop > 0) {
      document.body.scrollTop = scrollTop - space[i];
      document.documentElement.scrollTop = scrollTop - space[i];
      i += 1;
      i === space.length ? i = 0 : '';
    } else {
      clearInterval(scrollTimer); // 清除计时器
    }
  }, spacingTime);
}

1.14 获取一个元素距离顶部的高度

function getTop(element) {
  var realTop = element.offsetTop; // 距离父元素的高度
  var parent = element.offsetParent; // 获取父元素
  while (parent !== null) {
    realTop += parent.offsetTop;
    parent = parent.offsetParent;
  }
  return realTop;
}
var child = document.getElementById("child");
var top = getTop(child);

1.15 scroll:设置元素滚动到可视区域

当一个元素不在浏览器可视区域时,需要把元素显示在可视区域,比如一个表单字段很多,当点击确认按钮,校验失败,需要跳转到校验失败的字段,把校验失败的字段显示在可视区域的顶部,

实现的方法是:

  • 1、获取该元素距离页面顶部的距离top。
  • 2、谁知滚动条的滚动距离为top
// 设置元素显示在窗口可视区域
setViewableArea = (id) => {
  const dom = document.getElementById(id);
  // 上面的方法
  const top = this.getTop(dom);
  document.body.scrollTop = top;
  document.documentElement.scrollTop = top;
}

1.16 JS根据图片的url获取图片的像素(宽高)

const url = 'https://threemodel.oss-cn-beijing.aliyuncs.com/barcolor2.png'
const image = new Image()
image.src = url
image.onload = () => {
  console.log(image.width, image.height)
}

2. JavaScript 相关

2.1 遍历对象属性,获取对象中key,做相关操作

遍历对象自己的属性:

var obj = {a: 5, b: 10, x:null, y: undefined, z: 'tt'}
for (key in obj) {
  // eslint代码检查推荐:Object.prototype.hasOwnProperty.call(object, key)
  if (obj.hasOwnProperty(key)) {
    console.log(key,obj[key]) 
  }
}

更简洁的写法:

var obj = {a: 5, b: 10, x:null, y: undefined, z: 'tt'}
Object.keys(obj).forEach(key => {
  if (obj[key]) {
    console.log(key,obj[key])
  }
});

2.2 数字千分位格式化

2.2.1 使用内置函数 toLocaleString

var num = 123456789012345678; // num超出范围,自动变成123456789012345680
num.toLocaleString();	// '123,456,789,012,345,680'

// 对于小数位数超过3个的,会自动截取到3位(四舍五入)
var num1 = 1234567894562.2256;
num1.toLocaleString();	// '1,234,567,894,562.226'
var num1 = 894562.12345678;
num1.toLocaleString('en-US');	// '894,562.123'

缺点:
1、toLocaleString('en-US') 方法依赖于特定的语言环境(locale),它会根据所提供的语言环境参数对数字进行格式化。这意味着不同的语言环境会有不同的格式化结果,例如,在某些语言中,数字的分组符号不是逗号 , 而是其他字符,像法语中可能是空格。所以需要指定'en-US'。如果你需要在不同语言环境的应用程序中使用,可能需要动态切换语言环境,否则会导致显示结果不符合预期。
2、此方法在数字小数位长度超过3位时,会截取保留3位小数(四舍五入)(chrome浏览器)。

2.2.2 使用正则表达式

// 首先将数字通过 toString() 方法转换为字符串,然后使用 split('.') 将整数部分和小数部分分开
// 对整数部分使用正则表达式 /\B(?=(\d{3})+(?!\d))/g 进行千分位添加操作。
// 最后使用 join('.') 把整数部分和小数部分重新拼接成完整的数字字符串。
function formatNumberWithSplitAndJoin(num) {
  // 不能转为数字的直接返回
  if (!Number(num)) {
    return num;
  }
  let parts = num.toString().split('.');
  parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  return parts.join('.');
}

// 示例
console.log(formatNumberWithSplitAndJoin(6789123.123456789))
// 6,789,123.123456789
console.log(formatNumberWithSplitAndJoin(12345678901234567))
// 12,345,678,901,234,568

2.2.3 Intl.NumberFormat 对象(ES2020)

function formatNumberWithIntl(num) {
  return new Intl.NumberFormat('en-US').format(num);
}
// 示例
let num = 123456789.123;
console.log(formatNumberWithIntl(num)); 
  • Intl.NumberFormat 是一个内置的对象,它可以根据不同的语言环境对数字进行格式化。
  • new Intl.NumberFormat('en-US') 创建一个使用美国语言环境的格式化对象。
  • format(num) 方法将传入的数字按照指定的语言环境进行格式化,会添加千分位分隔符。
  • 兼容性:主流现代浏览器(如 Chrome、Firefox、Safari、Edge 等最新版本)对 Intl.NumberFormat 提供了良好支持。这些浏览器能够完整实现 Intl.NumberFormat 的各种功能,包括不同语言环境下的数字格式化、货币格式化等。例如,在 Chrome 浏览器中,可以轻松使用以下代码实现数字的千分位格式化并按指定语言环境显示
  • 旧版浏览器:IE 浏览器(包括 IE11 及以下版本)完全不支持 Intl.NumberFormat。这意味着在使用 IE 浏览器的环境中,上述代码会抛出 ReferenceError,提示 Intl 未定义。在开发需要兼容 IE 浏览器的项目时,若要实现类似功能,需使用 polyfill 来模拟 Intl.NumberFormat 的行为。例如,可以引入 Intl.js 库,它是一个 JavaScript 实现的 Intl API 兼容库,

2.3 阻止事件冒泡

// 阻止事件冒泡
function stopHandler(e){  
  // 如果提供了事件对象,则这是一个非IE浏览器
  if ( e && e.stopPropagation ) {
    // 因此它支持W3C的stopPropagation()方法
    e.stopPropagation();
  } else {
    // 否则,我们需要使用IE的方式来取消事件冒泡
    window.event.cancelBubble = true;
  }
}  

2.4 阻止浏览器的默认行为

function stopDefault( e ) {
  //阻止默认浏览器动作(W3C)
  if ( e && e.preventDefault )
    e.preventDefault();
  //IE中阻止函数器默认动作的方式
  else
    window.event.returnValue = false;
  return false;
}

2.5 input输入框事件:获取焦点、失去焦点、值发生改变

  • 获取焦点:onFocus
  • 失去焦点:onBlur
  • 值发生改变:onchange
<input  type="text" onBlur=" " onFocus=" " onchange="function()" />

2.6 JS实现Input输入框高度自适应

html:

<textarea id="textarea" placeholder="回复内容"></textarea>

CSS:

#textarea {
    display: block;
    margin:0 auto;
    overflow: hidden;
    width: 200px;
    font-size: 14px;
    height: 18px;
    line-height: 24px;
    padding:2px;
}
textarea {
    outline: 0 none;
    border-color: rgba(82, 168, 236, 0.8);
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
}

JS:

/**
* 文本框根据输入内容自适应高度
* @param                {HTMLElement}        输入框元素
* @param                {Number}             设置光标与输入框保持的距离(默认0)
* @param                {Number}             设置最大高度(可选)
*/
var autoTextarea = function (elem, extra, maxHeight) {
  extra = extra || 0;
  var isFirefox = !!document.getBoxObjectFor || 'mozInnerScreenX' in window,
      isOpera = !!window.opera && !!window.opera.toString().indexOf('Opera'),
      addEvent = function (type, callback) {
        elem.addEventListener ?
          elem.addEventListener(type, callback, false) :
        elem.attachEvent('on' + type, callback);
      },
      getStyle = elem.currentStyle ? function (name) {
        var val = elem.currentStyle[name];

        if (name === 'height' && val.search(/px/i) !== 1) {
          var rect = elem.getBoundingClientRect();
          return rect.bottom - rect.top -
            parseFloat(getStyle('paddingTop')) -
            parseFloat(getStyle('paddingBottom')) + 'px';        
        };

        return val;
      } : function (name) {
        return getComputedStyle(elem, null)[name];
      },
      minHeight = parseFloat(getStyle('height'));

  elem.style.resize = 'none';

  var change = function () {
    var scrollTop, height,
        padding = 0,
        style = elem.style;

    if (elem._length === elem.value.length) return;
    elem._length = elem.value.length;

    if (!isFirefox && !isOpera) {
      padding = parseInt(getStyle('paddingTop')) + parseInt(getStyle('paddingBottom'));
    };
    scrollTop = document.body.scrollTop || document.documentElement.scrollTop;

    elem.style.height = minHeight + 'px';
    if (elem.scrollHeight > minHeight) {
      if (maxHeight && elem.scrollHeight > maxHeight) {
        height = maxHeight - padding;
        style.overflowY = 'auto';
      } else {
        height = elem.scrollHeight - padding;
        style.overflowY = 'hidden';
      };
      style.height = height + extra + 'px';
      scrollTop += parseInt(style.height) - elem.currHeight;
      document.body.scrollTop = scrollTop;
      document.documentElement.scrollTop = scrollTop;
      elem.currHeight = parseInt(style.height);
    };
  };

  addEvent('propertychange', change);
  addEvent('input', change);
  addEvent('focus', change);
  change();
};

// 执行
var text = document.getElementById("textarea");
autoTextarea(text);// 调用

参考链接:https://www.cnblogs.com/milude0161/p/5264102.html

2.7 自定义一个事件监听

有的时候发现有的事件没有监听方法,那么此时可以手动添加一个该事件的监听函数。

添加一个pushState监听事件:

var _wr = function (type) {
  var orig = history[type];
  return function () {
    var rv = orig.apply(this, arguments);
    var e = new Event(type);
    e.arguments = arguments;
    window.dispatchEvent(e);
    return rv;
  };
};
history.pushState = _wr('pushState');
window.addEventListener('pushState', function(e) {
  console.log('监听pushState');
});

参考资料:https://juejin.im/post/5c2708cd6fb9a049f06a5744#heading-6

2.8 复制一个对象(深拷贝)

1、如果只是需要简单地复制对象的属性,而不用考虑它的constructor,也不用考虑函数,正则,Data等特殊数据类型,可使用JSON来解决

var a = { a: 1, b: 2, c: 3 };
var b = JSON.parse(JSON.stringify(a))
b.c = 500;
console.log('a.c: ', a.c)
console.log('b.c: ', b.c)

function deepCopy(obj){
  if(typeof obj !== "object"){ return ;}
  var str = JSON.stringify(obj);
  return JSON.parse(str);
}

如果环境支持ES6语法以上,那么还可以使用扩展预算符:

var a = { a: 1, b: 2, c: 3 };
var b = { ...a};
b.c = 360;
console.log('a.c: ', a.c)
console.log('b.c: ', b.c)

2、需要把函数,正则等特殊数据类型也考虑在内,或者当前环境不支持JSON时。这时,我们可以通过递归来实现对象的深层复制:

function deepCopy(obj){
  var newObj = obj.constructor === Array ? []:{};
  newObj.constructor = obj.constructor;

  if(typeof obj !== "object"){ 
    return ;
  } else if(window.JSON){
    //若需要考虑特殊的数据类型,如正则,函数等,需把这个else if去掉即可
    newObj = JSON.parse(JSON.stringify(obj));
  } else {
    for(var prop in obj){
      if(obj[prop].constructor === RegExp ||obj[prop].constructor === Date){
        newObj[prop] = obj[prop];
      } else if(typeof obj[prop] === 'object'){
        //递归
        newObj[prop] = deepCopy(obj[prop]);
      } else {
        newObj[prop] = obj[prop];
      }
    }
  } 
  return newObj;
}

参考资料:https://segmentfault.com/a/1190000008891000

/**
 * 深层复制
 * @param source    要复制的对象
 * @returns {[]|{}}
 */
function deepClone (source) {
  if (!source && typeof source !== 'object') {
    throw new Error('error arguments', 'shallowClone')
  }
  const targetObj = source.constructor === Array ? [] : {}
  for (const keys in source) {
    if (source.hasOwnProperty(keys)) {
      if(source[keys].constructor === RegExp ||source[keys].constructor === Date){
        newObj[prop] = obj[prop];
      } else if (source[keys] && typeof source[keys] === 'object') {
        // 用于递归调用时,报错了,这个还有值
        targetObj[keys] = source[keys].constructor === Array ? [] : {};
        targetObj[keys] = deepClone(source[keys])
      } else {
        targetObj[keys] = source[keys]
      }
    }
  }
  return targetObj
}

2.9 ES6语法的解构赋值和扩展运算符

2.9.1 解构赋值

let [a, b, c] = [1, 2, 3];
let [bar, foo] = [1];
let [foo = true] = [];
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
// 如果变量名与属性名不一致,必须写成下面这样
let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; // baz === "aaa"

上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值。 如果解构不成功,变量的值就等于undefined。 解构赋值允许指定默认值。

解构不仅可以用于数组,还可以用于对象。变量必须与属性同名,才能取到正确的值。

注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。

ES6 变量的解构赋值 阮一峰

2.9.2 扩展运算符

扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。该运算符主要用于函数调用。

console.log(...[1, 2, 3])					// 1 2 3
console.log(1, ...[2, 3, 4], 5)		// 1 2 3 4 5

ES6 数组的扩展运算符

ES2018在对象中引入了扩展运算符,也可以对对象使用扩展运算符

var a = { a: 1, b: 2, c: 3 };
var b = { ...a};
b.c = 360;
console.log('a.c: ', a.c)
console.log('b.c: ', b.c)

上面的代码实现了简单的对象深拷贝。

参考资料:

https://www.cnblogs.com/chrischjh/p/4848934.html

2.10 函数防抖

/**
 * 防抖函数
 * @param  {function}   func    执行的函数
 * @param  {number}     delay   延迟执行的时间
 * @return {function}           包装过的支持防抖动函数
 */
export const debounce = (func, delay = 500) => {
  let timerId = null;
  let context;
  return (...args) => {
    context = this;
    if (timerId) {
      window.clearTimeout(timerId);
      timerId = null;
    }
    timerId = setTimeout(() => {
      func.apply(context, args);
      timerId = null;
    }, delay);
  };
};

2.11 JS让时间显示为多久以前

根据这个参考:https://segmentfault.com/a/1190000005625314

在上面参考的基础上,改为使用moment,

// 分钟、小时、天、月、年的秒数
const longTime = {
  minute: 60,
  hour: 60 * 60,
  day: 60 * 60 * 24,
  month: 60 * 60 * 24 * 30,
  year: 60 * 60 * 24 * 30 * 12,
}

/**
 * 获取时间距离当前间隔
 * @param  {string} time    时间,格式为:'2020-01-06 10:12:54' 或者为时间戳
 * @return {string}         返回多久以前,比如: 12秒前,5天前
 */
const getTime = time => {
  const limit = moment().diff(moment(time), 'second')
  let content = ''
  if (limit >= 0 && limit < longTime.minute) {
    content = `${limit}S前`
  } else if (limit >= longTime.minute && limit < longTime.hour) {
    content = `${Math.floor(limit / longTime.minute)}分钟前`
  } else if (limit >= longTime.hour && limit < longTime.day) {
    content = `${Math.floor(limit / longTime.hour)}小时前`
  } else if (limit >= longTime.day && limit < longTime.month) {
    content = `${Math.floor(limit / longTime.day)}天前`
  } else if (limit >= longTime.month && limit < longTime.year) {
    content = `${Math.floor(limit / longTime.month)}个月前`
  } else if (limit >= longTime.year) {
    content = '很久前'
  }
  return content
}

2.12 文件大小单位转换KB、MB、GB

/**
 * 格式化文件单位
 *
 * @param  {number | string} value      文件大小
 * @param  {array}           unitList   单位,数组第一个元素是传入的单位
 */
formatFileSize(value, unitList) {
  const unit = unitList || [ "Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
  if (!Number(value)) {
    return 0 + unit[0];
  }
  const advancedUnit = 1024; // 进制单位
  const originValue = Number(value);
  // unit单位索引
  let index = Math.floor(Math.log(originValue) / Math.log(advancedUnit));
  // 如果转换的单位超出了 单位数组范围,那么取到单位数组最后一位为止
  if (index > unit.length - 1) {
    index = unit.length - 1;
  }
  var resultValue = (originValue / Math.pow(1024, index)).toFixed(2);
  return resultValue + unit[index];
}

其他类似写法:https://www.cnblogs.com/willingtolove/p/9409979.html

2.13 JS处理文件下载方法

1、先调用接口获取到下载的资源,然后在下载到电脑本地,当文件很大,非常耗时的时候,会造成点击下载按钮自后,页面好像没有执行,没有反应,只有等文件资源全部下载结束,才会显示正在下载

  • 使用fetch
downLoad = (record) => {
  const params = { fileKey: record.fileId };
  const downloadUrl = '/api/downLoad';
  fetch(downloadUrl, {
    method: 'POST',
    body: window.JSON.stringify(params),
    credentials: 'include',
    headers: new Headers({
      'Content-Type': 'application/json',
    })
  }).then((response) => {
    response.blob().then(blob => {
      if (window.navigator && window.navigator.msSaveOrOpenBlob) {
        window.navigator.msSaveOrOpenBlob(blob, record.origFileName);
      } else {
        const aLink = document.createElement('a');
        document.body.appendChild(aLink);
        aLink.style.display = 'none';
        const objectUrl = window.URL.createObjectURL(blob);
        aLink.href = objectUrl;
        aLink.download = record.origFileName;
        aLink.click();
        document.body.removeChild(aLink);
      }
    });
  }).catch(() => {
    // console.log(error);
  });
};
  • 使用axios
import axios from "axios";

const downloadUrl = '/api/downLoad';
axios({
  url: downloadUrl,
  method: "post",
  headers: {
    "Content-Type": "application/x-www-form-urlencoded",
  },
  data: formData
}).then(res => {
  console.log("res: ", res);
  const fileName = info.fileName;
  const blob = new Blob([res.data]);
  // const blob = new Blob([res.data], {type: 'application/vnd.ms-excel'});
  if (window.navigator && window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(blob, fileName);
  } else {
    const aLink = document.createElement('a');
    document.body.appendChild(aLink);
    aLink.style.display = 'none';
    const objectUrl = window.URL.createObjectURL(blob);
    aLink.href = objectUrl;
    aLink.download = fileName;
    aLink.click();
    document.body.removeChild(aLink);
  }
});

2、直接打开链接,然后直接就显示下载的内容,这种的适用更广泛

  • 使用form表单形式
// fileKey: 文件标识
// downloadUrl: 下载url路径
// currentUserAccount: 需要的其他参数
function handleDownload ( fileKey, downloadUrl, currentUserAccount) {
  var form = document.createElement('form');
  form.setAttribute('style', 'display:none');
  form.setAttribute('method', 'post');
  form.setAttribute('action', downloadUrl);
  form.setAttribute('target', '_blank');

  var inputFileKey = document.createElement('input');
  inputFileKey.setAttribute('type', 'hidden');
  inputFileKey.setAttribute('name', 'fileKey');
  inputFileKey.setAttribute('value', fileKey);
  form.appendChild(inputFileKey);
  var inputCurrentUserAccount = document.createElement('input');
  inputCurrentUserAccount.setAttribute('type', 'hidden');
  inputCurrentUserAccount.setAttribute('name', 'currentUserAccount');
  inputCurrentUserAccount.setAttribute('value', currentUserAccount);
  form.appendChild(inputCurrentUserAccount);

  document.body.appendChild(form);
  form.submit();
  form.remove();
}
  • a标签,触发点击下载
function handleDownload ( id) {
  const aLink = document.createElement('a');
  aLink.style.display = 'none';
  aLink.href = `/api/download?id=${id}&aaa=33`; // 下载链接
  aLink.download = '文件.xls'; // 下载文件名字
  document.body.appendChild(aLink); // a标签添加到html中
  aLink.click(); // 触发点击事件,下载文件
  document.body.removeChild(aLink); // 删除添加的标签
}

2.14 获取文件的扩展名

// 参数fileName是文件名(带扩展名),字符串形式,如:'天境.甘青4日游.pdf'
// 返回 数组, 第一个元素是文件名,第二个元素是扩展名
function processFileName(fileName) {
  if (!fileName) {
    return [null, null];
  }
  const reg = /\.([a-zA-Z]*)$/;
  let extend = null;
  let result = fileName.match(reg);
  if (result) {
    extend = result[1] || null;
  }
  const name = fileName.replace(reg, '');
  return [name, extend]
}

2.15 代码判断IE浏览器

// 取得浏览器的userAgent字符串
var userAgent = navigator.userAgent;
// 判断是否IE<11浏览器
var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1;
// 判断是否IE的Edge浏览器
var isEdge = userAgent.indexOf("Edge") > -1 && !isIE;
// IE11浏览器判断, 工作中用到这个了,有效
var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;

2.16 JS屏蔽iframe调用

通过一些方法判断是否是顶层页面URL路径和当前页面URL路径是否是一个,如果不是一个,则把顶层页面设置成当前页面打开。

Window.top:返回窗口层级最顶层窗口的引用。

window.parent: 返回当前窗口的直接父对象。

// self.location === window.location === location
if(top.location != self.location){ 
  top.location = self.location; // 防止页面被框架包含 
} 

2.17 JS关闭当前页面

<button onclick="ClosePage()">点击关闭网页</button>
<script>
  // 第一种
  function ClosePage() {
    open(location, '_self').close();
  }
  // 第二种
  function close(){
    if (navigator.userAgent.indexOf("Firefox") != -1 || navigator.userAgent.indexOf("Chrome") !=-1) {
      window.location.href="about:blank";
      window.close();
    } else {
      window.opener = null;
      window.open("", "_self");
      window.close();
    }
  }
  // 第三种:变成空白页。经过测试,手机端可以
  function mobileClose() {
    window.location.href = "about:blank";
    window.open("", "_self");
    window.close();
  }

</script>

2.18 JS判断浏览器是PC端还是移动端

Navigator 对象包含有关浏览器的信息

userAgent 属性是一个只读的字符串,声明了浏览器用于 HTTP 请求的用户代理头的值

可以通过获取Navigator userAgent属性的属性值,再和相关的移动端类型进行匹配,来判断浏览器的类型,通过调整 match 方法的参数,也可以判断不同的浏览器类型:

// 移动端浏览器的标志
const str = 'Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini'
const reg = new RegExp(str, 'i')
// 如果是移动端,则返回 true
reg.test(navigator.userAgent)

// 另外一个更全的移动端标志
const str1 =
'Android|WebOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|phone|pad|pod|' +
'ios|Mobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|Symbian|Windows Phone'

其他参考资料

  1. javaScript & jquery完美判断图片是否加载完毕

  2. 分享前端开发常用代码片段

  3. 前端简洁并实用的工具类

Last Updated: 1/22/2025, 5:55:36 PM