# 一些经典常用功能

back:js 常见方法

🐉 使用 JavaScript 来操作 DOM 🐉 JavaScript 之 window 对象
需要扩充可点击区域的范围 Bootstrap-Table
JS 中的类型转换与比较 运算符
JS 中边角料收集 文本溢出截断省略,方案汇总
js 一些语法 跨域的四种解决方案
获取 url 中各个组成部分

# 为对象添加动态属性

返回顶部

let obj = {};
let objChild = {};
objChild["name"] = "huting";
obj["person"] = objChild;
1
2
3
4

或者 eval 表达式

let obj = {};
const key = "name";
const value = "huting";
eval("obj.p" + key + "='" + value + "'");
obj;
// {pname: "huting"}
eval("obj." + key + "='" + value + "'");
// "huting"
obj;
// {pname: "huting", name: "huting"}
1
2
3
4
5
6
7
8
9
10
let json = { name: "huting", age: 11 };
// undefined
json.newParam = "status";
// "status"
json.status = "0";
// "0"
// {name: "huting", age: 11, newParam: "status", status: "0"}
1
2
3
4
5
6
7

# 禁用右键

返回顶部

有时候你可能想要禁止用户点击右键。虽然这个需求很少见,但是可能派的上用场。

<body oncontextmenu="return false">
  <div></div>
</body>
1
2
3

# 如何更好的去除谷歌浏览器中 input 自动填充背景

返回顶部

当自动填充时会激活:-internal-autofill-selected伪类,然后就变成了淡紫色。

如果我们设置样式覆盖

input:-internal-autofill-selected {
  background: red !important;
}
1
2
3

然而并没有什么用;网上普遍的解决方式主要有两种:

    1. 使用内阴影进行覆盖
input {
  box-shadow: 0 0 0px 1000px white inset;
}
1
2
3
    1. 关闭自动填充功能

既然是由于自动填充导致的问题,关掉就行了呀

<input autocomplete="off" />
1

# 更好的解决方式

  • 方式一:利用background-clip: content-box

背景颜色默认是渲染到padding-box的,我们可以设置background-clip: content-box只渲染到content-box,这样背景就看不到了(当然还需指定一下高度为 0。)

input {
  height: 0;
  padding: 1.2em 0.5em;
  background-clip: content-box;
}
1
2
3
4
5

填充的文字颜色也是无法直接修改的(默认为 rgb(0,0,0)),原因相同,这里我们可以借助一下::first-line伪类

input::first-line {
  color: #fff;
}
1
2
3
  • 方式二:利用animation-fill-mode:forwards
<style>
div{
    animation:resetBg .1s forwards;
}
@keyframes resetBg {
  to {
    background: blue;
  }
}
</style>
<div style="background:red!important">div</div>
1
2
3
4
5
6
7
8
9
10
11

这样就比较容易了

input {
  animation: resetBg 0.1s forwards;
}
@keyframes resetBg {
  to {
    color: #fff;
    background: transparent;
  }
}
1
2
3
4
5
6
7
8
9

# 可搜索的下拉框、批量设置选中项,获取下拉框

返回顶部

# 时时刻刻都在过滤

<input type="hidden" id="itemsId" name="itemsId" maxlength="50">
<input autocomplete="off" type="text" class="input-text reset" id="itemsName" name="itemsName" value="" list="itemsValues" maxlength="255">
<datalist id="itemsValues">
</datalist>
1
2
3
4
function initItemsId() {
  $("#itemsValues").empty();
  $("#layer_form")[0].reset();
  $.ajax({
    url: ctx + "tsWbCommonController/getItemsByBranch", //请求的url地址
    dataType: "json", //返回格式为json
    async: false, //请求是否异步,默认为异步,这也是ajax重要特性
    type: "POST", //请求方式
    success: function(data) {
      for (var i = 0; i < data.length; i++) {
        $("#itemsValues").append(
          "<option value='" +
            data[i].name +
            "' data-id='" +
            data[i].id +
            "'>" +
            data[i].name +
            "</option>"
        );
      }
    },
  });
}

