Wiki

Table of Contents

WIKI

Java 中抽象类和接口的区别

[2020-05-24 Sun 14:36]

  • 抽象类要被子类继承,接口要被类实现;
  • 接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现;
  • 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量;
  • 接口是设计的结果,抽象类是重构的结果;
  • 抽象类和接口都是用来抽象具体对象的,但是接口抽象级别最高;
  • 抽象类可以有具体的方法和属性,接口只能有抽象方法和不可变常量;
  • 抽象类主要用来抽象类别,接口主要用来抽象功能。

比较抽象类和接口,按照其用途和结构逐个对比就好。

抽象类,用来让子类继承,它可以有具体的方法和属性,但主要还是抽象方法。一个抽象类是可以不包含抽象方法的,但如果一个抽象类不包含抽象方法,那定义一个抽象类是用来寻开心的吗 -_||

接口呢?一般来说,只包含方法声明,而且方法默认是 public abstract (公共抽象)的;如果非要包含变量,也只能是 public static final (公共静态常量)。

文件的描述符和重定向

[2020-05-12 Tue 18:36]

文件描述符 是和文件的输入、输出相关联的非负整数,Linux 内核(kernel)利用文件描述符来访问文件。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。

系统预留文件描述符:

  • 0 - stdin 标准输入;
  • 1 - stdout 标准输出;
  • 2 - stderr 标准错误。

实例:

 1: # 输出重定向
 2: # 1. 截取模式保存到文件 - 写入到文件之前,文件内容首先会被清空
 3: echo "this is a text line one" > test.txt
 4: # 2. 追加模式保存到文件 - 写入到文件之后,会追加到文件结尾
 5: echo "this is a text line one" >> test.txt
 6: 
 7: # 标准错误输出的重定向方法
 8: cat linuxde.net                 # → cat: linuxde.net: No such file or directory
 9: # 1. 没有任何错误提示,正常运行
10: cat linuxde.net 2> out.txt
11: # 2. 错误信息被保存到了 out.txt 文件中
12: cat linuxde.net &> out.txt
13: # 3. 将错误输出丢弃到 /dev/null 中,特殊的设备文件 - 黑洞
14: cat linuxde.net 2> /dev/null
15: 
16: # 输入重定向
17: echo < test.txt

数据归档和解压缩

[2020-05-12 Tue 18:35]

首先要弄清两个概念:打包和压缩。 打包 是指将一大堆文件或目录变成一个总的文件; 压缩 则是将一个大的文件通过一些压缩算法变成一个小文件。

1. tar 命令

利用tar命令,可以把一大堆的文件和目录全部打包成一个文件,这对于备份文件或将几个文件组合成为一个文件以便于网络传输是非常有用的。

# 语法
tar (选项) (参数)

实例:

 1: # 打包、压缩
 2: tar -cvf log.tar log2012.log      # 仅打包,不压缩!
 3: tar -zcvf log.tar.gz log2012.log  # 打包后,以 gzip 压缩
 4: tar -jcvf log.tar.bz2 log2012.log # 打包后,以 bzip2 压缩
 5: 
 6: # 查询
 7: tar -tvf log.tar                # 直接查询
 8: tar -ztvf log.tar.gz            # 查询以 gzip 压缩的文件
 9: tar -jtvf log.tar.bz2           # 查询以 bzip2 压缩的文件
10: 
11: # 解压缩
12: tar -zxvf log.tar.gz            # 以 gzip 解压缩
13: tar -jxvf log.tar.bz2           # 以 bzip2 解压缩
14: 
15: tar -zxvf log.tar.gz -C log     # 以 gzip 解压缩在目录 log

其中:

选项 说明
-v 显示操作过程
-f <FILE> --file=<FIEL> 指定备份文件
-c --create 建立新的备份文件
-t --list 列出备份文件的内容
-x --extract --get 从备份文件中还原文件
-z --gzip --ungzip 通过gzip指令处理备份文件
-j 支持bzip2解压文件
-C <DIR> 在特定目录解压缩

小结:

压 缩:tar -jcv -f filename.tar.bz2 要被压缩的文件或目录名称
查 询:tar -jtv -f filename.tar.bz2
解压缩:tar -jxv -f filename.tar.bz2 -C 欲解压缩的目录

