Wiki

Table of Contents

WIKI

刷新 DNS

[2020-01-28 Tue 13:54]

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

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

[2020-01-28 Tue 13:55]

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

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

滚动懒加载的实现

[2020-01-28 Tue 13:55]

→ 参考链接

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

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

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

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

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

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

// 初始化首页页码
let currentPage = 1;            // this.currentPage = 1

// 获取首页数据,apiGetTableData 为定义的获取数据的接口
// data 为请求参数
this.apiGetTableData(data).then(res => {
    $this.totalPage = res.totalPage; // 这里需要知道总页数
    $this.tableData = res.data;      // 表格数据
})

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

let DOM = document.querySelector(targetDom);

DOM.addEventListener('scroll', function() {
    let scrollDistance = DOM.scrollHeight - DOM.scrollTop - DOM.clientHeight;

    if(scrollDistance <= 0) {                      // 为 0 证明滚动条已经到底,可以请求接口
        if(this.currentPage < this.totalPage) {   // 当前页数小于总页数继续请求
            this.currentPage++;                   // 当前页数自增

            // 请求接口代码
            // data 为请求参数
            this.apiGetTableData(data).then(res => {
                this.tableData = $this.tableData.concat(res.data); // 将请求回来的数据和当前展示的数据合并
            })
        }
    }
})

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

FormData

→ 参考链接

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

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

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

创建一个空对象实例

var formData = new FormData();

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

初始化已有表单创建实例

假设已有表单如下:

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

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

// 获取页面已有的 form 表单
let form = document.getElementById('myForm');
// 用表单来初始化
let formData = new FormData(form);

// 还可以根据 name 来访问表单中的字段
let name = formData.get('name'); // 获取名字
let psw = formData.get('psw');   // 获取密码

// 还可以在此基础上,继续添加其他数据
formData.append('token', 'otherdata...');

操作方法

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() 返回一条数据,如此可以遍历所有的数据。
formData.get('name');       // 获取 key 为 name 的第一个值
formData.getAll('name');    // 返回一个数据,获取 key 为 name 的所有值

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

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

小程序跳转 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 丢失了,为什么呢?编码问题。

// 跳转到 H5 页面的小程序代码
targetUrl: function() {
    console.log(this.data.mod_textUrl);
    wx.navigateTo({
        url: '../webview/webview?url=' + encodeURIComponent(this.data.mod_textUrl) // 此处需要编码,因为有 '?' ,可能浏览器不认 
    })
}

// 跳转到的 H5 页面进行解码
onLoad: function(options) {
    this.setData({
        targetUrl: decodeURIComponent(options.url); // 用 decodeURIComponent 进行解码
    })
    console.log(options.url);
}

时间日期的格式化

[2020-01-28 Tue 13:58]

// 该插件用来格式化当前输入的时间/日期

// xxxx/xx/xx xx:xx:xx
const formatTime = (date) => {
    let year = date.getFullYear(),
        month = date.getMonth() + 1,
        day = date.getDate(),
        hour = date.getHours(),
        minute = date.getMinutes(),
        second = date.getSeconds();

    return [year, month, day].map(formatNumber).join('/') +
           ' '  +
           [hour, minute, second].map(formatNumber).jon(';');
}

// xxxx-xx-xx
const formatDate = (date) => {
    let year = date.getFullYear(),
        month = date.getMonth() + 1,
        day = date.getData();

    return [year, month, day].map(formatNumber).join('-');
}

const formatNumber = (n) => {
    n = n.toString();

    return n[1] ? n : '0' + n;  // 如 8 -> 08
}

// 导出方法
module.exports = {
    formatTime: formatTime,
    formatDate: formatDate
}

JS 获取 DPI

[2020-01-28 Tue 13:59]

//获取DPI
function js_getDPI() {
    var arrDPI = new Array();
    if ( window.screen.deviceXDPI != undefined ) {
        arrDPI[0] = window.screen.deviceXDPI;
        arrDPI[1] = window.screen.deviceYDPI;
    }
    else {
        var tmpNode = document.createElement( "DIV" );
        tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
        document.body.appendChild( tmpNode );
        arrDPI[0] = parseInt( tmpNode.offsetWidth );
        arrDPI[1] = parseInt( tmpNode.offsetHeight );
        tmpNode.parentNode.removeChild( tmpNode );
    }
    return arrDPI;
}

// 将 px 转成 mm
let mm = pxValue/dpi*2.54*10;   // dpi 是上面获取的,注意对应 XY 轴

CSS 换行

[2020-01-28 Tue 13:59]

→ 参考链接

文本换行有很多方式:

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

强制不换行

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

控制文本换行

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

强制单词内或链接内断行

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

input 中 placeholder、disabled 状态样式修改

[2020-01-28 Tue 14:00]

问题场景:

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

处理如下:

input::-webkit-input-placeholder {
    color: #ccc;
    -webkit-text-fill-color: #ccc;
    opacity: 1;
    -webkit-opacity: 1;
}

input:disabled {
    background: none;
    color: #333;
    -webkit-text-fill-color: #333;
    opacity: 1;
    -webkit-opacity: 1;
}

input:disabled::-webkit-input-placeholder {
    color: #ccc;
    -webkit-text-fill-color: #ccc;
    opacity: 1;
    -webkit-opacity: 1;
}

相关延伸:

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

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 是代表忽略当前目录下的几级目录。

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'

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

[2020-02-05 Wed 22:35]

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

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

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

Date: 2020-01-28 Tue 14:02

Author: Jack Liu

Created: 2020-02-08 Sat 21:27

Validate