function getItemsId() {
  $("#itemsName").on("input", function() {
    var $options = $("#itemsValues").children();
    for (var i = 0; i < $options.length; i++) {
      if (
        $options
          .eq(i)
          .val()
          .trim() ==
        $("#itemsName")
          .val()
          .trim()
      ) {
        $("#itemsId").val($options.eq(i).attr("data-id"));
        $.ajax({
          url: ctx + "tsWbRepair/getLeaderEtcByItemId", //请求的url地址
          dataType: "json", //返回格式为json
          async: true, //请求是否异步,默认为异步,这也是ajax重要特性
          data: { itemsId: $("#itemsId").val() }, //参数值
          type: "POST", //请求方式
          success: function(data) {
            $("#projectName").val(data[0].PROJECTNAME);
            $("#leaderId").val(data[0].COL_NAME);
            $("#telephone").val(data[0].COL_PHONE);
            $("#linkMan").val(data[0].LINKMAN);
            $("#linkPho").val(data[0].LINKPHO);
          },
        });
        break;
      } else {
        $("#itemsId").val("");
      }
    }
  });
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

# 更完美的下拉搜索

github

# 批量设置下拉框的值

返回

function batchNotInvolve() {
  layer.confirm(
    '确认要修改当前项目所有巡检类型为<span style="color: RED">“不涉及”</span>吗?',
    function(index) {
      var sels = $("select");
      for (var i = 0, length = sels.size(); i < length; i++) {
        sels[i].value = "4";
      }
      layer.close(index);
    }
  );
}
1
2
3
4
5
6
7
8
9
10
11
12

# 获取下拉框

返回

  • 指定统计某个 ID 范围的 select 的数量
var tn = $("#wrap select").size(); //统计select有几个
1
  • 不指定 name 的所有 select
$("select").size();
1
  • 指定 name 的 select
$('select[name="cmt"]').size();
1
  • option 数量吧
$("select[name=cmt] option").size();
1
  • <select class="selector"></select>

    • $(".selector").val("pxx");
    • $(".selector").find("option[text='pxx']").attr("selected",true);中括号里的等号的前面是属性名称
    • $(".selector").val();
    • $(".selector").find("option:selected").text();
  • 级联 select

$(".selector1").change(function() {
  // 先清空第二个
  $(".selector2").empty(); // 实际的应用中,这里的option一般都是用循环生成多个了
  var option = $("<option>")
    .val(1)
    .text("pxx");
  $(".selector2").append(option);
});
1
2
3
4
5
6
7
8

# js 获取各种宽高

返回顶部

  • 网页可见区域宽:document.body.clientWidth;
  • 网页可见区域高:document.body.clientHeight;
  • 网页正文全文宽:document.body.scrollWidth;
  • 网页正文全文高:document.body.scrollHeight;
  • body 总高度:document.body.offsetHeight;
  • body 总宽度:document.body.offsetWidth;
  • 网页正文部分上:window.screenTop;
  • 网页正文部分左:window.screenLeft;
  • 浏览器高度:window.outerHeight;
  • 浏览器宽度:window.outerWidth;
  • 屏幕分辨率的高:window.screen.height;
  • 屏幕分辨率的宽:window.screen.width;
  • 屏幕可用工作区高度:screen.availHeight;即屏幕高度减去上下任务栏后的高度,可表示为软件最大化时的高度
  • 屏幕可用工作区宽度:screen.availWidth;即屏幕宽度减去左右任务栏后的宽度,可表示为软件最大化时的宽度。

# 动态修改网页标签图标

返回顶部

(function() {
  var link =
    document.querySelector("link[rel*='icon']") ||
    document.createElement("link");
  link.type = "image/x-icon";
  link.rel = "shortcut icon";
  link.href = "http://www.stackoverflow.com/favicon.ico";
  document.getElementsByTagName("head")[0].appendChild(link);
})();
1
2
3
4
5
6
7
8
9
<link id="favicon" rel="shortcut icon" type="image/png" href="favicon.png" />;
$("#favicon").attr("href", "favicon2.png");
1
2

jquery:

$("link[rel='shortcut icon']").attr("href", "favicon.ico");
$("link[rel*='icon']").attr("href", "favicon.ico");
1
2

Vanilla JS version:

document.querySelector("link[rel='shortcut icon']").href = "favicon.ico";
document.querySelector("link[rel*='icon']").href = "favicon.ico";
1
2

more Modern:

const changeFavicon = (link) => {
  let $favicon = document.querySelector('link[rel="icon"]');
  // If a <link rel="icon"> element already exists,
  // change its href to the given link.
  if ($favicon !== null) {
    $favicon.href = link;
    // Otherwise, create a new element and append it to <head>.
  } else {
    $favicon = document.createElement("link");
    $favicon.rel = "icon";
    $favicon.href = link;
    document.head.appendChild($favicon);
  }
};

changeFavicon("http://www.stackoverflow.com/favicon.ico");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 确认对话框 confirm

返回顶部

if (confirm("确定删除(uuid:" + uuid + ")该设备吗?")) {
}
1
2

# 捕获回车键

返回顶部

# 原生

document.onkeyup = function(e) {
  //按键信息对象以函数参数的形式传递进来了,就是那个e
  var code = e.charCode || e.keyCode; //取出按键信息中的按键代码(大部分浏览器通过keyCode属性获取按键代码,但少部分浏览器使用的却是charCode)
  if (code == 13) {
    //此处编写用户敲回车后的代码
  }
};
1
2
3
4
5
6
7

可这样有个问题,在旧版 IE 下,按键信息对象并不是直接传递到函数中的,所有的事件对象是存储在window.event中的,所以为了兼容旧版 IE,我们可以先判断一下 window.event 这个对象存在不存在,若存在,说明是旧版 IE 浏览器,如果不存在,说明是 chrome、火狐之类的新式浏览器,
改良版如下:

document.onkeyup = function(e) {
  if (window.event)
    //如果window.event对象存在,就以此事件对象为准
    e = window.event;
  var code = e.charCode || e.keyCode;
  if (code == 13) {
    //此处编写用户敲回车后的代码
  }
};
1
2
3
4
5
6
7
8
9

# Jquery 版

思路和纯 JavaScript 代码类似,不过 Jquery 实现起来可能更简单一些,因为 Jquery 本身就已经在某些方面做了浏览器兼容性设置,所以代码会比较简洁一些

$(document).keyup(function(e) {
  //捕获文档对象的按键弹起事件
  if (e.keyCode == 13) {
    //按键信息对象以参数的形式传递进来了
    //此处编写用户敲回车后的代码
  }
});
1
2
3
4
5
6
7

# onclick 和 href

返回顶部

onclick的事件被先执行,其次是 href 中定义的(页面跳转或者 javascript)
同时存在两个定义的时候(onclick 与 href 都定义了),如果想阻止 href 的动作,在 onclick 必须加上 return false;
在 href 中定义的函数如果有返回值的话,当前页面的内容将被返回值代替

# 动态修改 title

返回顶部

1、原生方法(注意:不是用的innerHTML而是innerText

document.getElementsByTagName("title")[0].innerText = "innerText我是原生js方法";
document.title = "title我是原生js方法";
1
2

2、jquery

$("title").html("html我是jq方法");
$("title").text("text我是jq方法");
1
2

# 前端网页如何打开一个 PC 本地应用

返回顶部

注册表是 Microsoft Windows 中的一个重要的数据库,用于存储系统和应用程序的设置信息。
它是 Windows 操作系统中的一个核心数据库,其中存放着各种参数,可以直接控制一些 Windows 应用程序的运行。

我们需要的有关打开应用的注册表配置就存在HEY_CLASSES_ROOT

# HEY_CLASSES_ROOT

back

HKEY_CLASSES_ROOT 根键中主要包含的是所有启动应用程序需要的信息,其中包括:

  • 所有扩展名及应用程序和文档之间的关联信息。
  • 所有驱动程序的名字。
  • 当作指针的字符串,指向它们代表的实际文件。
  • 类标识 CLSID,这点在访问子健信息的时候非常重要,因为 Windows 中访问了子健的信息都是用 CLSID 来代替的。这里的标识在 Windows XP 系统中是唯一的。
  • DDE 和 OLE 信息。对于每个文件关联都可以使用 DDE 和 OLE 功能。
  • 应用程序和文档使用的图标

# 导出注册表信息

back

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Classes\postman]
"URL Protocol"=""
@="URL:postman"

[HKEY_CURRENT_USER\Software\Classes\postman\shell]

[HKEY_CURRENT_USER\Software\Classes\postman\shell\open]

[HKEY_CURRENT_USER\Software\Classes\postman\shell\open\command]
@="\"C:\\Users\\X\\AppData\\Local\\Postman\\app-6.0.10\\Postman.exe\" \"%1\""
1
2
3
4
5
6
7
8
9
10
11
12

启动软件主要依靠以下两个配置

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Classes\postman]
"URL Protocol"=""
@="URL:postman"