关于 CSS 中设置 height 为 100% 不起作用

[2020-04-25 Sat 15:57]

W3C 的规范,百分比的高度在设定时需要根据这个元素的父元素的高度。

Web 浏览器有计算有效宽度时会考虑浏览器窗口的打开宽度,缼省为页面整个横向宽度。

事实上,浏览器根本就不计算内容的高度,除非内容超出了视窗范围(导致滚动条出现),缺省为 height: auto 。或者你给整个页面设置一个绝对高度,否则浏览器就会简单的让内容往下堆砌,页面的高度根本就无需考虑。

!!!个人实践,在给 html、body 设置 background 相关属性的时候情况会很奇特,给其内的元素设置背景的时候就不存在这些奇葩问题。

所以,当我们想要设置竖直高度的百分比,需要对 html、body 进行一些初始化设置,如:

 1: html {
 2:     /* 设置根元素高度 */
 3:     height: 100%;
 4: }
 5: 
 6: body {
 7:     /* 设置 body 高度 */
 8:     height: 100%;
 9: }
10: 
11: /* body 内元素 .container */
12: .container {
13:     height: 60%;
14:     background: #f66;
15: }

其实试一下,你就会发现,如果直接对 body 设置 background 的背景图片或是背景色,都会占满整个容口。

JavaScript 中的 bind、call、apply 方法1

[2020-04-20 Mon 14:25]

如果你在浏览器的控制台执行 console.dir(Function) ,就会发现 apply、bind、call 方法都是 Function 的原型方法,也就是说,JavaScript 中的每一个 Function 对外都包含上述三种方法。

call、apply、bind 方法都用来重定义 this 这个对象的。来看一个简单的例子:

 1: var name = 'Amy', age = 16;
 2: var obj = {
 3:     name: 'Lucy',
 4:     objAge: this.age,
 5:     myFun: function() {
 6:         console.log(this.name + '年龄' + this.age);
 7:     }
 8: }
 9: var db = {
10:     name: 'Jack',
11:     age: 26
12: }
13: 
14: obj.myFun.call(db);             // → Jack年龄26
15: obj.myFun.apply(db);            // → Jack年龄26
16: obj.myFun.bind(db)();           // → Jack年龄26

注意: bind 方法返回的是一个函数,必须调用才会被执行。

call、bind、apply 这三个函数的第一个参数都是 this 的指向对象,区别在于第二个传参数:

  • call 的参数是直接放进去,用逗号分隔;
  • apply 的所有参数都必须放在一个数组里传进去;
  • bind 除了返回函数以外,参数和 call 一样。

JavaScript 的 event 对象中 target 和 currentTarget 属性的区别

[2020-04-18 Sat 18:33]

本质区别是:

  • event.target 返回触发事件的元素;
  • event.currentTarget 返回绑定事件的元素。

event.currentTarget 的作用是什么呢?可以理解为和 this 的作用差不多,始终返回的是绑定事件的元素。 target 的妙用在于 target 事件委托,常见于列表点击事件。

具体示例请参考: event对象中 target和currentTarget 属性的区别

JavaScript 对 url 的编码和解码

[2020-04-18 Sat 18:26]

有时候,你会发现一些 url 链接是编码过的,如这样: http%3A%2F%2Fw3cschool.cn%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab

JavaScript 中使用 encodeURIComponent() 方法可以对 URI 进行编码;使用 decodeURIComponent() 方法可以对 URI 进行解码。

W3C 提供了简单的实现,如下:

1: var uri="http://w3cschool.cn/my test.php?name=ståle&car=saab";
2: var uri_encode=encodeURIComponent(uri);
3: document.write(uri_encode);
4: document.write("<br>");
5: document.write(decodeURIComponent(uri_encode));

↓↓↓

http%3A%2F%2Fw3cschool.cc%2Fmy%20test.php%3Fname%3Dst%C3%A5le%26car%3Dsaab
http://w3cschools.com/my test.asp?name=ståle&car=saab

JavaScript indexOf

[2020-03-19 Thu 09:18]

indexOf() 方法可返回指定的字符串值在字符串中 首次 出现的位置:

  • 如果没有找到匹配的字符串则返回 -1 ;
  • indexOf() 方法区分大小写。
