幸いですlog

前端

description
Created
Aug 18, 2022 02:38 AM
Updated
Last updated August 18, 2022
Tags

CSS

1、padding与margin有什么不同

  • padding内边距,针对于自身
  • margin外边距,作用域外部对象

2、vw与百分比

  • vw只跟屏幕的分辨率有关系,
  • 百分比是参照父级元素

3、快速居中对齐

  • display: flex; margin: auto
  • display: flex; flex-column: center
  • display: inline-flex; align-items: center;justify-content: center;
flex: 将对象作为弹性伸缩盒显示 inline-flex:将对象作为内联块级弹性伸缩盒显示

4、行内与块级元素

  • 行内宽度由内容决定
  • 块级宽度继承父级

5、如何让字体变得更小

  • Transfrom: scale(0,5) 缩放

js

1、let 与var

  • var
// 1.声明提升=> 先上车后买票 console.log(name)// test var name = 'test' //2.没有局部作用域 =》红杏出墙 function fn2(){  for(var i = 0; i < 5; i++ ){ }  console.log(i) //6 } fn2() //3.声明覆盖 = 》套牌车 var name1 = "abc"; var name1 = "bbb"; console.log(name1) // bbb

2、深拷贝与前拷贝

// 数组与对象的赋值都叫浅拷贝 (藕断丝连)下贱 let arr = [1,2,3] let newArr = arr; newArr.push(4) console.log(arr, newArr) // 1,2,3,4   1,2,3,4 // 解构赋值 //针对一维数组和对象可以看到是深拷贝,多维的就是浅拷贝 let arr = [1,2,3] let newArr = [...arr] newArr.push(4) console.log(arr, newArr) // 1,2,3   1,2,3,4 let arr2 = [[1,2,3],[4,5,6]] let newArr2 = [...arr2]; newArr[0].push(88) console.log(arr, newArr) // [1,2,3,88],[4,5,6]   [1,2,3,88],[4,5,6]
深拷贝: JSON.parse(JSON.stringify(value)); =>只能满足80%场景,方法不能copy
//标准深拷贝 => 引用数据类型(数组,对象) function deepClone(source) {  // [] => Array(基类) {} => Object  const targetObj = source.constructor === Array ? [] : {};  for(let keys in source) {    if(source.hasOwnProperty(keys)){ //判断有没有当前属性      // keys => 3种类型、      // 引用数据类型      if(source[keys] && typeof source[key] === 'object'){        // 递归       targetObj[keys] = deepClone(source[keys]);     } else {        //基本数据类型,直接赋值        targetObj[keys] = source[keys];     }   } }  return targetObj; }

3、ArrayBuffer

JavaScript 中最基础的二进制对象 ArrayBuffer,可以表示对固定长度的连续内存的引用,但是用户不能直接操作这块内存,必须通过 "View Object" 来操作。
let buffer = new ArrayBuffer(16); // 创建长度为 16 byte 的连续内存
其中 “View Object" 大致可以分为两类
  • TypedArray
  • DataView
TypedArray 有一下几种
  • Uint8Array, Uint16Array, Uint32Array
  • – for unsigned integers of 8, 16, and 32 bits.
  • Uint8ClampedArray
  • – for 8-bit integers, “clamps” them on assignment.
  • Int8Array, Int16Array, Int32Array
  • – for signed integer numbers (can be negative).
  • Float32Array, Float64Array
  • – for signed floating-point numbers of 32 and 64 bits.
      notion image
  • Unit16Array 表示为使用 16 bits (2 bytes) 表示一个无符号整型 (0 ~ 2^16-1) 的数的数组
  • Int8Array 表示使用 8 bits 表示一个有符号整型 (-128 ~ 127)
  • Float32Array 表示使用 32 bits 表示一个浮点数
  • Unit7ClampedArray 在 0 ~ 255 范围内和 Unit8Array 是一样的,对超出范围的处理有所不同,和图像处理相关(一般像素范围也是 0 ~ 255)

4、this的指向问题

指向上一个调用者
console.log(this) //window function a() {  console.log(this) //window } window.a() let o = {  userName: '张三',  fn: function(){   console.log(this) } } o.fn(); //张三 var obj = {  userName: '张三',  fn: function(){   console.log(this.username) } } obj.fn() //张三 var j = {  a: 10,  b: {    a: 12,    fn function() { console.log(this.a) } } } j.b.fn();
箭头函数没有作用域 没有this
var id = 66; function fn5() {  setTimeout(()=>{    console.log(this.id) },500) } //fn5({id:22}) fn5.cell({id:22}) // bind() 不调用 只改变this指向 //call ,apply() 改编后 并且执行一次 // apply => [] call=>{}