[HKEY_CURRENT_USER\Software\Classes\postman\shell\open\command]
    @="\"C:\\Users\\X\\AppData\\Local\\Postman\\app-6.0.10\\Postman.exe\" \"%1\""
1
2
3
4
5
6
7
8

根据这两个配置,前端网页可以通过postman://协议来打开本地的 postman 应用。

# 网页端打开应用实例

back

  • 创建一个 reg 文件
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\cloudmusic]
"URL Protocol"=""
@=""

[HKEY_CLASSES_ROOT\cloudmusic\shell\open\command]
@="\"D:\\CloudMusic\\cloudmusic.exe\"\"%1\""
1
2
3
4
5
6
7
8
  • 文件命名与协议名称无关,只与[HKEY_CLASSES_ROOT]后定义的字段有关;
  • @="\"D:\\CloudMusic\\cloudmusic.exe\"\"%1\""中的"%1"为参数,不能随意删除。

# 检测协议是否存在

back

下载protocolcheck.js

<!DOCTYPE html>
<html>
<head lang="zh">
    <meta charset="UTF-8">
    <title>自定义协议探测</title>
</head>
<body>
    <h1>Click one of these labels:</h1>
    <div href="unexists:randomstuff">一个不存在的协议</div>
    <div href="ff://C:/Windows/System32/notepad.exe">一个存在的协议</div>
    <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
    <script src="protocolcheck.js"></script>
    <script src="example.js"></script>
