admin管理员组

文章数量:1547450

1,some、every的区别

自定义组件和keepalive

自定义组件是指开发者根据自己的需求,自己编写的组件。通过自定义组件,开发者可以实现一些特定的功能或者样式,以满足自己的需求。

而keep-alive是Vue.js提供的一个内置组件,用于缓存组件的状态,以提高组件的性能。当一个组件被包裹在keep-alive标签中时,该组件的状态将被缓存,即使组件被销毁,下次再次渲染时,组件的状态将被恢复。

自定义组件和keep-alive可以结合使用,以实现更复杂的功能。例如,可以将一个自定义组件包裹在keep-alive标签中,以实现组件的状态缓存。这样,在组件被销毁后,再次渲染时,组件的状态将被恢复,而不需要重新初始化。

另外,自定义组件和keep-alive也可以分别使用。自定义组件可以用于实现特定的功能或样式,而keep-alive可以用于提高组件的性能。根据具体的需求,开发者可以选择是否使用自定义组件和keep-alive。

1,for in,for of:

	for in 是ES5的语法,for of 是ES6的语法
	for in 是无序遍历数组或对象的,也就是随机遍历,不按照顺序来; for of 是按照顺序遍历的
	for in 是对key值遍历的,对于对象来说,遍历的是对象的key值,对于数组来说,遍历的是数组的下标; for of是对数值遍历的,不能遍历对象,可以遍历数组,是对数组的每一个元素数值遍历
	for in会把数组或对象的原型上的属性或方法也遍历出来 ,对于对象来说,可以使用对象的hasOwnProperty()这个方法判断是否是自身实例属性,可以只对自身属性遍历,或者使用Object.keys()方法获取对象键值组成的数组,这个数组不包含原型的属性和方法;而for of 只会把当前数组自己本身的元素值遍历出来
	普通的for循环能使用break、continue、 return跳出循环,forEach中可以使用return跳出循环,无法使用break和continue;在for in和for of是可以使用break和return和continue

**2,vuex

3,:is 动态组件

在 Vue 中,is 动态组件是一种特殊的组件,它可以根据不同的条件渲染不同的组件。is 动态组件可以通过在组件标签上使用 is 属性来实现。
,is 动态组件会自动销毁之前渲染的组件,并渲染新的组件。
is 动态组件可以用于实现一些动态的 UI,例如根据用户的权限动态渲染不同的组件,或者根据用户的操作动态切换不同的表单组件等。

4,插槽slot、路由守卫

插槽(slot)是 Vue 中一种用于组件间通信的机制,它允许我们在组件的模板中定义一些“插槽”,然后在使用组件时,将内容插入到这些插槽中。插槽可以用于实现组件的复用和灵活性。

路由守卫是 Vue Router 中一种用于控制路由跳转的机制,它允许我们在路由跳转前、跳转后、或者跳转过程中进行一些操作,例如验证用户权限、记录用户行为等。Vue Router 中提供了多种路由守卫,包括全局守卫、路由独享守卫和组件内守卫。

// 全局前置守卫
router.beforeEach((to, from, next) => {
  // 验证用户是否登录
  if (to.meta.requiresAuth && !auth.isLoggedIn()) {
    next('/login');
  } else {
    next();
  }
});

// 路由独享守卫
const router = new VueRouter({
  routes: [
    {
      path: '/admin',
      component: Admin,
      beforeEnter: (to, from, next) => {
        // 验证用户是否有管理员权限
        if (!auth.isAdmin()) {
          next('/403');
        } else {
          next();
        }
      }
    }
  ]
});

// 组件内守卫
export default {
  data() {
    return {
      user: null
    }
  },
  beforeRouteEnter(to, from, next) {
    // 获取用户信息
    api.getUserInfo().then(user => {
      next(vm => {
        vm.user = user;
      });
    });
  }
}

5,websocket

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

// 创建 WebSocket 连接
var socket = new WebSocket('ws://localhost:8080');

// 连接打开时触发
socket.onopen = function(event) {
  console.log('WebSocket is connected.');

  // 发送一个初始化消息
  socket.send('I am the client and I\'m listening!');
};

// 监听消息
socket.onmessage = function(event) {
  console.log('Client received a message', event.data);
};

// 监听 Socket 的关闭
socket.onclose = function(event) {
  console.log('Client noted that the connection is closed.');
};

// 监听连接错误
socket.onerror = function(error) {
  console.log('WebSocket Error: ', error);
};

websocket 的使用场景
WebSocket 主要用于实现实时应用,其使用场景非常广泛,包括:

聊天应用:这可能是 WebSocket 最常见的使用场景。通过 WebSocket,你可以实现一个实时的聊天系统,用户可以即时地发送和接收消息。

多人游戏:WebSocket 也常用于在线多人游戏。游戏中的每个玩家的动作可以实时地发送到服务器,然后服务器将这些动作广播给其他玩家。

实时通知:如果你的网站或应用需要向用户发送实时通知(例如,新的社交媒体消息,股票价格更新等),WebSocket 是一个很好的选择。

实时数据流:对于需要实时数据流的应用,例如股票交易应用、天气更新应用、实时交通信息等,WebSocket 都是非常合适的技术。

协同编辑和白板应用:通过 WebSocket,多个用户可以实时地在同一个文档或白板上进行协作。

物联网(IoT):WebSocket 也可以用于物联网设备和服务器之间的实时通信。

总的来说,任何需要实时、双向通信的场景,WebSocket 都可能是一个很好的选择。

6,数组方法 map、foreach区别,

map、forEach 和 Set 是 JavaScript 中的不同概念,它们有不同的用途:

map:map 是一个数组方法,它创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数。map 不会改变原始数组,而是返回一个新数组。例如:

复制let numbers = [1, 2, 3, 4];
let squares = numbers.map(x => x * x);
console.log(squares); // 输出: [1, 4, 9, 16]
forEach:forEach 也是一个数组方法,它用于遍历数组的每个元素,并对每个元素执行提供的函数。forEach 不返回任何值,也不会改变原始数组。例如:

复制let numbers = [1, 2, 3, 4];
numbers.forEach(x => console.log(x * x));
// 输出:
// 1
// 4
// 9
// 16
Set:Set 是一个内置对象,它存储唯一的值,无论这个值是原始值还是对象引用。Set 对象是值的集合,你可以按照插入的顺序迭代它的元素。Set 中的元素只会出现一次,即 Set 中的元素是唯一的。例如:

复制let mySet = new Set();
mySet.add(1);
mySet.add(2);
mySet.add(3);
mySet.add(2); // 这个值不会被添加到 Set 中,因为 Set 中已经有一个值为 2 的元素
console.log(mySet); // 输出: Set { 1, 2, 3 }
总的来说,map 和 forEach 是用于处理数组的方法,而 Set 是一种可以存储唯一值的数据结构。

1,es6数组的方法

:foreach、find、findIndex、map、set、from、flat、flatMap,数组实例的 copyWithin()

2,set、map区别:

1、Map 对象是键值对集合,和 JSON 对象类似,但是 key 不仅可以是字符串还可以是其他各种类型的值包括对象都可以成为Map的键,2、Set 对象类似于数组,且成员的值都是唯一的

1,性能优化:

图片懒加载,静态文件cdn缓存,分包拆包处理,动态路由,减少http请求,## 标题

2,JS延迟加载的几种方式:

  1. defer 属性2,async 属性3.动态创建DOM方式4.使用jQuery的getScript()方法5.使用setTimeout延迟方法,6.让JS最后加载
    3,defer、async区别:
    defer 和 async 都是用于异步加载 JavaScript 脚本的属性,它们的区别在于脚本的加载和执行顺序。
    defer 属性用于异步加载 JavaScript 脚本,但是脚本的执行会被推迟到页面解析完毕后再执行。也就是说,defer 属性会保证脚本的执行顺序与它们在页面中出现的顺序一致,但是脚本的执行会被推迟到页面解析完毕后再执行。
    async 属性也用于异步加载 JavaScript 脚本,但是脚本的执行不会被推迟,而是在加载完成后立即执行。也就是说,async 属性不能保证脚本的执行顺序与它们在页面中出现的顺序一致。

4,web端自适应布局

**5,flex属性

watch和computed的区别

watch 和 computed 是 Vue.js 中用于响应式数据处理的两个重要属性。

watch 是一个选项,用于监听数据的变化并执行相应的操作。你可以使用 watch 来观察一个或多个数据的变化,并在数据变化时执行自定义的回调函数。watch 适用于需要在数据变化时执行异步操作、复杂计算或执行副作用的场景。

以下是一个使用 watch 的示例:

复制export default {
data() {
return {
message: ‘Hello’,
count: 0
};
},
watch: {
message(newVal, oldVal) {
console.log(‘message changed:’, newVal, oldVal);
},
count(newVal, oldVal) {
console.log(‘count changed:’, newVal, oldVal);
}
}
};
在上述示例中,我们定义了一个 watch 对象,其中包含了对 message 和 count 数据的监听。当 message 或 count 发生变化时,相应的回调函数将被触发。

computed 是一个选项,用于定义计算属性。计算属性是基于响应式数据进行计算得出的属性,它会根据依赖的数据自动进行缓存,只有当依赖的数据发生变化时,才会重新计算。计算属性适用于需要根据其他数据进行复杂计算或处理的场景。

以下是一个使用 computed 的示例:

复制export default {
data() {
return {
firstName: ‘John’,
lastName: ‘Doe’
};
},
computed: {
fullName() {
return this.firstName + ’ ’ + this.lastName;
}
}
};
在上述示例中,我们定义了一个 computed 对象,其中包含了一个计算属性 fullName。fullName 是根据 firstName 和 lastName 进行计算得出的属性。当 firstName 或 lastName 发生变化时,fullName 会自动重新计算。

总结来说,watch 适用于监听数据的变化并执行自定义操作,而 computed 适用于基于响应式数据进行复杂计算得出属性的场景。在实际使用中,你可以根据具体需求选择使用 watch 或 computed。

6,window.onload 和document.onload区别(document.ready)

window.onload 和 document.onload 都是页面加载完成后执行的事件,但是它们的触发时机不同。
window.onload 是在页面所有资源(包括图片、样式、脚本等)都加载完成后才会触发,即页面完全加载完成后才会执行。
document.onload 是在页面 DOM 结构加载完成后就会触发,即在页面所有元素都被解析完成后就会执行,此时可能还有一些资源(如图片、样式、脚本等)没有加载完成。
因此,window.onload 事件的触发时机比 document.onload 事件晚,需要等待所有资源加载完成后才会执行,而 document.onload 事件的触发时机比较早,只需要等待页面 DOM 结构加载完成后就会执行。

7,vue响应式原理

Vue 的响应式原理是通过数据劫持和发布-订阅模式实现的。

当 Vue 实例化时,Vue 会对 data 对象中的每个属性进行劫持,即通过 Object.defineProperty() 方法将每个属性转换为 getter 和 setter,从而实现对属性的监听。

当数据发生变化时,setter 方法会通知订阅者(Watcher)进行更新。订阅者是一个观察者对象,它会将自己添加到属性的订阅列表中,当属性发生变化时,订阅者会接收到通知并进行更新。

Vue 的响应式原理还涉及到依赖收集和异步更新。

依赖收集是指在模板编译过程中,Vue 会对模板中使用到的属性进行依赖收集,即将模板中的每个属性与对应的订阅者关联起来,从而实现对模板的监听。

异步更新是指当数据发生变化时,Vue 会将所有需要更新的订阅者添加到一个队列中,然后在下一个事件循环中统一进行更新。这样可以避免频繁更新导致的性能问题。

总的来说,Vue 的响应式原理是通过数据劫持和发布-订阅模式实现的,它可以实现对数据和模板的监听,并在数据发生变化时进行更新,从而实现了数据驱动视图的目的。
在 vue3 中放弃了 Object.defineProperty 来进行数据劫持,而改用了 Proxy 替代原本的方案。

Object.defineProperty 的缺陷在于需要深度遍历并对每一个属性进行劫持,而对于没有属性的数组而言,数组的索引也可以视为被劫持的属性,但是和对象相同,对于新增的元素而言,不会触发监听事件,vue 对此的解决方案是劫持数组原型链上的函数,即便如此也仍旧无法监听对数组长度的修改。

而使用 Proxy 进行劫持则弥补了这些缺陷,阮一峰的《ECMAScript6 入门》中对于 Proxy 是这样描述的:

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

8,那些数组方法可以改变原数组

push():向数组的末尾添加一个或多个元素,并返回新的长度。

pop():删除并返回数组的最后一个元素。

shift():删除并返回数组的第一个元素。

unshift():向数组的开头添加一个或多个元素,并返回新的长度。

splice():在任意的位置给数组添加或删除任意个元素。

sort():对数组的元素进行排序。

reverse():颠倒数组中元素的顺序。

fill():用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。

例如:

复制let arr = [1, 2, 3, 4, 5];

arr.push(6); // arr 现在是 [1, 2, 3, 4, 5, 6]
arr.pop(); // arr 现在是 [1, 2, 3, 4, 5]
arr.shift(); // arr 现在是 [2, 3, 4, 5]
arr.unshift(1); // arr 现在是 [1, 2, 3, 4, 5]
arr.splice(2, 1, ‘a’); // arr 现在是 [1, 2, ‘a’, 4, 5]
arr.sort(); // arr 现在是 [1, 2, 4, 5, ‘a’]
arr.reverse(); // arr 现在是 [‘a’, 5, 4, 2, 1]
arr.fill(‘b’); // arr 现在是 [‘b’, ‘b’, ‘b’, ‘b’, ‘b’]
以上这些方法都会直接修改原数组。如果你不想改变原数组,你应该使用那些返回新数组的方法,如 map()、filter()、slice() 等。

9,shh(外部安全机制)

SSH(Secure Shell)是一种网络协议,用于在不安全的网络中安全地传输数据。它通过加密和身份验证机制,保证了数据传输的安全性和完整性。
SSH 协议主要包括三个部分:
连接协议:用于建立连接和协商加密算法。
用户身份验证协议:用于验证用户身份,包括密码验证、公钥验证等。
传输协议:用于在加密通道中传输数据,包括远程命令执行、文件传输等。
SSH 协议的安全性主要体现在以下几个方面:
加密传输:SSH 协议使用加密算法对数据进行加密传输,从而保证数据传输的安全性。
身份验证:SSH 协议支持多种身份验证方式,包括密码验证、公钥验证等,从而保证用户身份的安全性。
安全通道:SSH 协议建立了一个安全通道,所有数据都在该通道中传输,从而保证数据传输的完整性和机密性。
总的来说,SSH 协议是一种安全可靠的网络协议,它通过加密和身份验证机制,保证了数据传输的安全性和完整性,被广泛应用于远程登录、文件传输等场景。

10,promise

11,防抖和节流**:

防抖是执行最后一次
防抖(Debounce)是指在一定时间内,如果事件被触发多次,只执行最后一次。也就是说,当事件被触发后,如果在指定的时间内再次触发该事件,就会重新计时,直到指定的时间内没有再次触发该事件,才会执行该事件的处理函数。

节流是执行第一次
节流(Throttle)是指在一定时间内,无论事件被触发多少次,只执行一次。也就是说,当事件被触发后,如果在指定的时间内再次触发该事件,就会被忽略,直到指定的时间过去后才会再次执行该事件的处理函数。

六,格上财富

标题12,$nextTick原理

Vue.js 中的 $nextTick 方法用于延迟执行一段代码,它将在下次 DOM 更新循环结束之后执行回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

其原理是基于 JavaScript 的事件循环和任务队列的。Vue.js 在更新 DOM 时,会异步地批量更新,以避免因数据频繁变化导致的重复渲染,提高性能。当你设置 Vue.js 的数据时,Vue.js 将开启一个异步队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。然后,在下一个的事件循环 “tick” 中,Vue 刷新队列并执行实际(已去重的)工作。

Vue 在内部尝试对异步队列使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。

因此,$nextTick 允许你在下一个 DOM 更新循环之后延迟执行一段代码,从而确保 Vue.js 已经完成了数据更新和 DOM 的重新渲染。

