JavaScript核心

闭包和作用域

  1. 实现一个防抖或节流函数
    延迟执行,频繁触发,只有最后一次生效
    场景:等待用户操作完成后执行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    fucntion debounceFn(fn, delay) {
    let timer = null;
    return function(...args) {
    timer && clearTimeout(timer);
    timer = setTimeout(() => {
    fn.apply(this,args);

    }, delay)
    }
    }

    节流: 控制执行频率,固定时间段触发
    场景:滚动、拖拽、窗口调整
    定时器版本
    function throttleFn(fn, delay) {
    let timer = null;
    return function(...args) {
    if (!timer) {
    timer = setTimeout(() => {
    fn.apply(this,args);
    //执行完毕以后清空定时器
    timer = null

    }, delay)
    }
    }
    }

    时间戳版本
  2. 闭包在模块化中应用

    • 立即执行函数 + 闭包
    • ES Modules export / import
      原生模块作用域
      模块化本质:通过作用域隔离和依赖管理,实现代码高内聚低耦合
  3. 如何避免闭包引起的内存泄漏
    及时解除引用:手动将变量设为null
    不要引用多余的变量
    注意dom元素的引用,可以只引用dom的某个属性,而非整个dom对象
    合理使用模块化和类: 通过类的生命周期管理闭包,在不需要时主动清理
    避免在循环中创建闭包:把函数作为入参

    • 浏览器的垃圾回收机制
      被闭包引用的变量无法被垃圾回收机制识别为不再使用

      找出不再被程序引用的对象,释放他们所占用的内存

      如何找出:
      判断标准:

    • 类的生命周期

原型和继承

  1. 实现一个继承方案并比较各种继承方式的优缺点
    • 原型链继承
    • 构造函数继承
    • 组合继承
    • 原型式继承
      1
      2
      3
      4
      5
      function createObject(proto) {
      function F() {}
      F.prototype = proto;
      return new F();
      }
    • ES6 Class 继承
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      Class Parent {
      constructor(name) {
      this.name = name;
      }

      sayName() {

      }
      }

      Class Child extends Parent {
      constructor (name, age) {
      super(name);
      this.age = age;
      }
      }
  2. new操作符的内部实现原理
    • 创建了一个空对象
    • 将新对象的原型指向构造函数的prototype
      obj.proto = constructor.portotype
    • 绑定this并执行构造函数
    • 返回执行结果,如果执行结果不是对象或者null 返回新创建的对象
    1
        
  3. Class与原型继承的区别

异步编程

  1. Promise实现原理以及手写Promise

  2. async/await 底层实现原理
    基于Generator函数和Promise实现的
    async 函数 相当于自动执行的generator函数,无需手动调用next()
    await 会暂停函数执行,等待右侧表达式的Promise完成状态变更

  3. 如何处理多个并行异步请求的错误
    Promise.all(promises)
    Promise.allSettled(promises)

后端语言java、golang

React

  1. useEffect和useLayoutEffect得区别
    主要区别于他们的触发时机
    useEffect: 在渲染完成后异步执行,不会阻塞浏览器的绘制操作
    useLayoutEffect:比useEffect早一些,在浏览器绘制操作之前同步执行
  2. hooks的了解
  3. useCallBack和useMemo的区别

JS

  1. 判断数据类型有哪些
    什么类型的数据没有constructor

亮点

  1. 低代码
  2. 插件
  3. 公共的业务组件

Vue3 比Vue2提升在哪里 https://blog.csdn.net/weixin_44727080/article/details/112977564

1、性能快了1.2-2倍

    1、diff算法的优化
      vue2的虚拟dom是进行全量比较的
      vue3新增静态标记,在于上次虚拟节点比较的时候,只对比***带有patch flag***的节点
    2、静态提升
      vue2 无论元素是否参与更新,每次都会被重新创建,然后再渲染
      vue3.0 对于不参与更新的元素,会做**静态提升hoistStatic(会这些节点从render中提取出来,变成了全局变量)**,只会被创建一次,在渲染时直接复用即可
    3、事件侦听器的缓存
    4、ssr渲染
       当有大量静态的内容时候,这些内容会被当做纯字符串推进一个buffer里面,即使存在动态绑定,会通过模板插值嵌入进去,这样会比通过虚拟dom来渲染的快很多很多。
       当静态内容达到一定量级时候,会用_createStaticVNode方法在客户端去生成一个static node,这些静态node,会被直接innerHtml,就不需要创建对象,然后根据对象渲染。

2、支持按需编译、按需导入,比vue2x体积小

    体现在4个方面
      1、更高效的**tree-shaking**https://www.jb51.net/article/282641.htm
      tree-shaking 移除掉项目中永远不会执行的代码dead code; 其实现原理是依赖于ES6的模块特性,因为ES6模块的依赖关系的是确定的,静态的与运行状态没有关系,可以做静态分析
       采用了新的模板编译方式
      2、支持模块化
       Vue3全面支持ES模块化,并且通过使用**ES模块系统来组织和加载代码**。相比之前的Vue2,这种模块化的方式更加轻量化。通过将应用程序拆分为多个独立的模块,可以更好地管理代码,并且在开发过程中可以更方便地共享和复用模块。这样一来,就可以减少重复的代码,并且在构建过程中只需要打包使用到的模块,从而缩小了打包大小。
      3、静态组件提升
    异步加载组件的优化 **suspense内置组件**https://www.jb51.net/javascript/2880700uw.htm
      1、异步请求并行加载
      Vue3 Suspense 中的另一个优化技术是让异步组件懒加载并执行**提前预取**。
        通过**懒加载**,只有在使用时才会加载组件,而不是在页面初始加载时就把所有组件都加载好。
        通过执行提前预取,可以在没有等待用户点击前提前加载组件,以确保在需要时可以立即使用。
      
       

3、支持组合式api,类似于react中的hooks

vue中如何把model层的数据更新到view层

watch和computed的区别

webpack和vite的区别

vite: 其实现原理是利用es6的import会发送请求去加载文件的特性,拦截这些请求,做一些预编译,省去webpack冗长的打包时间
构建速度:vite在开发环境有快速的冷启动和热重载能力,基于ES模块导入原理,无需打包就可以实时编译
Webapck 则可以用于更复杂的构建任务
打包方式:vite是通过模块直接引入进行开发的,通过原生ES模块的形式可以直接在浏览器运行;webpack将所有的模块打包为一个或多个静态资源文件。
配置:
vite通过vite.config.js文件作简单的配置
webpack:配置复杂,
mode
entry
output
modules
optimization: 优化配置
webpack4以后会根据mode来执行不同得优化,所有得优化可以手动配置和重写
plugins:

  CleanWebpackPlugin: 打包前会清空build下的目录,避免保留一些不必要的文件
  progress-bar-webpack-plugin: 打包进度条美化
  **MiniCssExtractPlugin**:
  背景:css文件打包到js中,当js文件加载时,会创建一个style标签去生成样式;网络不好的情况下会出现闪屏现象,等js完全加载完以后,才会出来页面
  功能:会将css单独提取到一个文件中,为每个包含css的js文件创建一个css文件,并且支持css和sourceMaps的按需加载
  webpack-bundle-analyzer:打包可视化分析工具
  optimize-css-assets-webpack-plugin:优化css资源,压缩css文件
  CopyWebpackPlugin:单个文件或整个目录复制到构建目录