1: let str = 'Hello world, welcome to the universe.';
2: let n = str.indexOf('welcome');  // → 13
3: let m = str.indexOf('e', 5);     // → 14
4: let v = str.indexOf('none');     // → -1

具体语法如下:

string.indexOf(searchvalue, start)
参数 描述
searchvalue 必需,规定需检索的字符串值
start 可选的整数参数,规定在字符串中开始检索的位置。它的合法值是 0 到 string Object.length - 1 。如果省略该参数,则将从字符串的首字符开始检索。

与之相似的还有 lastIndexOf() 方法,可返回一个指定的字符串值在字符串中 最后一次 出现的位置。

#. Array includes()

延伸一下,我们来看一下 JavaScript Array includes() 方法。

includes() 方法用来判断一个数组是否包含一个指定的值,如果是返回 true ,否则 false

1: [1, 2, 3].includes(2);     // true
2: [1, 2, 3].includes(4);     // false
3: [1, 2, 3].includes(3, 3);  // false
4: [1, 2, 3].includes(3, -1); // true
5: [1, 2, NaN].includes(NaN); // true

具体语法如下:

arr.includes(searchElement)
arr.includes(searchElement, fromIndex)
参数 描述
searchElement 必须,需要查找的元素
fromIndex 可选,默认为 0 。从该索引出开始查找 searchElement 。如果为负值,则按升序从 array.length + fromIndex 的索引处开始搜索

npm 安装是 –save 和 –save-dev 的区别2

[2020-03-09 Mon 10:42]

在生产环境中需要使用到的包安装时添加 --save ,只在开发环境中用到的包安装时添加 --save-dev

以 npm 安装 vue 为例。

1. npm install vue

  • 会把 vue 包安装到 node_modules 目录中;
  • 不会修改 package.json 文件;
  • 之后运行 npm install 命令时,不会自动安装 vue 。

2. npm install vue –save

  • 会把 vue 包安装到 node_modules 目录中;
  • 会在 package.json 文件中的 dependencies 属性下添加 vue ;
  • 之后运行 npm install 命令时,会自动安装 vue 包到 node_modules 目录中;
  • 之后运行 npm install --production 或者注明 NODE_DEV 变量值为 production 时,不会自动安装 vue 到 node_modules 目录中。

3. npm install vue –save-dev

  • 会把 vue 包安装到 node_modules 目录中;
  • 会在 package.json 文件中的 devDependencies 属性下添加 vue ;
  • 之后运行 npm install 命令时,会自动安装 vue 包安装到 node_modules 目录中;
  • 之后运行 npm install --production 或者注明 NODE_DEV 变量值为 production 时,不会自动安装 vue 包安装到 node_modules 目录中。

4. npm install vue –global

  • 会把 vue 包安装到全局环境中而不是当前项目的 node_modules 目录中(其实是全局环境中的 node_modules 啦);
  • 不会修改 package.json 文件;
  • 之后运行 npm install 命令时,不会自动安装 vue 。

Axios 为什么需要实例

[2020-03-09 Mon 10:18]

默认会导出实例 axios ,通常只需使用这个 axios 就可以了。

但有时你可能需要创建多个实例,比如你需要访问多个服务地址,而这些服务请求和响应的结构都完全不同,那么,你就可以通过 axios.create 创建不同的实例来处理。

比如 axios1 是用 http 状态码确定响应是否正常,而 axios2 是服务器自己定义的状态码,又或者它们请求头不同,支持的 Content-Type 不同,那么可以单独为 axios1axios2 写拦截器。

Emacs 宏操作

[2020-02-28 Fri 12:02] https://www.jianshu.com/p/6ad946eb8ebc

Key/Command Description
C-x ( 开启宏记录
C-x ) 关闭宏记录
C-x e 执行刚录制的宏
C-u n C-x e 执行 n 次刚录制的宏
M-x name-last-kbd-marco 给刚记录的宏命名
M-x insert-kbd-marco 把刚命名的宏记录写入到文件中

可以设置一个专门的文件(如 ~/.emacs.d/macro.el )来记录宏,然后在 init.el 中加载改文件( (load-file "~/.emacs.d/macro.el") ), 如此便可以实现持久化。

