git文章
@ -19,7 +19,7 @@ timezone:
|
|||||||
## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
|
## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
|
||||||
url: https://www.colorfulsweet.site
|
url: https://www.colorfulsweet.site
|
||||||
root: /
|
root: /
|
||||||
permalink: :year/:month/:day/:title/
|
permalink: :title/
|
||||||
permalink_defaults:
|
permalink_defaults:
|
||||||
|
|
||||||
# Directory
|
# Directory
|
||||||
|
|||||||
80
source/_posts/JavaScript/函数形参与arguments.md
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
---
|
||||||
|
title: 函数形参与arguments
|
||||||
|
date: 2018-4-14 00:28:25
|
||||||
|
tags:
|
||||||
|
- JavaScript
|
||||||
|
- 函数
|
||||||
|
categories:
|
||||||
|
- JavaScript
|
||||||
|
---
|
||||||
|
|
||||||
|
在之前我们知道 , 在JS当中函数的形参与调用时传入的实参并不需要必须对应
|
||||||
|
在函数的内部有一个对象`arguments` , 这是一个类数组 , 其中包含调用时传入的实参
|
||||||
|
当然函数在调用的时候 , 会按照形参的位置给形参赋值
|
||||||
|
<!-- more -->
|
||||||
|
但是如果我们在函数内部对形参进行赋值 , 或者对arguments当中的元素进行赋值 , 会出现怎样的情况呢
|
||||||
|
|
||||||
|
这在一般模式和严格模式下会有不同的行为
|
||||||
|
### 一般模式
|
||||||
|
调用时对于没有对应到实参的形参进行赋值
|
||||||
|
```javascript
|
||||||
|
function func1(arg0, arg1) {
|
||||||
|
arg1 = 10;
|
||||||
|
console.log(arg1, arguments[1]);
|
||||||
|
}
|
||||||
|
func1(19);// 10 undefined
|
||||||
|
|
||||||
|
function func2(arg0, arg1) {
|
||||||
|
arguments[1] = 10;
|
||||||
|
console.log(arg1, arguments[1]);
|
||||||
|
}
|
||||||
|
func2(21);// undefined 10
|
||||||
|
```
|
||||||
|
上面两个函数都有两个形参 , 实际调用时传入了一个实参 , **arg1**是没有与实参对应的
|
||||||
|
这时候对形参赋值 , 或者对arguments当中对应的元素赋值 , 各自的行为都是**独立**的 , 彼此不会产生影响
|
||||||
|
|
||||||
|
形参与实参有对应的情况
|
||||||
|
```javascript
|
||||||
|
function func1(arg0) {
|
||||||
|
arg0 = 10;
|
||||||
|
console.log(arg0, arguments[0]);
|
||||||
|
}
|
||||||
|
func1(19);// 10 10
|
||||||
|
|
||||||
|
function func2(arg0) {
|
||||||
|
arguments[0] = 10;
|
||||||
|
console.log(arg0, arguments[0]);
|
||||||
|
}
|
||||||
|
func2(21);// 10 10
|
||||||
|
```
|
||||||
|
可以看到 , 在这种情况下 , 形参与arguments当中的元素是双向绑定的 , 修改一个会自动影响另一个
|
||||||
|
|
||||||
|
### 严格模式
|
||||||
|
在严格模式下同样执行与上面类似的代码
|
||||||
|
```javascript
|
||||||
|
"use strict";
|
||||||
|
function func1(arg0) {
|
||||||
|
arg0 = 10;
|
||||||
|
console.log(arg0, arguments[0]);
|
||||||
|
}
|
||||||
|
func1(19);// 10 19
|
||||||
|
|
||||||
|
function func2(arg0) {
|
||||||
|
arguments[0] = 10;
|
||||||
|
console.log(arg0, arguments[0]);
|
||||||
|
}
|
||||||
|
func2(21);// 21 10
|
||||||
|
|
||||||
|
function func3(arg0) {
|
||||||
|
arguments[0] = 10;
|
||||||
|
console.log(arg0, arguments[0]);
|
||||||
|
}
|
||||||
|
func3();// undefined 10
|
||||||
|
|
||||||
|
function func4(arg0) {
|
||||||
|
arg0 = 10;
|
||||||
|
console.log(arg0, arguments[0]);
|
||||||
|
}
|
||||||
|
func4();// 10 undefined
|
||||||
|
```
|
||||||
|
可见严格模式之下 , 无论是哪种情况 , arguments与形参都是独立的 , 不会进行绑定 , 之间互不影响
|
||||||
114
source/_posts/JavaScript/变量的定义提升.md
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
---
|
||||||
|
title: 变量的定义提升
|
||||||
|
date: 2018-4-14 00:30:18
|
||||||
|
tags:
|
||||||
|
- JavaScript
|
||||||
|
- 函数
|
||||||
|
categories:
|
||||||
|
- JavaScript
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
从一道笔试题说起
|
||||||
|
```javascript
|
||||||
|
function Foo() {
|
||||||
|
getName = function () { console.log (1); };
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
Foo.getName = function () { console.log (2);};
|
||||||
|
Foo.prototype.getName = function () { console.log (3);};
|
||||||
|
var getName = function () { console.log (4);};
|
||||||
|
function getName() { console.log (5);}
|
||||||
|
|
||||||
|
//请写出以下输出结果:
|
||||||
|
Foo.getName();
|
||||||
|
getName();
|
||||||
|
Foo().getName();
|
||||||
|
getName();
|
||||||
|
new Foo.getName();
|
||||||
|
new Foo().getName();
|
||||||
|
new new Foo().getName();
|
||||||
|
```
|
||||||
|
<!-- more -->
|
||||||
|
#### 第一问
|
||||||
|
Foo是一个函数对象 , `Foo.getName = … `在其中定义了一个名为getName的属性 , 也是一个函数
|
||||||
|
所以第一问当中的调用输出的应该是2
|
||||||
|
|
||||||
|
#### 第二问
|
||||||
|
这里涉及到了变量的定义提升问题 , 如果不了解容易误认为答案是5
|
||||||
|
例如如下语句
|
||||||
|
```javascript
|
||||||
|
console.log("x" in window);
|
||||||
|
var x;
|
||||||
|
```
|
||||||
|
虽然变量的定义是在第二个语句 , 但是输出的结果仍然是true
|
||||||
|
因为代码执行时 JS引擎会把变量的声明语句提升到最上方
|
||||||
|
但是提升的仅仅是变量声明 , 如果声明变量的时候包含初始化
|
||||||
|
则会将初始化作为单纯的一条赋值语句保留在原处
|
||||||
|
例如
|
||||||
|
```javascript
|
||||||
|
console.log("x" in window);
|
||||||
|
var x = 10;
|
||||||
|
```
|
||||||
|
在JS引擎处理之后会改变为
|
||||||
|
```javascript
|
||||||
|
var x;
|
||||||
|
console.log("x" in window);
|
||||||
|
x = 10;
|
||||||
|
```
|
||||||
|
> 补充说明 : 只有显式的变量定义才会被提升
|
||||||
|
> 隐式的变量定义并不会
|
||||||
|
> 比如
|
||||||
|
```
|
||||||
|
console.log("x" in window);//false
|
||||||
|
x = 10;
|
||||||
|
```
|
||||||
|
> 输出就是false , 因为x未定义
|
||||||
|
|
||||||
|
全局函数的定义与全局变量的定义本质是一样的
|
||||||
|
所以它也会被提升到顶部
|
||||||
|
但是 `var x = function(){}`与`function x(){}`两种定义方式最终效果相同
|
||||||
|
执行过程却是不同的
|
||||||
|
```javascript
|
||||||
|
console.log(x);//function x(){}
|
||||||
|
function x(){}
|
||||||
|
console.log(x);//function x(){}
|
||||||
|
```
|
||||||
|
或者
|
||||||
|
```javascript
|
||||||
|
console.log(x);//undefined
|
||||||
|
var x = function(){}
|
||||||
|
console.log(x);//function x(){}
|
||||||
|
```
|
||||||
|
那么具体到这个题目
|
||||||
|
代码
|
||||||
|
```javascript
|
||||||
|
var getName = function () { console.log (4);};
|
||||||
|
function getName() { console.log (5);}
|
||||||
|
```
|
||||||
|
会被JS引擎在解析时修改为
|
||||||
|
```javascript
|
||||||
|
var getName;
|
||||||
|
function getName() { console.log (5);}
|
||||||
|
getName = function () { console.log (4);};
|
||||||
|
```
|
||||||
|
显然 , 第三行的赋值会将第二行的定义覆盖掉
|
||||||
|
最终这个全局的getName函数输出的值是4
|
||||||
|
|
||||||
|
#### 第三问
|
||||||
|
Foo() 是在全局的基础上调用的 , 也就是由window对象调用的
|
||||||
|
所以return this返回的是window对象
|
||||||
|
但是在这个函数的内部 , 修改了全局的getName的值
|
||||||
|
现在名为getName的全局函数输出是1了
|
||||||
|
所以再调用window.getName() 的输出当然是1
|
||||||
|
|
||||||
|
#### 第四问
|
||||||
|
同样是调用全局的getName函数 , 所以结果和第三问一样 , 也是1
|
||||||
|
|
||||||
|
#### 第五问
|
||||||
|
成员访问的点号( . )优先级高于 new , 所以结果与第一问相同 , 也是2
|
||||||
|
|
||||||
|
#### 第六问
|
||||||
|
括号运算符的优先级高于点号( . )
|
||||||
|
实际执行为 `( new Foo( ) ).getName()`
|
||||||
|
所以调用的是原型对象上的getName函数 , 输出是3
|
||||||
87
source/_posts/JavaScript/实现bind方法.md
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
---
|
||||||
|
title: 实现bind方法
|
||||||
|
date: 2018-4-14 00:35:19
|
||||||
|
tags:
|
||||||
|
- JavaScript
|
||||||
|
- prototype
|
||||||
|
categories:
|
||||||
|
- JavaScript
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
bind方法来自于`Function.prototype`
|
||||||
|
这个方法会创建一个新函数 , 当这个函数被调用时 , 第一个参数将会作为它运行时的this , 之后的参数会作为实际调用时传递的实参前作为实参
|
||||||
|
<!-- more -->
|
||||||
|
语法
|
||||||
|
<pre>
|
||||||
|
func.bind(thisArg [,arg1[,arg2[, ...]]])
|
||||||
|
</pre>
|
||||||
|
**应用示例 :**
|
||||||
|
```javascript
|
||||||
|
var obj = {
|
||||||
|
name : "Sookie",
|
||||||
|
show : function() {
|
||||||
|
console.log(this.name);
|
||||||
|
console.log(arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var _show = obj.show.bind(obj,"aa","bb");
|
||||||
|
_show("cc");
|
||||||
|
/*output:
|
||||||
|
Sookie
|
||||||
|
{ '0': 'aa', '1': 'bb', '2': 'cc' }
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
如果要实现一个bind方法 , 需要用到柯里化
|
||||||
|
```javascript
|
||||||
|
Function.prototype.bind = function(context) {
|
||||||
|
var me = this;//调用bind的函数对象
|
||||||
|
var args = Array.prototype.slice.call(arguments, 1);//传入的固定实参
|
||||||
|
return function () {
|
||||||
|
//实际调用时传入的参数
|
||||||
|
var innerArgs = Array.prototype.slice.call(arguments);
|
||||||
|
//合并两个参数数组
|
||||||
|
var finalArgs = args.concat(innerArgs);
|
||||||
|
//调用该函数
|
||||||
|
return me.apply(context, finalArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
这里解释一下 , arguments并不是数组对象 , 而是**类数组**
|
||||||
|
+ 具有 : 指向对象元素的数字索引 , 以及length属性
|
||||||
|
+ 不具有 : push , slice等数组对象的方法
|
||||||
|
|
||||||
|
> 数组对象的\_\_proto\_\_是Array
|
||||||
|
而arguments的 \_\_proto\_\_是Object
|
||||||
|
|
||||||
|
如果要把一个arguments转化为一个数组对象 , 可以使用如下方式
|
||||||
|
<pre>
|
||||||
|
var args = Array.prototype.slice.call(arguments);
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
#### 嗅探
|
||||||
|
在运行时如果对标准库当中的内容有修改
|
||||||
|
( 可能是出于兼容性的需要 , 比如旧版本的标准库当中无此函数 )
|
||||||
|
```javascript
|
||||||
|
Function.prototype.bind = Function.prototype.bind || function(context) {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
这属于一个加分项
|
||||||
|
由于标准库当中的函数多是经过了深度优化的
|
||||||
|
一般要比我们自己写的函数效率更高 更健壮
|
||||||
|
所以如果标准库中存在 , 其实没有必要用我们自己写的方法去替换
|
||||||
|
这里就是进行`嗅探`
|
||||||
|
> 这是一个典型的 `Monkey patch(猴子补丁)`
|
||||||
|
> 主要有以下几个用处
|
||||||
|
> + 在运行时替换方法 属性等
|
||||||
|
> + 在不修改第三方代码的情况下增加原来不支持的功能
|
||||||
|
> + 在运行时为内存中的对象增加patch而不是在磁盘的源代码中增加
|
||||||
|
|
||||||
|
#### 更严谨的做法
|
||||||
|
由于需要调用bind方法的一定是一个函数 , 所以有必要在bind的内部做一个校验
|
||||||
|
```javascript
|
||||||
|
if(typeof this !== "function") {
|
||||||
|
throw new TypeError("what is trying to be bound is not callable");
|
||||||
|
}
|
||||||
|
```
|
||||||
86
source/_posts/JavaScript/实现call方法.md
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
---
|
||||||
|
title: 实现call方法
|
||||||
|
date: 2018-4-14 00:56:44
|
||||||
|
tags:
|
||||||
|
- JavaScript
|
||||||
|
- prototype
|
||||||
|
categories:
|
||||||
|
- JavaScript
|
||||||
|
---
|
||||||
|
|
||||||
|
> call方法在使用一个指定的this值和若干个指定参数值的前提下调用某个函数
|
||||||
|
<!-- more -->
|
||||||
|
常规调用方式
|
||||||
|
```javascript
|
||||||
|
var obj = {
|
||||||
|
name : "Sookie",
|
||||||
|
func : function(msg) {
|
||||||
|
console.log(this.name + " : " + msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var fn1 = obj.func;
|
||||||
|
fn1.call(obj, "Hello");
|
||||||
|
```
|
||||||
|
|
||||||
|
现在如果要尝试实现一个call方法
|
||||||
|
|
||||||
|
#### 雏形
|
||||||
|
```javascript
|
||||||
|
Function.prototype.call2 = function(context) {
|
||||||
|
context.fn = this;
|
||||||
|
context.fn();
|
||||||
|
delete context.fn;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
初步实现了不传参情况下的函数调用
|
||||||
|
但是还有不少缺陷
|
||||||
|
|
||||||
|
#### 对参数的处理
|
||||||
|
|
||||||
|
由于需要处理实际参数 , 而且实际参数的数量又是不确定的
|
||||||
|
所以我们可以考虑使用`eval`来执行这个函数
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
Function.prototype.call2 = function(context) {
|
||||||
|
context.fn = this;
|
||||||
|
var args = [];
|
||||||
|
for(let i=1 ; i<arguments.length ; i++) {
|
||||||
|
args.push("arguments[" + i + "]");
|
||||||
|
}
|
||||||
|
eval("context.fn(" + args + ")");
|
||||||
|
delete context.fn;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
比如实际调用函数的时候需要传入2个参数 , 包括前面的context , 所以arguments当中就有3个元素
|
||||||
|
|
||||||
|
那么就相当于执行
|
||||||
|
context.fn(arguments[1], arguments[2])
|
||||||
|
|
||||||
|
#### 返回值与完善
|
||||||
|
|
||||||
|
还需要处理函数的返回值
|
||||||
|
另外 , 在我们的call方法当中 , 对上下文对象添加了fn属性 , 最后又删除了它
|
||||||
|
如果这个对象上原本就有这个属性 , 那么就对这个对象产生了破坏
|
||||||
|
可以预先把这个对象保存下来
|
||||||
|
```javascript
|
||||||
|
Function.prototype.call2 = function(context) {
|
||||||
|
var _fn = null;
|
||||||
|
var flag = false;
|
||||||
|
if("fn" in context) {
|
||||||
|
_fn = context.fn;
|
||||||
|
}
|
||||||
|
_fn = context.fn;
|
||||||
|
context.fn = this;
|
||||||
|
var args = [];
|
||||||
|
for(let i=1 ; i<arguments.length ; i++) {
|
||||||
|
args.push("arguments[" + i + "]");
|
||||||
|
}
|
||||||
|
var result = eval("context.fn(" + args + ")");
|
||||||
|
if(flag) {
|
||||||
|
context.fn = _fn;
|
||||||
|
} else {
|
||||||
|
delete context.fn;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
```
|
||||||
69
source/_posts/git/Git(1) - 初见.md
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
---
|
||||||
|
title: Git(1) - 初见
|
||||||
|
date: 2018-4-18 02:35:13
|
||||||
|
tags:
|
||||||
|
- git
|
||||||
|
- 版本控制
|
||||||
|
categories:
|
||||||
|
- Git
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
Git是分布式版本控制系统,与SVN类似的集中化版本控制系统相比,集中化版本控制系统虽然能够令多个团队成员一起协作开发,但有时如果中央服务器宕机的话,谁也无法在宕机期间提交更新和协同开发。甚至有时,中央服务器磁盘故障,恰巧又没有做备份或备份没及时,那就可能有丢失数据的风险。
|
||||||
|
<!-- more -->
|
||||||
|
但Git是分布式的版本控制系统,客户端不只是提取最新版本的快照,而且将整个代码仓库镜像复制下来。如果任何协同工作用的服务器发生故障了,也可以用任何一个代码仓库来恢复。而且在协作服务器宕机期间,你也可以提交代码到本地仓库,当协作服务器正常工作后,你再将本地仓库同步到远程仓库。
|
||||||
|
|
||||||
|
#### Git的优势
|
||||||
|
+ 能够对文本版本控制和多人协作开发
|
||||||
|
+ 拥有强大的分支特性 , 所以能够灵活地以不同的工作流协同开发
|
||||||
|
+ 分布式版本控制系统 , 即使无网络的情况下也能提交代码到本地仓库 , 有网络时再同步到远程仓库
|
||||||
|
+ 当团队中某个成员完成某个功能时 , 通过pull request操作来通知其他团队成员 , 其他成员可以进行review code后再合并代码
|
||||||
|
|
||||||
|
#### Git的特性
|
||||||
|
+ 版本库当中的文件有3种状态 , 分别是`已提交(committed)` , `已修改(modified)` , `已暂存(staged)`
|
||||||
|
+ 直接记录快照 , 而非差异比较
|
||||||
|
+ 多数操作仅添加数据
|
||||||
|
+ 几乎所有的操作都是在本地执行
|
||||||
|
+ 时刻保持数据的完整性
|
||||||
|
|
||||||
|
### 准备工作
|
||||||
|
#### config
|
||||||
|
Git自带一个`git config`工具来帮主设置git的相关配置
|
||||||
|
```bash
|
||||||
|
#查看操作系统中所有用户的通用配置
|
||||||
|
git config --system --list
|
||||||
|
|
||||||
|
#查看当前用户的配置
|
||||||
|
git config --global --list
|
||||||
|
```
|
||||||
|
如果是当前仓库中 , 则在.git/config 中的配置是只针对该仓库的 , 每个级别的配置会覆盖上一个级别的配置
|
||||||
|
```bash
|
||||||
|
#可以单独查看某一项配置信息
|
||||||
|
#如果没有指定级别,则表示查看最终生效的配置信息
|
||||||
|
git config user.name
|
||||||
|
|
||||||
|
#或者指定某个级别的某个属性
|
||||||
|
git config --global user.name
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 设置用户信息
|
||||||
|
```bash
|
||||||
|
git config --global user.name "NewName"
|
||||||
|
#如果不加global则表示只修改当前库当中的配置信息
|
||||||
|
```
|
||||||
|
#### .gitignore
|
||||||
|
每个库中都可以存在一个该文件
|
||||||
|
用来配置不需要git进行追踪的文件 , 比如日志 , 编译的临时文件等
|
||||||
|
内容规范如下
|
||||||
|
+ `#`开头表示注释
|
||||||
|
+ 可以使用标准的glob模式匹配
|
||||||
|
+ 匹配模式以`/`开头防止递归
|
||||||
|
+ 匹配模式以`/`结尾指定目录
|
||||||
|
+ 要忽略指定模式以外的文件或目录 , 可以在模式前加上`!`表示取反
|
||||||
|
|
||||||
|
glob模式是一种简化的正则表达式
|
||||||
|
+ `*` 匹配零个或多个任意字符
|
||||||
|
+ `[abc]` 只包含括号内的任意一个字符
|
||||||
|
+ `[0-9]` 横线表示范围
|
||||||
|
+ `?` 匹配任意一个字符
|
||||||
|
+ `**` 匹配任意的目录结构
|
||||||
144
source/_posts/git/Git(2) - 基础操作.md
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
---
|
||||||
|
title: Git(2) - 基础操作
|
||||||
|
date: 2018-4-18 08:22:13
|
||||||
|
tags:
|
||||||
|
- git
|
||||||
|
- 版本控制
|
||||||
|
categories:
|
||||||
|
- Git
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### 版本库的基础操作
|
||||||
|
|
||||||
|
版本库也可以称为`仓库`, 也就是一个目录 , 这个目录里面的所有文件都被Git管理起来 , 每个文件的修改 删除等 , Git都能追踪
|
||||||
|
<!-- more -->
|
||||||
|
#### 创建版本库
|
||||||
|
```bash
|
||||||
|
#定位到需要创建仓库的目录下执行
|
||||||
|
git init
|
||||||
|
```
|
||||||
|
执行以后就把这个目录变为git可以管理的仓库
|
||||||
|
该目录下就会多了一个**.git**目录 , 这个目录是git用来追踪管理版本的 , 勿手动修改
|
||||||
|
|
||||||
|
#### 添加文件到版本库
|
||||||
|
```bash
|
||||||
|
#添加全部暂存区和历史区不存在的或者有更改的.c文件
|
||||||
|
git add *.c
|
||||||
|
|
||||||
|
#添加全部暂存区和历史区不存在或者有更改的文件
|
||||||
|
git add .
|
||||||
|
|
||||||
|
#添加指定文件到版本库
|
||||||
|
git add test.c
|
||||||
|
```
|
||||||
|
使用`git status`可以查看当前版本库的状态
|
||||||
|
例如
|
||||||
|

|
||||||
|
这个版本库当中有01.txt是已经添加到版本库但是没有提交的新文件 ( 该文件当前的状态就是`staged - 已暂存` )
|
||||||
|
使用`git rm --cached 01.txt`可以从暂存库当中移除01.txt , 相当于是add的逆操作
|
||||||
|
02.txt是没有添加到版本库的文件
|
||||||
|
|
||||||
|
#### 提交文件
|
||||||
|
提交操作针对的是暂存区当中的文件 ( 或者说是已暂存状态的文件 )
|
||||||
|
```bash
|
||||||
|
#提交暂存区所有的内容到版本库
|
||||||
|
git commit -a
|
||||||
|
|
||||||
|
#提交暂存区中指定的文件到版本库
|
||||||
|
git commit 01.txt
|
||||||
|
```
|
||||||
|
> 提交时可以直接使用-m参数来添加提交的注释
|
||||||
|
> 例如 `git commit -a -m "我是注释"`
|
||||||
|
> 如果未添加 , 提交时则会自动调用vi编辑器来编辑提交注释信息
|
||||||
|
> 也可以修改core.edit来设定喜欢的编辑器
|
||||||
|
|
||||||
|
如果提交01.txt完毕以后 , 再次修改了01.txt
|
||||||
|

|
||||||
|
此时该文件的状态就是`modified - 已修改`
|
||||||
|
使用`git add`可以将其添加到暂存区
|
||||||
|
|
||||||
|
#### 比较差异
|
||||||
|
`git diff`命令用于比较指定文件的差异
|
||||||
|
```bash
|
||||||
|
#查看所有有变动的文件
|
||||||
|
git diff
|
||||||
|
|
||||||
|
#查看指定文件的变动
|
||||||
|
git diff 01.txt
|
||||||
|
|
||||||
|
#查看暂存区中文件的变动
|
||||||
|
git diff --staged
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
#### 查看提交历史记录
|
||||||
|
|
||||||
|
使用`git log`可以按照提交时间列出所有的提交
|
||||||
|
```bash
|
||||||
|
#仅显示最近x次的提交 git log -x
|
||||||
|
git log -2 #查看最近2次的提交
|
||||||
|
|
||||||
|
#简略显示每次提交的内容变动
|
||||||
|
git log --stat
|
||||||
|
|
||||||
|
# --pretty对展示内容进行格式化
|
||||||
|
git log --pretty=oneline #在一行内仅显示每次提交的hash码与注释
|
||||||
|
|
||||||
|
#自定义格式化
|
||||||
|
git log --pretty=format:"%h - %an,%ar : %s"
|
||||||
|
```
|
||||||
|
format当中的占位符含义
|
||||||
|
|
||||||
|
| 选项 | 说明 |
|
||||||
|
|----|-----|
|
||||||
|
|%H|提交对象(commit)的完整哈希字串|
|
||||||
|
|%h|提交对象的简短哈希字串|
|
||||||
|
|%T|树对象(tree)的完整哈希字串|
|
||||||
|
|%t|树对象的简短哈希字串|
|
||||||
|
|%P|父对象(parent)的完整哈希字串|
|
||||||
|
|%p|父对象的简短哈希字串|
|
||||||
|
|%an|作者(author)的名字|
|
||||||
|
|%ae|作者的电子邮件地址|
|
||||||
|
|%ad|作者修订日期(可以用 –date= 选项定制格式)|
|
||||||
|
|%ar|作者修订日期,按多久以前的方式显示|
|
||||||
|
|%cn|提交者(committer)的名字|
|
||||||
|
|%ce|提交者的电子邮件地址|
|
||||||
|
|%cd|提交日期|
|
||||||
|
|%cr|提交日期,按多久以前的方式显示|
|
||||||
|
|%s|提交说明|
|
||||||
|
|
||||||
|
#### 撤销操作
|
||||||
|
##### 重新提交
|
||||||
|
如果执行`git commit`之后发现了漏掉了一个文件 , 再进行一次提交又显得多余
|
||||||
|
这时候可以使用**amend**进行重新提交
|
||||||
|
```bash
|
||||||
|
git commit --amend
|
||||||
|
```
|
||||||
|
##### 取消暂存
|
||||||
|
执行了git add 之后 , 如果要进行撤销
|
||||||
|
( 与git rm作用类似 )
|
||||||
|
```bash
|
||||||
|
git reset HEAD 03.txt
|
||||||
|
```
|
||||||
|
但是reset还可以对已提交的内容进行版本的回退
|
||||||
|
```bash
|
||||||
|
#回退当上一个版本
|
||||||
|
git reset --hard HEAD^
|
||||||
|
```
|
||||||
|
> 如果要回退当上上个版本就是HEAD^^
|
||||||
|
也可以使用简便写法`git reset --hard HEAD~100`表示回退到100个版本之前
|
||||||
|
|
||||||
|
此时执行了回退 , 我们发现最后一次提交所做的修改已经没有了
|
||||||
|
如果还想找回来 , 可以执行`git reflog`来查看操作记录 , 找到最后一次提交的版本号
|
||||||
|

|
||||||
|
执行以后发现是8725f93
|
||||||
|
于是执行`git reset --hard 8725F93`
|
||||||
|
即可再次恢复到最新版本
|
||||||
|
|
||||||
|
##### 撤销修改
|
||||||
|
当文件被修改 , 但还没有git add到暂存区 ( 或者从暂存区当中撤销回到工作区也一样 )
|
||||||
|
```bash
|
||||||
|
git checkout -- filename
|
||||||
|
```
|
||||||
|
> 注意 : 该操作会导致修改彻底丢失 , 无法恢复
|
||||||
54
source/_posts/git/Git(3) - 分支.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
title: Git(2) - 基础操作
|
||||||
|
date: 2018-4-18 09:20:13
|
||||||
|
tags:
|
||||||
|
- git
|
||||||
|
- 版本控制
|
||||||
|
categories:
|
||||||
|
- Git
|
||||||
|
---
|
||||||
|
|
||||||
|
### 分支操作
|
||||||
|
在git当中 , 对于每次提交 , git都把他们串成一条时间线
|
||||||
|
这条时间线就是一个分支 , 默认只有master这一条主分支
|
||||||
|
HEAD相当于是一个指针 , 指向的是当前操作的分支
|
||||||
|
<!-- more -->
|
||||||
|
```bash
|
||||||
|
#创建分支dev
|
||||||
|
git branch dev
|
||||||
|
|
||||||
|
#切换到分支dev
|
||||||
|
git checkout dev
|
||||||
|
|
||||||
|
git checkout -b dev #相当于同时执行上面两条命令
|
||||||
|
#创建并切换到该分支
|
||||||
|
|
||||||
|
#查看分支
|
||||||
|
git branch
|
||||||
|
|
||||||
|
#合并分支dev到当前分支
|
||||||
|
git merge dev
|
||||||
|
|
||||||
|
#删除分支dev
|
||||||
|
git branch -d dev
|
||||||
|
```
|
||||||
|
通常在参与一个多人开发的项目时 , 需要创建一个分支进行开发 , 完成后把这个分支合并到主分支
|
||||||
|

|
||||||
|
这里代表合并成功
|
||||||
|
|
||||||
|
#### 解决冲突
|
||||||
|
如果不同的分支当中对同一个文件进行了修改 , 那么就会产生冲突 , 导致无法直接合并
|
||||||
|

|
||||||
|
这里提示的信息是03.txt文件在合并时产生了冲突
|
||||||
|
查看03.txt文件可以发现
|
||||||
|

|
||||||
|
|
||||||
|
这时候就需要手动去解决冲突
|
||||||
|
修改03.txt文件之后
|
||||||
|
在master分支当中执行 ( 此时因为处于处理分支合并冲突的过程当中 , 所以并不能切换分支 )
|
||||||
|
```bash
|
||||||
|
git add 03.txt
|
||||||
|
git commit -a -m "resolve conflict 03"
|
||||||
|
```
|
||||||
|
此时 , 这次的分支合并才算完成
|
||||||
|
子分支当中的修改内容并没有受到影响
|
||||||
56
source/_posts/git/Git(4) - 远程仓库.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
title: Git(4) - 远程仓库
|
||||||
|
date: 2018-4-19 00:20:13
|
||||||
|
tags:
|
||||||
|
- git
|
||||||
|
- 版本控制
|
||||||
|
categories:
|
||||||
|
- Git
|
||||||
|
---
|
||||||
|
|
||||||
|
在多人的协作开发当中 , 我们需要一个公共的远程库 , 每个人都可以从远程库把项目clone到自己的电脑上进行开发 , 之后把自己编写的代码推送到远程库
|
||||||
|
完全可以自己搭建一台运行的Git服务器 , 或者利用GitHub这种公共的Git托管服务
|
||||||
|
<!-- more -->
|
||||||
|
这里用[GitLab](https://gitlab.com/)来进行测试
|
||||||
|
|
||||||
|
#### 创建SSH key
|
||||||
|
由于本地和远程仓库之间的传输是通过SSH加密的 ( 这个取决于Git托管服务本身的架构 , 如果不是的话可以跳过这个步骤 )
|
||||||
|
```bash
|
||||||
|
ssh-keygen -t rsa -C "email地址"
|
||||||
|
```
|
||||||
|
执行完成后在本地的用户主目录里面找到`.ssh`目录 , 里面有`id_rsa`和 `id_rsa.public`
|
||||||
|
前一个是密钥 , 后一个是公钥
|
||||||
|
把公钥的内容添加到自己账号的SSH keys的设置当中
|
||||||
|

|
||||||
|
Title是自己看的 随便写即可
|
||||||
|
|
||||||
|
#### 添加远程库
|
||||||
|
在GitLab上创建一个名为git_learn的远程库
|
||||||
|
我的账号对应的SSH链接就是`git@gitlab.com:sookie/git_learn.git`
|
||||||
|
在本地的git仓库里面执行
|
||||||
|
```bash
|
||||||
|
#添加远程库
|
||||||
|
git remote add origin git@gitlab.com:sookie/git_learn.git
|
||||||
|
```
|
||||||
|
origin是本地仓库中给这个远程库起的名字
|
||||||
|
一个本地仓库可以对应多个远程库
|
||||||
|
|
||||||
|
然后就可以把本地库的所有内容推送到远程库上
|
||||||
|
```bash
|
||||||
|
#把master分支推送到名为origin的远程库
|
||||||
|
git push -u origin master
|
||||||
|
```
|
||||||
|
第一次推送的时候需要加`-u`参数
|
||||||
|
之后只需要执行`git push origin master`即可
|
||||||
|
|
||||||
|
#### 克隆远程库
|
||||||
|
如果需要从一个远程库克隆出一个本地库
|
||||||
|
需要使用
|
||||||
|
```bash
|
||||||
|
git clone git@gitlab.com:sookie/git_learn.git
|
||||||
|
```
|
||||||
|
如果有多个人协作开发,那么每个人各自从远程克隆一份就可以了。
|
||||||
|
> 对于远程库的地址 , 还有`https://gitlab.com/sookie/git_learn.git`这样的地址
|
||||||
|
> 这是由于Git支持多种协议
|
||||||
|
> 如果服务器只开放了http端口 , 那么就不能使用ssh协议而只能用https
|
||||||
|
> 原生的git协议速度比较快
|
||||||
109
source/_posts/前端杂烩/CSS中的字体.md
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
---
|
||||||
|
title: CSS中的字体
|
||||||
|
date: 2018-4-7 10:55:37
|
||||||
|
tags:
|
||||||
|
- 前端
|
||||||
|
- css
|
||||||
|
categories:
|
||||||
|
- 前端杂烩
|
||||||
|
---
|
||||||
|
|
||||||
|
在CSS当中 , 我们通常使用`@font-face`来定义字体
|
||||||
|
除了可以引入外部字体之外 , 也可以给系统本地的字体定义别名
|
||||||
|
比如
|
||||||
|
```css
|
||||||
|
@font-face {
|
||||||
|
font-family : YH;
|
||||||
|
src : local("microsoft yahei");
|
||||||
|
}
|
||||||
|
.font {
|
||||||
|
font-family:YH;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
这样我们就可以在需要使用这个字体的地方直接使用这个别名
|
||||||
|
<!-- more -->
|
||||||
|
> 通常不推荐在网页当中引入外部的中文字体包
|
||||||
|
> 因为中文字体包通常很大 , 会导致严重的加载缓慢
|
||||||
|
|
||||||
|
然而在Mac系统当中没有微软雅黑字体 , 我们希望在Mac系统上使用苹方字体 , windows系统上使用微软雅黑字体
|
||||||
|
```css
|
||||||
|
@font-face {
|
||||||
|
font-family : BASE;
|
||||||
|
src: local("PingFang SC"),
|
||||||
|
local("Microsoft Yahei");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
这样字体的应用就更加简便了
|
||||||
|
|
||||||
|
### unicode-range
|
||||||
|
这个属性可以给特定的字符指定特定的字体
|
||||||
|
通过unicode编码去指定字符
|
||||||
|
比如我们需要给一段文字当中的引号使用宋体 , 其他的文字使用微软雅黑或者苹方字体
|
||||||
|
可以这样做
|
||||||
|
```css
|
||||||
|
@font-face {
|
||||||
|
font-family: BASE;
|
||||||
|
src: local('PingFang SC'),
|
||||||
|
local('Microsoft Yahei');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: quote;
|
||||||
|
src: local('SimSun');
|
||||||
|
unicode-range: U+201c, U+201d;
|
||||||
|
/* 中文前引号与后引号对应的unicode编码 */
|
||||||
|
}
|
||||||
|
.font {
|
||||||
|
font-family: quote, BASE;
|
||||||
|
}
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
> FireFox浏览器对字体名称的大小写敏感
|
||||||
|
|
||||||
|
unicode-range的用法
|
||||||
|
```css
|
||||||
|
/* 支持的值 */
|
||||||
|
unicode-range: U+26; /* 单个字符编码 */
|
||||||
|
unicode-range: U+0-7F;
|
||||||
|
unicode-range: U+0025-00FF; /* 字符编码区间 */
|
||||||
|
unicode-range: U+4??; /* 通配符区间 */
|
||||||
|
unicode-range: U+0025-00FF, U+4??; /* 多个值 */
|
||||||
|
```
|
||||||
|
|
||||||
|
> **前端领域的字符表示方式总结**
|
||||||
|
> 1. HTML中字符输出使用`&#x`配上charCode值
|
||||||
|
> 2. 在JavaScript文件中为防止乱码转义,则是`\u`配上charCode值
|
||||||
|
> 3. 在CSS文件中,如CSS伪元素的content属性,直接使用`\`配上charCode值
|
||||||
|
> 4. unicode-range是`U+`配上charCode值
|
||||||
|
|
||||||
|
----
|
||||||
|
### 补充 : **使用千位分隔符表示大数字**
|
||||||
|
在移动端 , 对于超过一定个数的连续数字 , 系统会默认当做电话号码来处理 , 而不是一个数字
|
||||||
|
点击这个数字的时候 , 可以触发系统的电话呼叫
|
||||||
|
|
||||||
|
如果我们想干掉这个特性 , 通常的做法是使用`<meta>`标签
|
||||||
|
```xml
|
||||||
|
<meta name="format-detection" content="telephone=no"
|
||||||
|
```
|
||||||
|
这样就意味着本来可以进行便捷呼叫的手机号码 , 变成了一串普通的数字
|
||||||
|
对于确实表示数字含义的一串数字来说 ( 不是编码或者流水号之类的内容 ) , 只是这样做也是影响体验的
|
||||||
|
它本身也不方便进行辨识
|
||||||
|
我们可以考虑将其格式化为包含千位分隔符的一个字符串
|
||||||
|
|
||||||
|
处理方式
|
||||||
|
#### 正则表达式
|
||||||
|
用法举例
|
||||||
|
```javascript
|
||||||
|
String(123456789).replace(/(\d)(?=(\d{3})+$)/g, "$1,");
|
||||||
|
```
|
||||||
|
#### 使用`toLocalString()`方法
|
||||||
|
用法举例
|
||||||
|
```javascript
|
||||||
|
(123456789).toLocaleString('en-US');
|
||||||
|
```
|
||||||
|
对于中文场景下,toLocaleString('en-US')中的'en-US'理论上是可以缺省的
|
||||||
|
但是如果产品可能海外用户使用,则保险起见,还是保留'en-US'
|
||||||
|
|
||||||
|
在这种情况下 , 如果我们想要美化这个逗号
|
||||||
|
使用JS进行筛选处理会十分繁琐
|
||||||
|
我们就可以使用`unicode-range`单独对其中的逗号进行处理
|
||||||
59
source/_posts/前端杂烩/HTML5的缓存策略.md
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
title: HTML5的缓存策略
|
||||||
|
date: 2018-4-10 13:01:24
|
||||||
|
tags:
|
||||||
|
- HTML5
|
||||||
|
categories:
|
||||||
|
- 前端杂烩
|
||||||
|
---
|
||||||
|
|
||||||
|
HTML5当中新增了两种浏览器端的缓存方式
|
||||||
|
分别是`sessionStorage`和`localStorage`
|
||||||
|
|
||||||
|
+ **sessionStorage** - 用于会话级别数据的缓存 , 这些数据只有在同一个会话中的页面才能访问 , 当会话结束后数据就会随之销毁
|
||||||
|
+ **localStorage** - 用于持久化的本地存储 , 除非主动删除数据 , 否则数据是永远不会过期的
|
||||||
|
<!-- more -->
|
||||||
|
在此之前 , 本地缓存的方式主要就是cookie
|
||||||
|
但是cookie有很多弊端 , 比如
|
||||||
|
+ 存储容量是受限的
|
||||||
|
+ 每次请求一个新的页面 , cookie都会被带过去 , 浪费了带宽
|
||||||
|
+ 无法跨域调用
|
||||||
|
+ 明文存储 , 安全性很差
|
||||||
|
|
||||||
|
当然有了web storage , 也并不能完全取代cookie , 因为cookie的作用是与服务器进行交互 , 作为HTTP规范的一部分而存在 , 而Web Storage仅仅是为了在本地存储数据而已
|
||||||
|
|
||||||
|
---
|
||||||
|
在支持web storage的浏览器当中 , `sessionStorage`和`localStorage`都是window当中的全局对象 , 可以直接使用
|
||||||
|
用法都很简单
|
||||||
|

|
||||||
|
可以直接使用继承自原型对象的这几个方法 , 添加 获取 移除 键值对 , 也可以当做普通的JS对象来使用 , 直接给对象属性赋值
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
localStorage.setItem("name","Sookie");
|
||||||
|
//或者 localStorage.name = "Sookie";
|
||||||
|
localStorage.getItem("name");
|
||||||
|
//或者 localStorage.name;
|
||||||
|
localStorage.removeItem("name");
|
||||||
|
//或者 delete localStorage.name
|
||||||
|
```
|
||||||
|
除此之外 , `key()`方法可以获取到Storage当中指定索引的键 , 与length配合可以用于遍历所有缓存的数据
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
for(let index=0 ; index<localStorage.length ; index++) {
|
||||||
|
let key = localStorage.key(index);
|
||||||
|
let value = localStorage.getItem(key);
|
||||||
|
console.log(key + " = " + value);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
####事件
|
||||||
|
浏览器提供了`storage`事件 , 用于监听**localStorage**的变化
|
||||||
|
> 需要注意的是 , 在某一个页面设置这个事件的回调函数之后 , 在本页面对localStorage进行操作 , 是不会触发这个事件的 , 在另外一个标签中打开该页面 , 才会触发这个事件
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
window.addEventListener("storage",function(e){
|
||||||
|
console.log(e);
|
||||||
|
});
|
||||||
|
```
|
||||||
|

|
||||||
130
source/_posts/前端杂烩/viewport.md
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
---
|
||||||
|
title: viewport
|
||||||
|
date: 2018-4-9 11:01:56
|
||||||
|
tags:
|
||||||
|
- 前端
|
||||||
|
categories:
|
||||||
|
- 前端杂烩
|
||||||
|
---
|
||||||
|
|
||||||
|
在移动设备上的页面开发 , 首先需要搞清楚的就是`viewport` , 这是适配和响应各种不同分辨率的移动设备的前提条件
|
||||||
|
|
||||||
|
#### 概念
|
||||||
|
通俗地讲 , 移动设备上的viewport是指设备的屏幕上能用来显示网页的那块区域
|
||||||
|
<!-- more -->
|
||||||
|
> 关于**像素(px)**
|
||||||
|
> 这是css当中常见的定义像素值的单位
|
||||||
|
> 但是这个值并不能完全等同于设备的物理像素
|
||||||
|
> 因为页面是可以被缩放的 , 如果缩放到2倍
|
||||||
|
> 那么1px在页面上就会占用2个物理像素的距离
|
||||||
|
|
||||||
|
#### 移动设备的3个viewport
|
||||||
|
##### layout viewport
|
||||||
|

|
||||||
|
它的宽度是大于浏览器可视区域的宽度的
|
||||||
|
宽度值可以通过`document.documentElement.clientWidth`来获取
|
||||||
|
还需要一个viewport来代表浏览器可视区域的大小
|
||||||
|
|
||||||
|
##### visual viewport
|
||||||
|

|
||||||
|
它的宽度可以通过`window.innerWidth`来获取
|
||||||
|
|
||||||
|
现在已经有两个viewport了 , 但是浏览器还觉得不够 , 因为越来越多的网站都会为移动设备进行单独的设计 , 所以还必须要有一个能完美适配移动设备的viewport
|
||||||
|
> 完美适配指的是 :
|
||||||
|
> 1. 不需要用户缩放和横向滚动条就能正常地查看网页的所有内容
|
||||||
|
> 2. 显示的文字大小合适 , 不会因为在高密度像素的屏幕里显示得太小而无法看清 . 当然不只是文字 , 其他元素的大小也是同样的道理
|
||||||
|
|
||||||
|
##### ideal viewport
|
||||||
|
这是移动设备的理想viewport , 它并没有一个固定的尺寸 , 不同的设备有不同的尺寸
|
||||||
|
例如所有iphone设备的ideal viewport的宽度都是320px , 无论它的屏幕宽度是320还是640
|
||||||
|
安卓设备则比较复杂 , 有很多不同的值
|
||||||
|
页面中元素大小如果根据ideal viewport来适配 , 则不会出现在像素密度太高的屏幕上 , 元素显示太小的问题了
|
||||||
|
|
||||||
|
#### 利用meta标签对viewport进行控制
|
||||||
|
移动设备默认的viewport是layout viewport , 但是在进行移动设备网站的开发时 , 我们需要的是ideal viewport
|
||||||
|
通常需要在head标签当中添加
|
||||||
|
```xml
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
||||||
|
```
|
||||||
|
属性说明 :
|
||||||
|
+ `width` - 控制viewport宽度 , 可以指定一个值 , 或者特殊的值 , **device-width**为设备的宽度
|
||||||
|
+ `height` - 与width相对应 , 指定高度 , 这个属性并不重要 , 很少使用
|
||||||
|
+ `initial-scale` - 初始缩放比例 , 比如1.0
|
||||||
|
+ `maximum-scale` - 允许用户缩放到的最大比例
|
||||||
|
+ `minimum-scale` - 允许用户缩放到的最小比例
|
||||||
|
+ `user-scalable` - 用户是否可以手动缩放 , 值为yes或者no
|
||||||
|
|
||||||
|
要得到ideal viewport只需要把width设置为**device-width**即可
|
||||||
|
需要说明的是 , 有关缩放的属性都是相对于ideal viewport进行缩放的
|
||||||
|
所以如果只写
|
||||||
|
```xml
|
||||||
|
<meta name="viewport" content="initial-scale=1" />
|
||||||
|
```
|
||||||
|
也可以达到ideal viewport的效果
|
||||||
|
|
||||||
|
---
|
||||||
|
#### 视区的相关单位
|
||||||
|
+ `vw` - 相对于视区的宽度 , 视区总的宽度为100vw
|
||||||
|
+ `vh` - 相对于视区的高度 , 视区总的高度为100vh
|
||||||
|
+ `vmin` - 相对于视区的宽度与高度当中较小的一个
|
||||||
|
+ `vmax` - 相对于视区的宽度与高度当中较大的一个
|
||||||
|
|
||||||
|
比如某种情况下视区的宽度为1000px
|
||||||
|
div的width为2vw , 那么这个div的实际显示宽度就是20px
|
||||||
|
高度同理
|
||||||
|
|
||||||
|
##### 实际应用
|
||||||
|
1. 弹性布局
|
||||||
|
|
||||||
|
实践当中 , 如果我们需要把两个元素横向并排布局
|
||||||
|
设置浮动之后 , 分别指定宽度为25%与75%
|
||||||
|
与指定宽度为 25vw和75vw
|
||||||
|
相比并没有什么优势 , 实际的作用也是一样的
|
||||||
|
|
||||||
|
在布局方面要发挥更大的作用 , 需要结合一个CSS的函数`calc`
|
||||||
|
就是calculate的缩写
|
||||||
|
这个函数的作用是**执行表达式的计算**
|
||||||
|
|
||||||
|
如果不使用这个函数 , 我们通常是需要使用一些预处理工具 , 比如sass , 才能在css当中编写表达式
|
||||||
|
让预处理工具在打包css代码的过程中完成这个计算
|
||||||
|
但是这样终究比较局限 , 因为视区的宽度高度是页面实际渲染的时候才确定的
|
||||||
|
如果涉及到视区的计算 , 则无法完成
|
||||||
|
|
||||||
|
回到最初的问题 , 按照宽度的百分比横向排列两个div
|
||||||
|
直接用百分比当然是可以的 , 但是如果这个元素有 **border margin padding**当中的任意一个 , 右边的div就会被挤到下一行
|
||||||
|
( 如果是单个元素宽度100%的话 , 盒子会被撑破 , 超出父元素的宽度 )
|
||||||
|
|
||||||
|
这时候我们就可以用calc函数配合vw来解决这个问题
|
||||||
|
```css
|
||||||
|
.left,.right {
|
||||||
|
height : 600px;
|
||||||
|
border : 3px solid black;
|
||||||
|
}
|
||||||
|
.left {
|
||||||
|
background : blue;
|
||||||
|
width : calc(25vw - 6px);
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
background : pink;
|
||||||
|
width : calc(75vw - 6px);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
> 出于兼容性的考虑 , 最好给calc加上`-webkit-`和`-moz-`的前缀
|
||||||
|
|
||||||
|
|
||||||
|
2. 弹性字体
|
||||||
|
|
||||||
|
在响应式布局中 , 字体的大小最好是能跟随视区的大小进行自动调整
|
||||||
|
才能达到比较好的体验
|
||||||
|
可以采用如下方式
|
||||||
|
```css
|
||||||
|
:root {
|
||||||
|
font-size: calc(1vw + 1vh + .5vmin);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
`:root`伪类匹配DOM文档树的根元素
|
||||||
|
|
||||||
|
> **补充说明**
|
||||||
|
> 使用视区的相关单位的值对应的属性 , 不会跟随页面的缩放变化
|
||||||
|
> 比如第二个例子当中的字号
|
||||||
|
> 在放大页面的时候 , 文字的大小是不会改变的
|
||||||
96
source/_posts/前端杂烩/响应式布局.md
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
---
|
||||||
|
title: 响应式布局
|
||||||
|
date: 2018-4-6 10:55:37
|
||||||
|
tags:
|
||||||
|
- 前端
|
||||||
|
- css
|
||||||
|
categories:
|
||||||
|
- 前端杂烩
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 媒体查询
|
||||||
|
媒体查询可以使用`@media`在css样式当中进行断点 , 让指定的css样式按照要求进行生效
|
||||||
|
```css
|
||||||
|
@media (max-width:768px) {
|
||||||
|
.box {
|
||||||
|
color : red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
上面写在媒体查询当中的css代码 , 在页面视窗宽度小于768px时生效
|
||||||
|
<!-- more -->
|
||||||
|
##### 根据媒体类型进行断点
|
||||||
|
+ all 所有设备
|
||||||
|
+ print 用于打印机和打印预览
|
||||||
|
+ screen 用于电脑屏幕 平板电脑 智能手机等
|
||||||
|
+ speech 屏幕阅读器等发声设备
|
||||||
|
|
||||||
|
##### 逻辑操作符
|
||||||
|
使用逻辑操作符可以构建复杂的媒体查询 , 有`and` , `not` , `only`等
|
||||||
|
```css
|
||||||
|
@media (min-width: 700px) and (orientation: landscape) {
|
||||||
|
/* 宽度大于700并且横屏的时候应用该效果 */
|
||||||
|
.box1 { color: red; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
只用于屏幕显示( 打印输出不生效 )
|
||||||
|
```css
|
||||||
|
@media only screen and (max-width:1150px){
|
||||||
|
div{border:solid 1px;}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 按需加载CSS
|
||||||
|
其实与上面的媒体查询作用是一样的 , 只不过在页面引入css时添加媒体查询条件
|
||||||
|
```xml
|
||||||
|
<link type="text/css" rel="stylesheet" href="base.css" media="(max-width:500px)"/>
|
||||||
|
```
|
||||||
|
浏览器在执行渲染的时候 , 实际和媒体查询是一样的 , 相当于给整个文件当中的css包装了一层媒体查询
|
||||||
|
|
||||||
|
#### REM
|
||||||
|
这是一个应用于长度的单位 , 所有可以用长度值来声明的CSS样式 , 都可以以它当做单位 , 比如width , font-size等等
|
||||||
|
|
||||||
|
这个单位代表的是相对于`html`的`font-size`的值
|
||||||
|
比如
|
||||||
|
```css
|
||||||
|
html {
|
||||||
|
font-size:100px;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
/* 为了防止元素继承html的字号,干扰全局样式,所以重置为默认 */
|
||||||
|
font-size:initial;
|
||||||
|
}
|
||||||
|
.box2 {
|
||||||
|
width : 0.5rem;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
那么box2的实际宽度就是 0.5 × 100px = 50px
|
||||||
|
基于这种机制 , 我们就可以编写页面`resize事件`的回调函数
|
||||||
|
在函数当中获取当前视窗的宽度与高度 , 去动态改变根元素(html节点)的font-size的值
|
||||||
|
从而让页面中的元素适应视窗大小的变化
|
||||||
|
( 假定设计稿给出的宽度是750px )
|
||||||
|
```javascript
|
||||||
|
(function (doc, win) {
|
||||||
|
var docEl = doc.documentElement,
|
||||||
|
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
|
||||||
|
recalc = function () {
|
||||||
|
var clientWidth = docEl.clientWidth;
|
||||||
|
if (!clientWidth) return;
|
||||||
|
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!doc.addEventListener) return;
|
||||||
|
win.addEventListener(resizeEvt, recalc, false);
|
||||||
|
doc.addEventListener('DOMContentLoaded', recalc, false);
|
||||||
|
})(document, window);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 设置viewport的width
|
||||||
|
这种方案 , 就是直接指定viewport的width大小
|
||||||
|
```xml
|
||||||
|
<meta name="viewport" content="width=750" />
|
||||||
|
```
|
||||||
|
但是使用了这种方案之后
|
||||||
|
因为已经将宽度定死了 , 所以针对宽度执行的媒体查询就会失效
|
||||||
|
存在很大的弊端
|
||||||
|
而使用REM方案是可以使用媒体查询的
|
||||||
BIN
source/images/git/git_diff.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
source/images/git/git_merge.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
source/images/git/git_modified.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
source/images/git/git_reflog.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
source/images/git/git_status.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
source/images/git/gitlab_ssh.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
source/images/git/冲突代码.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
source/images/git/分支冲突.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
source/images/前端杂烩/css_font.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
source/images/前端杂烩/localstorage.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
source/images/前端杂烩/storage_event.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
source/images/前端杂烩/viewport1.png
Normal file
|
After Width: | Height: | Size: 316 KiB |
BIN
source/images/前端杂烩/viewport2.png
Normal file
|
After Width: | Height: | Size: 315 KiB |
@ -38,7 +38,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="post-thumbnail" data-img="<%- post.photos[0] %>">
|
<div class="post-thumbnail" data-img="<%- post.photos[0] %>">
|
||||||
<a href="<%= post.permalink %>" title="<%= post.title %>">
|
<a href="<%= post.permalink %>" title="<%= post.title %>">
|
||||||
<% if (post.thumbnail) { %>
|
<%
|
||||||
|
var numSum = 0
|
||||||
|
let dateNum = parseInt(date(post.date, 'YYYYMMDDHHmmss'))
|
||||||
|
let mutipart = 10
|
||||||
|
while(dateNum % mutipart != dateNum) {
|
||||||
|
numSum += Math.floor(dateNum % mutipart / (mutipart/10))
|
||||||
|
mutipart *= 10
|
||||||
|
}
|
||||||
|
if (post.thumbnail) {
|
||||||
|
%>
|
||||||
<!--
|
<!--
|
||||||
<%- image_tag(post.thumbnail, { class: "thumbnail" }) %>
|
<%- image_tag(post.thumbnail, { class: "thumbnail" }) %>
|
||||||
-->
|
-->
|
||||||
@ -46,9 +55,9 @@
|
|||||||
<% } else if (post.photos.length) { %>
|
<% } else if (post.photos.length) { %>
|
||||||
<img class="thumbnail" src="<%- url_for('img/loading2.gif') %>" data-echo="<%= url_for(post.photos[0]) %>" alt="<%= post.title %>" >
|
<img class="thumbnail" src="<%- url_for('img/loading2.gif') %>" data-echo="<%= url_for(post.photos[0]) %>" alt="<%= post.title %>" >
|
||||||
<% } else if (theme.CDN) { %>
|
<% } else if (theme.CDN) { %>
|
||||||
<img class="thumbnail" src="<%- url_for('img/loading2.gif') %>" data-echo="<%- url_for(theme.CDN + 'thumbnail/' + date(post.date, 'YYYY-MM-DD').charAt(date(post.date, 'YYYY-MM-DD').length - 1) + '.jpg') %>" alt="默认配图" >
|
<img class="thumbnail" src="<%- url_for('img/loading2.gif') %>" data-echo="<%- url_for(theme.CDN + 'thumbnail/' + numSum%10 + '.jpg') %>" alt="默认配图" >
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<img class="thumbnail" src="<%- url_for('img/loading2.gif') %>" data-echo="<%- url_for('img/thumbnail/' + date(post.date, 'YYYY-MM-DD').charAt(date(post.date, 'YYYY-MM-DD').length - 1) + '.jpg') %>" alt="默认配图" >
|
<img class="thumbnail" src="<%- url_for('img/loading2.gif') %>" data-echo="<%- url_for('img/thumbnail/' + numSum%10 + '.jpg') %>" alt="默认配图" >
|
||||||
<% } %>
|
<% } %>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||