浮生如斯的博客


  • 首页

  • 分类

  • 归档

  • 标签

  • 公益404

Mac下git多个SSH KEY配置

发表于 2018-01-04   |   分类于 技术   |  

自己的电脑上有用到几个不同的git,之前只是clone github上http的地址拿下来看,后来个人项目也需要开发,就需要好几个ssh key,写下这个记录一下过程,省的每次忘记流程还重新记录。

生成SSH KEY

  • 生成SSH KEY时,首先进入~/.ssh/目录下,使用ssh-keygen -t rsa -C "your_email@example.com"生成ssh key信息,第一次提示”Enter file in which to save the key (/Users/JeromeGao/.ssh/id_rsa)”时,可以使用默认文件名字,但是之后生成ssh key记得填写相应的文件名,,以便区分,”Enter passphrase (empty for no passphrase)”是私钥密码,可以直接回车也可以输入密码,如果输入密码请记住私钥的密码, 下面导入私钥的时候要用到。
    命令:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    cd ~/.ssh/
    ➜ .ssh ssh-keygen -t rsa -C "your_email@example.com"
    Generating public/private rsa key pair.
    Enter file in which to save the key (/Users/JeromeGao/.ssh/id_rsa): id_rsa_gittest
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in id_rsa_gittest.
    Your public key has been saved in id_rsa_gittest.pub.
    The key fingerprint is:
    SHA256:5/5+BIyhVKH3MRoGIs5vn36aKmuppQqgIBJ69KTHND8 gaojianqi6@126.com
    The key's randomart image is:
    +---[RSA 2048]----+
    | . . ..o. |
    | o . ..o. |
    |. . * ...++o |
    |.o * + .o.+oo |
    |* o + E S o .. |
    |*. . . o + . |
    |o .. o . . |
    |. o+ . o. . |
    |..oo.o..+o.oo. |
    +----[SHA256]-----+
  • 将SSH 私钥增加到ssh-agent: ssh-add ~/.ssh/xxx_rsa, 这里会提示输入一次私钥的密码;

  • 查看已经添加过的SSH KEY: ssh-add -l;
  • 在相对应的网站上找到SSH KEYS,然后打开~/.ssh/id_rsa.pub, 复制公钥内容到Key中,然后点击添加就完成了

一台机器上管理多个GIT帐号的SSH KEY

  • 如果你在一台机器上,使用多个git账号,则重复上面步骤之后,需要编辑文件~/.ssh/config:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #Github  (github 配置)
    Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa_github

    #company (公司git 配置)
    Host company
    HostName git.company.com
    User git
    IdentityFile ~/.ssh/id_rsa

    #gitlab (gitlab 配置)
    Host gitlab
    HostName gitlab.com
    User git
    IdentityFile ~/.ssh/id_rsa_gitlab

解释一下这个配置文件:

Host:一个”别名”,可以随意命名, 像git、company这样的命名也可以;
HostName:工作的git仓库存储地址;
IdentityFile: 所使用的公钥文件
配置完毕,用下面的命令测试一下:

测试SSH KEY

1
2
3
4
5
6
# 测试是否联通,出现welcome就表示成功
➜ .ssh ssh -T git@gitlab.com
Welcome to GitLab, !

# 可以出来调试信息
➜ .ssh ssh -v git@gitlab.com

记得配置自己的username和email,一般在网站新建项目时会提示你配置

1
2
git config user.name your_name
git config user.email your_email

ssh命令收集

1
2
3
4
5
6
# 将SSH 私钥增加到ssh-agent
ssh-add ~/.ssh/xxx_rsa
# 查看已经添加过的SSH KEY
ssh-add -l
# 运行ssh-agent,它会打印出来它使用的环境和变量
ssh-agent

微信分享踩过的坑

发表于 2017-04-26   |  

微信分享在SPA网页中配置的分享会失效

之前主要是在iPhone上面测试H5网页分享出去的效果,所以一直也没有发现单页应用在android上pushState一次之后就分享信息就会失效。
JSSDK不知道什么时候更新的官方信息:

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。

所以如果你用的vue router或者react router的话,在pushState页面路径变化之后,可以在判断当前页面是微信浏览器并且是android手机的情况下,重新发起获取微信配置信息,然后调用wx.config(),这样就没问题了。

1
2
3
4
5
6
7
8
// react router历史记录
const history = syncHistoryWithStore(browserHistory, store);

history.listen((location) => {
// 判断android下面 每次URL变化时重新获取wxJSConfig信息
if (isWeixin() && isAndroid())
window.getWXJSConfigInfo();
});

