一些问题的记录
javascript vue react 前端
正向代理 & 反向代理
详情可以看这篇文章https://zhuanlan.zhihu.com/p/464965616
主要区别:
1. 直接访问
浏览器的请求直接到了最终生成网页的服务器, 中间没有经过任何的 http 代理服务器
2. 正向代理(forward proxy)
一个正向代理服务器并没有直接响应请求的能力, 它不过是把请求转发到最终的网页服务器上, 再把后者的响应再转发给请求者, 也就是浏览器。
正向代理是由客户端自己配置的,浏览器也能知道走了代理服务器。
最常见的例子就是 VPN。
3.反向代理(reverse proxy) 反向代理与正向代理的一个很大区别就是, 它不需要客户端(浏览器)去做什么配置, 并没有什么配置代理服务器的操作。
比如客户端的请求发送给了一台nginx服务器,nginx 内部对请求做了转发,再将结果返回给浏览器,对浏览器来说这一切都是透明的,它无从知道自己是否被代理了。
最常用的场景就是做负载均衡。
v-text 和 v-html 区别
v-text 实际上是改变了元素的textContent属性,而v-html改变的元素的innerHtml属性,所以v-html可以渲染出html元素。
this
ES6 class 内默认严格模式,内部的方法 this 默认不会指向 window,会指向 undefined; Babel 转义的代码也会默认加上’use strict’,this 默认也会指向 undefined this 的四种绑定规则
- 默认绑定 即独立执行 foo()
- 隐式绑定 被一个对象执行 obj.foo(), 此时 this 指向 obj
- 显式绑定 call/apply/bind foo.call(“niko”), 此时 this 指向 String(“niko”)
- new 绑定 new Foo() => 创建一个新对象 并且赋值给 this
虚拟 DOM 的主要作用
- diff 算法 最小化更新 减少渲染开销
- 跨平台开发
- React 官方文档提到,虚拟 DOM 使 React 声明式编程
PWA
有些脚手架生成的项目默认会带上一些 PWA 的配置,比如各种尺寸的 logo,manifest.json 文件。
- PWA 全程 Progressive Web App, 渐进式 Web 应用
- 一个 PWA 应用首先是一个网页,可以通古 Web 技术编写出一个网页应用。
- 随后添加上 App Manifest 和 Service Worker 来实现 PWA 的安装和离线等功能;
- 这种 Web 存在的形式,也称之为 Web App;
应用
比如说在手机端(基本都是 Android 端,ios 有各种限制),Chrome 浏览器,打开一个网页后,如果该网页有 PWA 配置,就可以将该网页添加至桌面图标,像一个原生 app 一样。
- manifest 文件里配置了各个尺寸适配的桌面图标,应用名称等各种信息。
- Service Worker 可以缓存网页的信息,可以做到断网时离线打开。
- PWA 还能实现消息推送等一些 native app 有的功能。
js 的 label 语法
多层循环的时候,break、continue 可以直接跳出指定的循环。
var num = 0;
start: for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
if (i == 5 && j == 5) {
break start;
}
num++;
}
}
console.log(num); //55
var num = 0;
start: for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
if (i == 5 && j == 5) {
continue start;
}
num++;
}
}
console.log(num); //95
Vue React 的区别
渲染过程
-
Vue
template -> render() -> render 函数内使用 h(‘div’, {class: ‘test’}, children) -
React
render() -> jsx 通过 babel 转化成 React.createElement(‘div’, {class: ‘test’}, children)
数据管理
-
Vue
Object.definProperty()/Proxy 数据劫持,数据改变时自动调用 render() -
React
手动调用 setState(),setState 时会去调用 render()
html 中 label 标签及它的 for 属性
abel 中的 for 属性规定了 label 与哪个表单元素绑定。for 属性的值和表单元素的 id 值一样,即可完成该 label 标签与该表单元素的绑定。
<label for="test">test</label> <input type="" name="" id="test" />
此时该 label 便签和 input 便签完成了绑定,当鼠标点击“test”时,input 元素会被触发,用户即可完成输入,提高了用户体验。
PS: input、select、textarea、button 和 h5 的 datalist、keygen、output。 其中当 label 标签和 select 标签绑定后,点击 label 标签文本内容,不能触发 select 便签。
calc(100%-100px)不加空格不生效的问题
<!--这样是不生效的-->
<div style="width: 200px;height:200px;background: tomato">
<div style="height:100px; width:calc(100%-100px); background: #bfa"></div>
</div>
<!--这样是不生效的-->
<div style="width: 200px;height:200px;background: tomato">
<div style="height:100px; width:calc(100% - 100px); background: #bfa"></div>
</div>
分割规则:
DIMENSION: {num}{ident}
ident: [-]?{nmstart}{nmchar}*
nmstart: [_a-z]|{nonascii}|{escape}
nmchar: [_a-z0-9-]|{nonascii}|{escape}
nonascii: [^\0-\237]
unicode: \\[0-9a-f]{1,6}(\
\
|[ \
\
\ \f])?
escape: {unicode}|\\[^\
\
\f0-9a-f]
calc(100%-100px)
手动解析一下 calc(100%-100px)。先过 DIMENSION 语法,{num}{ident}将其分割为 num:100、ident:%-100px。 其实,应该是%和-100px,两个被作为单位解析。因为-100px 符合 nmchar 语法,没有将其拆分。如果-100px 有个空格,就会拆分为-和 100 以及 px。但是这个例子,只能较好的解释为什么在-后面加空格。为什么前面也要加空格?
calc(100px-100px)
在编译时时,会将其直接拆分为 100 和 px-100px,将 px-100px 过 nmchar 完全符合[_a-z0-9-]。将其保留作为单位解析。但是 px-100px 不属于 CSS 中任何一个单位,也并无单位的定义。(这个案例,会更加好的解释,为什么-的前后都需要加空格。)如果-的前后有空格,就会被拆分为 100px(数字 100 和单位 px)、-、100px(数字 100 和单位 px)来解析。
原因
为什么要把-放在里面?写成 calc(100% -100px)或者 calc(100px -100px)为什么不行?在这里,要引入一个正负数的概念,因为在数学标识符当中还有正号和负号这两个标识符。光看 calc(100% -100px)和 calc(100px -100px)的后半部分,-100px 是不是更像是这里为-100 和 px。因为在 CSS 中是有负数的概念的,就像 margin 和 padding 中会常常用到负数。再引出一个新的例子:
width: calc(500px - -100px);
如果没有对于负号的定义应该就会 500px、-、-、100px,两个减号怎么编译呢。在-的前后都加上空格,区别开减法和负号。
bundle chunk verdor
bundle 指的是整体的打包产物,包含 JS 和各种静态资源。 chunk 指的是打包后的 JS 文件,是 bundle 的子集。 vendor 是指第三方包的打包产物,是一种特殊的 chunk。
ESM & CJS
首先 ESM 模块可以引入 ESM 模块,CJS 模块可以引入 CJS 模块。 如果是不同的模块格式:
// index.cjs
const { add } = require("./util.mjs");
async function foo() {
console.log(add(1, 2));
}
foo();
// index.mjs
import { add } from "./util.cjs";
export function foo() {
console.log(add(1, 2));
}
foo();
// util.cjs
function add(a, b) {
return a + b;
}
module.exports = { add };
// util.mjs
export function add(a, b) {
return a + b;
}
进入 esm-cjs 目录中执行 node index.mjs,代码能够正常执行,说明 ESM 模块是能够直接引入 CJS 模块的。
但如果反过来,执行 node index.cjs,就会产生报错,说明 CJS 模块并不能直接引入 ESM 模块。
其中的根本原因就在于: CJS 模块是通过 require 进行同步加载的,而 ESM 模块是通过 import 异步加载。同步的 require 方法并不能导入 ESM 模块。
将 index.cjs 的内容修改如下:
async function foo() {
const { add } = await import("./util.mjs");
console.log(add(1, 2));
}
foo();
当我们把 require 方法改成 await import 的方式之后,代码能够正常执行了。不过需要注意一个关键的前提,在 CJS 中导入 ESM 的时候,必须要有异步的执行环境,否则是无法导入 ESM 模块的。