标题13,事件循环和任务队列

事件循环和任务队列是 JavaScript 异步编程的核心机制。

事件循环(Event Loop):JavaScript 是单线程的,这意味着它一次只能做一件事。但是,许多 JavaScript 操作(例如网络请求、定时器等)是异步的,这就需要一种机制来处理这些异步操作。这就是事件循环的作用。事件循环的任务是不断地检查任务队列,看是否有任务需要执行,如果有,就执行它。

任务队列(Task Queue):当一个异步操作完成时,它的回调函数就会被放入任务队列中。任务队列是一个先进先出的数据结构,存储了待执行的任务。

事件循环和任务队列的工作流程大致如下:

当 JavaScript 引擎执行完同步代码后,就会开始检查任务队列。

如果任务队列中有待执行的任务,就从队列中取出一个任务并执行。

执行完一个任务后,再次检查任务队列,如果还有待执行的任务,就再取出一个任务执行,依此类推。

如果任务队列中没有任务,就等待,直到有新的任务被添加到队列中。

这个过程会一直循环下去,直到程序结束,这就是所谓的事件循环。

在这个过程中,JavaScript 可以处理异步操作,例如网络请求、定时器等。当这些异步操作完成时,它们的回调函数就会被添加到任务队列中,等待执行。这就是 JavaScript 如何处理异步操作的。

标题14,宏任务和微任务

先执行宏任务,再检查有没有微任务,如果有就执行微任务,然后渲染dom,最后进入下一次事件循环。

更官方的解释:先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕。
————————————————
为什么有人认为微任务先执行?
setTimeout(() => {
console.log(“宏任务”);
}, 0);
Promise.resolve().then((e) => {
console.log(“微任务”);
});
因为上面的代码会先输出微任务,再输出宏任务,

这是因为宏任务试下一个时间循环开始的宏任务,而微任务是这次事件循环就执行的微任务,他们之间隔了一个dom渲染,所以造成了微任务比宏任务更快执行的错觉。
————————————————

标题15,前端理由的原理 history hash,前端路由 history有时候404是什么原因

前端路由主要有两种模式:Hash 模式和 History 模式。

Hash 模式:基于锚点,以及 onhashchange 事件。在 URL 中 hash 的变化并不会导致浏览器向服务器发送请求,不会刷新页面。

History 模式:基于 HTML5 中的 History API。主要使用 pushState、replaceState、popstate 这三个方法来控制浏览器历史记录的增删改,从而改变 URL。

关于 History 模式下出现 404 的问题,这是因为当你直接在浏览器地址栏输入 URL 或者刷新页面时,浏览器会向服务器发送请求,而服务器并没有对应的处理路由的逻辑,所以就会返回 404 错误。

解决这个问题的常见做法是在服务器端添加一个覆盖所有情况的路由,当未匹配到任何静态资源时,就返回同一个 index.html 页面,这个页面就是你的单页应用。这样一来,服务器就不会返回 404 错误了,而是将路由处理的职责交给了前端路由,前端路由在匹配到相应的路由后,就会展示对应的页面。

19Hash 模式 History 模式区别

Hash 模式和 History 模式是前端路由的两种常见模式,主要区别在于 URL 的表现形式和是否需要服务器的支持。

Hash 模式:Hash 模式的 URL 中会包含一个 “#” 符号,例如:http://localhost:8080/#/user/id。这种模式利用了浏览器的 hashchange 事件,当 URL 中的 hash 值发生变化时,就会触发这个事件,然后根据新的 hash 值来更新页面。这种模式的优点是兼容性好,可以在所有支持 JavaScript 的浏览器中运行。缺点是 URL 中的 “#” 符号不美观。

History 模式:History 模式的 URL 看起来像是正常的 URL,没有 “#” 符号,例如:http://localhost:8080/user/id。这种模式利用了 HTML5 的 History API,包括 pushState、replaceState 和 popstate 事件,可以在不刷新页面的情况下改变 URL 并与之对应的状态。这种模式的优点是 URL 看起来更美观。缺点是需要服务器的支持,因为当用户直接访问一个像 http://localhost:8080/user/id 这样的 URL 时,如果服务器没有进行正确的配置,就会返回 404 错误。

在 Vue-router 中,默认使用的是 Hash 模式,如果要使用 History 模式,需要在创建 Vue-router 实例时指定 mode 选项为 'history’。

History 模式: 为什么可以返回404页面

在 History 模式下,URL 看起来像是正常的 URL,例如:http://localhost:8080/user/id。当用户直接在浏览器地址栏输入这样的 URL 或者通过链接访问时,浏览器会向服务器发送一个 HTTP 请求,请求这个 URL 对应的资源。

然而,对于单页面应用(SPA),服务器上实际上并不存在 /user/id 这样的资源。服务器上通常只有一个 index.html 文件,所有的路由管理都是在前端完成的。

因此,如果服务器没有进行特殊配置,当收到一个 /user/id 这样的请求时,服务器会返回 404 错误,因为它找不到对应的资源。

为了解决这个问题,服务器需要进行一些配置,使得对于所有的页面请求,都返回同一个 index.html 文件。然后,由前端的路由系统接管,根据 URL 的路径部分来决定显示哪个页面。这样,无论用户直接访问哪个 URL,都能正确地显示对应的页面,而不会返回 404 错误。

标题16,nextTick和promise执行顺序

nextTick 需在 Node.js 环境下才可使用,常用场景为在 Vue 框架中使用

new Promise((resolve) => {
    console.log(1);
    
    process.nextTick(() => {
    	console.log(2);
    });
    
    resolve();
    
    process.nextTick(() => {
    	console.log(3);
    });
    
    console.log(4);
}).then(() => {
    console.log(5);
});
 
setTimeout(() => {
    console.log(6);
}, 0);
 
console.log(7);

// 输出顺序
1
4
7
2
3
5
6
结论显而易见,nextTick 和 Promise.then 的执行顺序为:nextTick > Promise.then

标题17,https原理 和为什么更安全 加密方式?

HTTPS比HTTP更安全的原因在于它使用了SSL/TLS协议来加密传输的数据,这使得数据在传输过程中不容易被窃取或篡改。

以下是HTTPS相比于HTTP更安全的几个方面:

数据加密:在HTTP协议中,数据是明文传输,容易被窃取。而HTTPS协议则是在传输数据包之前就进行了加密,即使数据被窃取,也无法解读其内容。

数据完整性:HTTPS协议可以检测数据在传输过程中是否被篡改。如果数据被篡改,接收方可以立即发现。

身份验证:HTTPS协议需要服务器向可信任的证书颁发机构申请证书,用户在访问网站时,可以验证服务器的身份,防止用户访问到假冒的网站。

因此,HTTPS协议在保护用户隐私、防止数据被窃取和篡改等方面,都比HTTP协议更加安全。

HTTPS协议 使用什么加密方式

HTTPS协议使用的是SSL/TLS协议进行加密。SSL(Secure Sockets Layer,安全套接层)和TLS(Transport Layer Security,传输层安全)协议是一种安全协议,用于在互联网上保护数据的完整性和安全性。

SSL/TLS协议使用了混合加密机制,包括对称加密和非对称加密:

非对称加密:在握手阶段使用,主要用于在客户端和服务器之间安全地交换对称加密的密钥。非对称加密的优点是安全,缺点是加密和解密过程计算量大,速度慢。

对称加密:在数据传输阶段使用,主要用于加密实际的数据内容。对称加密的优点是计算量小,速度快,适合大量数据的加密和解密。

SSL/TLS协议还使用了数字证书来验证服务器的身份,防止中间人攻击。数字证书由可信任的第三方证书颁发机构(CA)签发,包含了服务器的公钥和一些身份信息。

标题18,自定义组件和keepalive

8,浏览器在输入url后经历了什么

URL 解析:浏览器会解析 URL,获取协议、主机名、端口号、路径等信息。

DNS 解析:浏览器会根据主机名查询 DNS 服务器,获取主机的 IP 地址。

建立 TCP 连接:浏览器会使用 HTTP 协议与服务器建立 TCP 连接。

发送 HTTP 请求:浏览器会向服务器发送 HTTP 请求,请求中包含请求方法、请求头、请求体等信息。

服务器处理请求并返回 HTTP 响应:服务器会根据请求内容进行处理,并返回 HTTP 响应,响应中包含状态码、响应头、响应体等信息。

浏览器解析渲染页面:浏览器会根据响应内容解析 HTML、CSS、JavaScript 等资源,并渲染页面。

断开 TCP 连接:浏览器在完成页面渲染后会断开与服务器的 TCP 连接。

总的来说,浏览器在输入 URL 后需要进行 URL 解析、DNS 解析、建立 TCP 连接、发送 HTTP 请求、服务器处理请求并返回 HTTP 响应、浏览器解析渲染页面等一系列操作,才能最终将页面呈现给用户。

三次握手,四次挥手:

TCP协议是一种面向连接的协议,它使用三次握手来建立连接,使用四次挥手来关闭连接。这是因为在TCP连接的建立和关闭过程中,客户端和服务器之间需要进行一些协商和确认,以确保数据的可靠传输和连接的正确关闭。
在TCP连接的建立过程中,客户端向服务器发送一个SYN包,表示请求建立连接。服务器收到SYN包后,向客户端发送一个SYN-ACK包,表示确认请求,并请求建立连接。客户端收到SYN-ACK包后,向服务器发送一个ACK包,表示确认建立连接。这样就完成了TCP连接的建立,共进行了三次握手。
在TCP连接的关闭过程中,客户端向服务器发送一个FIN包,表示请求关闭连接。服务器收到FIN包后,向客户端发送一个ACK包,表示确认请求。但是服务器可能还有数据需要发送给客户端,因此需要在发送完数据后再向客户端发送一个FIN包,表示关闭连接。客户端收到FIN包后,向服务器发送一个ACK包,表示确认关闭连接。这样就完成了TCP连接的关闭,共进行了四次挥手。
因此,TCP协议使用三次握手来建立连接,使用四次挥手来关闭连接,以确保数据的可靠传输和连接的正确关闭。

9,抽象组件

抽象组件是指在 Vue.js 中,用于提供公共逻辑和功能的组件,但不会渲染任何实际的 DOM 元素。抽象组件通常用于封装可复用的逻辑,以便在多个组件中共享和重用。

在 Vue.js 中,可以通过以下方式创建抽象组件:

使用 Vue.extend 方法创建组件构造器:

复制const AbstractComponent = Vue.extend({
// 抽象组件的配置
});
在这种方式下,AbstractComponent 是一个组件构造器,可以通过 new AbstractComponent() 来创建实例,但不会渲染任何实际的 DOM 元素。

使用 render 函数创建函数式组件:

复制const AbstractComponent = Vueponent(‘AbstractComponent’, {
functional: true,
render(h, context) {
// 抽象组件的渲染逻辑
}
});
在这种方式下,AbstractComponent 是一个函数式组件,通过 render 函数来定义组件的渲染逻辑,但不会生成实际的 DOM 元素。

抽象组件通常用于封装公共的逻辑和功能,例如混入 (mixin)、高阶组件 (higher-order component)、插件 (plugin) 等。通过使用抽象组件,可以实现代码的复用和逻辑的封装,提高开发效率和代码的可维护性。

需要注意的是,抽象组件本身不会被直接使用,而是作为其他组件的基础或扩展来使用。在其他组件中,可以通过继承、混入、组合等方式来使用抽象组件提供的公共逻辑和功能。

10,前端如何实现路由**

created 和 mounted请求接口有什么区别

created 和 mounted 是 Vue.js 生命周期钩子函数,用于在组件生命周期的不同阶段执行代码。

created 钩子函数在组件实例被创建后立即调用,此时组件的数据观测 (data observer) 和事件初始化已完成,但尚未挂载到 DOM 中。在 created 钩子函数中,你可以进行一些初始化的操作,例如数据的获取、事件的监听等。

mounted 钩子函数在组件被挂载到 DOM 后调用,此时组件已经被渲染到页面上。在 mounted 钩子函数中,你可以访问到组件的 DOM 元素,并进行一些需要 DOM 的操作,例如初始化第三方库、绑定事件等。

关于请求接口的区别,一般来说,如果你需要在组件创建后立即请求接口并使用接口返回的数据进行初始化操作,你可以将请求放在 created 钩子函数中。这样可以确保在组件挂载到 DOM 之前就已经获取到了数据。

如果你需要在组件挂载到 DOM 后再请求接口,例如需要使用到组件的 DOM 元素或计算属性的值等,你可以将请求放在 mounted 钩子函数中。这样可以确保在组件渲染到页面上后再进行接口请求。

需要注意的是,如果你在 created 或 mounted 钩子函数中进行异步操作(例如发送异步请求),应该使用 Promise 或 async/await 来处理异步逻辑,以确保数据的正确获取和处理。

总结来说,created 钩子函数适合在组件创建后立即进行初始化操作,而 mounted 钩子函数适合在组件挂载到 DOM 后进行操作,包括请求接口。根据具体需求,你可以选择在 created 或 mounted 钩子函数中请求接口。

v-model 和双向数据绑定

v-model 是 Vue.js 提供的一个指令,用于实现表单元素和数据的双向绑定。双向数据绑定是指当表单元素的值发生变化时,数据也会相应地更新;反之,当数据发生变化时,表单元素的值也会相应地更新。

使用 v-model 可以简化表单元素和数据之间的绑定操作。你可以将 v-model 应用在表单元素上,例如 、、 等,将其与 Vue 实例中的数据进行绑定。

以下是一个使用 v-model 的示例:

复制

{{ message }}

在上述示例中,我们使用 v-model 将 元素与 Vue 实例中的 message 数据进行双向绑定。当输入框的值发生变化时,message 数据会自动更新;反之,当 message 数据发生变化时,输入框的值也会相应地更新。

需要注意的是,v-model 实际上是语法糖,它相当于同时使用了 :value 和 @input 这两个指令。:value 用于将数据绑定到表单元素的值上,@input 用于监听表单元素的输入事件并更新数据。

总结来说,v-model 是 Vue.js 提供的一个方便的指令,用于实现表单元素和数据的双向绑定。通过 v-model,你可以简化表单元素和数据之间的绑定操作,实现数据的实时更新和同步。

history和hash的区别,实现原理?hash怎么监听改变的?

history 和 hash 是浏览器中用于管理页面导航的两种方式,它们有以下区别和实现原理:

区别:

history 使用浏览器的 history API,通过修改 URL 的路径和查询参数来实现页面导航。例如,history.pushState() 可以将新的 URL 添加到浏览器的历史记录中,而不会引起页面的刷新。