微信分享更改规则,网页必须分享当前页面的URL

项目里有一个用户登录之后在微信中分享会分享另外一个域名的页面,这个在前两天还在用的功能,突然就出了bug,测试了好久,一直在找签名和自己代码的问题,最后偶然间发现是微信的分享规则变化,改成分享当前页面URL后,就可以了。
吐槽一下微信的分享规则越来越封闭了,而且开启了分享的debug之后并没有提示出明确的出错信息,导致调试走了很多弯路。
官方链接:
JSSDK自定义分享接口的策略调整

react的滑动效果,react-swipe和react-motion

发表于 2017-04-18   |   分类于 技术   |  

这次在项目中需要用到焦点图滑动效果和在页面一个浮层中增加一个滑动的动画效果,之前已经写过很多次滑动效果的页面了,但是都没有留下记录。
现在记载下这次在项目中使用react-swipe和react-motion的收获。

react-swipe

安装需要同时安装swipe-js-jso包:

1
npm install react swipe-js-iso react-swipe

常用属性介绍:
continuous: 循环到最后一个时继续滑动是否从头开始,默认为true
transitionEnd:滑动动画结束时调用,callback(index, item), index为当前滑动的下标,item为当前被滑动的元素
因为swipe没有提供轮滑图中显示的提示圆点之类,自己可以根据下标在上面加上提示用户的圆点等。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// import ReactSwipe from 'react-swipe';
<div className="welfare-focus-wrap">
<ReactSwipe className="carousel" swipeOptions={{continuous: true, transitionEnd: (index) => {
this.setState({
focusIndex: index,
});
}}}>
{
this.state.activityDetails.map((item, index) =>
<div className={`welfareFocusWrap focusIndex${index}`} key={`welfareFocus${index}`} onClick={() => { location.href = item.activityUrl;}}>
<img src={item.pictureUrl} className="welfareFocusImg" />
</div>)
}
</ReactSwipe>
<div className="welfare-focus-circle-wrap">
{
this.state.activityDetails.map((item, index) =>
<div
className={`welfareFocusCircle ${this.state.focusIndex == index ? 'checked' : ''}`}
key={`welfareFocusCircle${index}`} />)

}
</div>
</div>

github地址:react-swipe 、swipe-js-iso

react-motion

在没实际写代码测试时候,对motion的概念感觉似懂非懂,翻了很多介绍react-motion的资料,在写了代码测试之后,理解react-motion是做了对
动画过程中从A点到B点平滑的变化数值,在数值变化过程中,react-motion会不断的调用回调方法,把变动的数值传入到需要渲染的dom中,
这个比自己实现的定时滑动会更加的平滑自然。

因为要兼容手机不同分辨率滑动的单位距离不一致,所以在Motion的外层div的onLoad事件中,每次通过元素的clientWidth来获得滑动的距离,在react中不得已使用了
dom,谁有更好的办法欢迎告诉我。

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
const stepbarLeft = this.state.stepbarLeft;
const oldStepbarLeft = curQuestionIndex > 0 ? (curQuestionIndex -1)*stepbarLeft : 0;
const newStepbarLeft = stepbarLeft*curQuestionIndex;
const currentNode = (
<Motion defaultStyle={{left: oldStepbarLeft }} style={{left: spring(newStepbarLeft)}}>
{
// 在动画执行过程中,react-motion会不断的调用此方法,返回动画进行过程中相应的数值,可以自己cosole输出interpolatingStyle看
interpolatingStyle => {
return (
<div className="questionPageCurNode" style={interpolatingStyle}>
<img src={questionPageCurrentImage} className="questionPageCurDot" />
<span className="questionPageCurSequence">{ curQuestionIndex + 1 }</span>
</div>
);
}
}
</Motion>
);

return (
<div className="questionPageHeader" onLoad={() => {
const left = document.querySelectorAll('.questionPageNode')[3].clientWidth + document.querySelectorAll('.questionPageLine')[3].clientWidth;
this.setState({
stepbarLeft: left,
conentLeft: document.querySelector('.questionPageContentsArea').clientWidth,
});
}}>
<div className="questionPageStepbar">
{stepbar}
{currentNode}
</div>
</div>
);

github地址:react-motion
Motion参考资料:React Motion 缓动函数剖析

React和Webpack项目构建

发表于 2016-08-25   |   分类于 技术   |  

这次在项目中使用了React,并使用webpack来打包js文件,gulp来编译stylus等其他事情。

最开始我们想达到的效果,希望能够根据webpack能够把reactjs打包成项目可以使用的文件,在项目目录中新建webpack.config.js文件

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
var path = require('path');
var webpack = require('webpack');