如这个例子:用宏定义了下翻 15 行和上翻 15 行的快捷键。

1: ;; macro.el
2: (fset 'next-lines
3:     "\C-u15\C-n")
4: (fset 'previous-lines
5:     "\C-u15\C-p")
1: ;; init.el
2: 
3: ;; ...
4: ;; 加载 macro.el
5: (load-file "~/.emacs.d/macro.el")
6: ;; 绑定快捷键
7: (global-set-key (kbd "C-x n RET") 'next-lines)
8: (global-set-key (kbd "C-x p RET") 'previous-lines)
9: 

如何设置终端 256 色

[2020-02-28 Fri 11:37] https://stackoverflow.com/questions/63950/how-to-make-emacs-terminal-colors-the-same-as-emacs-gui-colors?r=SearchResults

设置 TERM.bashrc 文件中,如下:

1: export TERM=xterm-256color

如此,便设置好了。

加入我们使用在终端中使用 Emacs ,执行 M-x list-colors-display ,便可以看到 256 色已经全部激活,如此,终端下使用 Emacs 和 Emacs GUI 的颜色便相差无几了。

JavaScript JSON.stringify()

[2020-02-27 Thu 09:02]

JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串。语法如下:

JSON.stringify(value[, replacer[, space]])

参数说明:

  • value ,必需,要转换的 JavaScript 值(通常为对象或数组);
  • replacer ,可选,用于转换结果的函数或数组;
  • space ,可选,文本添加缩进、空格和换行符。

其中,对于 replacer ,如果它为 函数 ,则 JSON.stringify 将调用该函数,并传入每个成员的键和值。使用返回值而不是原始值。如果此函数返回 undefined ,则派出成员。根对象的键是一个空字符串: "" 。如果 replacer 是一个 数组 ,则仅转换该数组中具有键值的成员,成员的转换顺序与键在数组中的顺序一样。

其中,对于 space ,如果它是一个 数字 ,则返回值文本在每个级别缩进指定数组的空格,如果 space 大于 10 ,则文本缩进 10 个空格。 space 也可以使用 非数字 ,如 \t

 1: var str = {"name":"菜鸟教程", "site":"http://www.runoob.com"}
 2: 
 3: // 只有一个参数的情况
 4: str_pretty1 = JSON.stringify(str)
 5: // → {"name":"菜鸟教程","site":"http://www.runoob.com"}
 6: 
 7: // 使用参数情况
 8: str_pretty2 = JSON.stringify(str, null, 4)
 9: // 
10: // {
11: //     "name": "菜鸟教程",
12: //     "site": "http://www.runoob.com"
13: // }
14: 

Java 中的接口方法为什么必须是 public

[2020-02-05 Wed 22:35]

子类重写父类方法时,方法的访问权限不能小于原访问权限。接口是一种约束和规范,是一种 更加抽象的抽象类 ,在接口中,方法的默认权限就是 public ,所以子类重写后只能是 public

接口中没有变量(既然是约束和规范,怎么能够定义一个大家都可以改的东西呢),只能是常量,默认修饰符为 public static final

  • 接口必须要具体类实现才有意义,所以必须是 public
  • 接口中的属性对所有实现类只有一份,所以是 static
  • 要使实现类向上转型成功,所以必须使 final 的。

Tagging

[2020-01-28 Tue 14:01]

Command Description
git tag Listing your tags
git tag -l "v1.8.5" Listing the 1.8.5 series
git show v1.2 Show you've tagged the commit
git tag -a v1.4 -m "my version 1.4" Annotated tags
git tag -a v1.2 9fceb02 Tagging later
git tag -a v1.2 9fceb02 -m "my version 1.2" Tagging later and Annotated it
git push origin v1.5 Sharing Tags
git push origin --tags Push a lot of tags at once
git tag -d v1.4 Deleting tags
git push origin --delete <tagname> Deleting a remote tag
git checkout 2.0.0 Checking out tags
git checkout -b version2 v2.0.0 Switched to a new branch 'version2'

git 比较两次 commit 之间的差异

[2020-01-28 Tue 14:00]

→ 参考链接

如何使用 git 比较两次 commit 之间的差异文件呢?可以按下述步骤进行:

  • 通过 git log 查看提交历史,获取提交 hash 码,如 hash1、hash2;
  • 通过 git diff hash1 hash2 --stat ,查看这两次提交的差异文件,如 test1、test2;
  • 通过 git diff hash1 hash2 test1 ,查看指定差异文件 test1 具体修改的代码;
  • 通过 git diff hash1 hash2 test1 > patch_file ,可以将 test1 的差异部分提取成补丁文件;
  • 通过 git diff hash1 hash2 test1 test2 > patch_file ,可以将多个文件的差异生成到同一个补丁文件。

生成补丁后,到相关目录下可以打补丁,如 pathc -p1 < patch_file ,其中 -p1 是代表忽略当前目录下的几级目录。

input 中 placeholder、disabled 状态样式修改

[2020-01-28 Tue 14:00]

问题场景:

  • 有时按业务需求更改 inputplaceholder 样式和 disabled 状态下的样式;
  • IOS 和安卓移动端样式兼容性问题,样式不一致。

处理如下:

 1: input::-webkit-input-placeholder {
 2:     color: #ccc;
 3:     -webkit-text-fill-color: #ccc;
 4:     opacity: 1;
 5:     -webkit-opacity: 1;
 6: }
 7: 
 8: input:disabled {
 9:     background: none;
10:     color: #333;
11:     -webkit-text-fill-color: #333;
12:     opacity: 1;
13:     -webkit-opacity: 1;
14: }
15: 
16: input:disabled::-webkit-input-placeholder {
17:     color: #ccc;
18:     -webkit-text-fill-color: #ccc;
19:     opacity: 1;
20:     -webkit-opacity: 1;
21: }

相关延伸:

  • ::-webkit-input-placeholder {} 使用 webkit 内核的浏览器
  • :moz-placeholder {} Firefox 版本 4-18
  • ::moz-placeholder {} Firefox 版本 19+
  • -ms-input-placeholder {} IE 浏览器

CSS 换行

[2020-01-28 Tue 13:59]

→ 参考链接

文本换行有很多方式:

  • <br/> 标签元素,能够强制使得所在位置文本换行;
  • <p> 元素, <div> 设定宽度,都可以对文本内容实现自适应换行;
  • 对于长单词或链接,默认不会断开换行,方式 2 就不能够在这些文本内部进行换行,此时需要 word-wrap: break-word;word-break: break-all; 实现强制断行。

1. 强制不换行

1: div {
2:     white-space: nowrap;
3: }
4: /*
5: white-space:
6: - normal  默认
7: - pre     换行和其他空白字符都将受到保护
8: - nowrap  强制在同一行内显示所有文本,直到文本结束或者遭遇 <br> 对象
9: */

2. 控制文本换行

 1: div {
 2:     word-break: normal;
 3:     word-break: break-all;
 4:     word-break: keep-all;
 5: }
 6: /*
 7: word-break:
 8: - normal        依据亚洲语言与非亚洲语言的文本规则,允许在字内换行
 9: - break-all     该行为与亚洲语言的 normal 相同,也允许非亚洲语言文本行的任意字内断开,该值适合包含一些非亚洲文本的亚洲文本
10: - keep-all      与所有非亚洲语言的 normal 相同,对于中文、韩文、日文,不允许字断开,适合包含少量亚洲文本的非亚洲文本
11: */

3. 强制单词内或链接内断行

1: div {
2:     word-wrap: break-word;
3: }
4: /*
5: word-wrap:      属性用来表明是否允许浏览器在长单词和链接内进行断句
6: - normal        只在允许的断字点换行
7: - break-word    在长单词或 URL 地址内部进行换行
8: */

JS 获取 DPI

[2020-01-28 Tue 13:59]

 1: //获取DPI
 2: function js_getDPI() {
 3:     var arrDPI = new Array();
 4:     if ( window.screen.deviceXDPI != undefined ) {
 5:         arrDPI[0] = window.screen.deviceXDPI;
 6:         arrDPI[1] = window.screen.deviceYDPI;
 7:     }
 8:     else {
 9:         var tmpNode = document.createElement( "DIV" );
10:         tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
11:         document.body.appendChild( tmpNode );
12:         arrDPI[0] = parseInt( tmpNode.offsetWidth );
13:         arrDPI[1] = parseInt( tmpNode.offsetHeight );
14:         tmpNode.parentNode.removeChild( tmpNode );
15:     }
16:     return arrDPI;
17: }
18: 
19: // 将 px 转成 mm
20: let mm = pxValue/dpi*2.54*10;   // dpi 是上面获取的,注意对应 XY 轴

时间日期的格式化

[2020-01-28 Tue 13:58]

 1: // 该插件用来格式化当前输入的时间/日期
 2: 
 3: // xxxx/xx/xx xx:xx:xx
 4: const formatTime = (date) => {
 5:     let year = date.getFullYear(),
 6:         month = date.getMonth() + 1,
 7:         day = date.getDate(),
 8:         hour = date.getHours(),
 9:         minute = date.getMinutes(),
10:         second = date.getSeconds();
11: 
12:     return [year, month, day].map(formatNumber).join('/') +
13:            ' '  +
14:            [hour, minute, second].map(formatNumber).jon(';');
15: }
16: 
17: // xxxx-xx-xx
18: const formatDate = (date) => {
19:     let year = date.getFullYear(),
20:         month = date.getMonth() + 1,
21:         day = date.getData();
22: 
23:     return [year, month, day].map(formatNumber).join('-');
24: }
25: 
26: const formatNumber = (n) => {
27:     n = n.toString();
28: 
29:     return n[1] ? n : '0' + n;  // 如 8 -> 08
30: }
31: 
32: // 导出方法
33: module.exports = {
34:     formatTime: formatTime,
35:     formatDate: formatDate
36: }

小程序跳转 H5 时 url 参数截断

[2020-01-28 Tue 13:57]

→ 参考链接

先来看一个例子,原来的 url 为 https://ultimavip.cn/m/mposter.html?source=gxw_001_t_mposter ,跳转后变为 https://ultimavip.cn/m/mposter.html ,参数 ?source=gxw_001_t_mposter 丢失了,为什么呢?编码问题。

 1: // 跳转到 H5 页面的小程序代码
 2: targetUrl: function() {
 3:     console.log(this.data.mod_textUrl);
 4:     wx.navigateTo({
 5:         url: '../webview/webview?url=' + encodeURIComponent(this.data.mod_textUrl) // 此处需要编码,因为有 '?' ,可能浏览器不认
 6:     })
 7: }
 8: 
 9: // 跳转到的 H5 页面进行解码
10: onLoad: function(options) {
11:     this.setData({
12:         targetUrl: decodeURIComponent(options.url); // 用 decodeURIComponent 进行解码
13:     })
14:     console.log(options.url);
15: }

FormData

→ 参考链接

FormData 类型是什么? FormData 类型是在 XMLHttpRequest Level 2 定义的,它为序列化表单以及创建与表单格式相同的数据(用于 XHR 传输)提供便利。

如何初始化一个 formData 对象实例呢?如下:

  • 创建一个空对象实例;
  • 使用已有表单来初始化一个对象实例。

1. 创建一个空对象实例

1: var formData = new FormData();

后续,可以调用 append() 方法来添加数据。

2. 初始化已有表单创建实例

假设已有表单如下:

1: <form id="myForm" action="" method="post">
2:   <input type="text" name="name" />名字
3:   <input type="password" name="psw" />密码
4:   <input type="submit" value="提交" />
5: </form>

下面是用这个表单元素作为初始化参数,来实例化一个 formData 对象,如下:

 1: // 获取页面已有的 form 表单
 2: let form = document.getElementById('myForm');
 3: // 用表单来初始化
 4: let formData = new FormData(form);
 5: 
 6: // 还可以根据 name 来访问表单中的字段
 7: let name = formData.get('name'); // 获取名字
 8: let psw = formData.get('psw');   // 获取密码
 9: 
10: // 还可以在此基础上,继续添加其他数据
11: formData.append('token', 'otherdata...');

3. 操作方法

formData 里面存储的数据形式是什么?一对 key/value 组成一条数据, key 是唯一的,一个 key 可能对应多个 value 。如果是使用表单初始化,每一个表单字段对应一条数据,它们的 HTML name 属性即为 key 值, value 属性对应 value 值。

key value
k1 [v1, v2, v3]
k2 v4

可以用如下方法操作数据:

  • 获取数据,通过 get(key)/getAll(key) 来获取对应的 value 值;
  • 添加数据,通过 append(key, value) 来添加数据,若 key 不存在会新增,若 key 已存在会添加到数据末尾;
  • 修改数据,通过 set(key, value) 来设置数据,若 key 不存在会新增,若存在会修改对应的 value 值;
  • 判断是否该数据,通过 has(key) 来判断是否对应的 key 值;
  • 删除数据,通过 delete(key) ,来删除数据;
  • 遍历,通过 entries() ,来获取一个迭代器,每条用一次 next() 返回一条数据,如此可以遍历所有的数据。
1: formData.get('name');       // 获取 key 为 name 的第一个值
2: formData.getAll('name');    // 返回一个数据,获取 key 为 name 的所有值

通过 XHR 来发送数据,如下:

1: let xhr = new XMLHttpRequest();
2: xhr.open('post', 'login');
3: xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
4: xhr.send(formData);

滚动懒加载的实现

[2020-01-28 Tue 13:55]

→ 参考链接

什么时候需要懒加载呢?数据量大,一页显示不完,网页渲染事件长,影响体验。如何解决?分页,或数据懒加载。

先设定了基础前提,假设视窗可以显示 30 数据,总共有 56 条数据要展示。

如何实现数据懒加载呢?先来看三个属性:

  • scrollHeight ,元素总高度,包含滚动条中的内容,只读;
  • scrollTop ,当元素出现滚动条时,向下拖动滚动条时,内容向上滚动的距离,可读写;
  • clientHeight ,元素内容及其边框所占的空间大小,即可视区域大小高度。

如何判断滚动条到底部了呢?很显然,当 scrollHeight - scrollTop - clientHeight = 0 时,滚动条就到底部了。

来看代码,在第一次请求数据的时候,先设置一个变量来记录请求次数(其实后台也是做分页的处理):

1: // 初始化首页页码
2: let currentPage = 1;            // this.currentPage = 1
3: 
4: // 获取首页数据,apiGetTableData 为定义的获取数据的接口
5: // data 为请求参数
6: this.apiGetTableData(data).then(res => {
7:     $this.totalPage = res.totalPage; // 这里需要知道总页数
8:     $this.tableData = res.data;      // 表格数据
9: })

监听表格 DOM 对象的滚动事件:

 1: let DOM = document.querySelector(targetDom);
 2: 
 3: DOM.addEventListener('scroll', function() {
 4:     let scrollDistance = DOM.scrollHeight - DOM.scrollTop - DOM.clientHeight;
 5: 
 6:     if(scrollDistance <= 0) {                      // 为 0 证明滚动条已经到底,可以请求接口
 7:         if(this.currentPage < this.totalPage) {   // 当前页数小于总页数继续请求
 8:             this.currentPage++;                   // 当前页数自增
 9: 
10:             // 请求接口代码
11:             // data 为请求参数
12:             this.apiGetTableData(data).then(res => {
13:                 this.tableData = $this.tableData.concat(res.data); // 将请求回来的数据和当前展示的数据合并
14:             })
15:         }
16:     }
17: })

如此,就实现表格滚动下拉时的数据懒加载。

JavaScript 中的 || 和 && 所遵循的短路现象

[2020-01-28 Tue 13:55]

|| 时,找到为 true 的分项就停止处理,并返回该分项的值,否则执行完,并返回最后的分项的值;

&& 时,找到为 false 的分项就停止处理,并返回该分项的值,否则执行完,并返回最后的分项的值。

刷新 DNS

[2020-01-28 Tue 13:54]

windows 下 刷新 DNS 的方法:打开 cmd → 输入 ipconfig /flushdns 。 Github 有时候,连接很慢,甚至有打不开的状况,此时,可以尝试刷新一下 DNS ,会有意象不到的效果哦。

Footnotes:

Date: 2020-01-28 Tue 14:02

Author: Jack Liu

Created: 2020-05-24 Sun 15:16

Validate