优化:减少打包时间
优化loader: 1、优化loader文件的搜索范围 include、exclude 
            2、可以将babel编译过的文件缓存下来,下次只需要编译更改过的代码即可
            
1
loader:'babel-loader?cacheDirectory=true'

vue3中ref、reactive的区别

ref和reactive区别:

如果在template里使用的是ref类型的数据,那么vue会自动帮我们添加.value,
如果在template里使用的是reactive类型的数据,那么vue不会自动帮我们添加.value。

vue是如何决定是否需要自动添加.value的?

vue在解析数据之前,会自动判断这个数据是否是ref类型,
如果是就自动添加.value,如果不是就不自动添加.value。

vue是如何判断当前的数据是否是ref类型的?

通过当前数据的**__v_ref**来判断的。如果有这个私有属性,并且取值为true,那么就代表是一个ref类型的数据。

开发人员如何判断当前的数据类型?

isRef和isReactive来分别判断是否是普通函数和对象。

setUp函数的执行时机和注意点

setup函数的执行时机:

 setup函数是在beforeCreate和created之间执行的。
 beforeCreate:表示组件刚刚被创建出来,组件的data和methods还没初始化号;
 created:表示组件刚刚被创建出来,并且组件的data的methods已经初始化好了。

setup注意点:

 ①由于在执行setup函数的时候,还没执行created生命周期方法,所以在setup函数中,是无法使用data和methods的。
 ②由于我们不能在setup函数中使用data和methods,所以vue为了避免我们错误的使用,他直接将setup函数中的this值修改为了Undefined。
 ③setup函数只能是同步,不能是异步的。

flex详细属性解析

flex:1 是三个属性的简写, flex: 1 1 0%;
flex-grow:定义项目的放大比例,默认为0
flex-shrink: 定义项目的缩小比例,空间不足,项目将缩小
flex-basis: 上面两个属性分配多余空间之前, 计算项目是否有多余空间, 默认值为 auto, 即项目本身的大小

谈谈对组件化的理解

promise是如何实现异步的

结合事件循环去解释

浏览器缓存

useEffect和useState的理解

useEffect是为函数组件处理副作用(dom操作、获取数据)的

封装过的组件

js中apply()、call()、bind()的区别

js中作用域和变量提升的理解

在es6之前没有块级作用域,只有全局作用域和函数作用域
es6提出let和const

为什么html文件中js引入要放到后面

对vuex(redux)的理解,如何实现的 (其实就是结构组成,内部联系)

是js中应用程序开发的状态管理模式, 组件之间用来传递数据的数据中心,
采用集中式存储管理所有组件的状态

Vuex提供了mapState、MapGetters、MapActions、mapMutations等辅助函数给开发在vm中处理store

利用vue的插件机制
vuex是利用vue的mixin混入机制,在beforeCreate钩子前混入vuexInit方法,vuexInit方法实现了store注入vue组件实例,并注册了vuex store的引用属性$store

处理过哪些浏览器兼容问题

前端如何实现响应式布局

1、

babel用来做什么的

是一个js代码编译器,将js中es5以上的语法转化为es5,兼容低版本浏览器的运行
比如es6中的箭头函数
工作流程:三步
解析parse(@babel/parser): 将源代码字符串转成抽象语法树(AST)
AST:以树状形式表现编程语言的语法结构
转换transform(@babel/traverse):通过@babel/traverse遍历抽象语法树(AST),并调用Babel配置文件中的插件,对抽象语法树(AST)进行增删改
生成generate(@babel/generator):通过@babel/generator把转换后的抽象语法书(AST)生成目标代码

什么是虚拟DOM

虚拟dom本质就是一个普通得js对象,用来描述视图得界面结构
diff算法的本质就是对比新旧VDOM树的变更差异

防抖和节流

防抖:是指触发事件在N秒内只执行了一次,1、如果在n秒内又触发了事件,则会2、重新计算函数得执行事件(执行最后一次),比如:表单元素得校验、模糊搜索等功能;

节流:一段时间内只能触发一次,如果这段时间内触发了多次事件,只有第一次生效会触发回调函数,一段时间过后才能再次触发;n秒内执行第一次

js实现深拷贝的方式

1、递归函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  //使用递归的方式实现数组、对象的深拷贝
export function deepClone (obj) {
let objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
//判断ojb子元素是否为对象,如果是,递归复制
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = deepClone(obj[key]);
} else {
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
};

2、JSON.stringify()
如果对象的属性是string、number、Boolean可以使用
缺点:
1、如果对象的属性是Date对象,转换后会变成字符串
2、属性中有RegExp正则或者Error对象,序列化后会变成空对象
3、属性中有function、undefined、symbol,则序列化的结果会把function、undefined丢失
4、JSON.stringify() 只能序列化对象的可枚举的自有属性,例如如果 obj 中的对象是有构造函数生成的,
则使用JSON.parse(JSON.stringify(obj)) 深拷贝后,会丢弃对象的 constructor;
5、如果对象中存在循环引用的情况也无法正确实现深拷贝,并且会导致死循环,最后抛出异常

3、loadsh中的cloneDeep方法
也是通过递归的思路实现的
4、jquery的extend()方法进行深拷贝(推荐在JQ中使用)Jquery自身携带extend

1
2
3
4
let obj = { a: { c: 2, d: [1, 3, 5], e: "哇哇哇" }, b: 4 };
let newObj = $.extend(true, {}, obj1);
//拷贝完成obj.b = 20;console.log(newObj.b); //输出 4

HTTP请求常用请求头以及http缓存方式

前端首屏加载优化方案&首屏空白问题如何解决

Map、Set、WeakMap之前的区别以及使用场景

iframe通信方式以及对应的使用场景

1.简历中的过往项目经历会展开来问包括技术点(注意逻辑及方法论)

2.核心优势中描述的技术点(必问),面试官考察是否如简历描述的那样熟悉
#1、vue\react
都是创建UI得javaScript库
基于组件开发
都使用虚拟DOM
TS
3.您了解或理解哪些常见的设计模式
设计模式是一套通用得可复用得解决方案,用来解决在软件设计中得通用问题
工厂模式:封装实例得创建过程
单例模式:全局只有一个实例,如TS
观察者模式:比较常见
迭代器模式:除了for和forEach,还有iterator
装饰器模式:
原型模式:原型和原型链是js基础知识
代理模式:如Vue3中得proxy