var BUILD_DIR = path.resolve(__dirname, 'content/jsx');
var APP_DIR = path.resolve(__dirname, 'content/scripts');

module.exports = {
//是否让webpack监听入口相关的文件
watch: true,
//配置入口文件,入口文件可以以对象的形式配置,也可以以数组的形式配置,后缀名可以省略
entry: {
index: path.join(BUILD_DIR, 'index.jsx')
},
//输出文件出口
output: {
/*
输出路径,在这我们要手动创建一个文件夹,名字可以自己命名,
输出的文件路径是相对于本文件的路径
**/

path: APP_DIR, //输出路径
filename: '[name].bundle.js' //输出文件名,文件可以自己定义,[name]的意思是与入口文件的文件对应,可以不用[name]
},
resolve: {
extensions: ['', '.js', '.jsx'],
/*
* 别名配置,配置之后,可以在别的js文件中直接使用require('d3'),将导入的文件作为一个模块导入到你需要的项目中,不用配置别也可会当作模块导入项目中,只是你要重复写路径而已。
**/

alias: {
'd3': 'd3/d3.min.js'
}
},
module: {
/*
* 标题:加载器(loaders)
* 作用:需要下载不同别的加载器,如css,js,png等等
**/

loaders: [
{
test: /\.js(x?)$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel',
query: {
presets: ['react', 'es2015', 'stage-0']
}
}
],
}
};

Webpack的一些命令:

1
2
3
4
$ webpack --config XXX.js //使用另一份配置文件(比如webpack.config2.js)来打包
$ webpack --watch //监听变动并自动打包
$ webpack -p//压缩混淆脚本,这个非常非常重要!
$ webpack -d//生成map映射文件,告知哪些模块被最终打包到哪里了

但是这样打包出来的文件会很大,

这个可以使用webpack的externals来设置webpack将依赖的库指向全局变量,从而不导入这个js文件。

但是如果引用的包比较多的情况下,维护起来会比较麻烦,所以使用webpack的dll plugin来解决这个问题。
使用这个功能需要把打包过程分成两步:

  1. 打包ddl包
  2. 引用ddl包,打包业务代码

首先建一个,webpack.dll.config.js文件

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
var webpack = require('webpack');
var path = require('path');

var APP_DIR = path.resolve(__dirname, 'content/scripts');

var vendors = [
"react",
"react-bootstrap",
"react-dom",
"react-redux",
"react-router",
"react-router-redux",
"redux",
"redux-logger",
"redux-promise",
"redux-thunk",
"whatwg-fetch"
];

module.exports = {
output: {
path: path.join(APP_DIR, '/'),
filename: '[name].dll.js',
/**
* output.library
* 将会定义为 window.${output.library}
* 在这次的例子中,将会定义为`window.[name]_[chunkhash]`
*/

library: '[name]_[chunkhash]',
},
entry: {
vendor: vendors,
},
plugins: [
new webpack.DllPlugin({
/**
* path
* 定义 manifest 文件生成的位置
* 也可以设置[name]manifest.json,[name]部分由entry的名字替换
*/

path: 'manifest.json',
/**
* name
* dll bundle 输出到那个全局变量上
* 和 output.library 一样即可。
*/

name: '[name]_[chunkhash]',
context: __dirname
})
]
};

webpack.DllPlugin 的选项中:

path 是 manifest.json 文件的输出路径,这个文件会用于后续的业务代码打包;
name 是 dll 暴露的对象名,要跟 output.library 保持一致;
context 是解析包路径的上下文,这个要跟接下来配置的 webpack.config.js 一致。

PS:自己用gulp来执行的webpack打包,只打出来vendor文件,没有出来manifest.json,改用webpack命令打包就好了。

运行之后会生成两个文件,一个是所有引用的js文件,另一个是manifest.json:

1
2
3
4
5
6
7
8
9
➜  webapp git:(dev_jerome) ✗ ./node_modules/.bin/webpack --config webpack.dll.config.js 
Hash: fd919a411af8bb56f919
Version: webpack 1.13.2
Time: 2389ms
Asset Size Chunks Chunk Names
vendor.dll.js 1.6 MB 0 [emitted] vendor
[0] dll vendor 12 bytes {0} [built]
+ 533 hidden modules
➜ webapp git:(dev_jerome) ✗

再在原来的webpack.config文件里面增加DllReferencePlugin的配置,需要注意的是这里面的context需要和dll.config里面的context一样。

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
var path = require('path');
var webpack = require('webpack');

var BUILD_DIR = path.resolve(__dirname, 'content/jsx');
var APP_DIR = path.resolve(__dirname, 'content/scripts');