hash 使用 URL 的哈希部分(即 # 后面的内容)来实现页面导航。例如,example/#/page1 和 example/#/page2 是两个不同的页面,浏览器在加载这些 URL 时不会向服务器发送请求。

实现原理:

history:history API 允许 JavaScript 修改浏览器的历史记录,而不会引起页面的刷新。通过调用 pushState() 或 replaceState() 方法,可以将新的 URL 添加到历史记录中或替换当前的 URL。当用户点击浏览器的前进或后退按钮时,浏览器会触发 popstate 事件,从而可以监听到 URL 的变化并进行相应的处理。

hash:当 URL 的哈希部分发生变化时,浏览器会自动滚动到对应的锚点位置,并触发 hashchange 事件。通过监听 hashchange 事件,可以捕获 URL 哈希部分的变化,并进行相应的处理。

监听 hash 的变化:

可以使用 window.onhashchange 属性或 addEventListener 方法来监听 hashchange 事件。当 URL 的哈希部分发生变化时,浏览器会触发该事件,并执行相应的回调函数。

例如,可以使用以下代码来监听 hash 的变化:

复制window.addEventListener(‘hashchange’, function() {
// 哈希部分发生变化时的处理逻辑
});
总结来说,history 和 hash 是浏览器中用于管理页面导航的两种方式。history 使用浏览器的 history API,通过修改 URL 的路径和查询参数来实现页面导航;hash 则使用 URL 的哈希部分来实现页面导航。通过监听相应的事件,可以捕获 hash 的变化并进行相应的处理。

滚动穿透?前端如何实现路由

滚动穿透是指在弹出层或模态框等浮动元素出现时,背后的页面仍然可以滚动。这可能会导致用户在浮动元素上滚动时,背后的页面也会滚动,造成用户体验上的混乱。

为了解决滚动穿透的问题,可以使用以下方法之一:

禁止背后页面滚动:在浮动元素出现时,可以通过给背后的页面添加 overflow: hidden 样式来禁止滚动。这样用户在浮动元素上滚动时,背后的页面就不会滚动。

固定背后页面的滚动位置:在浮动元素出现时,可以通过 JavaScript 获取背后页面的滚动位置,并将其保存下来。然后,通过给背后的页面添加 position: fixed 样式,并将滚动位置设置为固定值,可以实现固定背后页面的滚动位置。

前端如何实现路由:

前端路由是指在单页面应用(SPA)中,通过 JavaScript 控制页面的切换和渲染,而不是通过传统的页面跳转。常见的前端路由实现方式有以下几种:

使用 hash:通过监听 hashchange 事件,根据 URL 的哈希部分来切换页面内容。可以使用原生 JavaScript 或第三方库(如 Vue Router、React Router)来实现。

使用 history API:通过使用浏览器的 history API,可以在不刷新页面的情况下改变 URL,并根据 URL 的路径来切换页面内容。可以使用原生 JavaScript 或第三方库(如 Vue Router、React Router)来实现。

使用第三方库:许多流行的前端框架和库都提供了自己的路由功能,例如 Vue Router、React Router、Angular Router 等。这些库提供了更高级的路由功能,例如路由嵌套、路由守卫、动态路由等。

需要根据具体的项目需求和技术栈选择合适的前端路由实现方式。无论使用哪种方式,前端路由的核心思想是通过 JavaScript 控制页面的切换和渲染,以提供更流畅的用户体验。

2,webpack打包优化

Webpack 是一个强大的模块打包工具,但是如果不进行适当的优化,可能会导致打包后的文件过大,加载速度慢,影响用户体验。以下是一些常见的 Webpack 优化策略:

Tree Shaking:Webpack 2 开始支持 ES6 模块的 Tree Shaking,可以在打包时自动去除没有被引用的代码,减小打包文件的体积。

代码分割:通过 SplitChunksPlugin 或者动态 import(),将代码分割成多个小文件,可以实现按需加载,提高首屏加载速度。

懒加载:通过动态 import(),可以实现模块的懒加载,即在需要的时候再加载某个模块。

使用 DllPlugin:通过 DllPlugin 和 DllReferencePlugin,可以将第三方库单独打包,这样在开发环境下就不需要每次都重新打包这些库,可以提高打包速度。

使用 IgnorePlugin:通过 IgnorePlugin,可以忽略掉一些不需要的模块,减小打包文件的体积。

使用 Happypack:通过 Happypack,可以实现多线程打包,提高打包速度。

使用 terser-webpack-plugin:通过 terser-webpack-plugin,可以压缩和优化 JavaScript 代码。

使用 compression-webpack-plugin:通过 compression-webpack-plugin,可以生成 gzip 压缩文件,减小文件体积,提高加载速度。

以上只是一些基本的优化策略,实际上还有很多其他的优化方法,需要根据项目的具体情况进行选择和调整。

3,nodejs

4,闭包

5,reduce

6,运维做了什么

7,nginx

8,v-for :key的作用

10 ,叠加器
11,
ps自学:
1,首页预加载:https://blog.csdn/weixin_34414196/article/details/91480981
2,同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。它的存在可以保护用户隐私信息,防止身份伪造等(读取Cookie)。,
同源策略限制内容有:
Cookie、LocalStorage、IndexedDB 等存储性内容

web端自适应布局

在 Web 端实现自适应布局,可以使用以下几种方法:

使用 CSS 媒体查询:通过使用 @media 规则,可以根据不同的屏幕尺寸应用不同的样式。你可以定义不同的 CSS 规则,针对不同的屏幕尺寸设置不同的布局和样式。

复制/* 在小屏幕上应用的样式 /
@media screen and (max-width: 768px) {
/
设置适合小屏幕的布局和样式 */
}

/* 在中等屏幕上应用的样式 /
@media screen and (min-width: 769px) and (max-width: 1024px) {
/
设置适合中等屏幕的布局和样式 */
}

/* 在大屏幕上应用的样式 /
@media screen and (min-width: 1025px) {
/
设置适合大屏幕的布局和样式 */
}
使用 CSS Flexbox 布局:Flexbox 是一种弹性盒子布局模型,可以方便地实现自适应布局。通过设置容器的 display: flex,可以使其内部的子元素自动排列,并根据可用空间进行伸缩。

复制.container {
display: flex;
flex-wrap: wrap;
}

.item {
flex: 1;
}
使用 CSS Grid 布局:CSS Grid 是一种二维网格布局模型,可以将页面划分为行和列,并通过设置网格属性来控制元素的位置和大小。使用 CSS Grid 可以更灵活地实现自适应布局。

复制.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap: 10px;
}
使用响应式框架:使用流行的响应式框架,如 Bootstrap、Tailwind CSS 等,可以快速实现自适应布局。这些框架提供了一套预定义的 CSS 类和组件,可以根据不同的屏幕尺寸自动调整布局和样式。

以上是一些常用的方法,你可以根据具体需求选择适合的方式来实现 Web 端的自适应布局。需要注意的是,为了确保良好的用户体验,还应该进行移动设备的测试和优化,以适应不同尺寸和触摸操作的需求。

3,事件驱动、事件循环

事件驱动是一种编程模型,它基于事件的发生和处理来驱动程序的执行。在事件驱动模型中,程序会等待事件的发生,一旦事件发生,程序会调用相应的处理函数来处理事件。事件可以是用户输入、网络连接、定时器等。

事件循环是事件驱动模型的核心机制之一。事件循环是一个无限循环,它会不断地等待事件的发生,一旦事件发生,就会调用相应的处理函数来处理事件。事件循环会不断地重复这个过程,直到程序结束。

在事件驱动模型中,事件循环是程序的主线程,它负责等待事件的发生和处理事件。当事件发生时,事件循环会将事件加入到事件队列中,然后等待处理函数的调用。处理函数会从事件队列中取出事件,并进行相应的处理。处理完事件后,处理函数会返回到事件循环中,等待下一个事件的发生。

常用的算法有哪些 及其原理

计算机科学中有许多常用的算法,以下是其中的一部分:

排序算法:这是一类用于对数据进行排序的算法。常见的排序算法包括冒泡排序(通过重复地交换相邻的不正确的项,使得较大的元素逐渐移到序列的尾部)、选择排序(不断地选择剩余元素中的最小者)、插入排序(构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入)、快速排序(通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序)、归并排序(采用分治法的一个非常典型的应用)等。

搜索算法:这是一类用于查找数据的算法。常见的搜索算法包括线性搜索(从数据结构的一端开始,顺序地检查每一个元素)、二分搜索(在有序的数据结构中,从中间开始比较,每次都能排除一半的数据)、深度优先搜索(沿着树的深度遍历树的节点,尽可能深的搜索树的分支)、广度优先搜索(从根节点开始,沿着树的宽度遍历树的节点)等。

图算法:这是一类用于处理图形数据结构的算法。常见的图算法包括 Dijkstra 算法(用于查找图中两点之间的最短路径)、Floyd-Warshall 算法(用于查找图中所有对的最短路径)、Prim 算法和 Kruskal 算法(用于查找图的最小生成树)等。

动态规划:这是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划解决问题时,需要遵循无后效性和最优子结构性质。

分治算法:这是一种将原问题划分成 n 个规模较小而结构与原问题相似的子问题,递归地解决这些问题,然后再合并其结果,就得到原问题的解。

贪心算法:这是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。

以上只是一部分常用的算法,实际上还有许多其他类型的算法,如哈希算法、回溯算法、随机化算法等。
4,DOM 节点,
5,闭包https://developer.mozilla/zh-CN/docs/Web/JavaScript/Closures

八,忘记哪家公司了

1,history和hash的区别,实现原理?hash怎么监听改变的?

history 和 hash 是浏览器中用于管理页面导航的两种方式,它们有以下区别和实现原理:

区别:

history 使用浏览器的 history API,通过修改 URL 的路径和查询参数来实现页面导航。例如,history.pushState() 可以将新的 URL 添加到浏览器的历史记录中,而不会引起页面的刷新。

hash 使用 URL 的哈希部分(即 # 后面的内容)来实现页面导航。例如,example/#/page1 和 example/#/page2 是两个不同的页面,浏览器在加载这些 URL 时不会向服务器发送请求。

实现原理:

history:history API 允许 JavaScript 修改浏览器的历史记录,而不会引起页面的刷新。通过调用 pushState() 或 replaceState() 方法,可以将新的 URL 添加到历史记录中或替换当前的 URL。当用户点击浏览器的前进或后退按钮时,浏览器会触发 popstate 事件,从而可以监听到 URL 的变化并进行相应的处理。

hash:当 URL 的哈希部分发生变化时,浏览器会自动滚动到对应的锚点位置,并触发 hashchange 事件。通过监听 hashchange 事件,可以捕获 URL 哈希部分的变化,并进行相应的处理。

监听 hash 的变化:

可以使用 window.onhashchange 属性或 addEventListener 方法来监听 hashchange 事件。当 URL 的哈希部分发生变化时,浏览器会触发该事件,并执行相应的回调函数。

例如,可以使用以下代码来监听 hash 的变化:

复制window.addEventListener(‘hashchange’, function() {
// 哈希部分发生变化时的处理逻辑
});
总结来说,history 和 hash 是浏览器中用于管理页面导航的两种方式。history 使用浏览器的 history API,通过修改 URL 的路径和查询参数来实现页面导航;hash 则使用 URL 的哈希部分来实现页面导航。通过监听相应的事件,可以捕获 hash 的变化并进行相应的处理。

2,滚动穿透?
3,webpack打包优化?
4,es6数组扁平化?es6用过什么?

vue的vdom

VDOM,即 Virtual DOM(虚拟 DOM),是一种编程概念,其中的对象会模拟真实的 DOM 对象。VDOM 的主要目标是提高在 JavaScript 和真实 DOM 之间进行频繁操作的效率。

Vue.js 使用 VDOM 进行渲染,这是因为直接操作 DOM 是非常昂贵的。每次有数据变化,都直接去操作 DOM,会导致大量的重排和重绘,性能上会有很大的问题。因此,Vue.js 采用了一种中间层,即 VDOM,来优化这个过程。

在 Vue.js 中,当组件的状态被改变时,Vue 会创建一个新的 VDOM,并与旧的 VDOM 进行对比。这个对比过程叫做“diffing”。通过这个过程,Vue 可以计算出需要在真实 DOM 中进行哪些改变,然后在一次操作中执行这些改变,从而避免了不必要的重排和重绘。

这种方式可以极大地提高渲染的效率。因为在 JavaScript 中操作对象比在真实的 DOM 中插入或删除节点要快得多。所以,通过使用 VDOM,Vue.js 可以提供更快的渲染速度和更高的性能。

重排和重绘

重排(Reflow)和重绘(Repaint)是浏览器渲染过程中的两个概念,它们都会影响网页的渲染性能。

重排(Reflow):当渲染树中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建,这就称为重排。重排是 DOM 的变化影响了元素的几何属性(元素的位置和尺寸大小),浏览器需要重新计算元素的几何属性,重新渲染页面。比如改变窗口大小、改变字体大小、添加或删除可见的 DOM 元素、激活 CSS 伪类(例如::hover)、设置 style 属性等。

重绘(Repaint):当渲染树中的一些元素需要更新属性,而这些属性只是影响了元素的外观、风格,而并未影响布局的,比如 background-color,我们将这样的变化称为重绘。重绘是当节点需要更改外观并不会影响布局的时候,比如改变 color 就叫做重绘。重绘的代价比重排要小,改变元素的背景色、文字颜色等。

注意:重排必将引起重绘,而重绘不一定会引起重排。重排的性能消耗比重绘的要大得多的多。真正影响性能的是重排(Reflow),不是重绘(Repaint)。

5,原型链是什么?

在JavaScript中,每个对象都有一个原型对象(prototype),原型对象又有自己的原型对象,这样就形成了一个原型链(prototype chain)。原型链是JavaScript中实现继承的一种机制,它允许对象通过继承属性和方法来扩展自己的行为。
当我们访问一个对象的属性或方法时,JavaScript引擎会先查找该对象本身是否具有该属性或方法,如果没有,则会沿着原型链向上查找,直到找到该属性或方法或者到达原型链的顶端(即Object.prototype)为止。如果最终仍然没有找到该属性或方法,则返回undefined。
例如,我们可以通过以下方式创建一个对象,并将其原型设置为另一个对象:

6,vue3.0做了什么?

Vue 3.x 都做了哪些优化
Vue 3.x 相比于 Vue 2.x 做了很多优化和改进,主要包括以下几点:

性能优化:Vue 3.x 在编译阶段做了很多优化,包括静态树提升、静态属性提升、事件侦听器缓存等,这些优化可以减少渲染时的计算量,提高渲染性能。另外,Vue 3.x 还引入了 Proxy 作为新的响应式系统,这比 Vue 2.x 中的 Object.defineProperty 有更好的性能和更低的内存使用。

体积优化:Vue 3.x 的核心库体积更小,gzip 后大约只有 10KB,这是因为 Vue 3.x 将很多非核心的功能(如过渡、非父子组件通信等)移动到了单独的模块中,只有在需要时才会引入。

组合式 API:Vue 3.x 引入了组合式 API,这是一种新的编写组件逻辑的方式,可以更好地组织和复用代码。

更好的 TypeScript 支持:Vue 3.x 的源码完全用 TypeScript 重写,因此对 TypeScript 的支持更好。

多根节点组件:Vue 3.x 允许组件有多个根节点,这在 Vue 2.x 中是不允许的。

新的自定义指令 API:Vue 3.x 的自定义指令 API 更加灵活和强大。

Fragment、Suspense、Teleport 等新特性:Vue 3.x 引入了一些新的内置组件和特性,如 Fragment(用于返回多个根节点的组件)、Suspense(用于处理异步组件的加载状态)、Teleport(用于将组件的子元素传送到 DOM 的其他位置)等。

更好的安全性:Vue 3.x 做了很多安全性改进,包括对插槽内容的更严格检查、对模板表达式的更严格限制等。

以上就是 Vue 3.x 相比于 Vue 2.x 的主要优化和改进。

7,父子传值,兄弟传值?

refs
Props 和 emit
inject provide
$attr

8,浏览器有垃圾回收机制为什么还用destroy?

浏览器的垃圾回收机制主要是针对不再使用的内存空间进行自动回收,以防止内存泄漏。然而,这个机制并不是万能的,有些情况下需要我们手动进行销毁(destroy)操作。

对象引用:如果一个对象被其他对象引用,那么即使你不再使用这个对象,它也不会被垃圾回收机制回收。因此,我们需要手动解除引用,让垃圾回收机制可以正常工作。

事件监听:如果一个对象注册了事件监听器,那么即使你不再使用这个对象,只要事件监听器还在,这个对象就不会被垃圾回收。因此,我们需要手动移除事件监听器。

外部资源:如果一个对象持有外部资源(如网络连接、文件句柄等),那么这些资源不会被垃圾回收机制管理。因此,我们需要手动关闭或释放这些资源。

性能优化:即使浏览器的垃圾回收机制可以自动回收内存,但是这个过程需要消耗一定的计算资源。如果我们能够及时销毁不再需要的对象,可以减少垃圾回收的负担,从而提高程序的运行效率。

因此,虽然浏览器有垃圾回收机制,但是在某些情况下,我们仍然需要手动进行销毁操作。

9,created可以发送请求嘛?

可以 只是这是时候还没有挂载$el 实例化后请求可以

10,浏览器兼容?

11,为什么loader可以实现浏览器兼容?

在前端开发中,我们经常会使用一些新的 JavaScript 语法或者 API,但是这些新特性在一些老版本的浏览器中可能不被支持。为了解决这个问题,我们可以使用一些工具,如 Babel,将我们的代码转换成老版本浏览器可以理解的代码。这就是所谓的 “transpiling”。

Loader 是 Webpack 中的一个重要概念,它的作用是对模块源代码进行转换。例如,我们可以使用 Babel Loader 将 ES6 语法转换成 ES5 语法,使得我们的代码可以在老版本的浏览器中运行。

除了 Babel Loader,还有许多其他的 Loader 可以帮助我们实现浏览器的兼容性,例如:

PostCSS Loader:可以帮助我们自动添加 CSS 前缀,以实现 CSS 的兼容性。

File Loader:可以帮助我们处理图片和字体文件,使得它们可以在不同的浏览器中正确显示。

Style Loader 和 CSS Loader:可以帮助我们处理 CSS 文件,使得它们可以在 JavaScript 中被正确引用和使用。

总的来说,通过使用合适的 Loader,我们可以将一些新的、不被所有浏览器支持的语法或者 API 转换成被广泛支持的形式,从而实现浏览器的兼容性。

12,vue-router模式?

13,上线前进行那些配置?

14,call apply bind

bind的作用是只修改this指向,但不会立即执行fn;会返回一个修改了this指向后的fn。需要调用才会执行:bind(thisArg, arg1, arg2, arg3, …)()。bind的传参和call相同。

function greet(arg1, arg2) {
console.log(this.name + ": " + arg1 + " " + arg2);
}

call 和 apply 都是函数对象的一个方法,它们都是用来改变函数的执行上下文,即函数体内部的 this 指向的对象。

call 方法接受的是参数列表,而 apply 方法接受的是一个参数数组。以下是它们的基本用法:

var person = {name: “John”};

greet.call(person, “Hello”, “World”); // 输出 “John: Hello World”
greet.apply(person, [“Hello”, “World”]); // 输出 “John: Hello World”
在这个例子中,greet 函数的 this 被 call 和 apply 方法改变为 person 对象。

另外,call 和 apply 也常常被用于借用其他对象的方法:

复制var person1 = {name: “John”};
var person2 = {name: “Jane”};

function greet() {
console.log("Hello, " + this.name);
}

greet.call(person1); // 输出 “Hello, John”
greet.call(person2); // 输出 “Hello, Jane”
在这个例子中,greet 函数借用了 person1 和 person2 的 name 属性。

vue 的$attr传值

在 Vue 中,$attrs 是一个包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外) 的对象。当你不知道父组件会传递什么属性给子组件,或者你想要把某些属性应用到子组件的根元素,而不是通过 prop 传递,这时候就可以使用 $attrs。