JS

1.用setTimeout实现一个setInterval

setInterval会将回调函数放在任务队列前还是任务队列后,取决于当前执行的上下文(JS运行环境)和其他任务得优先级
*使用递归函数,不断去调用setTimeout达到setInterval的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function mySetInterval(fn, millisec,count){
function interval(){
if(typeof count===‘undefined’||count-->0){
setTimeout(interval, millisec);
try{
fn()
}catch(e){
count = 0;
throw e.toString();
}
}
}
setTimeout(interval, millisec) //
}

2.怎么理解闭包的
闭包是能读取外层函数内部变量的函数
访问所在作用域
函数嵌套
在所在作用域外被调用
适用的场景:
1、返回值;

1
2
3
4
5
6
7
8
9
 	//1.返回值 最常用的
function fn(){
var name="hello";
return function(){
return name;
}
}
var fnc = fn();
console.log(fnc())//hello

2、函数赋值
1
2
3
4
5
6
7
8
9
10
  var fn2;
function fn(){
var name="hello";
//将函数赋值给fn2
fn2 = function(){
return name;
}
}
fn()//要先执行进行赋值,
console.log(fn2())//执行输出fn2

3、自执行函数
1
2
3
4
5
6
7
8
9
10
11
12
	(function(){
var name="hello";
var fn1= function(){
return name;
}
//直接在自执行函数里面调用fn2,将fn1作为参数传入
fn2(fn1);
})()
function fn2(f){
//将函数作为参数传入
console.log(f());//执行函数,并输出
}

for循环中通过定时器输出i
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   for( var i=0;i<5;i++){
setTimeout(function(){
console.log(i);
}
,0);
}
// 输出结果 5 5 5

for( var i=0;i<5;i++){
(function(lockedIndex){
setTimeout(function(){
console.log(lockedIndex);
}
,0);
})(i);
}
// 输出 "1,2,3,4,5"
/**
*
*/
for( let i=0;i<5;i++){
setTimeout(function(){
console.log(i);
}
,0);
}
// 输出 "1,2,3,4,5"
/**
* let 有块级作用域
*
*/

4、循环赋值
5、setter和getter;
6、迭代器(执行一次函数往下取一个值)
1
2
3
4
5
6
7
8
9
10
11
12
13
var arr =['aa','bb','cc'];
function incre(arr){
var i=0;
return function(){
//这个函数每次被执行都返回数组arr中 i下标对应的元素
return arr[i++] || '数组值已经遍历完';
}
}
var next = incre(arr);
console.log(next());//aa
console.log(next());//bb
console.log(next());//cc
console.log(next());//数组值已经遍历完

3.作用域、原型链

原型链:对象之间的继承关系通过构造函数的prototype指向父类对象,直到指向Object对象为止形成的指向链条。

通俗讲: 原型链是原型对象创建过程的历史记录。

注:在javascript中,所有的对象都拥有一个**__proto__属性指向该对象的原型prototype** 。
特殊:

1、函数的显示原型指向的对象默认是空的Object对象实例,但是Object本身除外

1
2
3
4
function Fun() {}
console.log(Fun.prototype instanceof Object); // true
console.log(Object.prototype instanceof Object); // false
console.log(Function.prototype instanceof Object); // true

2、Object 的原型对象是原型链的尽头!它的原型对象的隐式原型指向 null

1
console.log(Object.prototype.__proto__ === null); // true

3、所有函数都是Function的实例,Function本身也是 (即:Function = new Function)

instance of的实现

1
2
3
4
5
6
7
8
9
function instanceofF(A, B) {
var L = A.__proto__;
var R = B.prototype;
if (L === R) {
//A的内部属性__proto__指向B的原型对象
return true;
}
return false;
}

作用域就是限制变量只能在某个区域内有效

函数提升优先于变量提升
变量提升:在当前上下文中,js代码自上而下执行之前,会先做一些代码解析的工作,处理一下变量的声明

4.原生JS实现一个拖拽库,说一下思路

5.JS数据类型说一下

8种
基本数据类型: undefined、Null、Number、Boolean、String、
ES6新增
Symbol:创建后独一无二不可改变,为解决全局变量冲突的问题
BigInt:数字类型的数据,可表示任意精度格式的整数,用来存储和操作大整数
复杂数据类型:Array、Object、Function

检测数据类型的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1typeof      // 基本数据类型
2、instance of // 只能判断引用型数据Object
3、constructor // 不能判断null和undefined,如果创建一个对象来改变它的原型,constructor就不能用来判断数据类型了;
4Object.prototype.toString.call() // 都可以判断
//判断基本数据类型
console.log(Object.prototype.toString.call(123456)) // [object Number] --数字
console.log(Object.prototype.toString.call('hello world'))// [object String] --字符串
console.log(Object.prototype.toString.call(null)) // [object Null] --Null
console.log(Object.prototype.toString.call(true)) // [object Boolean] --布尔型
console.log(Object.prototype.toString.call(undefined)) // [object Undefined]--Undefined

//判断原生引用类型(部分):

function fun() {}
console.log(Object.prototype.toString.call(fun)) // [object Function] --函数

var now = new Date();
console.log(Object.prototype.toString.call(now)) // [object Function] --日期

var arr = [1,2,3,4,5];
console.log(Object.prototype.toString.call(arr)) // [object Array] --数组

var obj = {name:'ZhangSan', age:25}
console.log(Object.prototype.toString.call(obj)) // [object Object] --对象

var reg = /^1[3456789]\d{9}$/
console.log(Object.prototype.toString.call(reg)) // [object RegExp] --正则表达式

5、ES6继承 https://www.jb51.net/article/230913.htm
本质上所有的继承都离不开原型链
1、原型链继承—extends
缺点: 多个实例会导致原型对象上的内容时共享的,内容之间会互相影响
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function ParentClass() {
this.name = '一碗周'
}
ParentClass.prototype.getName = function () {
return this.name
}

// 定义子类,将来用于继承父类
function ChildClass() {}

// * 将子类的原型指向父类的实例化,子类拥有父类实例化后的内容
ChildClass.prototype = new ParentClass()

// 将子类进行实例化
var child = new ChildClass()

console.log(child.getName()) // 一碗周



2、借助构造函数继承: 缺点不会继承父类原型对象上的方法和属性
3、组合式继承:
使用原型链或原型式继承实现对原型的属性和方法的继承。
通过结构构造函数实现对实例对象的属性的继承。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 父级对象
function Parent() {
this.parent = 'parent'
}
// 为 Parent 父级对象的原型增加属性
Parent.prototype.name = '一碗周'
// 子级对象
function Child() {
this.child = 'child'
// 使用 call() 或者 apply() 方法调用父级构造函数 实现继承。
Parent.call(this)
}
// 解决不会继承构造函数的原型对象的问题
Child.prototype = Parent.prototype

