2022-28周 项目问题整理

新知识

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 }));
});

dispatchEvent
CustomEvent

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'
]

常用rules

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之前的,合并远程更新的,合并本地更新的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值