背景

最近刚入react的坑,前端的布局和控件设计用的是阿里的开源框架:ant-design。ant-design不失为一款好用的设计框架,与bootstrap类似,比bootstrap好看,只是必须结合react使用。跟阿里其他的开源工具类似地,存在一个共同的通病,亦或者可以说是所有国有开源软件的通病:文档写的不够细致。
ant-design也是这样,在官方文档中经常有一些说的不够的地方,让使用者看的莫名所以。最典型的要数针对控件的API的事件参数的说明了,在这上面已经踩了很多的坑。有的是不知道参数传入的意义,有的是参数传递的使用方法说的不够具体等。本篇就一个具体的问题:Select选择器的onSelect事件记录一下踩坑的经历。

问题

我在开发中用到了如下代码片段:

1
2
3
4
5
6
const options = options.map(d => {
return <Option key={d.id}>{d.value}</Option>;
});
<Select onSelect={this.props.onSelect}>
{options}
</Select>

其中key属性是按照react的官方要求,遍历数组元素生成控件时要添加一个唯一的key属性供react的diff算法渲染。
渲染没有问题,在下拉选择的时候onSelect获取的参数值总是跟预期的不一致,在上例中,onSelect接收的总是key的值,然而官方文档里说:被选中时调用,参数为选中项的value值。

探索

文档除了那一句话外就没多说了,既然文档写的语焉不详,那么只好写测试自己琢磨了。

  1. 测试代码1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import { Select } from 'antd';
    const Option = Select.Option;


    ReactDOM.render(
    <Select value="test"
    onSelect={function(value){alert(value);}}
    >

    <Option key={1}>
    111
    </Option>
    <Option key={2}>
    222
    </Option>
    </Select>

    , mountNode);

    运行后发现确实是选择111时弹出1,选择222时弹出2,获取的是key。。。

  2. 测试代码2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import { Select } from 'antd';
    const Option = Select.Option;


    ReactDOM.render(
    <Select value="test"
    onSelect={function(value){alert(value);}}
    >

    <Option value={1}>
    111
    </Option>
    <Option value={2}>
    222
    </Option>
    </Select>

    , mountNode);

    怀疑官网说的value不是option的value值而是value属性,于是将key属性换成value。结果果然是选择111时弹出1,选择222的时候弹出2了。

验证了猜想,文档里说的onSelect的参数是被选中项的value属性而不是值,并且可恶的地方在于,没有设置value属性的时候竟然会返回key属性。。。要么说明下,要么按照文档的如实返回,返回key属性这不是挖坑了吗!

第二次遇到这个问题了,第一次删除了.git目录重新下载了项目,结果commit记录什么的都不对了,损失惨重,这次又遇到这个问题没敢轻举妄动了,折腾了很久,终于找到了问题的根源,这里记录一下以备忘,顺便给遇到同样问题的朋友们一点启发。

这个问题的根源在于跨平台造成的换行符的不一致造成。回想两次操作,都是在push的时候提示要将CRLF替换成LF,”warning: CRLF will be replaced by LF”。接受IDE的建议修改以后,所有的文件的换行符都被替换,于是pre-commit文件的行尾也多了”\r”字符,导致运行时报错。