例如:

<!-- 父组件 -->
<child-component id="myId" custom-attr="customAttrValue"></child-component>
<!-- 子组件 -->
<template>
  <div v-bind="$attrs">
    <!-- 其他代码 -->
  </div>
</template>

在这个例子中,父组件传递了 id 和 custom-attr 给子组件,这些属性不是子组件的 prop。在子组件中,我们使用 v-bind=“$attrs” 将这些属性绑定到子组件的根元素上。这样,子组件的根元素就会有 id=“myId” 和 custom-attr=“customAttrValue” 这两个属性。

注意:在 Vue 2.x 中,你需要在子组件中添加 inheritAttrs: false 选项,以防止 $attrs 中的属性被添加到子组件的根元素上。在 Vue 3.x 中,这已经成为了默认行为。
九。忘记哪家公司2

1,post,get区别?

post,get区别
GET和POST是HTTP协议中两种最常见的请求方法,它们的主要区别如下:

数据传输方式:GET请求的数据会附在URL之后,以?分割URL和传输数据,参数之间以&相连,如http://www.example?name=John&age=18。而POST请求的数据则放在HTTP请求体中。

数据安全性:由于GET请求的数据直接暴露在URL中,所以安全性较低,不适合传输敏感信息。而POST请求的数据在请求体中,安全性较高。

数据长度:GET请求的数据长度受限于URL长度,而POST请求的数据长度没有限制。

缓存:GET请求的结果会被浏览器默认缓存,而POST不会。

服务器处理:对于GET请求,服务器会直接返回结果,而POST请求需要服务器对请求体进行解析。

幂等性:GET请求是幂等的,意味着无论进行多少次操作,结果都是一样的。而POST请求不是幂等的,每次请求都可能得到不同的结果。

请求历史:GET请求会被浏览器保存在历史记录中,而POST请求则不会。

对数据类型的支持:POST支持更多的数据类型,GET只支持ASCII字符。

以上就是GET和POST的主要区别,但具体使用哪种请求方法,需要根据实际情况和需求来决定。

2,bfc如何触发?

BFC(Block Formatting Context)是Web页面的可视化CSS渲染的一部分,是块级盒布局发生的区域,也是浮动元素与其他元素的交互限定区域。

以下几种方式可以触发BFC:

根元素或包含根元素的元素

浮动元素(元素的 float 不是 none)

绝对定位元素(元素的 position 为 absolute 或 fixed)

行内块元素(元素的 display 为 inline-block)

表格单元格(元素的 display为 table-cell,HTML表格单元格默认为该值)

表格标题(元素的 display 为 table-caption,HTML表格标题默认为该值)

匿名表格单元格元素(元素的 display为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot的默认属性)

overflow 值不为 visible 的块元素

display 值为 flow-root 的元素

contain 值为 layout、content或 paint 的元素

弹性元素(display为 flex 或 inline-flex元素的直接子元素)

网格元素(display为 grid 或 inline-grid 元素的直接子元素)

多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)

column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。

以上这些情况都会触发BFC。

*4,项目中的优化?

*5,实现公共组件?

*6,异步有哪些?

setTimeout、setInterval promise Generator、async/await addEventListener

*7,父子生命周期?

挂载(初始化相关属性)
beforeCreate
created
beforeMount
mounted
更新(元素或组件的变更操作)
beforeUpdate
updated
销毁(销毁相关属性)
beforeDestroy
destroyed

一个完整的父子组件生命周期:

父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted->
beforeUpdate->子beforeUpdate->子updated->父updated->
beforeDestroy->子beforeDestroy->子destroyed->父destroyed
8,v-model?可以监听对象嘛?
vue2中不可以 只可以绑定到对象的属性上,vue3可以 但是需要:【property】

9,flex:1
basic shrink shadow
10,圣杯模式?
11,懒加载原理?
12,css动画?
13,computed和watch的区别?

十,58同城

  • 1,事件机制

* *require和import区别?AMD、cmd区别

require和import都是用于在JavaScript中引入模块的方法,但它们的使用方式和实现方式有所不同。
require是CommonJS规范中定义的模块加载方法,它是同步加载模块的方式。在Node.js中,可以使用require方法来加载模块
import是ES6中定义的模块加载方法,它是异步加载模块的方式。在现代浏览器和支持ES6的Node.js版本中,可以使用import语句来加载模块
AMD(Asynchronous Module Definition)是异步模块定义规范,它使用define函数来定义模块,使用require函数来加载模块。在AMD中,模块的依赖关系是在模块定义时声明的
CMD(Common Module Definition)是通用模块定义规范,它使用define函数来定义模块,使用require函数来加载模块。在CMD中,模块的依赖关系是在模块执行时动态解析的

标题http 链接 和tcp链接

HTTP(HyperText Transfer Protocol)和 TCP(Transmission Control Protocol)都是网络协议,但它们工作在不同的层次,并且有不同的职责。

TCP 是一种面向连接的、可靠的、基于字节流的传输层通信协议。在 TCP/IP 协议族中,TCP 负责在两台主机之间建立连接,保证数据包的顺序传输和错误检查。如果数据包在传输过程中丢失或损坏,TCP 会自动重发数据包,直到所有数据都被正确接收。TCP 还提供了流量控制和拥塞控制机制。

HTTP 则是一种应用层协议,它基于 TCP 连接,用于在 Web 浏览器和服务器之间传输 HTML 页面、图片、视频等资源。HTTP 协议定义了客户端和服务器之间的请求和响应格式,以及如何解析这些格式。

在一个典型的 Web 交互过程中,首先由客户端发起一个 TCP 连接,然后在这个连接上发送 HTTP 请求。服务器接收到请求后,处理请求并返回 HTTP 响应。响应被客户端接收和解析后,TCP 连接可以被关闭,或者被保持开启以便复用。

总的来说,TCP 负责在网络中传输数据,而 HTTP 则负责定义和解析这些数据的格式。

* 3,npm机制

  • 4,跨域的标签有哪些 都用来干嘛

* 5,asycn await与promise区别

Promise 和 async/await 都是 JavaScript 中处理异步操作的方式,它们之间的主要区别在于语法和可读性。

Promise 是 ES6 引入的一种异步编程的解决方案,它通过 then 方法来链接异步操作。例如:

doSomething()
  .then(result => doSomethingElse(result))
  .then(newResult => doThirdThing(newResult))
  .catch(error => console.error(error));

async/await 是 ES7 引入的,它是基于 Promise 实现的,但提供了更好的可读性和更简洁的语法。它允许在异步函数(用 async 关键字声明的函数)内部使用 await 关键字等待 Promise 的结果。例如:

async function doAll() {
  try {
    const result = await doSomething();
    const newResult = await doSomethingElse(result);
    await doThirdThing(newResult);
  } catch (error) {
    console.error(error);
  }
}

可以看到,使用 async/await 的代码更接近于传统的同步代码,更易于理解。

然而,虽然 await 使得异步代码看起来像同步代码,但它并不会阻塞后面的代码执行,这是它与同步操作的主要区别。在等待 Promise 解析的过程中,其他的代码仍然可以继续执行。只有在 async 函数内部,await 后面的代码会等待 Promise 解析后再执行。

  • 6,缓存机制?大小限制?怎么扩展?
    7,整个图片怎么存在缓存中?base64过大怎么处理?
    8,doctype是干嘛的?严格模式与混杂模式的区别?
    9,微前端?
    10,项目体量是多少?
    11,generator与yield?

十一,不知道哪家公司3
1,serve-word是干嘛的?
2,图片转成文件是哪个loader?
3,plugins哪个插件处理rem?
*4,项目中比较满意的点?

5,路由懒加载? webpack打完包的区别?

*6,vue3.0了解哪些?

Vue 3.0 是 Vue.js 的下一个主要版本,相比于 Vue 2.x,它带来了许多重大的改进和新特性,包括:

更快的渲染速度:Vue 3.0 使用了新的响应式系统,可以更快地跟踪数据变化,从而提高渲染性能。

更小的体积:Vue 3.0 的体积比 Vue 2.x 更小,同时还提供了更好的 Tree-shaking 支持,可以更好地优化打包体积。

更好的 TypeScript 支持:Vue 3.0 对 TypeScript 的支持更加完善,可以提供更好的类型检查和代码提示。

更好的组合 API:Vue 3.0 引入了 Composition API,可以更好地组织和复用组件逻辑,同时还提供了更好的 TypeScript 支持。

更好的自定义渲染器:Vue 3.0 提供了更好的自定义渲染器支持,可以更方便地实现 SSR、微前端等场景。

更好的性能调试工具:Vue 3.0 提供了更好的性能调试工具,可以更方便地分析和优化应用性能。

总的来说,Vue 3.0 带来了许多重大的改进和新特性,可以提供更好的开发体验和更好的性能表现。同时,由于 Vue 3.0 与 Vue 2.x 在 API 和语法上有一些不兼容的变化,因此需要开发者进行一定的学习和适配。

7,link标签都干嘛了?script怎么实现异步?
8,SEO、用的什么plugin?

vue指令 计算属性

Vue.js 中的指令是一种特殊的 HTML 属性,用于给 HTML 元素添加特定的行为或功能。Vue.js 内置了很多指令,其中包括计算属性指令 computed。

computed 是一种计算属性指令,用于在 Vue.js 实例中定义计算属性。计算属性是一种基于依赖的缓存属性,它的值会根据它所依赖的属性的值自动计算,并且只有在它所依赖的属性发生变化时才会重新计算。

使用 computed 指令可以将计算属性定义为一个函数,该函数会自动缓存计算结果,并且只有在它所依赖的属性发生变化时才会重新计算。

十二,建信金科
1,界面级优化有哪些
2,无父母宽高,实现子元素是正方形 水平垂直居中
3,promise。all怎么实现?promise调用另一个promise怎么做
4,深度子组件传值怎么传?
5,实现一个tree组件,怎么实现组件自递归?

闭包

闭包是指在一个函数内部定义的函数,该函数可以访问外部函数的变量和参数,即使外部函数已经返回,闭包仍然可以访问这些变量和参数。闭包可以用来创建私有变量和方法,以及实现函数式编程中的柯里化、偏函数等高级技巧。

6,nexttick原理

nextTick 是 Vue.js 提供的一个异步方法,它的作用是在下次 DOM 更新循环结束之后执行延迟回调。其原理如下:

nextTick 方法会将回调函数存储到一个队列中。

在同一事件循环中,多次调用 nextTick 方法会将回调函数全部存储到同一个队列中。

在下次 DOM 更新循环结束之后,Vue.js 会遍历队列中的所有回调函数,并依次执行它们。

在执行回调函数之前,Vue.js 会先对队列进行排序,按照组件的更新顺序执行回调函数,从父组件到子组件。

由于 Vue.js 的更新是异步执行的,因此在某些情况下,我们需要等待 DOM 更新之后才能执行一些操作,例如获取更新后的 DOM 元素的位置、尺寸等信息。此时,我们可以使用 nextTick 方法来延迟执行这些操作,以确保它们在 DOM 更新之后执行。

需要注意的是,nextTick 方法并不是在下一次事件循环中执行回调函数,而是在当前事件循环的异步任务队列中添加一个任务,在下一次事件循环中执行这个任务。因此,如果在当前事件循环中多次调用 nextTick 方法,它们会被合并成一个任务,只会执行一次。

*7,vue和react区别

*8.兄弟组件传值方式

9,虚拟列表?

虚拟列表是一种优化技术,用于处理大量数据的列表。它通过只渲染可见区域内的数据项,而不是渲染整个列表,来提高性能和减少内存占用。

虚拟列表通常使用两个重要的属性:可见区域的高度和每个数据项的高度。通过这些属性,虚拟列表可以计算出可见区域内需要渲染的数据项数量,并只渲染这些数据项。当用户滚动列表时,虚拟列表会动态地计算新的可见区域,并更新渲染的数据项。

虚拟列表的优点包括:

提高性能:只渲染可见区域内的数据项,减少了渲染的数量,从而提高了性能。

减少内存占用:只渲染可见区域内的数据项,减少了内存占用,从而减少了浏览器的负担。

支持大量数据:虚拟列表可以处理大量数据,而不会影响性能和内存占用。

虚拟列表在现代Web应用程序中非常常见,特别是在需要处理大量数据的情况下。它可以用于各种类型的列表,包括表格、下拉列表、菜单等。

10,SSR、?

*11,mvvm模式

12,diff算法是什么,广度还是深度?

diff 算法是指在进行 Virtual DOM 更新时,比较新旧 Virtual DOM 树的差异,然后将差异更新到真实的 DOM 树上的算法。diff 算法的核心思想是尽量复用已有的 DOM 节点,减少 DOM 操作的次数,从而提高性能。

diff 算法的具体实现可以分为以下几个步骤:

首先比较新旧 Virtual DOM 树的根节点,如果节点类型不同,则直接替换整个节点。

如果节点类型相同,则比较节点的属性和事件,将发生变化的属性和事件更新到真实的 DOM 节点上。

然后比较节点的子节点,采用深度优先遍历的方式,逐层比较子节点。

在比较子节点时,先将新旧子节点列表的头尾节点进行比较,如果相同,则直接复用该节点,然后将头指针和尾指针向中间移动一位,继续比较下一个节点。