const child = new Child()
console.log(child.name) // 一碗周

4: 原型式继承
Object.create()方法实现继承

ES6的class类 https://blog.csdn.net/weixin_44691513/article/details/108416033

ES6 的class与ES5写法的几个核心注意点:
ES5 的构造函数Point,对应 ES6 的Point类的构造方法。
类的所有方法都定义在类的prototype属性上面。
定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了
方法之间不需要逗号分隔,加了会报错
ES6的class使用方法与ES5的构造函数一模一样

constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
类必须使用new关键字来调用

Class的静态属性和方法
static 表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”

super

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Person{
constructor(name){
this.name=name;
this.sex="男";
}
}
class Student extends Person{
constructor(name,age){
super(name);
this.age=age;
}
}
let s=new Student("张三",11);
console.log(s.name);
console.log(s.age);
console.log(s.sex);


ES6 为new命令引入了一个new.target属性,该属性一般用在构造函数之中,返回new命令作用于的那个构造函数。
如果构造函数不是通过new命令调用的,new.target会返回undefined,因此这个属性可以用来确定构造函数是怎么调用的。

6.JS的GC(垃圾回收)机制 https://blog.csdn.net/qq_42543177/article/details/124644363

垃圾回收不是实时的,会周期性的释放程序中已经不在被引用的垃圾对象
判断是否被引用的方法
1、标记清除法
这是目前浏览器大多基于标记清除法。我们可以分为两个阶段:
标记:从根节点遍历为每个可以访问到的对象都打上一个标记,表示该对象可达。
清除:在没有可用分块时,对堆内存遍历,若没有被标记为可达对象就将其回收。
优点:实现简单。
缺点:a 内存过于碎片化。
   b 内存分配速度慢。
解决方法:标记-整理法
标记整理法和标记清除法标记阶段一致,只是整理阶段是先将被引用的对象移动到一端,然后清理掉标记的内存。
2、引用计数法: 引用计数法就是追踪每个变量被引用的次数,当引用数为0将可以被回收掉。
优点:当引用数为0时会被立即回收
缺点:a 计数器的增减处理频繁,会导致空间的使用效率降低。
    b 循环引用无法收回,导致内存泄漏。

7.JS高级函数
map、filter、reduce、sort、every、some、find、findIndex

CSS

1.清除浮动的方法
浮动的原理:使当前元素脱离文档流
*1 父元素设置overflow: hidden/auto;浏览器会自动检查浮动区域的高度
*2 结尾处添加div空标签设置clear:both;
3 父元素div定义高度
2.CSS选择器
基础: 通配符
、标签、类(class)、id、
结构: 后代(包含)选择器(用空格隔开)、子代选择器(>)、兄弟选择器(~)
属性:
伪类:动态伪类(:link :visited :active :hover :focus)、结构伪类
::
权重值大小比较:!important>行内样式>id选择器>class选择器=伪类选择器=属性选择器>标签选择器=伪元素选择器>通配符选择器>继承样式。
就近原则: 相同权重的选择器,哪个选择器最后定义的,就选择哪个选择器
3.styled-components sass less的区别

styled-components:  是一个使用**CSS-in-JS技术**实现的样式组件库,
它是一个为React和React Native设计的库。它允许我们在应用中使用JavaScript和CSS混合起来编写样式级组件。并且它是支持Sass的,不需要添加任何库。
**sass、less 都是css预编译处理器** https://blog.csdn.net/weixin_62765236/article/details/127332140
*1 编译环境不同 sass安装需要ruby环境、在服务端处理的  less通过js编译,在客户端处理
*2 变量符不同 less@ sass $
*3 sass支持条件语句, less不支持
*4 sass有输出设置、less没有
   sass工具库 compass lessUI库 bootstrap
*5 引入外部文件不同 sass 引用的外部文件命名必须以_开头
   less引入外部文件和css@import没有什么差别

4.盒模型

标准盒模型:box-sizing: content-box
IE盒模型: box-sizing: border-box
5.CSS动画

transition: 渐变动画
transform: 转变动画
animation: 自定义动画库
6.水平垂直居中 https://blog.csdn.net/weixin_44370837/article/details/116602151
绝对定位+transform
绝对定位+margin
绝对定位+ margin auto 父子元素宽高都未知

1
2
3
4
5
6
7
8
 .work2 {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
margin:auto;
}

父元素使用flex布局,并设置相关的属性值为center
使用table-cell实现
1
2
3
4
5
6
7
8
9
10
.par-work2 {
height: 500px;
width: 500px;
display: table-cell;
vertical-align: middle;
text-align: center;
}
.son-work2 {
display: inline-block;
}

使用grid布局
1
2
3
4
5
6
7
8
.par-work3 {
display: grid;
height: 500px;
}
.son-work3 {
align-self: center; /*设置单元格内容的垂直位置*/
justify-self: center; /*设置单元格内容的水平位置*/
}

7、css常见的布局

圣杯布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 <title>圣杯布局</title>
<style>
*{
margin: 0;
padding: 0;
}
.center{
padding: 0 200px;
}
.middle,.left,.right{
float: left;
height: 50px;
}
.middle{
width: 100%;
background: pink;
}
.left,.right{
width: 200px;
}
.left{
background: red;
margin-left: -100%;
position: relative;
left: 200px;
}

/*为什么要使用定位
因为center添加了padding,意味着盒子宽度增加了,原来设置左右盒子的位置也就发生了变化,设置相对定位,偏移padding左右的值就可以在视觉上实现相应的功能 */
.right{
background: green;
margin-left: -200px;
position: relative;
left: 200px;
}
</style>
</head>
<body>
<div class="center"><div class="middle">中间</div></div>
<div class="left">左边</div>
<div class="right">右边</div>

</body>

双飞翼布局
是针对圣杯布局的一个优化方案(使用了定位).解决方法就是在center中在添加一个一个inner盒子,并为其设置margin-left和margin-right,这样中间盒子的内容区域就不会被覆盖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>双飞翼布局</title>
<style>
*{
margin: 0;
padding: 0;
}
.center{
width: 100%;
background: pink;
}
.center,.left,.right{
float: left;
height: 50px;
}
.left,.right{
width: 200px;
}
.left{
background: red;
margin-left: -100%;
}
.right{
background: green;
margin-left: -200px;
}
.middle{
margin-left: 200px;
margin-right: 200px;
}
body{
min-width: 900px;
}
</style>
</head>
<body>
<div class="center">
<div class="middle">中间</div>
</div>
<div class="left">左边</div>
<div class="right">右边</div>

</body>
</html>

React