1
2
.git/hooks/pre-commit: line 4: [: 127 : integer expression expected
.git/hooks/pre-commit: line 5: exit: 0 : numeric argument required

找到问题的原因后,解决方案就呼之欲出了。删除掉多余的字符即可。

1
2
cp .git/hooks/pre-commit /tmp/pre-commit
tr -d '\r' < /tmp/pre-commit > .git/hooks/pre-commit

如果还有其余文件报错,一并处理即可。

最近接手了一个烂摊子项目,据说是多少年前的了,没有人会部署本地环境,只能在服务器上通过脚本部署。这么一来就没法使用IDE的调试功能了,排查问题很不方便,跟同事一沟通,发现他们之前是用远程调试来排查问题。用了这么久Idea了,今天还是第一次知道还有远程调试这个功能。本篇就记录一下怎么在Idea里开启远程调试。

  1. 开启远程访问端口启动服务
    以java应用启动为例,启动参数里要添加这条额外的命令:

    1
    -Xrunjdwp:transport=dt_socket,address=8089,server=y,suspend=n

    其中的address就是要开启的远程访问端口

阅读全文 »

背景

最近换了个团队,被逼搞起了java+react。在使用webpack打包编译react代码或者使用maven启动java的时候,IntelliJ IDEA卡的跟孙子似的,人生就在这一分一秒的等待中度过,真是让人焦虑的不行。可是我大Think carbon x1可是8G的大内存机器,怎么会这么慢呢。。一开始听说idea就是内存杀手的我还以为是正常的,直到又一次项目直接起不来,并且还报错内存不够用,这真是让人不能接受了,8G的内存起个java说内存不够用?于是听说过jvm参数一说的我怀疑了下是不是idea设置的不太对。。

JVM参数

设置JVM内存的参数有四个:

  1. -Xmx Java Heap最大值,默认为物理内存的四分之一
  2. -Xms Java Heap初始值,最好将-Xmx和-Xms设置为相同值,避免垃圾回收时由于差值造成时间开销增大
  3. -Xmn Java Heap Young区大小,最好保留默认值
  4. -Xss 每隔线程Stack的大小,最好保留默认值

修改Idea JVM参数

打开idea的安装目录,切换到bin目录下,找到jvm的参数配置文件,32位程序为idea.exe.vmoptions,64位位idea64.exe.vmoptions
我的打开后看了下,-Xmx和-Xms默认都是设置了128m。。尼玛,什么年代了,给分配128兆内存,怪不得卡成翔。
果断调整设置分配4096m,其他保持默认不修改。

1
2
3
4
5
6
7
8
9
10
11
-Xms4096m
-Xmx4096m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-Xverify:none //关闭Java字节码验证,从而加快了类装入的速度,并使得在仅为验证目的而启动的过程中无需装入类,缩短了启动时间。

如果想提高启动速度,还可以将idea打开时默认加载的插件去掉一些自己不用的。路径是File->Settings->Plugins,勾掉自己不常用的。

关闭重启idea,那酸爽,没系安全带的我差点翻了车。。再试一下webpack打包,那是飞一样的感觉~~

背景

轮播效果在web开发中使用很频繁,之前一直是使用网上找来的插件,今天研究了一下自己实现了一下,没多大难度,还是很简单的,顺便再组件化了一把,以后再有需要就使用自己的了不用再用第三方插件了。知其然知其所以然,本篇博文对此做一分享。

实现原理

让我们先来看一下轮播的实现原理。
轮播其实很类似于我们小时候玩的抽卡片的小玩意儿:底下一层是绘制好的图案,上面一层开了一个窗口,通过转动上层的窗口来展示底层不同的图案。
轮播也是这样,我们可以理解为:底层排列好了要轮播的图片,上层的窗口每次只展示一个图片,每点击一次窗口就滑动一次。

阅读全文 »

背景

作为一个技术玩家,手机不ROOT真是怎么都不舒服。不ROOT没有掌控感:预装不能卸载、广告不能拦截、高级一点的应用不能安装…不能忍,于是今天又闲不下来折腾了下,结果又踩坑了。妈的,安卓手机品牌多样,真是踩坑无穷尽。这次倒是想到提前各种备份,还是栽在了短信恢复这事上。虽然现在短信已经用的不多了,有用的信息并不像以前那样多,但强迫症如我还是不恢复不舒服斯基。本篇博文主要想就锤子手机刷机root之后的短信恢复问题做一简单分享。绝对全网独家,别无他所,转载请注明出处,谢谢!

问题描述

刷机root过程略去不表,我是2.6.2系统,使用手机端kingroot获取root权限成功。在root之前使用优优刷机助手备份了各种数据。优优刷机助手备份的短信格式是”.csv”格式的,因此本篇分享的方案也仅对”.csv”格式的备份文件起作用。

在备份完成获取root成功后,本欲使用优优刷机助手继续恢复数据,怎料在恢复短信的时候提示要更改默认短信应用才行,没截图了,找了一张豌豆荚的,提示一样:

阅读全文 »

偷懒是优秀程序员的美好品德。

背景

作为一个码农,我们的原则是尽量把能自动化完成的任务交给机器。工作上一些流程性的邮件完全可以通过自动化实现。前端获取邮件信息,后端将信息组装发送出去。本篇博文将如何使用sendEmail发送邮件做一记录。

安装

点击此处,从官网下载sendEmail二进制文件。

使用

官网的说明已经很完善,或者直接运行sendEmail命令,会打出详尽的命令参数。

主要的参数有:

1
2
3
4
5
6
7
8
9
-t 收件人
-f 发件人
-u 邮件主题
-m 邮件内容 (也可以通过读取文件方式)
-s 发送邮件服务器
-a 发送附件
-cc 抄送人
-xu 发件人验证
-xp 发件人密码

阅读全文 »

背景

我有个Node.js项目,需要在node环境下调用shell命令。开始时只是单机调用,很简单,拼接好了shell命令,使用node的child_process调用一下就好了。随着系统规模的扩大,需要在node下进行调度,将任务分发到不同的机器上,于是就需要使用到ssh远程执行。简单一点的命令也还是可以执行的,但随着执行命令也复杂起来,参数里面有开始包含",'时,问题就开始复杂了。

node执行shell命令或脚本

让我们一步步来看一下这个问题是如何复杂起来的。首先先看一下,node下如何执行shell脚本或命令。
以执行命令为例:(执行脚本可以等同于执行命令,只需要将大量命令先写成脚本,再执行脚本即可)

node提供了一个child_process的子进程API,借助该API可以调用系统命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
var exec = require('child_process').exec;

var cmd = "ls -al";

var out = exec(cmd);

out.stdout.on('data',function(data){
console.log("stdout: " + data);
});

out.on('exit',function(code){
console.log(code);
});

上述代码片段将运行ls -al后输出结果,并输出命令执行后的返回码。

阅读全文 »

安装node的时候经常会下载到xz格式的压缩包,它是tar包外层在用xz压缩一遍,压缩比更高。

用的不是很多,但正因为此每次用到都要查一下,记录一下:

1
2
3
4
5
6
#解压:
xz -d file.xz
tar -xvf file.tar

#如果没有xz命令,安装一下
sudo yum install xz

背景

今天在写脚本的时候遇到这么一个问题,cp复制过程中报错:

1
cp: will not overwrite just-created `xxxx'

没来由的,cp这么基础的命令怎么还会出错?想了想我这命令也就复制的文件多一点,可能是cp的文件太多了,导致cp参数超限了。于是开始验证,同样的复制命令,删除了一些文件之后就cp成功了。

虽然根据谷歌查找到的资料显示,我这cp的源文件长度还远没有到达最大限制。不纠缠于此,既然文件太多了,那么使用xargs来复制吧。

xargs

直接附上命令:

1
find ${src_dir} -type f | xargs -i cp {} ${dst_dir}

由于cp是二元操作,需要传入源文件,这里需要使用xargs的替换模式。使用-i参数,然后可以使用{}表示来自标准输入的参数。