module.exports = {
watch: true,
entry: {
index: path.join(BUILD_DIR, 'index.jsx')
},
output: {
path: APP_DIR,
filename: '[name].bundle.js'
},
resolve: {
extensions: ['', '.js', '.jsx']
},
module: {
loaders: [
{
test: /\.js(x?)$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel',
query: {
presets: ['react', 'es2015', 'stage-0']
}
}
],
},
externals: {
"jquery": "jQuery"
},
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./manifest.json')
}),
new webpack.NoErrorsPlugin()
]
};

webpack.DllReferencePlugin 的选项中:

context 需要跟之前保持一致,这个用来指导 Webpack 匹配 manifest.json 中库的路径;
manifest 用来引入刚才输出的 manifest.json 文件。
DllPlugin 本质上和我们手动分离第三方库是一样的,但是对依赖包极多的项目来说,自动化明显加快了生产效率。

可以在package.json里面设置运行脚本,如果依赖的脚本没有变化的话可以只用执行bundle任务。

1
2
3
4
"scripts": {
"build": "webpack --config webpack.dll.config.js && gulp bundle",
"bundle": "./node_modules/.bin/gulp bundle"
}

下面是依赖的gulp文件

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
var gulp = require('gulp');
var webpack = require('webpack');
var webpackStream = require('webpack-stream');
var webpackConfig = require('./webpack.config.js');
var path = require('path');
var watch = require('gulp-watch');
var gulpWebpack = require('gulp-webpack');
var gutil = require('gulp-util');

gulp.task('bundle', function () {
var ENTYR_DIR = path.join(__dirname, "content/jsx");
var DIST_DIR = path.join(__dirname, "content/scripts");

return gulp.src(path.join(ENTYR_DIR, "index.jsx"))
.pipe(webpackStream(require('./webpack.config.js')))
.pipe(gulp.dest(DIST_DIR));
});

gulp.task('bundle-dll', function () {

var myConfig = Object.create(require('./webpack.dll.config.js'));
myConfig.plugins = [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin()
];

// run webpack
webpack(myConfig, function(err, stats) {
if (err) throw new gutil.PluginError('webpack', err);
gutil.log('[webpack]', stats.toString({
colors: true,
progress: true
}));
callback();
});
});



gulp.task('bundle-watch', function () {

var ENTYR_DIR = path.join(__dirname, "content/jsx");
var DIST_DIR = path.join(__dirname, "content/scripts");

return gulp.src(['content/**/*.jsx', 'content/**/*.js'])
.pipe(watch(function () {
return gulp.src(path.join(ENTYR_DIR, "index.jsx"))
.pipe(webpackStream(webpackConfig))
.pipe(gulp.dest(DIST_DIR));
}));
});

gulp.task('webpack', function(callback) {
var myConfig = Object.create(webpackConfig);
myConfig.plugins = [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin()
];

// run webpack
webpack(myConfig, function(err, stats) {
if (err) throw new gutil.PluginError('webpack', err);
gutil.log('[webpack]', stats.toString({
colors: true,
progress: true
}));
callback();
});
});

gulp.task('gulpWebpack', function() {
var ENTYR_DIR = path.join(__dirname, "content/jsx");
var DIST_DIR = path.join(__dirname, "content/scripts");

return gulp.src(path.join(ENTYR_DIR, "index.jsx"))
.pipe(gulpWebpack(webpackConfig))
.pipe(gulp.dest(DIST_DIR));
});

参考文章: 如何十倍提高你的webpack构建效率

IE下Placeholder的兼容处理

发表于 2016-07-08   |   分类于 技术   |  

placeholder

placeholder是html5新增的一个属性,当input或者textarea设置了这个属性之后,placeholder的值会作为灰字提示显示在该输入框上,当文本框获取焦点之后或者用户输入一个字符之后,则提示文字消失。这个属性在IE 10中对他的支持才好一点,而用户还有好多使用IE7、8、9的,所以还是需要在旧的浏览器中对他进行一下处理。

解决办法

网上对placeholder的解决办法大多数是对placeholder进行判断,在不支持placeholder属性的浏览器中,检测blur和focus事件,直接把placeholder的值赋在该元素的value上,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function placeholder() {
if (/MSIE\s(\d+)/.test(navigator.userAgent) && navigator.userAgent.match(/MSIE\s(\d+)/)[1] < 10) {
$('[placeholder]').each(function() {
var pla = $(this).attr('placeholder');
$(this).focus(function() {
if ($(this).val() == pla) {
$(this).val('');
}
}).blur(function() {
if ($(this).val() == '') {
$(this).val(pla);
}
});
$(this).trigger('blur'); //此处利用blur事件,为了业务需求。防止页面上查询后,文本框需要保留搜索的关键被placeholder代替
});
}
}