1.redux中间件,用过哪些
redux-thunk
redux-saga
redux-promise
3.redux和context怎么抉择用哪个
redux:
4.用context实现一个redux说一下思路(用哪些hook)
5.useReducer
useReducer: 接受两个参数,reducer函数、初始的state
返回值:useReducer 会返回一个有状态的值和一个设置该状态的函数
可读性: 可以将状态更新逻辑和事件处理程序分离
可调试性:可以在reducer函数中打印日志
每个 action 都描述了一个单一的用户交互
6.useRef
获取dom元素/获取组件实例/ 用来存储可变数据
7.useMemo React.memo,单独说一下,对比说一下
useMemo: 入参创建的回调函数、依赖的数组
依赖的数据项改变才会重新计算,如果不设置依赖数据项,每次都会重新计算

React.memo:当其作用于函数式组件并且作为子组件时, 每次父组件更新后, 会浅对比传来的 props 是否变化, 若没变化, 则子组件不更新
减少了组件内重复的计算、优化组件渲染

useCallBaack和useMemo
useCallBaack 主要用来缓存回调函数,避免不必要的函数创建和重复渲染
useMemo用于缓存计算结果,避免不必要的重复计算,适用于计算开销较大的操作或昂贵的函数调用的场景。

8.封装过哪些hook,描述思路
使用过react的hook库 ahooks
封装一些公共的数据处理逻辑
如何去存储
如何去更新 同步reducer, 异步action
9.怎么自定义hooks,实现redux状态管理

浏览器、HTTP

1.常用的短链请求有哪些?什么区别
websocket:WebSocket是一种基于TCP协议的、双向的、实时的短连接协议,可以用于实现即时通讯、实时数据传输和游戏等应用。WebSocket的实现方式主要有两种:客户端-服务器模型和服务器-客户端模型。

http短链接:HTTP短连接是一种基于HTTP协议的临时连接,可以用于实现数据传输或共享资源,通常持续时间非常短,只有几秒钟到几分钟。HTTP短连接的实现方式主要有两种:基于请求响应模型和基于状态模型。
WebSocket++:WebSocket++是一种C++库,可以用于实现WebSocket协议。WebSocket++支持多种平台,包括Windows、Linux和Android等
.命令行接口:命令行接口是一种通过命令行界面进行短连接创建和管理的接口,通常使用在嵌入式系统中。命令行接口可以通过编写C或C++程序来实现,并支持多种协议,如HTTP、FTP和SMTP等。
WebSocket客户端库: WebSocket客户端库是一种C或C++库,可以用于实现WebSocket协议的客户端应用程序。这些库通常提供创建和管理短连接的API,并支持多种平台和协议。

HTTP的长连接和短连接本质上是TCP长连接和短连接。
HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。
IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠的传递数据包,使在网络上的另一端收到发端发出的所有包,并且顺序与发出顺序一致。TCP有可靠,面向连接的特点。
http1.0 默认是短链接,浏览器和服务器每进行一次HTTP操作,就进行一次链接,任务结束后链接中断
但从 HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议

1
2
Connection:keep-alive
// Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接要客户端和服务端都支持长连接。

TCP长连接 client向server发起连接, server接受client链接,双方建立连接 依赖于TCP的保活功能
如果一个给定的连接在两小时内没有任何的动作,则服务器就向客户发一个探测报文段,客户主机必须处于以下4个状态之一:
客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常的,服务器在两小时后将保活定时器复位
客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务端将不能收到对探测的响应,并在75秒后超时。服务器总共发送10个这样的探测 ,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。
客户主机崩溃并已经重新启动。服务器将收到一个对其保活探测的响应,这个响应是一个复位,使得服务器终止这个连接。
客户机正常运行,但是服务器不可达,这种情况与2类似,TCP能发现的就是没有收到探查的响应。

2.浏览器缓存

浏览器缓存也称为HTTP缓存,HTTP缓存简单理解就是本地(浏览器)缓存了HTTP响应,以便后续复用,减少向服务端的请求。
基于url缓存资源

强缓存: 直接使用浏览器缓存, 注意有效期

1
2
3
4
5
6
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Cache-Control: max-age=3600 //3600秒,表示一个小时内有效, 最大有效时长


协商缓存:浏览器缓存过期,向服务端发起请求询问资源是否变化,服务端判断无变化,返回304 浏览器使用本地缓存内容并更新有效期, 如果变了返回200 + 新的资源 浏览器缓存会更新

● last-modified:资源最后修改时间。
● ETag:资源的唯一编码,文件内容变更后更新。

3、✔️触发协商缓存的条件
● Cache-Control:no-cache :强制使用协商缓存。
● 本地缓存过期,或Cache-Control: max-age=0
响应header返回:Last-Modified
请求header携带:If-Modified-Since
服务资源获取时间无法判断以后使用ETag
响应header返回:ETag
请求header携带:If-None-Match
实践:
● 不经常变的静态资源,如JS、CSS、图片推荐使用强制缓存,Cache-Control: max-age=31536000。
● HTML文档推荐使用协商缓存,比如SPA的入口页面可以使用Cache-Control: no-cache强制每次都使用协商缓存。
● Last-Modified、ETag可同时使用,ETag优先级更高,但Last-Modified还有额外的价值,可用来标识文件的修改时间。
● 合理定制不同资源文件的缓存机制、缓存周期。
● 缓存的Header配置都是在服务端,可以通过Nginx配置。
3.浏览器存储
web storage localStorage sessionStorage
http Cookie
一开始是用与服务端通信
document.cookie去获取
键值对用;隔开, 保存Set-Cookie
4.跨域是怎么产生的
域名的协议、ip、端口三者有一个不同就会产生跨域
原因:由于浏览器的同源策略
5.HTTPS安全性怎么实现的
SSL传输加密,身份认证
1、信息保密,通过使用公开密钥和对称密钥的技术加密信息
2、信息完整性,确保SSL业务全部达到目的
SSL利用机密共享和hash函数组提供信息完整性服务,确保服务器和客户机之间的信息内容免受破坏。
3、双向认证,客户机和服务器相互识别的过程
4、SSL的安全性服务对终端用户来讲做到尽可能透明

HTTP2.0 https://zhuanlan.zhihu.com/p/89471776

1、是在1x的基础上的升级
2、2.0重点是对终端用户的感知延迟,网络以及服务器资源的使用等性能优化
二进制分帧:改善传输性能,实现低延迟和高吞吐量
在二进制分帧层上,http2.0会将所有传输信息分割为更小的消息和帧,并对它们采用二进制格式的编码将其封装,新增的二进制分帧层同时也能够保证http的各种动词,方法,首部都不受影响,兼容上一代http标准。其中,http1.X中的首部信息header封装到Headers帧中,而request body将被封装到Data帧中。
多路复用/连接共享
头部压缩
http1.x的头带有大量信息,而且每次都要重复发送。
http/2使用encoder来减少需要传输的header大小,通讯双方各自缓存一份头部字段表,既避免了重复header的传输,又减小了需要传输的大小
请求优先级:
●优先级最高:主要的html

  ●优先级高:CSS文件

  ●优先级中:js文件

  ●优先级低:图片