5、闭包

  • 避免变量被污染
  • 私有化
  • 保存变量、常驻内存
  • Active Object
  • 闭包的场景> 防抖、节流、库的封装(保证数据私有性)

通信

1、在浏览器中输入URL并回车后都发生了什么?

例如:https://www.baidu.com => 统一资源定位符(url),俗称网址
www:万维网
Https:超文本传输协议
baidu.com:域名
  • 第一次访问
  • 解析url。
  • 建立连接
    • tcp的三次握手(不是正式数据,完成3次握手之后,才开始传输数据。一旦建立,在任何一方关闭前,会一直保持下去)
      • 第一次:客户端向服务端发送syn包(seq=x),并进入SYN_SENT状态,等待确认
      • 第二次:服务端收到syn包,同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态
      • 第三次:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
  • 拿数据、渲染页面
  • 发完数据就会断开连接,(连续的可以使用websorket)
    • 四次挥手
      • 第一次:主动关闭放发送一个fin(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可以接受数据
      • 第二次:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)
      • 第三次:被动关闭方发送一个FIN,用来关闭数据传送,
      • 第四次:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号1
  • 第二次访问
  • 读区浏览器缓存

html

1、页面渲染

  • Reder tree
    • 并行构建
      • html: dom树 (display:none可以让页面渲染的更快)
      • Css: 结构体

性能优化

  • 加载
    • 减少http请求(精灵图,文件的合并)
    • 减少文件大小(资源压缩、图片压缩,代码压缩)
    • CDN(第三方库、大文件、大图)
    • SSR服务端渲染、预渲染
    • 懒加载
      • 获取设备的高度
      • 判断图片是否在可视范围内
      • <!-- data-src真实的url-><img src='./imag2/time.gif' data-src= './img2/time.jpg' alt =''><img src='./imag2/time.gif' data-src= './img2/time2.jpg' alt =''><img src='./imag2/time.gif' data-src= './img2/time3.jpg' alt =''><img src='./imag2/time.gif' data-src= './img2/time4.jpg' alt =''><img src='./imag2/time.gif' data-src= './img2/time5.jpg' alt =''><sript> let num = document.getElementByTaName('img').length; //5 let img = document.getElementByTaName('img'); let n = 0; lazyLoad(); window.onscroll = lazyLoad; function lazyLoad(){ const seeHeight = document.documentElement.clientHeight; //可见区域 const scrollTop = document.documentElement.scrollTop|| document.body.scrollTop  for(let i = n; i < num; i++){ if(img[i].offsetTop < seeHeight + scrollTop){ if(img[i].getAttribute("src") === "./img2/time.git") { img[i].src = img[i].getAttribute("data-src") } n = i + 1; } } }</sript>
    • 分包
  • 减少dom操作、避免回流,文档碎片

1、页面加载性能

  • 加载时间、用户体验

2、内存占用

  • 内存占用过大、浏览器崩掉等

3、动画与操作性能

  • 是否流畅无卡顿

4、电量消耗

  • 游戏方面、暂不考虑

WebPack

Typescript: ts文件使用tsc将Typescript代码转为js代码
React/Vue: 安装React-compiler/vue-compiler 讲jsx文件或.vue文件转换为render函数
Less/sass/postcss/compoent-style: 我们需要安装less-loader, sass-loader等一系列编译工具
语法降级:babel --->将es的新语法转换旧版浏览器可以接受的语法
体积优化:uglifyjs --> 将我们的代码进行压缩变成体积更小性能更高的文件。
稍为改动,
将app.tsx --> tsc --> app.jsx --> react-complier --> js文件
有一个东西能够帮你吧tsc, react-complier ,less ,babel,uglifyjs 全部集成到一起
我们只需要关心我们的写的代码就好了——构建工具。
浏览器支持esmodule
<script type='module'> </script>

构建工具

yarn add webpack webpack-cli --dev

vite

