我个人在7月份的笔记,不定期更新

一、typescript - 找不到参数类型为“字符串”的索引签名

个人习惯用策略模式去优化多个if/switch case的代码,

 getTitle(name: any) {
    const mapping={
      ApproveList: '签署审批',
      signRecord: '签署记录',
    }
    return mapping[name]
  }

但在ts下你可能会得到以下报错:

const mapping: {
    ApproveList: '签署审批',
    signRecord: '签署记录',
}
Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{ ApproveList: string; signRecord: string; }'.ts(7053)

原因是ts并不知道你传入的string索引,是否在对象中有对应的成员属性

知道问题了,我们就可以对应的解决方法:

  1. 声明一个类型。限制构成对象属性的字符串
  2. 以这个类型作为key,生成策略匹配的对象
  3. 以这个type类型作为函数参数
type RouteNames = 'ApproveList' | 'signRecord'

getTitle(name: RouteNames) {
    const mapping: Record<RouteNames, string> = {
      ApproveList: '签署审批',
      signRecord: '签署记录',
  
    }
    return mapping[name]
  }

this.title = this.getTitle(routeName as RouteNames) || ''

二、如何选择第三方 NPM 包?

  • 检查开源许可证
  • 看贡献频率和下载量
  • 权衡包体积大小
  • 是否有大型开发团队在进行维护
  • 评估安全性

检查开源许可证(License)

开源许可证是一种法律许可。通过它,版权拥有人明确允许,用户可以免费地使用、修改、共享版权软件。

版权法默认禁止共享,也就是说,没有许可证的软件,就等同于保留版权,虽然开源了,用户只能看看源码,不能用,一用就会侵犯版权。所以软件开源的话,必须明确地授予用户开源许可证。

License 通常分两大类:”CopyLeft(著佐权)” 和 “Permissive(宽松式)”:

CopyLeft:如果你使用了这个包,那么你的代码也必须开源。这对一些商业化的项目不太友好,比如 GPL 和 LGPL 协议。

Permissive:对包做了最低限度的使用限制,允许闭源,可以说几乎没有限制,但是各自又有一些区别,具体见下图。

Flower and water

评估安全性

包安全性是选择 NPM 包的另一个关键因素,在仓库的「Security」tab 下可以看到它的安全策略。

Flower and water

如果维护者已经采取了措施来确保安全性,会显示已激活。

对于项目中已有的 NPM 依赖,可以使用命令 npm audit 来进行安全性检查。

参考链接:

三、统一前端项目的 Node 版本和包管理器

锁定项目 Node 版本

通过在 package.json 中指定 engines 字段,可限定项目使用的 node 版本。 下面配置仅允许用户使用 14 或者 16的版本。更多的配置可以参考 package.json 、npm Docs 、semver

 // package.json 

  "engines": {
    "node": "14.x || 16.x"
  },

配置之后你会发现,该字段只对 yarn 生效。那如何对 npm 也生效呢?在项目根目录下的 .npmrc 文件中增加如下配置

// .npmrc

engine-strict = true,

以上配置完成后,npm install 试试吧,错误的 Node.js 将直接退出

锁定包管理器

利用 only-allow 工具包、npm scripts 快速实现锁定。

步骤一:在项目中 npm install -D only-allow

步骤二:在 package.json 文件中进行配置 scripts.preinstall , 允许输入的值 only-allow npm、only-allow pnpm、only-allow yarn

// package.json

"scripts": {
    "preinstall": "only-allow npm",
    ...
}

以上配置完成后,可以再乱用 (yarn、npm、pnpm) 试试

四、JSX中要注意的一些写法

.sync语法糖如何书写?

// template的sync语法糖:
<el-dialog title="提示" :visible.sync="dialogVisible" width="30%">
      <span>内容</span>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false"> </el-button>
        <el-button type="primary" @click="confirmUnbind"> </el-button>
      </span>
</el-dialog>

// template非语法糖
<el-dialog title="提示" :visible="dialogVisible" @update:visible = "val => this.dialogVisible = val"  width="30%">

// JSX 这么写

<el-dialog title="提示" visible={this.dialogVisible} {...{on:{'update:visible': val => this.dialogVisible = val}}} width="30%">
    <span>内容</span>
    <span slot="footer" class="dialog-footer">
        <el-button onClick={()=>...}> </el-button>
        <el-button type="primary" onClick={xxx函数名}> </el-button>
    </span>
</el-dialog>

v-bind=”$attrs” 如何书写?

<el-cascader
  ref="guiCascader"
  v-model={this.formData[item.key]}
  key={item.id}
  placeholder={item.placeholder || "请选择"}
  options={item.options}
  show-all-levels={item.showAllLevels || true}
  clearable={item.clearable || false}
  collapse-tags={item.collapseTags}
  {...{
    props: {
      ...this.$attrs,
      props: item.props
    }
  }}
/>

五、讲清楚同源、跨源、同站、跨站、Cookie 的 SameSite 属性

5.1源

image

