cristinazhou / Blog

1 stars 0 forks source link

学习笔记-日更 #6

Open cristinazhou opened 1 year ago

cristinazhou commented 1 year ago

2022.10.13 (被隔离居家办公的一天 时间相对自由一些)

知识点

1、vue3 composition api 与 options api 对比 2、websocket 相关(心跳机制) 3、redux middleware怎么应用的 Redux通关简洁攻略

middleware: dispatch的高阶函数封装,由applyMiddleware把原dispatch替换为包含middleware链式调用的实现。 applyMiddleware:是官方实现的一个storeEnhance,用于给redux提供插件能力,支持各种不同的Action。


// middleware 函数签名
type MiddlewareAPI = { dispatch: Dispatch, getState: () => State } 
type Middleware = (api: MiddlewareAPI) => (next: Dispatch) => Dispatch 
// 最外层函数的作用是接收middlewareApi ,给middleware提供store 的部分api,它返回的函数参与compose,以实现middleware的链式调用。

export default function applyMiddleware(...middlewares) { return (createStore) =>{
// 初始化store,拿到dispatch
const store = createStore(reducer, preloadedState)
// 不允许在middlware中调用dispath
let dispatch: Dispatch = () => {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.'
)
}
const middlewareAPI: MiddlewareAPI = { getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args) }
// 把api注入middlware
const chain = middlewares.map(middleware => middleware(middlewareAPI)) // 重点理解 // compose后传入dispatch,生成一个新的经过层层包装的dispath调用链 dispatch = compose(...chain)(store.dispatch) // 替换掉dispath,返回 return {
...store,
dispatch
}
} }

> storeEnhancer
> 从函数签名可以看出是createStore的高阶函数封装。
> type StoreEnhancer = (next: StoreCreator) => StoreCreator; 
> CreateStore 入参中只接受一个storeEnhancer ,如果需要传入多个,则用compose把他们组合起来,关于高阶函数组合的执行方式下文中的Redux Utils - compose有说明,这对理解下面middleware 是如何链式调用的至关重要,故请先看那一部分。
    compose(组合)是函数式编程范式中经常用到的一种处理,它创建一个从右到左的数据流,右边函数执行的结果作为参数传入左边。