打包:将我们系的浏览器不认识的代码、交给构建工具进行编译处理的过程叫做打包,打包完成以后会给我们一个浏览器可以认识的文件。
1、模块化支持、支持可以从node_modules引入代码+ 多种模块化支持。
2、处理代码兼容性,构建工具将于发对应的工具集成进来,自动化处理。
3、优化开发体验,
-构建工具会帮你自动监听文件的变化。当文件变化以后自动帮你调用对应的集成工具进行打包,然后在浏览器重新运行——热更新
-开发服务器:跨域的问题,用react-cli create-reat-element vue-cli 解决跨域问题
4、提高项目性能:压缩文件,代码分割。
不用每次都关系我们的代码在浏览器如何运行,我们只需要首次给构建工具提供一个配置文件,有了这个集成的配置文件以后,我们就可以在下次需要更新的时候调用一次对应的命令就好了,如果我们结合热更新,我们就更加不需要管任何东西,这就是构建工具去做的东西。
然而,当我们开始构建越来越大型的应用时,需要处理的 JavaScript 代码量也呈指数级增长。包含数千个模块的大型项目相当普遍。我们开始遇到性能瓶颈 —— 使用 JavaScript 开发的工具通常需要很长时间(甚至是几分钟!)才能启动开发服务器,即使使用 HMR(热更新),文件修改后的效果也需要几秒钟才能在浏览器中反映出来。如此循环往复,迟钝的反馈会极大地影响开发者的开发效率和幸福感。
项目越大--->webpack处理的js代码就越多
造成的结果:构建工具需要很长时间才能启动开发服务器

为什么webpack不能改

webpack支持多种模块化
const lodash = require('lodash') //commonjs import Vue from 'vue';//es6 es module ⬇️转换 webpack的编译原理,AST抽象语法分析工具 分析出你写的这个文件有哪些导入和导出操作 构建工具是运行在服务端的 const lodash = webpack_require('lodash') const Vue = webpack_require('vue'); webpack解析 (function(modules){ function webpack_require(){} //入口index.js //通过webpack的配置文件得来的:webpack.config.js ./src/index.js modules[entry](webpack_require); },({ "./src/index.js":(webpack_require)=>{ const lodash = webpack_require('lodash') const Vue = webpack_require('vue'); } }))
vite是基于es modules的,侧重点不一样,webpack更多关注兼容性。
Web pack先加载、在启动服务器(为什么要加载完?webpack支持多种模块化、她一个开始必须要统一模块化代码,所以意味着她需要将所有的依赖全部读一遍)
vite先开启开发服务器、按需加载需要的依赖。

安装问题

Vue-cli 内置了webpack
create-vite内置了vite
不需要做额外的配置就可以开箱即用。

导入

//既然最佳实践是node_modules,为什么e s官方在我们导入非绝对路径和非相对路径的资源的时候不默认帮我们搜寻node_modules呢?
浏览器中⬇️
Es module要么是绝对路径要么是相对路径,没有引入可能还import其他东西
vite查找方式依次向上查找

缓存

实际上vite在考虑另外一个问题的时候就顺便把这个问题解决了

依赖预构建:

首先vite会找到对应的依赖、然后调用esbuild,将其他规范的代码转换为esmodule规范,然后放到当前目录下的node_modules/.vite/deps,同时对es module规范的各个模块进行统一集成

解决3个问题:

1、不同的第三方包会有不同的导出格式。
2、对路径的处理上可以直接使用.vite/deps,方便路径重写。
3、叫做网络多包传输的性能问题(也是原声esmodule规范不敢支持node_modules的原因之一),有了依赖预构建以后无论他有多少的额外export和import ,vite都会尽可能的将将他们进行集成最后只生成一个或者几个模块。
Vite.config.js=webpack.config.js
export { default as a } from './a.js' import a from './a.js' export const a = a; vite重写以后 function a() { }
// vite.config.js export default { optimizeDeps: { //将指定数组中的依赖不进行预构建 exclude: ['lodash-es'] //当遇到lodash-es时不进行依赖构建。 } }

vite配置文件处理细节

1.vite配置文件的语法提示
1、如果使用的是webstorm,可以得到很好的语法不全
2、如果是vs code或者其他编辑器、需要进行一些特殊处理
2、环境配置处理
//策略模式 const envResolver = { "build": () => {}, "serve": () => {}, } envResolver["build"]();
vite内置了dotenv这个第三方库
dotenv会自动读取.env文件,并解析这个文件中的对应环境变量 并将其注入到process对象下(但是vite考虑和其他配置的一些冲突问题、他不会直接注入到process对象下)
涉及vite.config.js中的一些配置
  • root
  • envDir: 用来配置当前环境变量的文件地址