“源”是scheme(也被称为协议,例如HTTP和HTTPS),主机域名和端口(如果有指定)的结合。例如,给定一个URLhttps://www.example.com:443/foo,它的“源”是https://www.example.com:443。

一条请求的核心部分就是这三部分:scheme+主机域名+端口,三者能够唯一标识通信方,这三部分的组成也被称为套接字(socket)。

⚡️ 下文scheme统统指例如HTTP或者HTTPS这样的协议。

5.2同源和跨源

相同scheme、主机域名和端口结合的网站被认为是“同源”,其他的被认为是“跨源”。

5.3站(Site)

image

站(site)= eTLD+1

TLD 表示顶级域名,例如 .com、.org、.cn 等等,不过顶级域名并不是一成不变的,会随着时间推移增加。

TLD+1 表示顶级域名和它前面二级域名的组合,例如网址是:

https://www.example.com:443/foo

那么:

TLD 是 .com TLD+1 是 example.com

但是,这种表示方式是有缺陷的,例如对于下面的网址:

https://www.example.com.cn

如果按照上面的规则,它的 TLD+1 就是 com.cn,并不能表示这个站点,真正能表示这个站点的应该是 example.com.cn 才对,所以衍生出 eTLD 的概念,即有效顶级域名:

eTLD:com.cn

eTLD+1:example.com.cn

eTLD 由 Mozilla 维护在公共后缀列表(Public Suffix List)中,而「站」的定义就是这里的 eTLD+1。

5.4同站和跨站

eTLD+1 完全一致。

假设现在有源A:https://www.example.com:443

大家同样可以遮住第2列,猜一猜源B和源A是属于同站还是跨站:

源B答案
https://www.evil.com:443 跨站,部分域名不一样
https://login.example.com:443 同站,eTLD+1一样
http😕/www.example.com:443 同站,同上
https://www.example.com:**80 同站,同上
https://www.example.com:443 同站,同上
https://www.example.com 同站,同上

Cookie 的SameSite属性用来限制第三方 Cookie,从而减少安全风险。

它可以设置三个值:

  • Strict
  • Lax
  • None

Strict

Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。

Set-Cookie: CookieName=CookieValue; SameSite=Lax;

这个规则过于严格,可能造成非常不好的用户体验。比如,当前网页有一个 GitHub 链接,用户点击跳转就不会带有 GitHub 的 Cookie,跳转过去总是未登陆状态。

Lax

没有 SameSite 属性的 Cookies 默认为 SameSite=Lax

Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。

Set-Cookie: CookieName=CookieValue; SameSite=Lax;

导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。详见下表。

image

设置了Strict或Lax以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。

None

Chrome 计划将Lax变为默认设置。这时,网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。 下面的设置无效。

Set-Cookie: widget_session=abc123; SameSite=None

下面的设置有效

Set-Cookie: widget_session=abc123; SameSite=None; Secure

5.6 如何检查一个请求是“同站”,“同源”,或者“跨站”

Chrome发送伴随Sec-Fetch-SiteHTTP请求头的请求。其他浏览器截至2020年4月还没有支持Sec-Fetch-Site。这是获取元数据请求头 提案更广的一部分。这个头部会有一个如下其中之一的值:

  • cross-site
  • same-site
  • same-origin
  • none

5.7 和浏览器的“禁用第三方 cookie”功能有什么区别?

主流浏览器都有禁用第三方 cookie 的功能,它和 SameSite 有什么区别?我能总结 2 点:

  1. 该功能是由用户决定是否开启的,是针对整个浏览器中所有 cookie 的,即便有些浏览器可以设置域名白名单,那最小单位也是域名;而 SameSite 是由网站决定是否开启的,它针对的是某个网站下的单个 cookie。

  2. 该功能同时禁用第三方 cookie 的读和写,比如 a.com 发起了对 b.com 的请求,这个请求完全不会有 Cookie 请求头,同时假如这个请求的响应头里有 Set-Cookie: foo=1,foo 这个 cookie 也不会被写进浏览器里;而 SameSite 只禁用读,比如 b.com 在用户浏览器下已经写入了个 SameSite cookie foo,当 a.com 请求 b.com 时,foo 肯定不会被发送过去,但 b.com 在这个请求的响应里又返回了: Set-Cookie: bar=1; SameSite=Strcit,这个 bar 会成功写入浏览器的 cookie 里。

5.8 怎样才算第三方请求?

当一个请求本身的 URL 和它的发起页面的 URL 不属于同一个站点时,这个请求就算第三方请求。那么怎样算是同一个站点?是我们经常说的同源(same-origin)吗,cross-origin 的两个请求就不属于同一个站点?显然不是的,foo.a.com 和 bar.a.com 是不同源的,但很有可能是同一个站点的,a.com 和 a.com:8000 是不同源的,但它俩绝对是属于同一个站点的,浏览器在判断第三方请求时用的判断逻辑并不是同源策略,而是用了 Public Suffix List 来判断。

六、记住在单文件中禁用某项eslint的方法

/* eslint-disable @typescript-eslint/camelcase */