export default function compose(...funcs) { if (funcs.length === 0) { return (arg) => arg } if (funcs.length === 1) { return funcs[0] } // 简单直接的compose return funcs.reduce( (a, b) => (...args: any) => a(b(...args)) ) }


> 高阶函数的应用是非常值得借鉴的一个插件体系构建方式,不是直接设定生命周期,而是直接给予核心函数一次高阶封装,然后内部依赖compose完成链式调用.

**系统设计**
1、低代码设计思想  
[对低代码搭建的理解](https://github.com/ascoders/weekly/blob/master/%E5%89%8D%E6%B2%BF%E6%8A%80%E6%9C%AF/159.%20%E7%B2%BE%E8%AF%BB%E3%80%8A%E5%AF%B9%E4%BD%8E%E4%BB%A3%E7%A0%81%E6%90%AD%E5%BB%BA%E7%9A%84%E7%90%86%E8%A7%A3%E3%80%8B.md)

> 低代码不仅仅包括 “能写代码”,主要具备如下四个特性:物料接入、编排能力、渲染能力、出码能力。

通用搭建引擎要能够接入通用物料,即组件自身不关心搭建环境,就可以被搭建平台所使用。

这需要搭建平台本身不对组件代码实现有入侵,可以对组件暴露的 props 做完全控制,要做到自动识别组件有哪些 props 变量,并根据类型自动推荐编辑表单类型。

除了简单的文本、数字、下拉框等编辑器 Setter 之外,还有如下几种复杂编辑器:

回调函数编辑器。
Node 节点编辑器。
文本国际化编辑器。
表达式编辑器。
积木式搭建和富文本搭建存在哪些差异,除了富文本更倾向于记录静态内容外,还有哪些差异,两者是否可以结合?
从前端角度来看,富文本本质上是对一个 div 进行 contenteditable 申明,那么一个应用可以整体是 contenteditable 的,也可以局部几个区块是,这种代码层面的自由度体现在搭建上就是积木式搭建可以与富文本搭建自由结合。
![image](https://user-images.githubusercontent.com/12948259/197324770-d56a23d4-102b-4850-8430-b2cc5c973b20.png)

2、富文本编辑  notion 飞书,设计实现难点是什么 ? 面试官 提的富文本编辑中的blot 概念,当时完全没听懂  
[深入浅出富文本编辑器](https://mp.weixin.qq.com/s/Cs4jc5nHQDCAUtGRa3fuew)

> 摘要:如果业务中需要拓展一些功能卡片,如飞书文档的各种应用,可通过拓展 blot + 编写对应的组件来实现。此外还能够通过编写相应平台的解析器在非 web 场景的展示,轻松实现内容跨平台渲染。

[quilljs](https://quilljs.com/docs/quickstart/)

**coding:**

1、快排 (原地排序) 2、洗牌算法 3、url 解析


🤔 自律 自信 自由
cristinazhou commented 1 year ago

2022.10.14

cristinazhou commented 1 year ago

2022.10.16

1、路由的实现方式 Hash和History区别 2、微前端 3、项目迭代 CICD 流程

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。 Docker 技术的三大核心概念,分别是:

镜像(Image) 容器(Container) 仓库(Repository) 持续不是指“一直在进行”,而是“随时可进行”,一般来说包括这几个方面:

引入 CI/CD 以后,整个流程变成: 1、提交代码,push 到 git 远程仓库 2、git hook 触发 jenkins 的构建 job (自动) 3、 jenkins job 中拉取项目代码,运行 npm run build,如果失败,发送邮件通知相关人。(自动) 4、 jenkins job 中执行测试服务器的部署脚本 (自动) CI/CD 的关键在于自动化,使用脚本来自动化构建、部署,而 Webhook 则起到了中间桥梁的作用。

Webhook 简单来说就是一种反向 API 机制,是在特定情况下触发的一种 API,类似于触发器。 Github 的 Webhook: TRAVIS CI Travis CI 提供的是持续集成服务(Continuous Integration,简称 CI)。 它绑定 Github 上面的项目,只要有新的代码,就会自动抓取。 提供一个运行环境,完成构建,还能部署到服务器。 这些行为都可以在项目根目录的 .travis.yml 配置文件里面指定。

cristinazhou commented 1 year ago

2022.10.20

ps: 最近有需求要赶,学习上有一点偷懒……

cristinazhou commented 1 year ago

2022.10.21

1、mvc 设计思想, cocos 游戏开发基于mvc软件架构模式 2、js 内存机制 复习 浅谈JS内存机制 以下内容均是该文章的摘要 原始类型的数据是存放在栈中,引用类型的数据存放在堆中 ?

摘要: V8把数字分成两种类型:smi 和 heapNumber smi是范围为 :-2³¹ 到 2³¹-1的整数,在栈中直接存值;除了smi,其余数字类型都是heapNumber,需要另外开辟堆空间进行储存,变量保存其引用。 bigInt、string、symbol这些内存大小不固定的类型在栈中也是保存其堆内存的引用。同时我们在栈中可以声明很大的string,如果string存放在栈中明显也不合理。

image

js 垃圾回收

JS 把堆空间分成新生代和老生代两个区域,新生代中存放的是生存时间短的对象,通常只支持 1~8M 的容量;老生代中存放的生存时间长的对象,一些大的数据也会被直接分配到老生区中。而针对这两个区域,JS 存在两个垃圾回收器:主垃圾处理器和副垃圾处理器。这里先说说垃圾回收一般都有相同的执行流程:

  1. 标记空间中活动对象和非活动对象
  2. 回收非活动对象所占据的内存
  3. 内存整理,这步是可选的,因为有的垃圾回收器工作过程会产生内存碎片,这时就需要内存整理防止不够连续空间分配给大数据
  4. 副垃圾回收器

    副垃圾回收器主要是采用 Scavenge 算法进行新生区的垃圾回收,它把新生区划分为两个区域:对象区域和空闲区域,新加入的对象都会存放到对象区域,当对象区域快被写满时,会对对象区域进行垃圾标记,把存活对象复制并有序排列至空闲区域,完成后让这两个区域角色互转,由此便能无限循环进行垃圾回收。同时存在对象晋升策略,也就是经过两次垃圾回收依然还存活的对象,会被移动到老生区中。

主垃圾回收器

由于老生区空间大,数据大,所以不适用 Scavenge 算法,主要是采用标记-整理算法,其工作流程是从一组根元素开始,递归遍历这组根元素,在这个遍历过程中,能到达的元素称为活动对象,没有到达的元素就可以判断为垃圾数据。接着让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。垃圾回收工作是需要占用主线程的,必须暂停JS脚本执行等待垃圾回收完成后恢复,这种行为称为全停顿。 由于老生代内存大,全停顿对性能的影响非常大,所以出现了增量标记的策略进行老生区的垃圾回收。

// 测试代码
const [test, setTest] = useState(null);
useEffect(() => {
(async () => {
// 这里表达一个异步操作如:xhr、fetch、promise等等
await sleep(3000);
const obj = new TestObj();
setTest(obj);
})();
}, []);
// 如果把代码改成这样,就不会造成内存泄漏:
const [test, setTest] = useState(null);
useEffect(() => {
let unMounted = false;
(async () => {
await sleep(3000);
if (unMounted) return;
const obj = new TestObj();
setTest(obj);
})();
return () => {
unMounted = true;
};
}, []);
cristinazhou commented 1 year ago

2022.10.22

基础知识复习 es5 中类和 es6的class有什么区别 ?

  1. class类必须使用new调用,不能直接执行
  2. class类不存在变量提升
  3. class类无法遍历它的实例原型链上的属性和方法
  4. new.target 属性,es6为new命令引入了一个new.target 属性,它会返回new命令作用于的那个构造函数。如果不是通过new调用或Reflect.construct()调用的,new.target 会返回undefined。
  5. class 类有static静态方法 ,只能通过类调用,不会出现在实例上
cristinazhou commented 1 year ago

2022.10.23 webpack-dev-server 的原理

image

“start”: “webpack serve --open” 这里webpack会基于webpack.config.js 里的配置创建一个compiler, 然后基于compiler和devServer相关配置生成一个webpackDevServer实例,该实例会启用一个express服务来帮我们监听静态资源变化并更新。 更新: 因为webpack-dev-server 使用的是webpack的watch模式进行的编译,当我们更新了代码后,webpack是能够监听到代码的变化,代码变化后,webpack会再次将项目 代码进行打包编译,编译完成后,就会触发done钩子函数。 初始化时,在done钩子上挂载了回调,setupHooks里的websocketServer 对客户端进行消息广播,通知客户端项目代码有更新。


this.compiler.hooks.done.tap('webpack-dev-server', (status) => {
if(this.webSocketServer) {
this.sendStatus(this.webSocketServer.clients, this.getStatus(status))
this.stats = stats;
}

})



> 2、当客户端接收到websocket广播的消息后,会触发reloadApp方法(webpack打包时注入进去的),reloadApp会根据广播消息里更新类型选择是页面跟心liveReload还是模块更新hotReload。
3、客户端更新页面时,回去请求类似c390bbe00370dd079a6.hot-update.json, main.c390bbe00370dd079a6.hot-update.json这样两个文件,这两个文件是webapck使用了HotModuleReplacementPlugin编译时,每次增量编译就是多产出阿玲哥文件,分别描述chunk更新的mainfest文件和更新过后的chunk文件。
4、拿到这两个增量文件后,再去请求express服务器去获取最新编译打包的bundle.js
5、根据更新类型,选择是两个增量文件和bundle.js比对局部更新还是页面更新。

项目复习:
脚手架项目:

>  功能: 
> 1. 用户输入命令,准备创建项目。
> 2. 脚手架解析用户命令,并弹出交互语句,询问用户创建项目需要哪些功能。
> 3. 用户选择自己需要的功能。
> 4. 脚手架根据用户的选择创建 package.json 文件,并添加对应的依赖项。
> 5. 脚手架根据用户的选择渲染项目模板,生成文件(例如 index.html、main.js、App.vue 等文件)。
> 6. 执行 npm install 命令安装依赖。