vite给我们提供了一个些补偿措施:我们可以调用vite的loadEnv来手动确认env文件
Process.cwd方法:返回当前node进程的工作目录
.env:所有环境都需要用到的环境变量
.env.development: 开发环境需要用到的环境变量(默认情况下vite将我们的开发环境取名为development)
.env.production: 生产环境需要用到的环境变量(默认情况下vite将我们的生产环境取名为production)
yarn dev --mode development 会将mode设置development 传递进来
当我们调用loadenv的时候,他会做如下几件事:
1、直接找到.env 并解析其中的环境变量 并放进一个对象里
2、会讲传进来的mode这个变量的值进行拼接: .env.development,并根据我们提供的目录去取对应的配置文件并进行解析,并放进一个对象。
3、我们可以理解为
const baseEnvConfig = 读取.env的配置
Const modeEnvConfig = 读取env相关配置
const loadEnv = {...baseEnvConfig,...modeEnvConfig}
如果是客户端,vite会讲对应的环境变量会注入到import.meta.env
vite做了一个拦截,他为了防止我们将隐私性的变量直接送进import.meta.env中,所以做了一层拦截,如果你的环境变量不是以VITE开头的,就不会帮你注入到客户端、如果想要改这个变量,可以去envPrefix配置。
为什么vite.config.js可以书写成es module的形式、这是因为vite他在读取这个vite.config.js的时候会率先node去解析文件语法,如果发现你是esmodule规范会直接将你的esmodule规范进行替换变成commonjs规范

vite是怎么让浏览器可以识别.vue文件的。

yarn install vite yarn create 实际上就等于在安装create-vite脚手架,然后使用脚手架的指令去构建项目
实现一套简单的vite的开发服务器
1.解决我们刚刚的这个问题。
2.让大家对开发服务器的原理层面有一个基础的简单认识
会涉及到node的一些知识。
Koa: node端的一个框架
那么我们平时去访问一个网页的时候,我们敲下域名:baidu,com
//当请求来临以后会直接进入到use注册的回调函数 app.use(async (ctx)=> {//context 上下文request -->请求信息 响应信息 get请求/ console.log("ctx",ctx.request,ctx.response) //用中间 if(ctx.request.url === "/") { //这意味着其他人在找我们要跟路径的东西,比如你访问baidu.com console.log("////",path.resolve(_dirname,"./index.html")) const indexContent = await fs.promises.readFile(path.resolve(_dirname,'./index.html'));//服务端一般 console.log("indexContent",indexContent.toString()); ctx.response.body = indexContent //作为响应体发给对应的请求的人 //你响应体是填充好了,那你要以什么形式发给他呢?你希望对方拿到你的东西的时候以什么方式 //json ---> application/json text/html ctx.response.set("content-type","text/html"); //比如后台给我们一个获取用户信息的接口 if(ctx.request.url === '/api/getUserInfo') { //去数据库找到用户信息然后返回前端 } } }) //服务端采用文件流的方式操作

Vite天生就支持对css文件的直接处理

1、vite在读取到main.js中引用到index.css
2、直接使用fs模块去读区index.css中文件内容
3、直接创建一个style标签,将index.css中文件内容直接copy进style标签里
4、将style标签插入到index.html的head中
5、将该css文件的内容直接替换为js脚本(方便热更新或者css模块化),同时设置content-type为js,从而让浏览器以js脚本的形式来执行该css后缀的文件。

场景:

一个组件最外层的元素一般取名:wrapper
一个组件最底层的元素类命名我们一般取名: .footer
你取了footer这个名字,别人因为没有看到你的这个组件的源代码。也可以去取名footer
cssmodule可以解决这个问题。
全都是基于node
1、module.css(module是一种约定、表示需要开启css模块化)
2、他会将你的所有类名进行一定规则的替换(将footer 替换成 _footer_i22st_1)
3、同时创建一个映射对象{footer: " _footer_i22st_1"}
4、将替换过后的内容塞进style标签里然后放入到head标签中(能够读到index.html的文件内容)
5、将compoentA.modules.css内容进行全部抹出、替换成js脚本
5、将创建的映射对象在脚本中进行默认导出。
Less(预处理器):less给我们提供了一些方便且非常实用的方法。
嵌套

Vite.config.js