如果头尾节点不同,则进行全量比较,从旧子节点列表中查找与新子节点相同的节点,如果找到了,则将该节点移动到正确的位置上,然后将头指针和尾指针向中间移动一位,继续比较下一个节点。

如果旧子节点列表中没有与新子节点相同的节点,则直接将新子节点插入到正确的位置上,然后将头指针和尾指针向中间移动一位,继续比较下一个节点。

综上所述,diff 算法采用深度优先遍历的方式进行节点比较,同时在比较子节点时,采用头尾指针的方式进行优化,尽量复用已有的 DOM 节点,减少 DOM 操作的次数,从而提高性能。

13,object。defineProperty的缺点是什么?

Object.defineProperty 的缺点主要有以下几点:

只能劫持对象的属性,因此需要遍历对象的每个属性进行劫持,如果对象的属性较多,劫持的过程会比较耗时。

无法监听数组的变化,因为数组的 push、pop、splice 等方法并不会触发属性的 setter。

无法监听对象新增属性和删除属性的变化,因为 Object.defineProperty 只能劫持已经存在的属性。

对象的嵌套层级较深时,需要递归遍历每个属性进行劫持,劫持的过程比较复杂。

在 Vue.js 2.x 中,由于 Object.defineProperty 的限制,无法监听到对象属性的深层次变化,需要使用 Vue.set 或 this.$set 方法进行手动触发更新。

综上所述,Object.defineProperty 的缺点主要是劫持对象属性的效率较低,无法监听数组变化和对象新增、删除属性的变化,以及对于嵌套层级较深的对象需要递归遍历进行劫持,使用起来比较麻烦。

14,uni-app怎么做到不同端配置的?

在 uni-app 中,你可以在代码中使用 #ifdef、#ifndef、#endif 这三个编译条件判断语句来进行不同平台的代码编写。例如:

// #ifdef H5
console.log('这段代码只会在 H5 平台中执行');
// #endif

// #ifdef MP-WEIXIN
console.log('这段代码只会在微信小程序平台中执行');
// #endif

此外,uni-app 还提供了 pages.json 配置文件,你可以在这个文件中对不同平台进行配置。例如:

{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页",
        "app-plus": {
          "titleNView": {
            "backgroundColor": "#f00"
          }
        },
        "h5": {
          "titleNView": {
            "backgroundColor": "#0f0"
          }
        }
      }
    }
  ]
}

在这个例子中,app-plus 和 h5 分别对应了 App 和 H5 平台的配置。

总的来说,uni-app 通过条件编译和配置文件的方式,实现了不同端的配置。
15,promise与async,await的区别?await与同步的区别

16,mixin与mixins的区别

Mixin是一种面向对象编程中的概念,它指的是将一个类的方法和属性复制到另一个类中,以便让另一个类具有相同的功能。Mixin可以用于实现代码的复用和组合,从而减少代码的重复性。

在JavaScript中,Mixin通常是通过对象的复制来实现的。例如,我们可以定义一个mixin对象,它包含一些方法和属性,然后将它复制到其他对象中,以便让这些对象具有相同的功能。

Mixins是指将多个Mixin组合在一起使用的技术。例如,我们可以定义多个Mixin对象,然后将它们组合在一起,以便让一个对象具有多个功能。

在Vue.js中,Mixin是一种可重用的代码块,它可以在多个组件中共享。Mixin可以包含组件的选项,例如data、methods、computed等。当一个组件使用Mixin时,它会将Mixin中的选项合并到自己的选项中,从而实现代码的复用和组合。
总的来说,Mixin和Mixins都是用于实现代码的复用和组合的技术,Mixin是将一个类的方法和属性复制到另一个类中,而Mixins是将多个Mixin组合在一起使用。在JavaScript中,Mixin通常是通过对象的复制来实现的,在Vue.js中,Mixin是一种可重用的代码块,它可以在多个组件中共享。

二叉树算法

二叉树是一种常见的数据结构,它由节点和边组成,每个节点最多有两个子节点。二叉树的算法包括遍历、查找、插入、删除等操作。以下是一些常见的二叉树算法:

遍历二叉树

遍历二叉树有三种方式:前序遍历、中序遍历和后序遍历。前序遍历是先访问根节点,然后访问左子树,最后访问右子树。中序遍历是先访问左子树,然后访问根节点,最后访问右子树。后序遍历是先访问左子树,然后访问右子树,最后访问根节点。

查找二叉树

查找二叉树有两种方式:深度优先搜索和广度优先搜索。深度优先搜索是从根节点开始,沿着一条路径一直搜索到叶子节点,然后回溯到上一个节点,继续搜索下一条路径。广度优先搜索是从根节点开始,按照层级顺序依次搜索每个节点。

插入二叉树

插入二叉树是将一个新节点插入到二叉树中。插入节点时,需要找到插入位置,并将新节点插入到该位置。如果插入的节点已经存在,则需要更新该节点的值。

删除二叉树

删除二叉树是将一个节点从二叉树中删除。删除节点时,需要找到该节点,并将其从二叉树中删除。如果删除的节点有子节点,则需要将其子节点移动到删除节点的位置。

以上是一些常见的二叉树算法,它们在实际开发中都有广泛的应用。

项目中的难点:

1,公共组件的书写,el-table的二次封装
2,公共头部的封装
3,上传组件的 裁切封装
4,pdf转图片封装,
5,设计路由,由于是muatic框架,vue配合php技术栈,路由采用的php controller。
6,业务逻辑 邮件和短信有阻碍,广告投入才是王道 但是在数据回收模型上需加工。
7,开发模式

XSS及CSRF攻击是什么,如何防御

XSS(Cross Site Scripting)跨站脚本攻击:攻击者通过在目标网站上注入恶意脚本,当用户浏览该网站时,注入的脚本会被执行,从而可以获取用户的敏感信息,如cookies、session等。

防御XSS攻击的方法:

对用户输入的数据进行过滤和转义,不信任任何用户输入的内容。

使用HTTP-only的cookie,使得脚本无法读取到cookie。

对所有的API接口增加CSRF防御。

CSRF(Cross Site Request Forgery)跨站请求伪造:攻击者诱导用户去点击一个链接,这个链接是向一个信任的网站发送的请求,由于浏览器会自动带上cookie,所以如果用户在该网站上有权限,那么这个请求就会被执行。

防御CSRF攻击的方法:

使用验证码,确保请求是用户自愿发出的。

使用Referer Check,检查请求是否来自合法的源。

使用Anti-CSRF Token,服务器生成一个随机的token,每次用户提交请求时都必须包含这个token,服务器会验证这个token的合法性。

组件封装有哪些原则

组件封装是前端开发中的一种常见技术,它可以提高代码的复用性、可维护性和可读性。以下是一些组件封装的原则:

单一职责原则:每个组件应该只做一件事情,如果一个组件有多个职责,那么它就应该被拆分成多个组件。

开闭原则:组件应该对扩展开放,对修改关闭。这意味着我们应该能够在不修改组件的源代码的情况下,通过添加新的代码来改变组件的行为。

依赖倒置原则:组件应该依赖于抽象,而不是依赖于具体的实现。这意味着我们应该尽量使用接口和抽象类,而不是具体的类。

接口隔离原则:组件的接口应该尽可能小,只包含组件需要的方法和属性。这样可以减少组件之间的耦合度。

高内聚低耦合原则:组件的内部应该高度集中,处理具体的业务逻辑;组件之间的关系应该尽可能简单,减少相互依赖。

易用性原则:组件应该易于使用,接口设计应该简单明了,尽量减少使用者需要了解的知识。

可复用性原则:组件应该设计成可复用的,这样可以提高开发效率,减少重复代码。

封装变化原则:将可能发生变化的部分封装起来,减少对其他部分的影响。

以上原则并非一成不变,需要根据实际项目需求和团队情况灵活运用。

.Node服务怎么去定位CPU占用暴涨的情况? 怎么去定位内存泄露

定位Node.js服务CPU占用暴涨和内存泄露的情况,可以使用一些性能监控和分析工具。以下是一些常用的方法:

CPU占用暴涨:

使用Node.js的内置模块v8-profiler进行CPU分析。它可以生成CPU的分析数据,然后使用node-inspector来查看这些数据。

使用操作系统的工具,如Linux的top或htop,Mac的Activity Monitor,Windows的Task Manager,来监控CPU使用情况。

使用第三方的性能监控服务,如New Relic,AppDynamics等。

内存泄露:

使用Node.js的内置模块heapdump和memwatch来监控和分析内存使用情况。heapdump可以生成堆内存的快照,然后使用Chrome开发者工具的Profiles面板来查看。memwatch可以提供内存泄露的警告。

使用process.memoryUsage()方法来获取Node.js进程的内存使用情况。

使用第三方的性能监控服务,如New Relic,AppDynamics等。

在定位问题的过程中,需要注意的是,高CPU使用率可能是由于计算密集型的任务,而内存泄露通常是由于不正确的内存管理,如忘记释放不再使用的对象。因此,优化代码和改进内存管理是解决这些问题的关键。

对称加密与非对称加密的区别,HTTPS证书的作用

对称加密和非对称加密是两种常见的加密方式,它们的主要区别在于密钥的使用方式:

对称加密:加密和解密使用同一个密钥,这种方式加密速度快,但是密钥的管理和分发比较困难,如果密钥泄露,那么加密的信息就可能被破解。

非对称加密:使用一对密钥,一个是公钥,一个是私钥。公钥可以公开,任何人都可以使用公钥加密信息,但是只有对应的私钥才能解密信息。这种方式解决了密钥分发的问题,但是加密和解密的速度比对称加密慢。

HTTPS证书的作用:

HTTPS证书,也称为SSL证书,主要用于在用户和网站之间建立一个加密的连接,保证传输的数据不会被第三方窃取或篡改。当用户访问一个使用HTTPS的网站时,网站会将其公钥通过证书发送给用户,用户就可以使用这个公钥来加密信息,然后发送给网站,网站再使用私钥解密。

此外,HTTPS证书还包含了网站的身份信息,用户可以通过查看证书来验证网站的真实性,防止钓鱼网站的欺诈。证书的颁发机构(CA)会对申请证书的网站进行严格的审核,只有通过审核的网站才能获得证书。

什么是NGINX负载均衡,常用的NGINX负载均衡算法有哪些?

NGINX负载均衡是一种将网络流量分发到多个服务器的技术,以提高网站的可用性和响应速度,防止单个服务器的过载。NGINX是一种常用的反向代理服务器,它可以根据不同的负载均衡算法将请求分发到后端的多个服务器。

常用的NGINX负载均衡算法有:

轮询(Round Robin):这是默认的负载均衡算法,每个请求按照顺序分配到不同的后端服务器,如果服务器down掉,能自动剔除。

加权轮询(Weighted Round Robin):与轮询类似,但是每个服务器可以设置权重,根据权重的大小来分配请求,权重越大,分配的请求越多。这种方法可以让性能更强的服务器处理更多的请求。

IP Hash:每个请求的IP的hash结果分配到不同的服务器,这样每个访客固定访问一个后端服务器,可以解决session的问题。

最少连接(Least Connections):优先将请求分配给当前连接数最少的服务器,适用于请求处理时间较长,且请求处理时间差异较大的情况。

基于URL Hash的方法:根据访问URL的hash结果分配请求,使得每个URL定向到同一个后端服务器,适用于服务器缓存时提高效率。

以上就是NGINX的常用负载均衡算法,可以根据实际的业务需求和服务器性能来选择合适的算法。
如何定义客户端的首屏,如何通过技术手段来监控各种时间的耗时
首屏定义:首屏是指用户打开网页后,不滚动页面,所能看到的那部分内容。首屏时间是指从用户输入网址或点击链接开始,到首屏内容完全显示出来的时间。

监控各种时间的耗时的技术手段:

使用浏览器的Performance API:Performance API提供了很多与性能相关的数据,如页面加载时间、重定向时间、DNS查询时间、TCP连接时间、DOM解析时间、页面渲染时间等。通过这些数据,我们可以计算出首屏时间。

使用Navigation Timing API:这是一个W3C标准,提供了浏览器在处理网页的各个阶段所花费的时间,包括重定向时间、App Cache时间、DNS查询时间、TCP连接时间、请求时间、响应时间、处理DOM时间、加载事件时间等。

自定义首屏时间:由于首屏的定义因应用而异,有时候我们需要自定义首屏时间。比如,我们可以在首屏的关键内容加载完成后,手动调用Performance API的mark方法,标记一个时间点,然后与navigationStart时间相减,得到首屏时间。

使用第三方性能监控工具:有很多第三方的性能监控工具,如Google的Lighthouse、阿里的浏览器性能监控平台等,它们可以提供详细的性能报告,包括首屏时间。

以上方法可以结合使用,以获得更准确的首屏时间。

Hooks的原理

React Hooks 是 React 16.8 版本引入的新特性,它允许你在不编写 class 的情况下使用 state 以及其他的 React 特性。Hooks 的设计目标是让组件间的状态逻辑复用变得更容易。

Hooks 的工作原理主要基于以下两个部分:

JavaScript 闭包:Hooks 利用了 JavaScript 的闭包机制,每次渲染都有其自己的 Props 和 State。

链表数据结构:React 内部使用链表来保存和管理 Hooks。每个组件实例都有一个保存 Hooks 的链表,链表中的每个元素对应一个 Hook。当组件重新渲染时,React 会根据链表中的顺序来更新每个 Hook 的状态。

以下是一个简单的 useState Hook 的示例:

import React, { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

在这个例子中,useState 是一个 Hook。我们调用它来将我们的组件的一个 state 变量。在我们的例子中,它是我们要“记住”的 count 值。useState 返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。这和 this.setState 类似,但它不会把新的 state 和旧的 state 进行合并。

需要注意的是,只有在 React 的函数组件中才能使用 Hook。不要在循环、条件或嵌套函数中调用 Hook,而是要始终在你的 React 函数的最顶层使用它们。这样你就能确保 Hook 在每一次渲染中都在同一个顺序中被调用,这让 React 能够正确地保留 Hook 的状态。

diff

在计算机科学中,"diff"通常是指比较两个文件或数据集的差异的过程或结果。这个词源自Unix系统中的"diff"命令,该命令用于显示两个文件之间的差异。

在前端开发中,“diff"通常是指Virtual DOM(虚拟DOM)中的一种算法。当状态变化时,Virtual DOM会进行新旧两个DOM树的比较,然后计算出最小的修改步骤来更新真实的DOM,这个过程就叫做"diff”。

React和Vue等前端框架都使用了这种"diff"算法来提高性能。因为直接操作DOM非常消耗性能,而通过"diff"算法,我们可以尽可能地减少对DOM的操作,从而提高性能。

React中的"diff"算法主要有两个假设:

两个不同类型的元素会产生不同的树。

开发者可以通过key prop来指示哪些子元素在不同的渲染下能保持稳定。

基于这两个假设,React diff算法的时间复杂度从O(n^3)优化到了O(n)。

怎么优化H5让它可以在300ms以内打开

优化H5页面以在300ms内打开是一项挑战,因为这涉及到网络速度、服务器性能、页面大小等多个因素。然而,以下是一些可能的优化策略:

优化图片:使用更小的图片,或者使用更有效的图片格式(如WebP)。如果可能,考虑使用CSS或SVG来替代图片。

压缩和合并资源:使用工具如Gzip来压缩HTML、CSS和JavaScript文件。同时,尽可能地合并CSS和JavaScript文件,以减少HTTP请求的数量。

使用CDN:使用内容分发网络(CDN)可以将你的内容分发到全球的边缘服务器上,从而减少用户获取资源的时间。

延迟加载:只加载用户需要立即看到的内容,然后在后台加载其余的内容。这可以通过懒加载(lazy loading)技术实现。

缓存:利用浏览器缓存来存储常用的文件,这样用户在下次访问时就不需要再次下载这些文件。

优化CSS:将关键的CSS内联到HTML中,这样页面可以在下载一个文件后就开始渲染。

优化JavaScript:将JavaScript放到页面底部,或者使用async和defer属性,这样JavaScript的加载和执行就不会阻塞页面的渲染。

使用服务端渲染(SSR):这可以使浏览器更早地获取到可渲染的HTML,从而更早地开始渲染页面。

预加载和预渲染:使用和可以让浏览器预先加载和渲染页面,从而提高性能。

使用HTTP/2:HTTP/2支持多路复用,可以同时传输多个文件,从而减少加载时间。

请注意,这些策略的效果会因应用而异,所以你需要根据你的具体情况来选择和实施这些策略。

webpack plugin的原理是什么?

Webpack 插件(Plugin)的原理主要基于事件流机制实现,插件会在Webpack构建生命周期的特定时机触发一系列的事件。

Webpack 在运行的生命周期中会广播出许多事件,插件在监听到感兴趣的事件后,会执行特定的逻辑,并且插件可以调用Webpack提供的API改变输出结果。

插件的基本结构是一个类,它定义了一个 apply 方法。这个 apply 方法接收一个 compiler 对象参数,compiler 对象代表了完整的Webpack环境配置。这个 compiler 对象在Webpack启动时被实例化,它是返回的Webpack实例对象,你可以在它上面注册各种事件钩子函数。

例如,一个简单的插件可能是这样的:

复制class MyPlugin {
apply(compiler) {
compiler.hooks.done.tap(‘My Plugin’, (stats) => {
console.log(‘MyPlugin: Webpack build done!’);
});
}
}
在这个例子中,MyPlugin 插件在Webpack构建完成(done 事件)时会打印一条消息。tap 方法的第一个参数是插件的名称,第二个参数是回调函数,这个回调函数会在事件触发时执行。

Webpack插件系统的设计使得开发者可以在构建流程的各个阶段插入自定义的构建逻辑,从而实现对构建流程的高度自定义和扩展。

登录的cookie的执行流程

登录的cookie的执行流程通常如下:

用户打开浏览器,输入用户名和密码,点击登录。

服务器验证用户名和密码,如果验证通过,服务器会生成一个包含用户登录信息的cookie。

服务器将cookie通过HTTP响应头的Set-Cookie字段发送给浏览器。

浏览器收到HTTP响应后,会将cookie保存起来。

当用户再次访问该网站时,浏览器会自动将cookie通过HTTP请求头的Cookie字段发送给服务器。

服务器收到HTTP请求后,会解析Cookie字段,获取用户的登录信息,然后进行相应的处理。

如果用户点击退出登录,服务器会发送一个新的Set-Cookie指令,告诉浏览器删除这个cookie。

需要注意的是,cookie包含的信息可以被浏览器保存一段时间,例如,直到浏览器关闭,或者直到cookie的过期时间。此外,由于cookie可能包含敏感信息,因此需要通过安全的连接(HTTPS)来传输,以防止被窃取。

单点登录全流程

单点登录(Single Sign-On,SSO)是一种基于Web的身份验证方法,允许用户在多个应用程序之间共享同一套登录凭据。以下是单点登录的一般流程:

用户首次访问应用A时,由于尚未登录,会被重定向到认证服务器进行身份验证。

用户在认证服务器输入用户名和密码进行登录。

认证服务器验证用户凭据。如果验证成功,会创建一个包含用户身份信息的全局会话,并生成一个与全局会话关联的令牌(Token)。

认证服务器将令牌发送给用户的浏览器,并重定向用户回到应用A。

应用A从重定向请求中获取令牌,并向认证服务器发送令牌以验证其有效性。

认证服务器验证令牌,如果有效,会返回用户的身份信息。

应用A根据返回的身份信息创建一个本地会话,允许用户在应用A中进行操作。

当用户访问应用B时,应用B发现用户尚未登录,会重定向用户到认证服务器。

认证服务器发现用户已经在全局会话中登录,会生成一个新的令牌,并将其发送给用户的浏览器,然后重定向用户回到应用B。

应用B从重定向请求中获取令牌,并向认证服务器发送令牌以验证其有效性。

认证服务器验证令牌,如果有效,会返回用户的身份信息。

应用B根据返回的身份信息创建一个本地会话,允许用户在应用B中进行操作。

这样,用户只需要在认证服务器上登录一次,就可以在多个应用中进行操作,无需在每个应用中单独登录,从而实现了单点登录。

聊聊你对浏览器异步的理解

浏览器异步是指浏览器在执行某个任务时,不会阻塞其他任务的执行。在传统的同步编程中,当一个任务执行时,程序会一直等待该任务完成后才能执行下一个任务。而异步编程则允许程序在执行某个任务时,同时执行其他任务。

浏览器异步的实现方式主要有以下几种:

回调函数:通过将任务的处理逻辑封装在回调函数中,在任务完成后调用该回调函数来处理结果。这种方式在早期的异步编程中比较常见,但容易导致回调地狱问题,代码可读性较差。

Promise:Promise 是一种用于处理异步操作的对象,它可以将异步操作的结果以同步的方式进行处理。通过 Promise,可以链式调用多个异步操作,使代码更加清晰和可读。

async/await:async/await 是 ES2017 中引入的异步编程方式,它基于 Promise,并使用 async 和 await 关键字来简化异步代码的编写。async/await 让异步代码看起来像同步代码,提高了代码的可读性和可维护性。

浏览器异步的优势在于能够提高程序的性能和响应速度。通过将耗时的任务放在后台执行,浏览器可以继续执行其他任务,提高了用户体验。例如,在网页中加载图片时,浏览器可以异步加载图片,同时继续渲染页面,而不会因为图片加载而阻塞页面的显示。

然而,浏览器异步编程也存在一些问题。例如,异步操作的结果可能会导致代码的执行顺序变得不确定,需要额外的处理来确保代码的正确性。此外,异步编程也增加了代码的复杂性,需要更多的思考和设计来处理异步操作的结果和错误。

serverless 和传统部署的优劣势

Serverless和传统部署方式都有各自的优劣势,下面我将分别列举它们的特点:

传统部署的优势:

灵活性:传统部署方式可以完全控制服务器的配置和环境,可以根据需求进行自定义设置。

可扩展性:传统部署方式可以根据需要进行服务器的扩容,可以灵活地调整资源来满足应用程序的需求。

安全性:传统部署方式可以通过自定义的安全设置来保护服务器和应用程序的安全性。

传统部署的劣势:

管理复杂性:传统部署方式需要管理服务器的硬件和软件,包括操作系统、网络配置、负载均衡等,需要投入更多的时间和精力。

成本高昂:传统部署方式需要购买和维护服务器硬件,需要支付服务器的租用费用,成本较高。

弹性差:传统部署方式需要提前规划和配置服务器的资源,无法根据实际需求进行快速的弹性扩容和缩容。

Serverless的优势:

无服务器管理:Serverless将服务器的管理交给云服务提供商,开发者只需关注代码的编写和业务逻辑的实现,无需关心服务器的配置和维护。

弹性扩展:Serverless可以根据实际需求自动进行弹性扩容和缩容,根据请求的负载自动分配资源,提高了应用程序的可伸缩性。

按需付费:Serverless按照实际使用的资源进行计费,无需提前购买和维护服务器,可以降低成本。

Serverless的劣势:

限制性:Serverless平台对代码的执行时间、内存使用等有一定的限制,不适合长时间运行的任务。

依赖云服务商:Serverless依赖于云服务商提供的平台,对于某些特定的需求可能会受到限制。

调试和监控困难:由于Serverless将服务器的管理交给云服务商,开发者可能无法直接调试和监控应用程序的运行情况。

综上所述,传统部署方式适用于对服务器有更高的控制和定制需求的场景,而Serverless适用于弹性扩展和按需付费的场景。选择哪种部署方式应根据具体的业务需求和资源预算来决定。

Axios 的工作原理如下:

Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js。它提供了一种简洁、直观的方式来发送 HTTP 请求,并处理响应。

创建一个 Axios 实例:通过调用 axios.create() 方法创建一个 Axios 实例,可以在实例中设置默认的请求配置,例如基本 URL、请求头等。

发送请求:使用 Axios 实例的各种方法(如 axios.get()、axios.post() 等)发送请求。这些方法返回一个 Promise 对象,可以使用 .then() 和 .catch() 方法处理响应。

构建请求:在发送请求之前,可以通过配置对象设置请求的各种参数,例如 URL、请求方法、请求头、请求体等。

发送请求:Axios 将构建好的请求发送到服务器。它使用底层的 XMLHttpRequest 对象或者 Node.js 的 http 模块来发送请求。

处理响应:一旦服务器返回响应,Axios 将根据响应的状态码和数据进行处理。如果状态码在 2xx 范围内,Promise 将被解析为成功状态,并返回响应数据。否则,Promise 将被拒绝,并返回一个错误对象。

处理拦截器:Axios 允许在请求和响应发送之前或之后添加拦截器。拦截器可以用于在请求或响应被发送之前或之后进行一些通用的处理,例如添加认证信息、转换请求或响应数据等。

处理错误:如果请求过程中发生错误(例如网络错误),Axios 将返回一个拒绝的 Promise,并提供错误信息。

总的来说,Axios 提供了一个简单、灵活的方式来发送 HTTP 请求,并提供了丰富的功能和配置选项,使开发人员能够更方便地处理请求和响应。

前端和服务器发送的链接的方式 前端和服务器之间发送链接的方式有以下几种:

HTTP 请求:前端通过使用浏览器内置的 XMLHttpRequest 对象或者使用现代的 Fetch API,向服务器发送 HTTP 请求。这些请求可以是 GET、POST、PUT、DELETE 等不同的方法,可以携带参数、请求头等信息。

AJAX:AJAX(Asynchronous JavaScript and XML)是一种在不重新加载整个页面的情况下,通过 JavaScript 异步地向服务器发送请求并获取数据的技术。它可以使用 XMLHttpRequest 对象或者 Fetch API 来发送请求,并通过回调函数或者 Promise 来处理响应。

WebSocket:WebSocket 是一种在客户端和服务器之间建立持久性连接的协议,可以实现双向通信。前端可以使用 WebSocket API 来与服务器进行实时的双向数据传输,而不需要通过不断的轮询或者长轮询来获取数据。

RESTful API:REST(Representational State Transfer)是一种设计风格,用于构建可伸缩的网络应用程序。前端可以通过使用 RESTful API,按照一定的规范和约定,向服务器发送请求并获取数据。RESTful API 使用标准的 HTTP 方法(如 GET、POST、PUT、DELETE)来表示不同的操作,并使用 URL 来标识资源。

GraphQL:GraphQL 是一种用于前端和服务器之间数据查询和操作的查询语言和运行时。前端可以使用 GraphQL 客户端库来构建和发送 GraphQL 查询,并获取精确的数据响应,而不需要多次请求或者获取过多的数据。

这些方式都可以用于前端和服务器之间的通信,具体选择哪种方式取决于应用程序的需求和技术栈的选择。

div碰撞怎么判断

在前端中,判断两个

元素是否碰撞可以通过以下几种方法:

使用 getBoundingClientRect() 方法:该方法返回元素的大小及其相对于视口的位置。可以通过比较两个元素的位置和大小来判断它们是否相交或重叠。

复制const div1 = document.getElementById(‘div1’);
const div2 = document.getElementById(‘div2’);

const rect1 = div1.getBoundingClientRect();
const rect2 = div2.getBoundingClientRect();

if (
rect1.left < rect2.right &&
rect1.right > rect2.left &&
rect1.top < rect2.bottom &&
rect1.bottom > rect2.top
) {
// div1 和 div2 碰撞
} else {
// div1 和 div2 不碰撞
}
使用 Intersection Observer API:该 API 可以观察元素与其祖先或视口交叉的情况。可以创建一个 IntersectionObserver 实例,然后观察两个

元素的交叉情况。

复制const div1 = document.getElementById(‘div1’);
const div2 = document.getElementById(‘div2’);

const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
// div1 和 div2 碰撞
} else {
// div1 和 div2 不碰撞
}
});

observer.observe(div1);
observer.observe(div2);
使用第三方库:有一些专门用于处理碰撞检测的 JavaScript 库,例如 Matter.js、Phaser.js 等。这些库提供了更高级的碰撞检测功能,可以处理更复杂的场景。

js判断距离底部的距离的方法

要使用 JavaScript 判断距离底部的距离,可以使用以下方法:

使用 scrollTop、scrollHeight 和 clientHeight 属性:通过比较滚动容器的滚动位置(scrollTop)加上容器可见区域的高度(clientHeight)与容器的总高度(scrollHeight)之差,来判断距离底部的距离。

复制const container = document.getElementById(‘container’);

function isNearBottom() {
return container.scrollTop + container.clientHeight >= container.scrollHeight - 20;
}

if (isNearBottom()) {
// 距离底部的距离小于等于 20px
}
在上述代码中,我们定义了一个 isNearBottom 函数,通过比较滚动容器的滚动位置加上可见区域的高度是否接近滚动容器的总高度减去一个阈值(这里设为 20),来判断是否距离底部的距离。

使用 getBoundingClientRect() 方法:通过获取目标元素的位置信息,结合窗口的可见区域高度,来判断目标元素距离底部的距离。

复制const target = document.getElementById(‘target’);

function isNearBottom() {
const rect = target.getBoundingClientRect();
return rect.bottom <= window.innerHeight;
}

if (isNearBottom()) {
// 目标元素距离底部可见
}

cookie 有长度限制吗
是的,Cookie在大小上是有限制的。根据RFC 6265标准,每个Cookie的总大小不能超过4096个字节(4KB)。这包括Cookie的名称、值、属性和其他元数据。如果超过了这个限制,浏览器可能会忽略或截断Cookie。

需要注意的是,不同的浏览器对Cookie大小的限制可能会有所不同。一些浏览器可能会对单个Cookie的大小有限制,而其他浏览器可能会对所有Cookie的总大小有限制。此外,一些浏览器还可能对域名下的所有Cookie数量有限制。

因此,在开发中,建议尽量控制Cookie的大小,避免超过浏览器的限制。如果需要存储大量数据,可以考虑使用其他存储机制,如本地存储(localStorage)或会话存储(sessionStorage)。

cookie 可以跨域访问吗

Cookie的跨域访问是受到同源策略(Same-Origin Policy)的限制的。同源策略要求网页只能访问与其来源相同的资源,包括Cookie。换句话说,只有在同一个域名、协议和端口下的网页才能访问相同的Cookie。

这意味着,如果网页的域名、协议或端口与要访问的Cookie所在的域名、协议或端口不一致,那么网页将无法直接访问该Cookie。

然而,有一些方法可以实现在跨域情况下共享Cookie:

代理:可以通过在服务器端设置代理来实现跨域请求,并在代理服务器上进行Cookie的处理和传递。

CORS(跨域资源共享):如果服务器支持CORS,可以在响应头中设置Access-Control-Allow-Credentials: true,并在请求中设置withCredentials: true,以允许跨域请求携带Cookie。

前后端分离:如果前端和后端是分离的,可以通过在后端设置响应头中的Set-Cookie来实现在跨域情况下设置Cookie。

需要注意的是,这些方法都需要服务器端的支持和配置。在实际开发中,需要根据具体的需求和情况来选择合适的方法来处理跨域访问和共享Cookie的问题。

如何实现两个页面的通信

有多种方法可以实现两个页面之间的通信,以下是一些常见的方法:

URL参数:可以通过URL参数在两个页面之间传递数据。一个页面可以通过URL参数将数据传递给另一个页面,另一个页面可以通过解析URL参数来获取传递的数据。

LocalStorage或SessionStorage:可以使用浏览器的本地存储(LocalStorage或SessionStorage)来在两个页面之间共享数据。一个页面可以将数据存储在本地存储中,另一个页面可以从本地存储中读取数据。

PostMessage API:PostMessage API允许在不同的窗口或iframe之间进行跨域通信。一个页面可以使用PostMessage方法向另一个页面发送消息,并通过监听message事件来接收消息。

WebSocket:WebSocket是一种全双工通信协议,可以在客户端和服务器之间建立持久的连接,实现实时的双向通信。两个页面可以通过WebSocket进行通信,发送和接收消息。