$(document).ready(function() {
placeholder();
});

或者一些公用库对他也有很好的实现,如Placeholders.js。

但是,如果在项目中用到了验证表单的库,像jquery.validation这样的,也是对输入框的值进行了验证,那么在使用Placeholder的时候会有一些问题,比如发现值是错的对他改变了颜色之类的。

最终的解决办法

所以后来就决定在输入框后面加一个span元素,当页面dom加载完毕之后,对所有符合条件的input、textarea进行处理,默认把他们的placeholder赋值在后面的span元素上面,点击的时候隐藏提示,离开的时候判断输入框是否有值来对他进行显示。
代码中采用了Placeholders.js的一些思路,使用createTextNode来添加css,这样只用引进一个js文件就有默认的placeholder样式。

检查的时候会对display为none、type等于hidden、class为hidePassword和placehloder-check为false的直接跳过,不进行处理。

使用的时候需要提前引用jQuery。

写的时候遇到的问题

jQuery在父元素display为none时,计算width,会加上padding-left 和padding-right,而不去管box-sizing 是否为border-box,发现这个问题之后在代码中对当前元素进行了判断,如果是hidden的话,则使用width()方法获取宽度,不是的话,则全使用css(“width”)获取宽度。
判断方法:

1
.is(":visible")  .is(":hidden"))

项目地址:https://github.com/gaojianqi6/placeholder.jquery.js

JS的一些基础问题

发表于 2016-05-26   |   分类于 技术   |  

1、如果给定一个字符串,怎么返回成一个JS的Dom对象。 比如下面的这个字符串:

1
<div>测试<span>cd</span></div>

这个要用到浏览器的innerHTML来实现了,首先使用createElement来创建一个div元素,然后使用innerHTML把字符串设置为它的子元素,然后再返回他的子元素就可以了。实现例子:

1
2
3
4
5
6
7
function parseDom(str){
var objParent = document.createElement("div");
objParent.innerHTML = str;
return objParent.childNodes;
}

parseDom("<div>测试<span>cd</span></div>");

那这里面的childNodes返回的是一个数组,如果确定传入的是一个元素,则使用下标取第一个就行,parseDom(‘<div></div>’)[0]

2、给一个父元素,怎么遍历下面的所有子元素。

1
2
3
4
5
6
7
8
9
<div id="ID">
<div id="1">内容1</div>

<div id="2">
<div id="2_1">内容2.1</div>
<div id="2_1">内容2.1</div>
</div>
<div id="3">内容3</div>
</div>

使用childNodes获取元素的子节点,但是在FF和Chrome下面换行符也会当成一个元素储存在元素列表里,所以根据元素的nodeName来判断,如果是的话,则删除当前元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function getChildNodes(obj){
var nodes = obj.childNodes,
objNode,
i = 0;
for(; i < nodes.length; i++){
objNode = nodes[i];
//当元素里面有节点类型是文本并且文本类型节点的节点值是空的。就把他删除。
//nodeNames可以得到一个节点的节点类型,nodeValue表示得到这个节点里的值
// /\s/是非空字符在JS里的正则表达式,如:
// /\s/.test(" ") //true
// /\s/.test("sdf") //false
if(objNode.nodeName == "#text" && /\s/.test(objNode.nodeValue)){
obj.removeChild(objNode);
}
}
return obj.childNodes;
}

getChildNodes(document.getElementById("ID"));

3、给一个冒泡排序。

【轻松学排序算法】眼睛直观感受几种常用排序算法
js实现数组冒泡排序、快速排序原理
Javascript算法系列之快速排序(Quicksort)

4、retina屏幕如何实现真正1px的边框线

解决办法:
1、判断浏览器是否支持0.5PX的线,支持给html元素添加一个class

1
.hairlines div {   border-width: 0.5px; }

1
2
3
4
5
6
7
8
9
10
11
if (window.devicePixelRatio && devicePixelRatio >= 2) {
var testElem = document.createElement('div');
testElem.style.border = '.5px solid transparent';
document.body.appendChild(testElem);
if (testElem.offsetHeight == 1)
{
document.querySelector('html').classList.add('hairlines');
}
document.body.removeChild(testElem);
}
// 脚本应该放在 <body> 内, 如果在 <head> 里面运行,需要包装 $(document).ready(function() { })