在 vite.config.js中通过cs s属性去控制整个vite对于css的处理行为
  • localConvention(改变key的展示方式。驼峰、下划线、中划线)
  • scopeBehaviour 配置当前的模块化行为是模块化还是全局化(local,global)
  • hashPreFix: 生成hash会根据你的类名+一些其他的字符串(文件名+内部随机生成一个字符串)进行生成,如果你想要你生成hash更加的独特一点,你可以配置hashPreFix,你配置的这个字符串会参与到最终的hash生成,(hash: 只要你的字符串有一个字不一样,那么生成的hash就完全不一样,但是只要你的字符串完全一样,生成的hash就会一样)
  • globalModulePaths: [] 代表你不想要参与css模块化
// vite.config.js import {defineConfig} from 'vite'; export default defineConfig { optimizeDeps: { //将指定数组中的依赖不进行预构建 exclude: [] } css: { //对css的行为进行配置 //配置最终会传给postcss modules modules: { //对css模块化的默认行为进行覆盖 localConvention: "camelCase", scopeBehaviour: "local", generateScopeName: "[name]_[local]_[hash:5]", hashPreFix: "hello" } } }

Vite配置文件中css配置流程(preprocessorOptions篇)

主要是用来配置css预处理的一些全局参数。
// vite.config.js import {defineConfig} from 'vite'; export default defineConfig { optimizeDeps: { //将指定数组中的依赖不进行预构建 exclude: [] } css: { //对css的行为进行配置 //配置最终会传给postcss modules modules: { //对css模块化的默认行为进行覆盖 localConvention: "camelCase", scopeBehaviour: "local", generateScopeName: "[name]_[local]_[hash:5]", hashPreFix: "hello" }, preprocessorOptions: {// key + config key 代表预处理的名 less: {//整个的配置对象斗鱼最终给到less的执行参数(全局参数)中去 //假设没有使用构建工具,我们又想去编译less文件的话 math:"alawys" global:"全局变量"{ mainColor: red } }, sass: { } } } }
yarn add less # less的编辑器
你只要安装了node, 你就可以使用node index.js
你只要安装less 你可以使用lessc去编译less文件
less是可以定义变量

sourceMap

文件之间的索引:
假设我们的代码被压缩或者被编译过了,这个时候假设程序出错,他将不会产生正确的错误未知信息 如果设置了sourceMap,他就会有一个索引文件map

Postcss

他的工作基本和全屋净水系统一直,保证css在执行起来是万无一失的。
:root { // css的新提案:css变量 --globalColor: green; }
隐患:
系统兼容性你能考虑到吗?预处理器并不能解决这些问题:
Babel-->帮助我们让js执行起来万无一失
class App{} //es6的写法 转换为function App () {} //es3的语法
1、对未来css属性的一些使用降级问题
2、前缀补全:google非常卷 --webkit
Postcss 将语法进行编译转成原生css、在次对未来的高级css语法进行降级\前缀补全。
Babel 类型 将ts转换成js,然后再对语法进行降级。

安装

Yarn add postcss-cli postcss -D

配置

Posts.config.js

module.export = { plugins: [ postcssPresetEnv: path.resolve(__dirname,"varible.css")//让postcss知道那些全局变量需要储存下来 ] }
业内一个新的说法:postcsss是后处理器
// vite.config.js import {defineConfig} from 'vite'; export default defineConfig { optimizeDeps: { //将指定数组中的依赖不进行预构建 exclude: [] } css: { //对css的行为进行配置 //配置最终会传给postcss modules modules: { //对css模块化的默认行为进行覆盖 localConvention: "camelCase", scopeBehaviour: "local", generateScopeName: "[name]_[local]_[hash:5]", hashPreFix: "hello" }, preprocessorOptions: {// key + config key 代表预处理的名 } devSourceMap: true, postcss: {//或者新建一个postcss.config.js plugins: [postcssPresetEnv()] } } }
yarn dev vite

文件读取

node端去读区文件或者操作文件的时候,如果发现用的是相对路径、则会去使用process.cwd()来进行对应的拼接
process.cwd:获取当前的node执行目录
const path = require("path") //path 本质上就是一个字符串处理模块、它里面非常多的路径字符串处理方法

曾经也有 个和你一样的人来过这里。

「姿や形は問題ではなく、「魂」が問題です。」

Vercel Logo

「健全なる魂は健全なる精神と健全なる肉体に宿る。」

「あなたの魂、受け取りました。」

VercelVercel

本站累计 3782 次访问

Clover © 2022 幸いです 全著作権所有.