Broadcast Channel API:Broadcast Channel API允许在同一浏览器的不同页面之间进行通信。一个页面可以通过Broadcast Channel发送消息,其他页面可以通过监听Broadcast Channel来接收消息。

SharedWorker:SharedWorker是一种特殊的Web Worker,可以在多个页面之间共享数据和通信。多个页面可以通过SharedWorker进行通信,发送和接收消息。

根据具体的需求和场景,选择合适的通信方法来实现两个页面之间的数据传递和通信。

本地存储受跨域的限制吗

本地存储(LocalStorage和SessionStorage)是受到同源策略(Same-Origin Policy)的限制的,因此也受到跨域的限制。

同源策略要求网页只能访问与其来源相同的资源,包括本地存储。换句话说,只有在同一个域名、协议和端口下的网页才能访问相同的本地存储。

这意味着,如果网页的域名、协议或端口与要访问的本地存储所在的域名、协议或端口不一致,那么网页将无法直接访问该本地存储。

需要注意的是,虽然本地存储受到同源策略的限制,但是在同一个域名下的不同路径之间是可以共享本地存储的。例如,http://example/path1页面和http://example/path2页面可以访问相同的本地存储。

如果需要在跨域情况下共享数据,可以考虑使用其他跨域通信的方法,如PostMessage API、WebSocket、CORS等。

在H5端实现上传头像并添加裁切功能,可以使用以下步骤:

创建一个文件上传的input元素,用于选择并上传头像图片。

复制
监听文件选择事件,获取选择的图片文件。

复制const avatarUpload = document.getElementById(‘avatar-upload’);
avatarUpload.addEventListener(‘change’, function(event) {
const file = event.target.files[0];
// 处理上传的文件
});
使用FileReader读取图片文件,并将其显示在页面上。

复制const reader = new FileReader();
reader.onload = function(event) {
const image = new Image();
image.src = event.target.result;
// 将图片显示在页面上
};
reader.readAsDataURL(file);
使用裁切库(如Cropper.js)添加裁切功能。引入裁切库的脚本文件,并在图片加载完成后初始化裁切功能。

复制image.onload = function() {
const cropper = new Cropper(image, {
// 配置裁切功能的选项
});
};
在裁切完成后,获取裁切后的图片数据,并进行上传或其他操作。

复制const croppedImageData = cropper.getCroppedCanvas().toDataURL(‘image/jpeg’);
// 将裁切后的图片数据上传到服务器或进行其他操作
以上是一个简单的示例,具体的实现可能需要根据具体的需求和使用的裁切库进行调整。请注意,裁切功能的具体实现可能会涉及到一些细节,如裁切框的样式、裁切比例、裁切后的图片质量等,需要根据实际需求进行配置和调整。

改变vue数组属性值 为什么不更新

axios

Axios是一个基于Promise的HTTP客户端库,用于浏览器和Node.js中发送异步HTTP请求。它提供了一种简洁且易于使用的方式来处理HTTP请求和响应。

Axios的底层原理主要包括以下几个关键点:

  1. 基于XMLHttpRequest或者浏览器的fetch API发送请求:Axios在底层使用XMLHttpRequest对象或者浏览器的fetch API来发送HTTP请求。它通过创建一个XHR对象或者调用fetch方法发送请求,并监听相关事件以获取响应。

2.封装请求和响应:Axios封装了请求和响应的细节,使得开发人员可以更简单地处理HTTP请求。它提供了一系列的方法,如axios.get()、axios.post()等,来发送不同类型的请求,并且可以通过配置选项设置请求头、请求参数等。

3.Promise和异步处理:Axios使用Promise作为异步处理的基础。它返回一个Promise对象,开发人员可以使用.then()和.catch()方法来处理请求的成功和失败。Axios还支持使用async/await来更方便地处理异步操作。

4.拦截器:Axios提供了拦截器,可以在发送请求或响应之前拦截和处理数据。它允许开发人员在请求或响应被发送到服务器或浏览器之前,对其进行一些预处理,比如在请求中添加token,在响应中对数据进行处理等。

5.错误处理:Axios可以捕获HTTP请求返回的错误状态码,并根据错误类型执行相应的操作。它还提供了一个全局的错误处理方法.catch(),可以用来捕获和处理所有的请求错误。

6.取消请求:Axios支持取消请求,可以通过创建一个cancel token来取消正在进行的请求。这在某些场景下非常有用,比如当用户离开当前页面时取消未完成的请求。

下面的代码展示了Axios的底层原理和完整逻辑。封装了XMLHttpRequest对象来发送HTTP请求,并利用Promise处理异步操作。Axios通过request方法发送请求,并在发送前后调用请求拦截器和响应拦截器进行处理。其中,拦截器可以用于修改请求配置、处理响应数据等。在请求过程中,如果发生错误,会通过catch方法捕获并抛出。通过封装HTTP请求和提供拦截器功能,Axios使得发送HTTP请求更加简洁和灵活。

// 利用Promise封装异步请求
function request(method, url, data) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open(method, url, true);
    // 设置请求头
    xhr.setRequestHeader('Content-Type', 'application/json');
    
    // 注册xhr的回调函数
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        if (xhr.status >= 200 && xhr.status < 300) {
          // 请求成功,解析响应数据
          const responseData = JSON.parse(xhr.responseText);
          resolve(responseData);
        } else {
          // 请求失败,返回错误信息
          reject(new Error(xhr.statusText));
        }
      }
    };
    
    // 发送请求
    xhr.send(JSON.stringify(data));
  });
}
 
// 创建Axios类
class Axios {
  constructor() {
    // 定义拦截器
    this.interceptors = {
      request: [],
      response: []
    };
  }
 
  // 封装请求方法
  request(config) {
    // 调用请求拦截器
    this.interceptors.request.forEach(interceptor => {
      config = interceptor(config);
    });
 
    // 发送请求
    return request(config.method, config.url, config.data)
      .then(response => {
        // 调用响应拦截器
        this.interceptors.response.forEach(interceptor => {
          response = interceptor(response);
        });
 
        // 返回响应数据
        return response;
      })
      .catch(error => {
        // 捕获请求错误
        throw error;
      });
  }
 
  // 封装get请求
  get(url, config) {
    return this.request({
      method: 'GET',
      url,
      ...config
    });
  }
 
  // 封装post请求
  post(url, data, config) {
    return this.request({
      method: 'POST',
      url,
      data,
      ...config
    });
  }
 
  // 添加请求拦截器
  interceptorsRequestUse(handler) {
    this.interceptors.request.push(handler);
  }
 
  // 添加响应拦截器
  interceptorsResponseUse(handler) {
    this.interceptors.response.push(handler);
  }
}
 
// 创建Axios实例
const axios = new Axios();
 
// 使用示例
axios.interceptorsRequestUse(config => {
  // 修改请求配置
  config.headers.Authorization = 'Bearer token';
  return config;
});
 
axios.interceptorsResponseUse(response => {
  // 处理响应数据
  response.data = response.data.toUpperCase();
  return response;
});
 
axios.get('https://api.example/data')
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.error(error);
  });

总的来说,Axios的底层原理是基于XMLHttpRequest或者浏览器的fetch API发送请求,并使用Promise处理异步操作。它封装了请求和响应的细节,提供了简单易用的API来处理HTTP请求和响应。

JS 发起的请求可以暂停吗?

这里得先介绍一下 TCP/IP 网络模型, 网络模型自上而下分为 应用层、传输层、网络层和网络接口层。

上图表示的意思是,每次网络传输,应用数据在发送至目标前都需要通过网络模型一层一层的包装,就像寄快递一样,把要寄的物品先打包好登记一下大小,再装在盒子里登记一下目的地,然后再装到车上,最后送往目的地。

请求(Request) 这个概念就可以理解为客户端通过若干次数据网络传输,将单份数据完整发给服务端的行为,而针对某次请求服务端往客户端发送的答复数据则可以称之为 响应(Response)。

理论上应用层的协议可以通过类似于标记数据包序列号等等一系列手段来实现暂停机制。但是 TCP 协议并不支持,TCP 协议的数据传输是流式的,数据被视为一连串的字节流。客户端发送的数据会被拆分成多个 TCP 段(TCP segments),而这些段在网络中是独立传输的,无法直接控制每个 TCP 段的传输,因此也无法实现暂停请求或者暂停响应的功能。
解答提问
如果请求是指网络模型中的一次请求传输,那理所当然是不可能暂停的。

来看看提问者的使用场景 —— JS 发起的请求,那么可以认为问题当中的请求,应该是指在 JS 运行时中发起的 XMLHttpRequest 或者是 fetch 请求,而请求既然已经发起,那问的自然就是 响应是否能够被暂停 。

我们都知道像大文件分片上传、以及分片下载之类的功能本质上是将分片顺序定好之后按顺序请求,然后就可以通过中断顺序并记录中断点来实现暂停重传的机制,而单个请求并不具备这样的环境。

用 JS 实现 ”假暂停” 机制
虽然不能真正意义上实现暂停请求,但是我们其实可以模拟一个 假暂停 的功能,在前端的业务场景上,数据不是收到就可以直接打在客户脸上的(什么光速打击),前端开发者需要对这些数据进行处理之后渲染在界面上,如果我们能在请求发起之前增加一个控制器,在请求回来时,如果控制器为暂停状态则不处理数据,等待控制器恢复后再进行处理,是不是也能到达到目的?让我们试着实现一下。

假如我们使用 fetch 来请求。我们可以设计一个控制器 Promise 和请求放在一起用 Promise.all 包裹,当 fetch 完成时判断这个控制器的暂停状态,如果没有被暂停,则控制器也直接 resolve,同时整个 Promise.all 也 resolve 抛出。

return new Promise((res) => setTimeout(() => {
res(123)
}, 3000))
}

// 原本想使用 class extends Promise 来实现
// 结果一直出现这个问题 https://github/nodejs/node/issues/13678

function createPauseControllerPromise () {  
  const result = {  
    isPause: false,  
    resolveWhenResume: false,  
    resolve (value?: any) {},  
    pause () {  
      this.isPause = true  
    },  
    resume () {  
      if (!this.isPause) return  
      this.isPause = false  
      if (this.resolveWhenResume) {  
          this.resolve()  
      }  
    },  
    promise: Promise.resolve()  
  }  
  const promise = new Promise<void>((res) => {  
    result.resolve = res  
  })  
  result.promise = promise  
  
  return result  
}  
  
function requestWithPauseControl <T extends () => Promise<any>>(request: T) {  
  const controller = createPauseControllerPromise()  
    
  const controlRequest = request().then((data) => {  
      if (!controller.isPause) controller.resolve()  
      return data  
  }).finally(() => {  
      controller.resolveWhenResume = true  
  })  
    
  const result = Promise.all([controlRequest, controller.promise]).then(data => {  
      controller.resolve()  
      return data[0]  
  });  
    
  (result as any).pause = controller.pause.bind(controller);  
  (result as any).resume = controller.resume.bind(controller);  
    
  return result as ReturnType<T> & { pause: () => void, resume: () => void }  
}

用法
我们可以通过调用 requestWithPauseControl(_request) 来替代调用 _request 使用,通过返回的 pause 和 resume 方法控制暂停和继续。

  
if (Math.random() > 0.5) { result.pause() }  
  
setTimeout(() => {  
    result.resume()  
}, 4000)

vue 的双向数据绑定原理

vue 的双向数据绑定原理
Vue的双向数据绑定是通过Vue的响应式系统实现的。其原理可以简单概括为以下几个步骤:

数据劫持:Vue通过使用Object.defineProperty()方法来劫持(监听)数据对象的属性。在Vue初始化时,会遍历数据对象的所有属性,将其转换为getter和setter,并在getter和setter中进行依赖收集和派发更新。

依赖收集:在模板编译过程中,Vue会解析模板中的指令和表达式,并建立起模板中的依赖关系。当模板中的数据发生变化时,Vue会通过依赖收集将相关的Watcher对象添加到当前数据的依赖列表中。

数据更新:当数据发生变化时,Vue会触发setter方法,setter方法会通知相关的Watcher对象进行更新。Watcher对象会调用对应的更新函数,更新视图中的数据。

视图更新:当数据更新时,Vue会通过虚拟DOM和diff算法来计算出需要更新的最小DOM操作,然后将更新的部分应用到实际的DOM中,从而实现视图的更新。

通过以上步骤,Vue实现了双向数据绑定。当数据发生变化时,视图会自动更新;当用户在视图中输入数据时,数据也会自动更新。这种双向的数据绑定使得开发者可以更方便地处理数据和视图之间的同步,提高了开发效率。

生命周期 哪里请求接口 有什么不同吗?

react为什么不用双向数据绑定

还有哪些异步操作

nexttick原理 与源码
Generato
css 自适应
promise
闭包
为什么dom异步队列 nexttick相关

比较数组中的差值最大 和时间复杂度

fixed的元素 怎么根据父级宽度的改变而改变

主要有:left和right设为0
.data-distribution__footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 48px;
width: 100%;
background: #FFFFFF;
z-index: 99;
border: 1px solid #E5E6EB;
padding: 8px 24px;
display: flex;
justify-content: flex-end;
}

watch 和 computed 是 Vue.js 中用于响应式数据处理的两个重要属性。

watch 是一个选项,用于监听数据的变化并执行相应的操作。你可以使用 watch 来观察一个或多个数据的变化,并在数据变化时执行自定义的回调函数。watch 适用于需要在数据变化时执行异步操作、复杂计算或执行副作用的场景。

在上述示例中,我们定义了一个 watch 对象,其中包含了对 message 和 count 数据的监听。当 message 或 count 发生变化时,相应的回调函数将被触发。

computed 是一个选项,用于定义计算属性。计算属性是基于响应式数据进行计算得出的属性,它会根据依赖的数据自动进行缓存,只有当依赖的数据发生变化时,才会重新计算。计算属性适用于需要根据其他数据进行复杂计算或处理的场景。

created 和 mounted请求接口有什么区别

created 和 mounted 是 Vue.js 生命周期钩子函数,用于在组件生命周期的不同阶段执行代码。

created 钩子函数在组件实例被创建后立即调用,此时组件的数据观测 (data observer) 和事件初始化已完成,但尚未挂载到 DOM 中。在 created 钩子函数中,你可以进行一些初始化的操作,例如数据的获取、事件的监听等。

mounted 钩子函数在组件被挂载到 DOM 后调用,此时组件已经被渲染到页面上。在 mounted 钩子函数中,你可以访问到组件的 DOM 元素,并进行一些需要 DOM 的操作,例如初始化第三方库、绑定事件等。

关于请求接口的区别,一般来说,如果你需要在组件创建后立即请求接口并使用接口返回的数据进行初始化操作,你可以将请求放在 created 钩子函数中。这样可以确保在组件挂载到 DOM 之前就已经获取到了数据。

如果你需要在组件挂载到 DOM 后再请求接口,例如需要使用到组件的 DOM 元素或计算属性的值等,你可以将请求放在 mounted 钩子函数中。这样可以确保在组件渲染到页面上后再进行接口请求。

需要注意的是,如果你在 created 或 mounted 钩子函数中进行异步操作(例如发送异步请求),应该使用 Promise 或 async/await 来处理异步逻辑,以确保数据的正确获取和处理。

总结来说,created 钩子函数适合在组件创建后立即进行初始化操作,而 mounted 钩子函数适合在组件挂载到 DOM 后进行操作,包括请求接口。根据具体需求,你可以选择在 created 或 mounted 钩子函数中请求接口。

首白屏

https://blog.csdn/weixin_45724850/article/details/131733309
https://blog.csdn/weixin_61662162/article/details/130371676

为什么vue中data一定是一个函数

在Vue组件中,data选项必须是一个函数,而不能直接是一个对象。这是因为Vue组件可以同时存在多个实例,如果直接使用对象形式的data选项,那么所有的实例将会共享同一个data对象,这样就会造成数据互相干扰的问题。

因此,将data选项设置为函数可以让每个实例都拥有自己独立的data对象。当组件被创建多次时,每个实例都会调用该函数并返回一个新的data对象,从而保证了数据的隔离性。

