React面试题相关 2021-11-01React 面试题相关常用的 hooks 及优化什么是副作用:1. 副作用 ( side effect ): 数据获取,数据订阅,以及手动更改 React 组件中的 DOM 都属于副作用 2. 因为我们渲染出的页面都是静态的,任何在其之后的操作都会对他产生影响,所以称之为副作用
useState,在类组件中,可以用 this.state 来定义类组件的状态
useEffect useEffect 又称副作用 hooks。作用:给没有生命周期的组件,添加结束渲染的信号。执行时机:在渲染结束之后执行。如果不接受第二个参数,那么在第一次渲染完成之后和每次更新渲染页面的时候,都会调用 useEffect 的回调函数。在这,我们可以对第二个参数传入一个数组,这个数组表示的是更新执行所依赖的列表,只有依赖列表改变时(当数组中的任意一项变化的时候,useEffect 会被重新执行 ),才会触发回调函数。传入的为空数组[],那么即告诉 useEffect 不依赖于 state、props 中的任意值,useEffect 就只会运行一次,常用场景为页面获取数据的方法可以写入此处进行调用,以获取页面初始数据。传入一个值构建的数组、或者多个值构建的数组,如[num]、[num,val],上述代码变更为如下。那么此时只有当数组中的值(任意一项即可)改变时,才会重新触发回调函数。return 一个函数清除副作用。
123456789101112131415useEffect(() => { console.log('2222函数式组件结束渲染') const updateMouse = (e) => { console.log('打印当前位置') setPositions({ x: e.clientX, y: e.clientY }) } document.addEventListener('click', updateMouse) // 添加绑定方法事件(要修改依赖,绑定到依赖上) return () => { // 在每次执行useEffect之前都会执行上一次return中内容 document.removeEventListener('click', updateMouse) // 移除绑定方法事件(要修改依赖,绑定到依赖上) console.log('1111销毁') }})
useLayoutEffect。一般将 useLayoutEffect 称为有 DOM 操作的副作用 hooks。作用是在 DOM 更新完成之后执行某个操作。执行时机:在 DOM 更新之后执行。执行时机不同。useLayoutEffect 在 DOM 更新之后执行;useEffect 在 render 渲染结束后执行。执行示例代码会发现 useLayoutEffect 永远比 useEffect 先执行,这是因为 DOM 更新之后,渲染才结束或者渲染还会结束。
useMemo。使用 useMemo 可以传递一个创建函数和依赖项,创建函数会需要返回一个值,只有在依赖项发生改变的时候,才会重新调用此函数,返回一个新的值。简单来说,作用是让组件中的函数跟随状态更新(即优化函数组件中的功能函数)。1. 优化点击功能函数 2. 优化子组件 ...
Read more 面试题&面经问题 2021-10-23面试题(主要是面经问题)跨域问题当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”。第一:如果是协议和端口造成的跨域问题“前台”是无能为力的。
第二:在跨域问题上,仅仅是通过“URL 的首部”来识别而不会根据域名对应的 IP 地址是否相同来判断。“URL 的首部”可以理解为“协议, 域名和端口必须匹配”。跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。
解决办法
JSONP 方式利用 <script> 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP 请求一定需要对方的服务器做支持才可以。 JSONP 优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持 get 方法具有局限性,不安全可能会遭受 XSS 攻击。
cors 方式CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。虽然设置 CORS 和前端没什么关系,但是通过这种方式解决跨域问题的话,会在发送请求时出现两种情况,分别为简单请求和复杂请求。
postmessagepostMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
websocket
Node 中间件两次代理
Nginx 反向代理
思否资料掘金资料
HTML 相关http1.0 http1.1 http2 区别HTTP1.0、HTTP1.1 和 HTTP2.0 的区别
怎样把网站升级到 http/2
http1.1
缓存处理,在原先的If-Modified-Since, Expires之上添加了更多的缓存控制策略例如:Entity tag If-Unmodified-Since If-Match If-None-Match等
带宽优化及网络连接的使用,加入了 range 头域,允许请求部分资源例如 206 状态吗
错误通知的管理。新增了 24 个错误状态响应码。
host 头处理。
长连接。默认开启:Connection:keep-alive。在同一个 tcp 连接上可以传送多个 http 请求和响应
http2.0
新的二进制格式。
多路复用。一个连接可以传输多个资源,雪碧图、减少请求数等就没有必要了。突破了 chrome 同时并发 6 个请求的限制。
header 压缩
服务端推送(server push)可以提前让服务端推送资源而不是浏览器主动请求
强缓存和协商缓存github 缓存一系列文章网络协议系列 — 强缓存与协商缓存机制浏览器缓存看这一篇就够了说说缓存
CORS 跨域相关CORS 简单请求和预检请求
JS 相关JS 基础
js 基本数据类型 值类型:字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。 引用数据类型:对象(Object)、数组(Array)、函数(Function)。
== 和 === 的问题 == 在做比较的时候进行了隐式类型转换参考资料
new 一个对象时发生 ...
Read more Vue面试题相关 2021-10-21VueVuejs 响应式原理Vuejs 响应式原理
参考资料汪图南-个人博客-详细记录了 vue 及前端的一些资料
Vue 父子组件执行顺序父子组件加载渲染过程(同步引入组件):父 beforeCreate->父 created->父 beforeMount->子 beforeCreate->子 created->子 beforeMount->子 mounted->父 mounted
当异步引入子组件时,渲染顺序会有所变化:父 beforeCreate->父 created->父 beforeMount->父 mounted->子 beforeCreate->子 created->子 beforeMount->子 mounted
子组件更新:父 beforeUpdate->子 beforeUpdate->子 updated->父 updated
父组件更新过程:父 beforeUpdate->父 updated
销毁:父 beforeDestroy->子 beforeDestroy->子 destroyed->父 destroyed
Vue 的插件机制
如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。
Vue.use 是一个全局方法,它是在initGlobalAPI通过调用initUse来注册这个全局方法的。initUse方法并不复杂:1.检测是否已经注册了插件 2.处理参数,将第一个参数之后的全部转数组。3.调用 install 方法
在 install 方法中,我们成功获取到了 Vue 构造函数以及我们传递的参数,在随后我们就可以做一些其它事情,例如:注册公共组件、注册指令、添加公共方法以及全局 Mixin 混入等等。
vue 源码分析-4-Vue.use()插件机制Vue.use 插件机制
Vue 的四大生命周期和 8 个生命周期钩子函数1、创建 2、挂载 3、更新 4、销毁
beforeCreate vue 实例初始化之前调用
created vue 实例初始化之后调用
beforeMount 挂载到 DOM 树之前调用
mounted 挂载到 DOM 树之后调用
beforeUpdate 数据更新之前调用
updated 数据更新之后调用
beforeDestroy vue 实例销毁之前调用
destroyed vue 实例销毁之后调用
Nuxt 的生命周期以上是 nuxt.js 的生命周期流程图,红框内的是 Nuxt 的生命周期(运行在服务端),黄框内同时运行在服务端&&客户端上,绿框内则运行在客户端
Vue 的八种通信方式
props/$emit
$children/$parent
provide/reject provide 和 inject 不是响应式的,这点很重要,除非申明的属性是响应式的!
ref
eventbus
Vuex
localStorage/sessionStorage
$attr/$listenersvue 中 8 种组件通信方式, 值得收藏!
watch methods computer 的区别和用法computed 是计算属性的; 它会根据所依赖的数据动态显示新的计算结果, 该计算结果会被缓存起来。computed 的值在 getter 执行后是 ...
Read more React2021最佳实践 2021-08-28创建项目npx create-react-app ** --template typescript,其中**是项目名字,如果在当前空文件夹下面创建,直接输入一个点就可以了。如果出现安装依赖失败,仔细阅读提示,很有可能是使用的 node 版本不对,其中有一个包要求指定版本或者大约 15 版本的 node,这个要注意。如果运行时依赖有问题,很可能是因为上一步中断导致的问题,删除全部文件重新执行创建命令。
项目配置
baseUrl根路径设置。打开 tsconfig.json文件,在compilerOptions对象当中添加baseUrl: './src'即可设置文件根绝对路径。
添加项目级的 prettier。文档yarn add --dev --exact prettierecho {}> .prettierrc.json创建.prettierignore文件然后写入 js build coverage添加 commit 钩子自动格式化代码 npx mrm lint-staged 应该在 package.json 里面自动插入了一条lint-staged命令,查看一下有没有 hook 命令,没有的话手动加一下js "husky": { "hooks": { "pre-commit": "lint-staged" } },
添加 Eslint。yarn add eslint-config-prettier -D,在 package 里面 eslintConfig->extends 里面添加一条 prettier。这条的意思是 prettier 格式化和 eslint 时有冲突,这里我们用 prettier 的部分规则覆盖了 eslint 的部分规则。注意,部分情况下可能出现 prettier 已经解决了 eslint 的冲突,但是格式化的情况下没有自动修复,你需要右键 格式化代码(vscode),给文件(ts) 配置默认的格式化程序,选择 prettier 就可以了。
添加commitlint,用于 git 提交检查。npm install --save-dev @commitlint/{config-conventional,cli}先装两个插件,echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js执行创建一个文件。没有husky的话,先装一个 husky
123456"husky": { "hooks": { "pre-commit": "lint-staged", "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" }},
加一个 hook 命令,然后提交的时候就按照规范提交,例如feat: some msg注意feat: 是固定的,别忘了空格不然也不通过。文档npx husky add .husky/commit-msg 'np ...
Read more SQL学习笔记 2021-07-15检索数据 排序检索数据
关系数据库设计理论认为,如果不明确规定排序顺序,则不应该假定检索出的数据的顺序有任何意义。
使用ORDER BY
语句进行排序。SELECT prod_name FROM Products ORDER BY prod_name;
注意,order by 语句必须是最后一条字句,不然就会出错。
SELECT prod_id,prod_price,prod_name FROM Products ORDER BY prod_price,prod_name;
按多个列排序
SELECT prod_id,prod_price,prod_name FROM Products ORDER BY 2,3;
多个列排序的另一种写法,根据前面的 select 语句中的列位置排序
以上两种都是默认升序排序。SELECT prod_id,prod_price,prod_name FROM Products ORDER BY prod_price DESC,prod_name;
使用 DESC 关键字可以进行降序排序,如果多列降序,则每一列名后面都要加 DESC 关键字。与之相对的升序关键字是 ASC,不过一般用不到
Read more qiankun的接入及使用 2021-05-18| qiankun 微前端 React Vue 微前端框架 qiankun 的接入及使用 qiankun的接入 父应用
安装qiankun $ yarn add qiankun # 或者 npm i qiankun -S
在主应用中注册微应用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { registerMicroApps, start } from 'qiankun' ;registerMicroApps ([{ name : 'react app' , entry : '//localhost:7100' , container : '#yourContainer' , activeRule : '/yourActiveRule' , }, { name : 'vue app' , entry : { scripts : ['//localhost:7100/main.js' ] }, container : '#yourContainer2' , activeRule : '/yourActiveRule2' , }, ]); start ();
Read more 服务器小技巧 2021-04-20服务器操作小技巧SSH免密登录服务器
在本地(非服务器)终端输入命令生成密钥对 ssh-keygen -t rsa
将公钥复制到远程主机 ssh-copy-id 用户名@服务器地址, ssh-copy-id 会将公钥写到远程主机的 ~/.ssh/authorized_key文件中
本地ssh 用户名@服务器地址 免密码登录
生成ssh公钥用于各种Git服务
ssh-keygen -t ed25519 -C "xxxxx@xxxxx.com" 邮箱名随便起, ed25519是公钥名字防止和rsa重复
三次回车
cat ~/.ssh/id_ed25519.pub查看文件内容或者通过open打开目录去找
复制 ed25519.pub里面的内容贴到Git网站上面的SSH
Read more Vue的虚拟DOM和Diff算法 2021-01-01Vue的虚拟DOM和Diff算法 从snabbdom开始 snabbdom 一个著名的虚拟DOM库,核心代码200行,极度优化。
snabbdom Github地址
Read more 算法笔记 2020-09-04
算法笔记算法复杂度时间复杂度
渐进时间复杂度通常用大写O来表示,因此也被叫做大O表示法。
时间复杂度就是把程序的相对执行时间函数T(n)转化为一个数量级,这个数量级可以是1、n、n^2、logn等。
推导时间复杂度的几个原则:
1.如果运行时间是常数量级,则用常数1来表示
2.只保留时间函数中的最高阶项
3.如果最高阶项存在,则省略最高阶项之前的系数
js如何实现链表js链表实现
Read more EggShellDecorators源码解析 2020-08-11
准备工作:
1.首先fork一份代码到自己仓库并下载,主要用于边解析边做注释用 egg-shell-decorators
2.本地创建一个eggjs项目 用于分析参数及测试 npm init egg -type=ts
3.启动一个空白的ts项目 用于打印解析语法
解析开始根据文档开始使用,router.ts里面引入EggShell 将app做参数传递执行EggShell
看下蛋壳源码 index.js 发现EggShell是一个类,并且里面只有一个for循环,循环的是一个Map实例 ctMap的value的遍历,此时这个ctMap是空的,所以暂时没有任何作用,我们发现ctMap跟MethodHandler有关系。
index.js文件引入了一个类并进行了实例化 *const* methodHandler = new MethodHandler(ctMap); 在文件结尾将这个实例的方法一一导出,所以估计应该是这个实例对ctMap进行了操作,增加了一些东西,继续往下看
1234567891011121314module.exports = { EggShell, Get: methodHandler.get(), Post: methodHandler.post(), Put: methodHandler.put(), Delete: methodHandler.delete(), Patch: methodHandler.patch(), Options: methodHandler.options(), Head: methodHandler.head(), Middleware: methodHandler.middleware(), Prefix: ctHandler.prefix()};
来到 method-handler.js文件,可以看到 MethodHandler 这个类定义了许多方法,get、post等方法使用的都是同一种方法。方法名使用symbol做了特殊处理,核心方法是 mappingRequest 方法。
mappingRequest 方法里面,path是装饰器使用时候传递的参数,照常理和使用文档,path是路由地址。mthod是不同方法的类型,比如get、post,使用get、post等方法的时候调用此函数,顺便将请求类型一起传递过去。
mappingRequest 这个方法做了什么事呢:
1.将target 方法体作为key和value放入了cMap
2.使用 Reflect.defineMetadata 将path和请求方法放入到装饰器装饰的方法中
cMap是公共变量,此时调用了诸如Get、Post的装饰器,其已经加入cMap
回到EggShell继续,开始for of 循环map
循环的每一项如下:
c的结构如下
c BaseContextClass {
pathName: ‘controller.home’,
fullPath: ‘/Users/xaviershi/Desktop/WEB/TS/eggjs-egg/app/controller/home.ts’
}
c BaseContextClass {
pathName: ‘controller.test’,
fullPath: ‘/Users/xaviershi/Desktop/WEB/TS/eggjs- ...
Read more