**服务端推送**

Node

1.了解到node的相关库
sequelize、cors
egg
express

Git

1.git相关问题,git命名,gitflow等

ES6

1.promise 装饰器 promise常用方法,事件循环

promise API

状态:PromiseState pending、resolved、rejected
状态一旦变化是不可逆的
且一个promise对象只能改变一次
无论变为成功还是失败,都会有一个结果数据
成功的结果数据一般称为value,失败的结果数据一般称为reason
结果:promiseResult
通过resolve、reject来改变
https://blog.csdn.net/qq_52788258/article/details/127832724
Promise.all方法:(promises) => {}

事件循环
当JS引擎主线程执行JS代码时,会判断其是否为异步任务,若是异步任务则会立即交给webAPIs处理,若是同步任务则继续执行。
webAPIs得到异步任务后,会根据异步任务要求,开启对应的新线程处理,当开启的新线程执行完毕后,就会将异步任务的回调函数加入到 (异步宏任务队列)中被加入到(异步宏任务队列)的回调函数不会立即进入执行栈执行,而是等待所有同步任务执行完后,JS引擎主线程会来异步宏任务队列中捞取队首位置的回调函数,放到执行栈中执行。
JS引擎主线程在将执行栈中的同步任务执行完后,就会不停地去异步宏任务队列中捞取回调函数,如果捞取到则压入执行栈中执行,执行完后,再去异步宏任务队列中捞取,如果捞取不到,则会不停地捞取,重复以上动作,所以叫事件循环。
而JS主线程在事件循环机制中,会先依次捞取完异步微任务队列中的所有回调函数到执行栈中执行,当异步微任务队列空了之后,才会去异步宏任务队列中捞取回调函数到执行栈中执行

其他

1.react hook常用的方法有哪些
2.next最新版的特性
3.react最新特性
hooks 16.8引入的
react18:
Suspense for Data fetching(数据获取的暂停)
状态更新引入了自动批处理,该特性是自动的,不用做任何配置
**startTransition()**函数可让你优化一些渲染较慢的操作
useDeferredValue() hook上进行了一些改进。这个hook用于延迟更新,从而提高应用程序的性能
4.安全攻击性问题(浏览器安全的方法是,如果被攻击了怎么解决等)
5.性能优化您了解多少,说说您的了解,性能优化实践
http请求优化
资源加载优化
页面渲染优化: 减少页面的don操作、采用css动画、避免table
代码优化
6.ts规则、泛型

any类型和unknow类型的区别、

  1. any类型
  • 特点:
    完全绕过了TS的类型检查,可以赋值和接受任何类型的值
    对变量的任何操作都不会触发类型错误。
    相当于关闭了类型系统的保护。
  1. unknown类型
    • 特点:
      表示未知类型,比any更严格,是类型安全的替代方案
      可以接收任意类型的值,但是不能直接操作(除非先进行类型检查和类型断言)
      强制类型安全
      使用场景:
      处理动态API响应
      类型安全的动态渲染

**8.平常怎么提升自己技术,看什么书、什么论坛等

在刷题的痛苦中挣扎多年后,你是否也想要一份能“看得懂、跑得通”的算法学习资源?今天给大家推荐一个堪称算法学习天花板的 GitHub 项目:Hello Algo,它不仅图文并茂讲解核心算法,还附带多语言实现代码,真正做到了“所见即所得”。

本文将带你深入了解这个项目的独特魅力、适合人群及如何高效利用它,帮助你科学系统地搞定算法!

Hello Algo简介?

由krahets(清华博士,算法竞赛讲师)主导开发的开源项目,目标是通过图解 + 动画 + 多语言代码,让算法学习更直观、更易懂、更系统

项目以《Hello 算法》电子书为核心,每一章节配有高清插图和同步代码示例,目前已覆盖超 50 个算法与数据结构主题,支持包括 Python、Java、C++、Go、JS、TypeScript、C、Swift 等主流语言。

截止到现在,该项目已经:

  • 获得超过 49k+ GitHub Star
  • 拥有 7.3k+ Fork
  • 超过 400 页图文内容
  • 完整覆盖 数据结构 + 算法核心内容

可以说,是目前最全、最直观的算法学习资料,没有之一。

覆盖内容一览

Hello Algo 系统性地覆盖了如下模块(以下为部分章节):

数据结构

  • 数组、链表、栈、队列、哈希表
  • 树、图、堆、Trie 树、并查集
  • 二叉树的遍历、二叉搜索树、红黑树

算法思想

  • 二分查找、贪心、回溯、分治
  • 动态规划、滑动窗口、前缀和、双指针
  • 拓扑排序、并查集优化、图的遍历(BFS/DFS)

每一章节都遵循以下结构:

  1. 精美插图 + 动画演示
  2. 伪代码 + 多语言真实代码
  3. 可运行的代码环境和演示平台
  4. 练习建议与 LeetCode 配套题目

以“二叉树的层序遍历”为例,项目配套提供:

  • 算法逻辑图 + 动画(可运行演示)
  • Python、Java、C++ 等语言实现
  • LeetCode 对应练习题(如 102 题)

推荐理由

图解算法,不再抽象

相较于传统教科书式的解释,Hello Algo 每一个算法都配有动态图解。就像在看漫画学算法,复杂的知识点一下子就通透了。

图解 = 降维打击,初学者友好

多语言支持:从入门到高阶通吃

支持包括 Python、Java、C++、Go、JavaScript、TypeScript、C、Swift 在内的多种语言,哪怕你是前端、后端、嵌入式、移动端开发者,都可以无缝对接。

项目中代码目录结构清晰,支持VSCode一键运行。

项目持续更新 + 社区活跃

项目维护者是清华博士,长年深耕算法教育,并定期更新内容。目前PR和Issue响应速度都非常快,社区氛围非常活跃。

免费开源,阅读无门槛

整本电子书和所有代码完全开源,在线阅读地址为:
https://www.hello-algo.com/

GitHub 项目地址:https://github.com/krahets/hello-algo

适用人群

人群 推荐指数 使用建议
编程初学者 ⭐⭐⭐⭐⭐ 图解入门,先理解后动手
刷题党 ⭐⭐⭐⭐⭐ 作为知识复盘 + 模板库
面试准备者 ⭐⭐⭐⭐ 快速复习数据结构算法体系
转岗选手 ⭐⭐⭐⭐ 边学边练,零基础友好
老程序员回炉 ⭐⭐⭐ 查漏补缺,理解细节

无论你是算法菜鸟,还是需要系统复习准备秋招/面试,这份项目都能成为你的左膀右臂。

如何高效使用?

  1. 从图解开始,先理解流程:项目内动画+图像是关键,推荐先看图再写代码。
  2. 选定主语言,专注练习一套代码实现
  3. 配套 LeetCode 练习,加深理解与记忆
  4. 做错的题,用 Hello Algo 查源码+注释进行反思

