新知识
1、git submodule
在学习新项目的时候,遇到需求备注,需优先通过 git submodule 拉取其他仓库的代码才可开发项目;
了解:
一个已存在的Git仓库添加为正在工作的仓库的子模块;
git submodule add https://xxx,会添加 .gitmodules文件(也会进行版本控制)和资源文件
加载资源下来:
1、方式1:克隆项目下来,会是空目录; git submodule init 初始化本地配置文件,git submodule update 拉取资源;
git submodule update --init --recursive 合并操作
2、方式2:git clone --recursive-submodules 自动初始化并更新,嵌套子模块;
如果想要在子模块中查看新工作,可以进入到目录中运行 git fetch 与 git merge,合并上游分支来更新本地代码。
开发主项目时,如果拉取了子项目新的内容,提交的时候会自动提交绑定新版;其他人pull时,不会自动更新子项目,status会有提示,不会自动加载。
在子模块工作时, git submodule update --remote 拉取各个子模块,更新到本地工作,git submodule update --remote --merge 添加merge更新子模块自动合并,git push --recurse-submodules=check push时检查是否有遗留子模块未推送。
2、涉及emoji表情unicode长度不一的截取方法
原因:js设计之初,使用的是UCS-2编码处理字符串,只支持处理Unicode中基于多语言平面的字符(单字节、双字节);emoji表情或生僻字大多都不急于多语言平面,有些会被当做两个字符,如‘𠮷’;且有些表情为多个表情拼接而成。
无法不应用slice,使用Array.from进行转化,Array.from、for… of 都是按照 unicode字符去识别使用的。
Array.from(str).length
Array.from(str).slice(from, to);
3、eslint学习整理
增加项目代码健壮性的工具
eslint 中文官网
学习整理及常用配置文档地址
4、proto文件
RPC协议
以Google的协议缓冲区格式创建的开发者文件,一种用于交换数据的数据序列化格式; 指定一个或多个“消息”作为逻辑记录,每个逻辑记录包含“名称/值”对(例如,“个人”消息可以具有ID,名称和地址); 设计替代 XML 用于数据交换。
协议缓冲区用于序列化Java,C ++或Python程序中的对象。 这允许以通用格式编码数据,并在以三种语言编写的应用程序之间交换数据。
5、生成文件代码结构
treer npm包,命令:·treer -i ‘node_modules’ -e xx.md·,忽略node_modules文件,导出至xx.md
6、如何编辑一个google_extension
一个 Chrome 扩展其实就是一个配置(入口)文件 manifest.json 和一系列 html、css、js、图片文件的集合
文件结构
├── background.js
├── images
│ ├── 16.png
├── manifest.json // 配置文件
├── popup.html
└── popup.js
mainfest.json配置
{
"name": "extension_my",
"manifest_version": 2, // 必须为2
"description": "extension_my",
"version": "0.0.1",
"browser_action": { // 指定扩展的图标放在 Chrome 工具栏中
"default_icon": { // 图标文件位置
"19": "images/icon19.png",
"38": "images/icon38.png"
},
"default_title": "default_title", // 悬浮提示
"default_popup": "popup.html" // 图标所显示的页面位置
},
"options_page": "options.html", // 扩展的设置页面,配置后在扩展图标点击右键可以看到 选项,点击即打开指定页面
"permissions": [ // 定义了扩展需要向 Chrome 申请的权限,比如通过 XMLHttpRequest 跨域请求数据、访问浏览器选项卡(tabs)、获取当前活动选项卡(activeTab)、浏览器通知(notifications)、存储(storage)等,可以根据需要添加
"http://*/*",
"https://*/*",
"webRequest",
"webRequestBlocking"
],
"background": { // 使扩展常驻后台;scripts,表示在扩展启动时自动创建一个包含所有指定脚本的页面。
"service_worker": "background.js"
},
"chrome_url_overrides": { // 以自定义的页面替换 Chrome 相应默认的页面,比如新标签页(newtab)、书签页面(bookmarks)和历史记录(history)。
"newtab": "tab.html"
},
"content_scripts": [ // // 在此处使用数组往页面中引入JS或者CSS。
{
"matches": [ // 匹配时才会注入
"http://*/*",
"https://*/*"
],
"js": [ // 注入运行时js
"runtime.js"
],
"run_at": "document_idle" // 引入时机,对js来说很重要;"document_start"、"document_end"、"document_idle"
}
]
}
chrome.runtime
api地址
可以通过sendMessage和onMessage两个函数,分别在runtime.js和background.js中应用,将背景数据放入内容脚本,可以在背景写上一些请求函数帮助处理一些内容,如跨域接口请求;
// runtime.js
chrome.runtime.sendMessage({
beginTime,
detail,
}, async (response) => {
if (response === null) {
reject(chrome.runtime.lastError);
}
resolve(response);
});
// background.js
chrome.runtime.onMessage.addListener((request, _, sendResponse) => { // 提供http服务
(async () => {
try {
const { url, method, headers, body, form } = request.detail;
const options: RequestOption = { // 请求option配置
url,
method,
headers: headers,
body: body,
};
const result = await fetch(url, options); // 请求用例
sendResponse(result);
} catch (error) {
sendResponse({ error: chrome.runtime.lastError });
}
})().catch(error => {
sendResponse({ error: String(error) });
});
return true;
});
并在运行时监听请求事件,挂载document上,进行分发处理
document.addEventListener('req_event', async (event) => {
const detail = (event as any)?.detail || {};
document.dispatchEvent(new CustomEvent('res_event', { detail: detail }));
});
7、go语言基础用法
1、windows安装:
下载地址,包名:gox.x.windows-amd64.msi,安装之后环境变量可能会重启命令窗口不生效,重启电脑即可;
2、基本语法
Go 标记:关键字,标识符,常量,字符串,符号;
// 开头的单行注释。多行注释(块注释),以 /* 开头,并以 */ 结尾
字符串连接可以通过 + 实现;
fmt.Sprintf 格式化字符串并赋值给新串,// %d 表示整型数字,%s 表示字符串;
// 省略调用;调用的时候只需要Println(),而不需要fmt.Println()
import . "fmt"
iota,特殊常量,可以认为是一个可以被编译器修改的常量。iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。iota 可以被用作枚举值。
变量是一种使用方便的占位符,用于引用计算机内存地址
select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。
数据类型
字符串类型、数字类型、布尔类型;
派生类型:
包括:
(a) 指针类型(Pointer)
(b) 数组类型
© 结构化类型(struct)
(d) Channel 类型
(e) 函数类型
(f) 切片类型
(g) 接口类型(interface)
(h) Map 类型
type_name(expression) // 类型转换用于将一种数据类型的变量转换为另外一种类型的变量。type_name 为类型,expression 为表达式。
赋值操作符
&i 来获取变量 i 的内存地址,值类型变量的值存储在堆中。
内存地址会根据机器的不同而有所不同,甚至相同的程序在不同的机器上执行后也会有不同的内存地址。因为每台机器可能有不同的存储器布局,并且位置分配也可能不同。
更复杂的数据通常会需要使用多个字,这些数据一般使用引用类型保存。即 指针。指针实际上也被存在另外的某一个值中。
a , b , c := 1 , 2 , "str"
函数
函数作为另外一个函数的实参;
闭包:闭包是匿名函数,可在动态编程中使用
方法:一个包含了接受者的函数
局部变量、全局变量和形式参数;
func function_name( [parameter list] ) [return_types] {
函数体
}
// 返回多参数
func swap(x, y string) (string, string) {
return y, x
}
// 函数做实参
/* 声明函数变量 */
getSquareRoot := func(x float64) float64 {
return math.Sqrt(x)
}
/* 使用函数 */
fmt.Println(getSquareRoot(9))
// 闭包
func getSequence() func() int {
i:=0
return func() int {
i+=1
return i
}
}
// 方法:给一个类型变量添加方法;C++ 等语言中,实现类的方法做法都是编译器隐式的给函数加一个 this 指针,而在 Go 里,这个 this 指针需要明确的申明出来,其实和其它 OO 语言并没有很大的区别。
//该 method 属于 Circle 类型对象中的方法
func (c Circle) getArea() float64 {
//c.radius 即为 Circle 类型对象中的属性
return 3.14 * c.radius * c.radius
}
并发和通道
// 并发,需要通过 go 关键字来开启 goroutine, 同一个程序中的所有 goroutine 共享同一个地址空间。
go 函数名( 参数列表 )
go say("world");
// 通道(channel)是用来传递数据的一个数据结构。通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。操作符 <- 用于指定通道的方向,发送或接收。如果未指定方向,则为双向通道。 close() 函数来关闭
ch := make(chan int, 100) // 第二个参数指定缓冲区大小
close(ch)
数组
二维数组和range
package main
import "fmt"
func main() {
arr := [...][]int{
{1, 2, 3, 4},
{10, 20, 30, 40},
}
for i := range arr {
for j := range arr[i] {
fmt.Println(arr[i][j])
}
}
}
切片slice
s :=make([]int,len,cap)
s1 := s[startIndex:endIndex] // startIndex 包含, endIndex 不包含
// len() 方法获取长度。 cap() 可以测量切片最长可以达到多少。
var numbers = make([]int,3,5) // len=3 cap=5 slice=[0 0 0]
numbers = append(numbers, 0) // 增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。 允许追加空切片
numbers1 := make([]int, len(numbers), (cap(numbers))*2) // 创建更大
copy(numbers1,numbers) // 拷贝
Range
range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。
map
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type
/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)
delete(countryCapitalMap, "France")
指针
var a int= 20 /* 声明实际变量 */
var ip *int /* 声明指针变量 */
ip = &a /* 指针变量的存储地址 */
/* 使用指针访问值 */
fmt.Printf("*ip 变量的值: %d\n", *ip )
if(ptr == nil) /* ptr 是空指针 */
fmt.Printf("ptr 的值为 : %x\n", ptr ) // 0
结构体的接口方法
/* 定义接口 */
type interface_name interface {
method_name1 [return_type]
method_name2 [return_type]
method_name3 [return_type]
...
method_namen [return_type]
}
/* 定义结构体 */
type struct_name struct {
/* variables */
}
/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
/* 方法实现 */
}
error
是一个接口类型
type error interface {
Error() string
}
// 常用于函数返回错误信息,如下:
// 定义一个 DivideError 结构
type DivideError struct {
dividee int
divider int
}
// 实现 `error` 接口
func (de *DivideError) Error() string {
strFormat := `
Cannot proceed, the divider is zero.
dividee: %d
divider: 0
`
return fmt.Sprintf(strFormat, de.dividee)
}
// 定义 `int` 类型除法运算的函数
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
if varDivider == 0 {
dData := DivideError{
dividee: varDividee,
divider: varDivider,
}
errorMsg = dData.Error()
return
} else {
return varDividee / varDivider, ""
}
}
3、官方包管理器:go mod
问题
1、stylelint 校验 font-family-no-missing-generic-family-keyword 报错
font-family没有通用的关键词,改关键词所有浏览器都应实现与Serif, sans-serif ,cursive, fantasy, Monospace
匹配的通用字体列表
font-family: 'ch-icon';
// 添加通用字体,调整为
font-family: 'ch-icon' , sans-serif;
配置项
rules(null为禁用)、extends、processors、ingoreFiles、defaultServerity
rules支持自定义配置,传递数组,第一项为规则值,第二项为自定义配置:
'scss/at-rule-no-unknown': [true,
'serverity': 'warning', // 特别配置这两项
'message': 'no-know'
]
2、cherry-markdown组件样式调整
左右两栏加标题,调整大小;
// 效果预览栏 markdown-container 加在 markdown-container 的id上,即根部
.markdown-container::before {
content: '效果预览';
position: absolute;
display: block;
/* width: 100%; */
height: 50px;
line-height: 50px;
z-index: 1;
top: 10px;
left: 20px;
font-size: 18px;
font-weight: bold;
color: #000;
}
// 编辑栏
.cherry-editor::after {
content: 'markdown源码';
position: absolute;
top: 20px;
left: 20px;
font-size: 18px;
font-weight: bold;
color: #000;
}
3、diaplay:flex、flex:1 结合 table scroll,scroll脱离table
问题描述:
所用table组件为antd,使用display进行左右布局;
diaplay:flex、flex:1 遇到 table的项目时,table内容过度滑动的效果会跳出table调至整个布局位置,如下:
解决办法:
flex: 1; --> flex: auto; min-width: 0;
display: flex 下 min-width: auto;
min-width被定义为对抗width和max-width的属性,这意味着一旦元素宽度缩小到其隐式自动宽度一下,那么min-width:auto将启动并防止元素缩小。修复的方式就是将元素的min-width设置为0即可。
总结:
display: flex / inline-flex;
flex布局分为容器和项目两个模块: 容器、项目
对容器涉及属性及属性值如下:
flex-direction: row | row-reverse | column | column-reverse; // 主轴(项目的排列)的方向
flex-wrap: nowrap | wrap | wrap-reverse; // 一条轴线排不下,如何换行
flex-flow: <flex-direction> || <flex-wrap>; // 前两结合,默认 row nowrap;
justify-content: flex-start | flex-end | center | space-between | space-around; // 主轴上的对齐方式,space-between项目之间间隔相,space-around项目两侧间隔相等
align-items: flex-start | flex-end | center | baseline | stretch; // 交叉轴,即主轴垂直方向对齐方式
align-content: flex-start | flex-end | center | space-between | space-around | stretch; // 多根轴线的对齐方式
对项目涉及属性及属性值如下:
order: 1; // 项目排序,默认为0,越小越靠前
flex-grow: 0; // 存在剩余空间的放大比例,0为不放大默认值
flex-shrink: 1; // 空间不足的缩小比例,1为不缩小默认值,
flex-basis: <length> | auto ; // 自身占据位置,默认值为auto项目本来大小;定义分配多余空间之前项目占据的主轴空间;浏览器根据这个属性计算主轴是否有多余空间
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]; // 前三者简写,默认值为 0 1 auto;即不放大不缩小保持自身大小;
// 两个快捷值: flex: auto; -- 1 1 auto;即在自身基础上仅可放大不缩小;flex: none;0 0 auto; 自身基础仅缩小不放大;
align-self: ; // 项目自身对其方式,可覆盖容器的align-items属性,默认auto,继承父级。
flex: 1、flex: auto 的区别
flex: 1; 代表 [ <‘flex-grow’> <‘flex-shrink’>? || <‘flex-basis’> ]: 1 1 0;及不依赖自身大小仅可放大不缩小,长用来结合固定宽度列自适应另外内容列。
flex:auto; 代表 [ <‘flex-grow’> <‘flex-shrink’>? || <‘flex-basis’> ]: 1 1 auto;即在自身基础上仅可放大不缩小。
4、git rebase远程分支
git pull --rebase 重置pull之前的,合并远程更新的,合并本地更新的。