不过这个兼容不了安卓设备,而且ios 8以下不支持,所以还是得安卓支持才能用。。
2、使用图片完成border
一个6*6的图片
切图

1
.border{     border-width: 1px;     border-image: url(border.gif) 2 repeat; }

缺点是每次改变颜色都要重新切图。
3、用多背景渐变实现的,设置 1px 的渐变背景,50% 有颜色,50% 透明

1
.border {     background:     linear-gradient(180deg, black, black 50%, transparent 50%) top    left  / 100% 1px no-repeat,     linear-gradient(90deg,  black, black 50%, transparent 50%) top    right / 1px 100% no-repeat,     linear-gradient(0,      black, black 50%, transparent 50%) bottom right / 100% 1px no-repeat,     linear-gradient(-90deg, black, black 50%, transparent 50%) bottom left  / 1px 100% no-repeat; }

圆角没法实现,而且代码比较长
4、通过 viewport + rem 实现的
当 devicePixelRatio = 2 时,输出 viewport

1
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">

当devicePixelRatio = 3时,输出 viewport

1
<meta name="viewport" content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">

同时通过设置对应 viewport 的 rem 基准值,这种方式就可以像以前一样写 1px 了。
5、伪类 + transform
原理是把原先元素的 border 去掉,然后利用:before或者:after重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位

  • 单条 border

    1
    2
    .hairlines li{     position: relative;     border:none; }
    .hairlines li:after{ content: ''; position: absolute; left: 0; background: #000; width: 100%; height: 1px; -webkit-transform: scaleY(0.5); transform: scaleY(0.5); -webkit-transform-origin: 0 0;
  • 四条 border

    1
    2
    .hairlines li{     position: relative;     margin-bottom: 20px;     border:none; }
    .hairlines li:after{ content: ''; position: absolute; top: 0; left: 0; border: 1px solid #000; -webkit-box-sizing: border-box; box-sizing: border-box; width: 200%; height: 200%; -webkit-transform: scale(0.5); transform: scale(0.5); -webkit-transform-origin: left top; transform-origin: left top; }

样式使用的时候,也要结合 JS 代码,判断是否 Retina 屏

1
2
3
if(window.devicePixelRatio && devicePixelRatio >= 2){
document.querySelector('ul').className = 'hairlines';
}

可以支持圆角,唯一的一点缺陷是td用不了。

5、点击延迟300ms

问题由来

这要追溯至 2007 年初。苹果公司在发布首款 iPhone 前夕,遇到一个问题:当时的网站都是为大屏幕设备所设计的。于是苹果的工程师们做了一些约定,应对 iPhone 这种小屏幕浏览桌面端站点的问题。

这当中最出名的,当属双击缩放(double tap to zoom),这也是会有上述 300 毫秒延迟的主要原因。双击缩放,顾名思义,即用手指在屏幕上快速点击两次,iOS 自带的 Safari 浏览器会将网页缩放至原始比例。

解决办法

1、FastClick,监测touchend事件,通过Dom自定义事件触发一个模拟click事件,并且把浏览器300MS之后真正触发的click事件关掉;
2、touch-action 这个现在只在chrome和IE 10+支持,就是说在css设置touch-action: none后,那么对应的元素在被点击之后,浏览器不会启动缩放操作;

6、事件穿透 pointer-event

CSS pointer-events
pointer-events:auto | none | visiblepainted | visiblefill | visiblestroke | visible | painted | fill | stroke | all
当设置为none的时候,元素永远不会成为鼠标事件的target,当然如果需要禁止点透的节点是父子关系,那么这个方法是行不通的。

1、同样 FastClick可以解决;
2、用touchend代替tap事件并阻止掉touchend的默认行为preventDefault()

7、viewport作用。

手机浏览器的viewport(视觉窗口)

8、闭包的用途和原理。

闭包的场景:

  • 函数内部可以访问到外部的变量或者对象
  • 使用闭包可以在JavaScript中模拟块级作用域
  • 闭包可以用于在对象中创建私有变量, 不污染外部环境
  • 避免垃圾回收

最简形式, 还有jquery的ajax调用时候也是形成了一个闭包。:

1
2
3
4
5
6
function a(i)
{

return function(){
return i+1
}
}

这篇 javascript中闭包的工作原理 对闭包的工作原理讲解的到位。

9、面向对象方法的扩充。

一般使用prototype来扩充,具体的实现可以模仿jQ的构建方法,下面这一篇讲的比较好,逻辑清晰易懂。
jQuery 2.0.3 源码分析core - 整体架构

这只能算个日记吧。

发表于 2016-05-18   |   分类于 无题   |  

从地铁回去的时候经常怔怔的发呆,脑海里的思绪自己不去拨动,让他自己进行推演,会发现有时候会莫名的心慌,觉得自己这么大了,却好像一事无成,有时候却又在和周围过的不如自己好的对比,就莫名的信心膨胀,不过大部分时候,总觉得自己好像并没有什么骄傲的,拿出去可以夸奖的事情又有什么呢?有时候想了好久,自己将来到底会做什么,爱好拿起来又放下,到最后连拾起来的勇气都没有,总想到《练琴》里说的,当他再一起拿起了吉他,手上却久久的不敢拨动,好像怕惊醒了什么。

我想有好多的钱可以花,可以让我挥霍,让我胡吃海塞,天地任遨游,可是却觉得只是个梦,所以首先的一步还是要先有财物自由的钱吧,我觉得赚钱的话还是得靠产品,知乎前段时间出了一个产品,可以写一段话,然后把其中关键的字句给屏蔽,用户只能付费观看,如果看完觉得值的话会直接打给作者,如果看完觉得不行就捐给程序员买袜子,这是一个很好的想法,知乎变现的尝试之作,产品还是靠好idea;在豆瓣看电影的时候会有好多评分,会想怎么来根据评分选择电影呢,豆瓣没有这个功能还是把这个功能隐藏的很深,难道是用户没有这个需求来选择电影?

我的爱好有好多,长的也只是坚持一到两年就慢慢的开始淡了,因为我觉得最开始支撑起来的是好奇和事物的新奇度,坚持久了,发展深了,就会出现练习的枯燥,而这个时候恰恰是事物的瓶颈期,突破了,就是一个质的变化,而好多时候到这却选择了暂时性的放弃,真是满盘皆输。
房间那么小,却可以放的下世界地图;经历那么有限,心却那么大。

Github Pages从构建到评论(HEXO)

发表于 2016-05-17   |   分类于 构建工具   |  

这是我第一次搭建博客,本来是准备自己买服务器,然后写代码来搞一套,后来无意中发现有人提到github的博客,然后搜索了一下发现是github pages,就开始跟着教程一步步搭建博客,之间走过了很多的坑,因为现在网上的很多教程都是很久以前的资料,而且到处搬来搬去,在这里总结一下。

GitHub Pages是什么?

GitHub Pages 本用于介绍托管在 GitHub 的项目, 不过,由于他的空间免费稳定,用来做搭建一个博客再好不过了。

使用 GitHub Pages 建立博客

注册GitHub

访问:http://www.github.com/
注册你的username和邮箱,邮箱十分重要,GitHub上很多通知都是通过邮箱的。

建立博客项目

与 GitHub 建立好链接之后,就可以方便的使用它提供的Pages服务,GitHub Pages分两种,一种是你的GitHub用户名建立的username.github.io这样的用户&组织页(站),另一种是依附项目的pages。

想建立个人博客是用的第一种,形如gaojianqi6.github.io这样的可访问的站,每个用户名下面只能建立一个。

在github.com页面选择 New repository, 然后在Repository name里填写username.github.io(必须为这个仓库名)

开始Hexo

首先本地得装上了Node.js、Git和Hexo
安装Node.js: Nodejs官网
安装Git: Git
安装Git - 廖雪峰的官方网站
安装Hexo: Hexo

下载安装之后可以在本地启动查看一下,默认监听4000端口,打开浏览器,输入 localhost:4000 就可以看到一个hexo的默认博客主题页面出现在你面前。

配置 SSH keys

我们如何让本地git项目与远程的github建立联系呢?用SSH keys。

检查 SSH keys的设置

首先我们需要检查你电脑上现有的ssh key:

1
cd ~/.ssh 检查本机的ssh密钥

如果提示:No such file or directory 说明你是第一次使用git。

生成新的SSH Key:

1
2
3
ssh-keygen -t rsa -C "邮件地址@youremail.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/your_user_directory/.ssh/id_rsa):<回车就好>

然后系统会要你输入密码:

1
2
Enter passphrase (empty for no passphrase):<输入加密串>
Enter same passphrase again:<再次输入加密串>

在回车中会提示你输入一个密码,这个密码会在你提交项目时使用,如果为空的话提交项目时则不用输入。这个设置是防止别人往你的项目里提交内容。

注意:输入密码的时候没有*字样的,你直接输入就可以了。

添加 SSH Key 到 GitHub

在本机设置SSH Key之后,需要添加到GitHub上,以完成SSH链接的设置。

1、打开本地~\id_rsa.pub文件。此文件里面内容为刚才生成人密钥。如果看不到这个文件,你需要设置显示隐藏文件。准确的复制这个文件的内容,才能保证设置的成功。
2、登陆github系统。点击右上角的 Account Settings—>SSH Public keys —> add another public keys
3、把你本地生成的密钥复制到里面(key文本框中), 点击 add key 就ok了

测试

可以输入下面的命令,看看设置是否成功,git@github.com的部分不要修改:

1
ssh -T git@github.com

多个SSH Key, 具体可查看链接

1.生成指定名字的密钥

1
ssh-keygen -t rsa -C "邮箱地址" -f ~/.ssh/id_rsa_github

会生成id_rsa.pub和id_rsa_github两个文件

2.密钥复制到托管平台上

1
$  vim ~/.ssh/id_rsa_github.pub

3.修改config文件

1
vim ~/.ssh/config #修改config文件,如果没有创建 config

#Github  (github 配置)
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa_github

#oschina.net (开源中国 配置)
Host oschina.net
    HostName git.oschina.net
    User git
    IdentityFile ~/.ssh/id_rsa

配置完之后:
配置SSH完成
修改完之后可以测试一下。

1
ssh -T git@github.com   #github.com 对应Host

部署到github

到github新建一个项目,项目名为:你的用户名.github.io必须为这个名字

配置文件_config.yml

1
2
3
4
5
deploy:
type: git
repository: git@github.com:你的帐号/你的帐号.github.com.git
例如我的:repository: git@github.com:gaojianqi6/gaojianqi6.github.io.git
branch: master

之前有的教程deploy的type是github,这里需要改成git,然后运行下

1
npm install hexo-deployer-git --save

然后执行命令:

1
2
3
hexo clean
hexo generate
hexo deploy

命令缩写

1
2
3
hexo n #写文章
hexo g #生成
hexo d #部署 # 可与hexo g合并为 hexo d -g

在source文件夹里面添加CNAME文件,里面填写自己的独立域名。
有的使用Hexo和Github部署好之后但是一直404,有可能就是没有在根目录下面添加CNAME文件。

PS:以后的404页面,favicon.ico也是直接在source下面添加

将独立域名与 GitHub Pages 的空间绑定

选择ping命令之后出现的地址,在您自己的域名管理里面更改一下域名解析,这个可能需要几分钟之后才能生效。

1
$ ping username.github.io

选择Hexo主题

Hexo有很多可以选择的主题,可以在下面的链接中选择自己喜欢的主题:
有哪些好看的 Hexo 主题?
Hexo themes

我选择了Next主题,在这里查看怎么安装Next -> 安装Next

目录介绍

默认目录结构:

.
├── .deploy
├── public
├── scaffolds
├── scripts
├── source
|   ├── _drafts
|   └── _posts
├── themes
├── _config.yml
└── package.json

.deploy:执行hexo deploy命令部署到GitHub上的内容目录
public:执行hexo generate命令,输出的静态网页内容目录
scaffolds:layout模板文件目录,其中的md文件可以添加编辑
scripts:扩展脚本目录,这里可以自定义一些javascript脚本
source:文章源码目录,该目录下的markdown和html文件均会被hexo处理。该页面对应repo的根目录,404文件、favicon.ico文件,CNAME文件等都应该放这里,该目录下可新建页面目录。
_drafts:草稿文章
_posts:发布文章
themes:主题文件目录
_config.yml:全局配置文件,大多数的设置都在这里
package.json:应用程序数据,指明hexo的版本等信息,类似于一般软件中的 关于 按钮

404页面

有很多用作公益的404接入地址,我选择了腾讯的。404页面,每个人可以做的更多一点。
腾讯公益404
404公益_益云(公益互联网)社会创新中心
失蹤兒童少年資料管理中心404
在source目录下添加新建404.html,然后复制内容:

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>宝贝,公益404带你们回家</title>
</head>
<body>
<script type="text/javascript" src="http://www.qq.com/404/search_children.js" charset="utf-8" homePageUrl="http://yoursitename.com" homePageName="回到我的主页"></script>
</body>
</html>

评论插件

流行的评论插件有: 多说、友言、Disqus等
安装多说主题又是Next的,可以在这里查看。

图床

考虑到博客的速度,同时也为了便于博客的迁移,图床是必须的。可以看一下七牛,访问速度极快,支持日志、防盗链和水印。
也还可以考虑下面的图床服务 FarBox , Dropbox , 又拍云 。

Jerome Gao

Jerome Gao

博客, jerome, github, react.js

8 日志
3 分类
11 标签
© 2019 Jerome Gao
由 Hexo 强力驱动
主题 - NexT.Pisces