如果你每天花30分钟结合Hello Algo学习 + 刷题,坚持3个月,就能掌握80%面试中常考的算法题型。

写在最后

你还在为刷LeetCode毫无头绪而烦恼吗?还在被复杂的算法书吓退吗?别再盲目乱学了!

Hello Algo = 图解算法 + 多语言代码 + 系统学习路径,是每一位程序员都该收藏的宝藏项目。

趁现在就收藏学习,做那个真正掌握算法的人!

👉 GitHub 地址:https://github.com/krahets/hello-algo

觉得有帮助?欢迎转发 + 点个赞!别忘了关注我们,获取更多开发者神器推荐!

科技&Tools乐园 —— 持续推荐最实用的开源工具、AI神器与效率技巧!

你是否有过这样的困扰?

  • 想搭建一个网站,却被高昂的域名费用劝退;
  • 想做技术项目展示,但域名每年几十上百不划算;
  • 想体验 Cloudflare 或 GitHub Pages 建站流程,结果被卡在第一步“买域名”……

今天推荐这款隐藏宝藏平台:DigitalPlat 免费域名注册系统
地址:https://dash.domain.digitalplat.org/panel/main
完全免费、不限用途,新手小白 5 分钟内就能把网站上线!

DigitalPlat免费域名平台

一个由非盈利组织The Hack Foundation提供支持的公益项目,目标是为全球开发者、学生、项目实验者提供永久免费域名。只需注册一个账号,绑定GitHub,即可申请一个属于你自己的域名,比如:

  • yourname.us.kg
  • project.dpdns.org
  • blog.qzz.io

0 成本,0 广告,0 门槛!

平台核心功能速览

访问控制面板后,你会看到一个极其简洁但功能完整的界面:

注册免费域名
  • 支持 .us.kg.dpdns.org.xx.kg 等多个后缀
  • 检查域名是否可用,直接点击注册
  • 填写 NS 服务器(推荐 Cloudflare)即可完成配置
域名管理
  • 在“Domains”页面查看已注册域名
  • 支持修改NS、切换解析平台
  • 可以设置WHOIS信息是否公开
  • 支持域名续期,最长保留一年,提前180天可操作
GitHub 授权扩展名额
  • 默认每个账号只能注册一个域名
  • 绑定GitHub账号并Star官方仓库即可解锁更多名额
  • 社区活跃用户甚至可申请 3 个以上!

为什么这个平台值得推荐?

不仅仅是“免费”,关键的是它真的解决我们建站过程中的刚需问题

  1. 不用信用卡,不怕被套娃式收费。注册不需要绑定任何银行卡或信用卡,也没有“前 7 天免费,之后续费 XX 元”的套路。就是纯粹的公益项目!
  2. 灵活解析,支持Cloudflare、Afraid等平台。只需要将域名的 NS 设置为你自己的解析服务,后续想解析到哪里就解析到哪里。GitHub Pages、Vercel、Netlify都能轻松接入。
  3. 全球可用,支持中文用户。虽然平台页面是英文的,但逻辑非常简单(下面会教你一步步操作),而且后台注册信息支持中文拼音,国内用户完全无障碍使用。

新手小白 5 分钟上手指南

不懂域名管理也没关系,跟着下面这 5 步做,你马上能上线自己的网站!

注册账号