</body>
</html>

$(function () {
    $("div[href]").click(function (event) {
        window.protocolCheck($(this).attr("href"),
            function () {
                alert("协议未注册");
            });
        event.preventDefault ? event.preventDefault() : event.returnValue = false;
    });
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# parseInt

back

# 基本用法

只接受一个参数,可以当做第二个参数默认是 10:parseInt 的返回值只有两种可能,不是一个十进制整数,就是NaN

  • 将字符串转为整数。parseInt('123') // 123
  • 如果字符串头部有空格,空格会被自动去除。parseInt(' 81') // 81
  • 如果 parseInt 的参数不是字符串,则会先转为字符串再转换
  • 字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分
  • 如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回 NaN
  • 如果字符串以0x0X开头,parseInt 会将其按照十六进制数解析。parseInt('0x10') // 16
  • 如果字符串以 0 开头,将其按照 10 进制解析。parseInt('011') // 11
  • 如果参数以 0 开头,但不是字符串,则会先将数值转成字符串,然后解析,见规则第parseInt(011) // 9
  • 对于那些会自动转为科学计数法的数字,parseInt 会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果
parseInt(1000000000000000000000.5); // 1
// 等同于
parseInt("1e+21"); // 1

parseInt(0.0000008); // 8
// 等同于
parseInt("8e-7"); // 8
1
2
3
4
5
6
7

进制转换(接收两个参数):parseInt 方法还可以接受第二个参数(2到36之间

  • 第一个参数解析规则参照第一条基本用法
  • 如果第二个参数不是数值,会被自动转为一个整数。这个整数只有在2到36之间,才能得到有意义的结果,超出这个范围,则返回 NaN。如果第二个参数是0undefinednull,则直接忽略

# 页面打印

# iframe 打印

// 判断iframe是否存在,不存在则创建iframe
let iframe = document.getElementById(`deviceNo${param.no}`);
if (!iframe) {
  iframe = document.createElement("iframe");
  let doc = null;
  iframe.setAttribute("id", `deviceNo${param.no}`);
  iframe.setAttribute(
    "style",
    "position:absolute;width:0;height:0;left:-200px;top:-200px;"
  );
  document.body.appendChild(iframe);
  doc = iframe.contentWindow.document;
  // doc.write('<LINK rel="stylesheet" type="text/css" href="css/print.css">');
  doc.write(
    `<html><head><title>打印</title><meta charset="utf-8"><style media="print"> @page {  size: auto;  margin: 0; }</style></head><body><div style="width: 100%;height: 100%"><img src=${data} alt="" width="100%" height="100%"></div></body></html>`
  );
  // console.info(doc.body, navigator.userAgent, '-=-=-=-=-=-=')
  doc.close();
  iframe.contentWindow.focus();
}
const printImg = new Image();
printImg.src = data;
printImg.onload = () => {
  iframe.contentWindow.print();
};
if (navigator.userAgent.indexOf("MSIE") > 0) {
  document.body.removeChild(iframe);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# window 打印

window.print();
1

# 去除页眉页脚空间

<html>
  <head>
    <title>打印</title>
    <meta charset="utf-8" />
    <style>
      .printBox {
        width: 300px;
        height: 300px;
        border: 1px solid blue;
      }
    </style>
    <!-- 打印的样式,去除页眉页脚空间-->
    <style media="print">
      @page {
        size: auto;
        margin: 0mm;
      }
    </style>
  </head>
  <body></body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<style media="print">
  @page {
    size: 210mm 297mm;
    margin: 0mm;
  }
</style>
1
2
3
4
5
6

# 确保图片加载完成再做其他操作

const printImg = new Image();
printImg.src = data;

printImg.onload = () => {
  iframe.contentWindow.focus();
  iframe.contentWindow.print();
};
1
2
3
4
5
6
7

# React 动态增加 class

const allToolTips = document.getElementsByClassName("ant-tooltip");
if (allToolTips && allToolTips.length > 0) {
  // 类数组转换成真正的数组
  Array.from(allToolTips).forEach((item) => {
    // console.info(item, '-=-=-=-=-')
    if (item.classList.contains("ant-tooltip-hidden")) {
      return;
    }
    // console.info('0-0-0-0-0-0')
    item.classList.add("ant-tooltip-hidden");
  });
}
1
2
3
4
5
6
7
8
9
10
11
12