另外,data选项作为一个函数还具有一个重要的特性,就是它可以接收一个参数,这个参数是组件实例本身。这个特性在一些场景下非常有用,例如在定义组件时需要使用组件实例的一些属性或方法来计算初始数据。

因此,为了避免数据共享和保证数据隔离性,以及方便使用组件实例的属性和方法,Vue组件中的data选项必须是一个函数。

Vue 2 和 Vue 3的区别

1.双向数据绑定原理不同
Vue2 的双向数据绑定是利用ES5的一个APIObject.definePropert() 对数据进行劫持,结合发布订阅模式的方式来实现的。

Vue3 中使用ES6的Proxy API对数据代理。

Vue3 使用数据代理的优势有以下几点:1)definePropert 只能监听某个属性,不能对整个对象进行监听 2)可以省去for in,闭包等内容来提升效率(直接绑定整个对象即可)3)可以监听数组,不用再单独的对数组做特异性操作,Vue3可以检测到数组内部数据的变化

2.是否支持碎片
Vue2 不支持碎片。Vue3 支持碎片,就是说可以拥有多个根节点

3.API 类型不同
Vue2 使用选项类型api,选项型api 在代码里分割了不同的属性:data,computed,method等。

Vue3 使用合成型api,新的合成型api 能让我们使用方法来分割,相比于旧的api 使用属性来分组,这样代码会更加简便和整洁。

4定义数据变量和方法不同
Vue2是把数据放到了data 中,在 Vue2中 定义数据变量是data(){},创建的方法要在method:{}

Vue3 就需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。使用以下三个步骤来建立反应性数据:1)从vue 引入 reactive;2)使用 reactive ()方法来声明数据为响应性数据;3) 使用setup()方法来返回我们的响应性数据,从而template 可以获取这些响应性数据。

5.生命周期钩子函数不同
Vue2 中的生命周期:beforeCreate 组件创建之前;created 组建创建之后;beforeMount 组件挂载到页面之前执行;Mounted 组件挂载到页面之后执行,beforeUpdate 组件更新之前;updated组件更新之后

Vue3 中的生命周期:setup 开始创建组件;onBeforeMount 组件挂载到页面之前执行;onMounted 组件挂载到页面之后执行;onBeforeUpdate 组件更新之前;onUpdated 组件更新之后;

而且 Vue3 生命周期在调用前需要先进行引入。除了这些钩子函数外,Vue3 还增加了 onRenderTracked 和onRenderTriggered 函数。

6.父子传参不同
Vue2 父传子,用props ;子传父用事件Emitting Events。在Vue2 中,会调用this$emit 然后传入事件名和对象。

Vue3 父传子,用props;子传父用Emitting Events 。在Vue3 中的setup()中的第一参数content 对象中就有 emit,那么我们只要在setup()接收第二个参数中使用分解对象法取出emit 就可以在setup 方法中随意使用了。

7.指令与插槽不同
Vue2 中使用slot 可以直接使用slot ;v-for 与v-if 在Vue2中优先级高的是v-for 指令,而且不建议一起使用。

Vue3 中必须是使用v-slot的形式;vue 3中v-for 与v-if ,只会把当前v-if 当作v-for 的一个判断语句,不会相互冲突;

Vue3 中移除keyCode 作为v-on 的修饰符,当然也不支持config.keyCodes,取而代之的是使用键名来作为事件的修饰符来使用,于是Vue.config.keyCodes 也被弃用了-vue2我们在监听按键事件的时候,是可以通过在事件后面加上按键码来实现监听某一个按键的–mulingyuer/archives/831/# ;

vue和react的区别

1、监听数据变化的实现原理不同

Vue通过 getter/setter以及一些函数的劫持,能精确知道数据变化。

React默认是通过比较引用的方式(diff)进行的,如果不优化可能导致大量不必要的VDOM的重新渲染。为什么React不精确监听数据变化呢?这是因为Vue和React设计理念上的区别,Vue使用的是可变数据,而React更强调数据的不可变,两者没有好坏之分,Vue更加简单,而React构建大型应用的时候更加鲁棒。

2、数据流的不同

Vue1.0中可以实现两种双向绑定:父子组件之间,props可以双向绑定;组件与DOM之间可以通过v-model双向绑定。Vue2.x中去掉了第一种,也就是父子组件之间不能双向绑定了(但是提供了一个语法糖自动帮你通过事件的方式修改),并且Vue2.x已经不鼓励组件对自己的 props进行任何修改了。

React一直不支持双向绑定,提倡的是单向数据流,称之为onChange/setState()模式。不过由于我们一般都会用Vuex以及Redux等单向数据流的状态管理框架,因此很多时候我们感受不到这一点的区别了。

3、HoC和mixins

Vue组合不同功能的方式是通过mixin,Vue中组件是一个被包装的函数,并不简单的就是我们定义组件的时候传入的对象或者函数。比如我们定义的模板怎么被编译的?比如声明的props怎么接收到的?这些都是vue创建组件实例的时候隐式干的事。由于vue默默帮我们做了这么多事,所以我们自己如果直接把组件的声明包装一下,返回一个HoC,那么这个被包装的组件就无法正常工作了。

React组合不同功能的方式是通过HoC(高阶组件)。React最早也是使用mixins的,不过后来他们觉得这种方式对组件侵入太强会导致很多问题,就弃用了mixinx转而使用HoC。高阶组件本质就是高阶函数,React的组件是一个纯粹的函数,所以高阶函数对React来说非常简单。

4、组件通信的区别

Vue中有三种方式可以实现组件通信:父组件通过props向子组件传递数据或者回调,虽然可以传递回调,但是我们一般只传数据;子组件通过事件向父组件发送消息;通过V2.2.0中新增的provide/inject来实现父组件向子组件注入数据,可以跨越多个层级。

React中也有对应的三种方式:父组件通过props可以向子组件传递数据或者回调;可以通过 context 进行跨层级的通信,这其实和 provide/inject 起到的作用差不多。React 本身并不支持自定义事件,而Vue中子组件向父组件传递消息有两种方式:事件和回调函数,但Vue更倾向于使用事件。在React中我们都是使用回调函数的,这可能是他们二者最大的区别。

5、模板渲染方式的不同

在表层上,模板的语法不同,React是通过JSX渲染模板。而Vue是通过一种拓展的HTML语法进行渲染,但其实这只是表面现象,毕竟React并不必须依赖JSX。

在深层上,模板的原理不同,这才是他们的本质区别:React是在组件JS代码中,通过原生JS实现模板中的常见语法,比如插值,条件,循环等,都是通过JS语法实现的,更加纯粹更加原生。而Vue是在和组件JS代码分离的单独的模板中,通过指令来实现的,比如条件语句就需要 v-if 来实现对这一点,这样的做法显得有些独特,会把HTML弄得很乱。

举个例子,说明React的好处:react中render函数是支持闭包特性的,所以我们import的组件在render中可以直接调用。但是在Vue中,由于模板中使用的数据都必须挂在 this 上进行一次中转,所以我们import 一个组件完了之后,还需要在 components 中再声明下,这样显然是很奇怪但又不得不这样的做法。

6、渲染过程不同

Vue可以更快地计算出Virtual DOM的差异,这是由于它在渲染过程中,会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。

React在应用的状态被改变时,全部子组件都会重新渲染。通过shouldComponentUpdate这个生命周期方法可以进行控制,但Vue将此视为默认的优化。

如果应用中交互复杂,需要处理大量的UI变化,那么使用Virtual DOM是一个好主意。如果更新元素并不频繁,那么Virtual DOM并不一定适用,性能很可能还不如直接操控DOM。

7、框架本质不同

Vue本质是MVVM框架,由MVC发展而来;

React是前端组件化框架,由后端组件化发展而来。

8、Vuex和Redux的区别

从表面上来说,store注入和使用方式有一些区别。在Vuex中, s t o r e 被直接注入到了组件实例中,因此可以比较灵活的使用:使用 d i s p a t c h 、 c o m m i t 提交更新,通过 m a p S t a t e 或者直接通过 t h i s . store被直接注入到了组件实例中,因此可以比较灵活的使用:使用dispatch、commit提交更新,通过mapState或者直接通过this. store被直接注入到了组件实例中,因此可以比较灵活的使用:使用dispatchcommit提交更新,通过mapState或者直接通过this.store来读取数据。在Redux中,我们每一个组件都需要显示的用connect把需要的props和dispatch连接起来。另外,Vuex更加灵活一些,组件中既可以dispatch action,也可以commit updates,而Redux中只能进行dispatch,不能直接调用reducer进行修改。

从实现原理上来说,最大的区别是两点:Redux使用的是不可变数据,而Vuex的数据是可变的,因此,Redux每次都是用新state替换旧state,而Vuex是直接修改。Redux在检测数据变化的时候,是通过diff的方式比较差异的,而Vuex其实和Vue的原理一样,是通过getter/setter来比较的,这两点的区别,也是因为React和Vue的设计理念不同。React更偏向于构建稳定大型的应用,非常的科班化。相比之下,Vue更偏向于简单迅速的解决问题,更灵活,不那么严格遵循条条框框。因此也会给人一种大型项目用React,小型项目用Vue的感觉。

一、什么是vue,什么是react?

vue

   Vue是一个用于为Web构建的UI的渐进式框架。它最初于2014年由前Google开发人员Evan You发布,他使用AngularJS并决定排除Angular框架的痛点并构建轻量级的东西。 

    Vue是渐进式JavaScript框架。“渐进式框架”和“自底向上增量开发的设计”是Vue开发的两个概念。Vue可以在任意其他类型的项目中使用,使用成本较低,更灵活,主张较弱,在Vue的项目中也可以轻松融汇其他的技术来开发。特点:易用(使用成本低),灵活(生态系统完善)

react

React是由Facebook开发的用于构建用户界面的JavaScript库,Facebook对市场上JavaScript MVC框架都不太满意,Facebook就自己写了一套用于架设Instagram,React由此诞生。

    React主张是函数式编程的理念, 实现了前端界面的高性能高效率开发,react很擅长处理组件化的页面。React的官方网站提到了“学习一次,随处写作”这个关键功能,可以使用React框架在JavaScript中构建移动应用程序。在 React 中,所有的组件的渲染功能都依靠 JSX,它是JavaScript的语法扩展,它在创建UI组件和调试时非常简单有用。

二、共同点
数据驱动视图
组件化
都使用了 Virtual DOM + Diff算法
三、不同点
**核心思想不同:**Vue早期开发就尤雨溪大佬,所以定位就是尽可能的降低前端开发的门槛,让更多的人能够更快地上手开发。这就有了vue的主要特点:灵活易用的渐进式框架,进行数据拦截/代理,它对侦测数据的变化更敏感、更精确。

React 从一开始的定位就是提出 UI 开发的新思路。背靠大公司Facebook 的React,从开始起就不缺关注和用户,而且React想要做的是用更好的方式去颠覆前端开发方式。所以React推崇函数式编程(纯组件),数据不可变以及单向数据流,当然需要双向的地方也可以手动实现, 比如借助onChange和setState来实现。

**响应式原理不同:**Vue依赖收集,自动优化,数据可变。Vue递归监听data的所有属性,直接修改。当数据改变时,自动找到引用组件重新渲染。 react React基于状态机,手动优化,数据不可变,需要setState驱动新的state替换老的state。当数据改变时,以组件为根目录,默认全部重新渲染, 所以 React 中会需要 shouldComponentUpdate 这个生命周期函数方法来进行控制

**组件写法差异:**React推荐的做法是JSX + inline style, 也就是把 HTML 和 CSS 全都写进 JavaScript 中,即 all in js; Vue 推荐的做法是 template 的单文件组件格式(简单易懂,从传统前端转过来易于理解),即 html,css,JS 写在同一个文件(vue也支持JSX写法)

这个差异一定程度上也是由于二者核心思想不同而导致的。

**diff算法:**vue对比节点。当节点元素相同,但是classname不同,认为是不同类型的元素,删除重建,而react认为是同类型节点,只是修改节点属性。

vue的列表对比,采用的是两端到中间比对的方式,而react采用的是从左到右依次对比的方式。当一个集合只是把最后一个节点移到了第一个,react会把前面的节点依次移动,而vue只会把最后一个节点移到第一个。总体上,vue的方式比较高效。

**渲染过程:**Vue可以更快地计算出Virtual DOM的差异,这是由于它在渲染过程中,会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。

React在应用的状态被改变时,全部子组件都会重新渲染。通过shouldComponentUpdate这个生命周期方法可以进行控制,但Vue将此视为默认的优化。

如果应用中交互复杂,需要处理大量的UI变化,那么使用Virtual DOM是一个好主意。如果更新元素并不频繁,那么Virtual DOM并不一定适用,性能很可能还不如直接操控DOM。

vuex和redux:

从表面上来说,store注入和使用方式有一些区别。在Vuex中, s t o r e 被直接注入到了组件实例中,因此可以比较灵活的使用:使用 d i s p a t c h 、 c o m m i t 提交更新,通过 m a p S t a t e 或者直接通过 t h i s . store被直接注入到了组件实例中,因此可以比较灵活的使用:使用dispatch、commit提交更新,通过mapState或者直接通过this. store被直接注入到了组件实例中,因此可以比较灵活的使用:使用dispatchcommit提交更新,通过mapState或者直接通过this.store来读取数据。在Redux中,我们每一个组件都需要显示的用connect把需要的props和dispatch连接起来。另外,Vuex更加灵活一些,组件中既可以dispatch action,也可以commit updates,而Redux中只能进行dispatch,不能直接调用reducer进行修改。

从实现原理上来说,最大的区别是两点:Redux使用的是不可变数据,而Vuex的数据是可变的,因此,Redux每次都是用新state替换旧state,而Vuex是直接修改。Redux在检测数据变化的时候,是通过diff的方式比较差异的,而Vuex其实和Vue的原理一样,是通过getter/setter来比较的,这两点的区别,也是因为React和Vue的设计理念不同。React更偏向于构建稳定大型的应用,非常的科班化。相比之下,Vue更偏向于简单迅速的解决问题,更灵活,不那么严格遵循条条框框。因此也会给人一种大型项目用React,小型项目用Vue的感觉。

框架:Vue本质是MVVM框架,由MVC发展而来;

React是前端组件化框架,由后端组件化发展而来。

四、语法区别
路由:
循环:vue循环dom是在html里面使用v-for指令来进行循环,react是使用{数组.map((循环出来的数据,下表)=>{})}来进行循环的
解决跨域的区别:vue是写在vue.config.js里面,react可以写在package.json里也可以写在src文件夹下的setupProxy.js里

五、react和vue的选择

在以下情况选择vue

最新文档和更简单的语法。
更小,更快,更灵活。
需要丰富的HTML模板,易于开发。
在以下的情况选择react

需要构建移动应用程序。
需要构建大型应用程序。
轻量级,易于版本迁移。

typeof和instanceof的区别?

相同点:

1.两者都是数据类型检测的方式

区别:

  1. 返回的值不同

typeof返回的结果是字符串,返回值有number、string、boolean、function、undefined、object六个;

instance of返回的是布尔值,true或false;

  1. 判断的类型不同

typeof可以判断所有变量的类型。而对于丰富的对象实例,只能返回object(除function外),不能得到真实的数据类型。

instance of只能用来判断对象。可以对不同的实例对象进行判断,判断方法是根据对象的原型链依次向下查找,找到了,值为true,否则为false

Cookie属性

  1. Cookie属性Domain
    Domain是用来设置Cookie能够作用到的主机地址,存储在浏览器时不携带协议和端口。因为端口和协议不同并不会影响Cookie但是Cookie的部分属性只有在Https下才能有效,这也是Cookie的特性之一,不区分协议和端口。
    如果前面有个. 如下 .baidu.con 就证明当前的Cookie可以作用于当前域及其子域,假如下面的Cookie在 niuma.baidu 中是可以访问到的 而前面没有这个.的Cookie在 niuma.baidu 中无法访问到 只能在baidu 中访问到。

本文标签: 答案