打开官网(https://dash.domain.digitalplat.org/panel/main),点击注册(Sign Up):

  • 填写用户名、邮箱、密码、国家
  • 地址可以用拼音,电话填一个格式类似 +86-138xxxxxxx
  • 注册成功后,登录后台
绑 GitHub(扩展名额)

在页面右上角点击“Connect GitHub”按钮:

  • 登录你的 GitHub 账号,授权平台
  • 回到控制面板,刷新页面后名额会增加!
注册域名

进入“Register”页面:

  • 输入你想要的域名(例如 myblog
  • 选择后缀(比如 .dpdns.org
  • 填写NS(如果还没配置,暂时随便填两组,后续可以改成Cloudflare的)
  • 点击「Register」完成注册!
解析设置
  • 如果使用Cloudflare,添加域名后获取 NS
  • 回到控制面板,点击你的域名,修改为Cloudflare提供的NS地址
  • 在Cloudflare设置A或CNAME记录,指向你的服务器或GitHub Pages地址即可上线!
定期续期,长期使用

域名有效期为一年,提前180天可续期,只需在面板中点击续期按钮。

常见问题解惑

问题 解答
一个账号能注册几个? 初始1个,绑定GitHub并Star项目后可扩展到3个甚至更多
域名能否用于正式网站? 完全可以,但建议用于测试、项目展示、博客等场景,避免商业站点因后缀不常见而不被信任
是否有中文教程? 社区已有大量用户发布使用攻略,可搜索“DigitalPlat免费域名使用教程”
注册信息需要实名吗? 地址等信息可以填拼音,系统并不做实名验证

写在最后:属于你的网站,从这里开始

无论是:

  • 想写博客的程序员
  • 做项目展示的大学生
  • 测试部署的建站小白
  • 白嫖工具爱好者

这个平台都是你实现独立建站梦想的起点!0成本注册域名,5分钟上线网站,你还在等什么?

立即注册免费域名(https://dash.domain.digitalplat.org/panel/main)

如果觉得有用,欢迎点赞 + 收藏 + 分享给你的朋友们!
公众号【科技&Tools乐园】每天分享好玩、有趣、提升效率的科技工具,记得关注我,不错过每一篇干货爆文!

今天带大家操作,仅凭一个Cloudflare免费账户,轻松构建属于自己的 零信任访问系统,高效又安全。从内网服务远程访问,到设备接入控制,一站式搞定。

什么是 Zero Trust?

传统的理念是“只要进了内网就信你”,但这很容易导致内部账号泄露、被盗等问题。但Zero Trust模型强调:不默认信任任何设备、账号或网络,所有访问都必须验证。

Cloudflare Zero Trust 提供了全面的解决方案:

  • 替代内网的远程访问(Access + Tunnel)
  • 控制用户上网行为(Gateway + WARP)
  • 设置设备访问策略(设备态势感知)
  • 快速发布内网服务,限制外部访问

一、准备工作

注册账号并开启Zero Trust管理

  1. 访问官网:https://dash.cloudflare.com/,注册并登录
  2. 添加你的域名并按提示修改DNS到Cloudflare提供的NS
  3. 打开:https://dash.teams.cloudflare.com/
  4. 设置 Team 名称(如小方
  5. 获得类似 mysecureteam.cloudflareaccess.com 的访问入口

三、通过Tunnel暴露本地服务

安装cloudflared

Mac:

1
brew install cloudflared

Windows:

1
choco install cloudflared

Linux:

1
2
3
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64
chmod +x cloudflared-linux-amd64
sudo mv cloudflared-linux-amd64 /usr/local/bin/cloudflared

登录Cloudflare

1
cloudflared login

创建并配置Tunnel

1
2
3
4
5
6
7
8
9
10
11
cloudflared tunnel create mytunnel(自定义名字)

# 创建配置文件config.yml(就用这个文件名)
tunnel: mytunnel(自定义名字与创建时的相同)
credentials-file: /root/.cloudflared/mytunnel.json

ingress:
- hostname: blog.example.com(自定义子域)
service: http://localhost:8000(本地服务,主要是端口号一定要对应)
- service: http_status:404

启用DNS路由并启动

1
2
cloudflared tunnel route dns mytunnel blog.example.com
cloudflared tunnel run mytunnel

此时,你本地的服务将通过 https://blog.example.com 安全访问!

也可通过官网的Zero Trust创建

四、启用 Access 身份认证

  1. 打开 Zero Trust → Access → Applications
  2. 新建一个 Self-hosted App
  3. 设置:应用名称:如 “n8n 后台”,应用地址:https://blog.example.com
  4. 添加访问策略:视情况添加账号,也可仅允许你自己的账号登录,支持集成身份源(Google、GitHub、Okta、Azure AD等)

保存后,未登录者无法访问,会被重定向至登录页。

五、效果验证

  • 本地服务 → 公网发布 ✅成功
  • 身份登录控制 ✅启用 Google 登录
  • 未授权用户访问 ❌被拒绝
  • 多设备接入 ✅成功

六、拓展功能

功能 用途
Access 多因素认证 增强账户安全
网页隔离 RBI 不可信站点沙箱访问
Gateway DLP 防止上传敏感数据
Tunnel 多实例 可发布多个服务
Zero Trust CLI + API 自动化创建规则和策略

总结

Cloudflare Zero Trust是一个极具潜力的安全体系:

  • ✅ 免费支持前 50 用户
  • ✅ 替代传统 VPN,权限精细控制
  • ✅ 几分钟就能发布本地系统到公网
  • ✅ 无公网 IP、无需端口映射也能使用
  • ✅ 支持全平台(Win/Mac/iOS/安卓)

有了 Cloudflare Zero Trust,从此再也不用担心“公网暴露+无控制”的风险,1 分钟就能为服务加一层安全大门!

可发展方向与后续预告

  1. 本地 n8n 自动化后台 -> Tunnel + Access
  2. 远程访问内网系统 -> WARP + Access
  3. SaaS权限统一入口 -> Access + Google登录
  4. 安全发布博客 -> Pages + Access
  5. 禁止员工访问不良网站 -> Gateway DNS + WARP

如果对你有帮助,请点赞收藏哦!或者你有什么需要的话,可以留言或者关注我私信我哦!

Cloudflare 是一个为全球数百万网站提供服务的“网络超级加速器”,今天我带你认识一下这个浑身是宝的 Cloudflare —— 它不仅仅是一个 CDN!

Cloudflare 是什么?

成立于 2009 年的美国科技公司,起初是为了帮助网站抵御 DDoS 攻击,后来不断扩展产品线,目前已经发展成一个 全球最强的 Web 性能与安全平台之一

你可以将它理解为一个全球分布式的中转站,你的用户访问网站的请求,会先到 Cloudflare 的边缘节点处理,再转发到你的服务器。这样做有几点核心好处:

  • 加速网站访问速度
  • 过滤恶意请求
  • 隐藏源站 IP 提高安全
  • 降低服务器负载
  • 附加强大工具如防火墙、缓存规则、边缘函数等

基础功能详解

1、网站性能优化与加速

提供免费的 DNS 托管,并号称是“全球最快的 DNS 服务”。根据DNSPerf(https://www.dnsperf.com/) 数据,Cloudflare 的解析延迟常年位居第一。

  • 全球最快的 DNS(1.1.1.1 同源技术),并且免费托管。可自己配置TTL、秒级解析、支持DNSSEC,防止域名劫持。
  • CDN(内容分发网络),智能缓存策略(HTML、CSS、JS、图片等),缓存规则可自行配置。图片自动压缩、延迟js加载,加速首屏加载。内容、TCP自动优化
2、安全防护功能
  • 免费无限量 DDoS 防护以及分布式节点自动检测攻击
  • 自定义防火墙规则(可按IP、国家、路径等)
  • 速率限制、访问规则管理、SSL/TLS管理以及可自签源站证书
3、开发者工具支持
  • Cloudflare Pages,前端静态网站部署平台,支持CI/CD、GitHub自动部署,可自定义域名,自带缓存、HTTP3、SSL、Preview功能。这里可见小编自建平台(https://tools.fangxing.dns-dynamic.net/)
  • Cloudflare Workers,Serverless无服务器计算平台,可编写js/ts逻辑,部署在边缘节点
  • KV全局分布式存储,适合缓存、设置等。还支持DI SQL以及R2对象存储数据库

关键是所有操作支持API自动化

4、分析与监控

供访问日志分析,无需在服务器装监控插件

  • 请求次数、带宽、缓存命中率、攻击类型和来源IP等图表可视化

高级的玩法

来看看开发者生态吧!

Workers

允许在全球节点上运行JS代码,响应用户请求,0延迟。

每月免费10w次请求,可结合KV、D1数据库使用,适合API代理、A/B测试、URL重写等。

Turnstile & Email Routing

免费无感验证码系统和自定义域名邮箱转发,解决在使用一些网站或者APP的时候的邮箱问题。

Zero Trust

为现代企业提供的一套完整的零信任安全访问解决方案,允许企业用户在不依赖传统内网隔离的情况下,对内部资源、SaaS应用、远程员工设备等进行访问控制、身份验证、威胁检测等。此功能小编正在研究中,敬请期待!

为什么推荐使用?

开发者、建站者、企业主,Cloudflare可以为你提供这些优势

  1. 成本极低:免费方案足以满足中小网站的性能与安全需求。
  2. 提升用户体验:访问速度快,缓存命中高,SEO排名也好。
  3. 一站式管理:从DNS到SSL、CDN、防火墙、监控一键集成。
  4. 开发者友好:强大的API、CLI工具、边缘函数支持自动化部署。
  5. 安全加固:减少服务器被攻击风险,避免网站流量被劫持。

如何开始使用?

三步进入Cloudflare:

  1. 进入官网:https://dash.cloudflare.com/
  2. 注册账号,添加你的域名
  3. 根据提示更改DNS到Cloudflare提供的服务器

几分钟后,你的网站将享受全套加速与安全服务!

结语

Cloudflare是每个现代网站必备的工具之一。从个人博客、网站到企业级系统,它都能提供合适的解决方案。小编自己就长期使用Cloudflare来托管域名、搭建网站、加速资源和实现API中转。

如果你还没用上Cloudflare,现在快去开启这项黑科技吧!

喜欢这篇文章的话,欢迎点赞,分享,关注我哦!你的支持是我最大的动力哦!