2024 前端面试题(GPT回答 + 示例代码 + 解释)No.61 - No.100

本文题目来源于全网收集,答案来源于 ChatGPT 和 博主(的小部分……)

格式:题目 h3 + 回答 text + 参考大佬博客补充 text + 示例代码 code+ 解释 quote + 补充 quote

上一篇链接:2024 前端面试题(GPT回答 + 示例代码 + 解释)No.41 - No.60


目录 No.61 - No.100


61. 如何从一个页面 跳转 到另一个页面?

在 JavaScript 中,可以使用以下几种方法从一个页面跳转到另一个页面:

  1. 使用 window.location.href
    使用 window.location.href 属性可以改变当前窗口或标签页的 URL,从而实现页面跳转。例如:

    // 跳转到指定页面
    window.location.href = "https://www.example.com";
    
  2. 使用 window.location.replace
    使用 window.location.replace 方法可以在不产生历史记录的情况下跳转到新页面。这意味着用户无法通过浏览器的后退按钮返回到原始页面。例如:

    // 用新页面替换当前页面
    window.location.replace("https://www.example.com");
    
  3. 使用 window.location.assign
    使用 window.location.assign 方法也可以实现页面跳转,类似于 window.location.href,但是会在浏览器的历史记录中添加一个新条目,因此用户可以通过后退按钮返回到原始页面。例如:

    // 在当前页面打开新页面
    window.location.assign("https://www.example.com");
    
  4. 使用 a 标签
    可以创建一个 <a> 标签,并设置其 href 属性为目标页面的 URL,然后使用 JavaScript 触发点击事件来模拟页面跳转。例如:

    // 创建并点击 <a> 标签进行页面跳转
    const link = document.createElement("a");
    link.href = "https://www.example.com";
    link.click();
    

62. 如何编码与解码URL?

  • encodeURI 函数用于将字符串编码为有效的 URL 字符串,对于特殊字符(如空格、中文字符等)会进行编码。例如:
const url = "https://www.example.com/?query=编码测试";
const encodedUrl = encodeURI(url);
console.log(encodedUrl);
// 输出:https://www.example.com/?query=%E7%BC%96%E7%A0%81%E6%B5%8B%E8%AF%95
  • decodeURI 函数用于将编码后的 URL 字符串解码为原始字符串。例如:
const encodedUrl = "https://www.example.com/?query=%E7%BC%96%E7%A0%81%E6%B5%8B%E8%AF%95";
const decodedUrl = decodeURI(encodedUrl);
console.log(decodedUrl);
// 输出:https://www.example.com/?query=编码测试

除了 encodeURIdecodeURI,还有两个类似的函数:encodeURIComponentdecodeURIComponent。它们用于对 URL 的组成部分进行编码和解码,包括特殊字符(如问号、等号、斜杠等),以及保留字(如冒号、逗号等)。

总结一下:

  • encodeURIdecodeURI 用于编码和解码完整的 URL。
  • encodeURIComponentdecodeURIComponent 用于编码和解码 URL 的组成部分。

63. [x, y, z].map(Math.pow)的结果是什么?

x0
y1
z2


64. toString() 与 valueOf() 的区别

toString()方法返回对象的字符串表示形式。当JavaScript需要将一个对象转换为字符串时,会自动调用该对象的toString()方法。例如:

var obj = {
  name: "John",
  age: 25,
  toString: function() {
    return this.name + ", " + this.age + " years old";
  }
};

console.log(obj.toString()); // 输出:John, 25 years old
console.log(String(obj)); // 输出:John, 25 years old

valueOf()方法返回对象的原始值表示形式。当JavaScript需要将一个对象转换为原始值时(如进行数学运算),会自动调用该对象的valueOf()方法。例如:

var obj = {
  value: 42,
  valueOf: function() {
    return this.value;
  }
};

console.log(obj.valueOf()); // 输出:42
console.log(Number(obj)); // 输出:42

需要注意的是,toString()valueOf()方法可以根据具体需求进行重写,以便返回适合的字符串或原始值表示。如果没有重写这些方法,默认情况下会返回对象的内部标签。

总结来说,toString()方法用于将对象转换为字符串,而valueOf()方法用于将对象转换为原始值。


66. form 和 input 如何关闭自动完成功能?

要关闭HTML5表单的自动完成功能,可以使用以下两种方法之一:

  1. 在form元素上添加autocomplete属性并将其设置为"off"。例如:
<form autocomplete="off">
  <!-- 表单内容 -->
</form>

这将告诉浏览器不要自动填充表单字段。

  1. 在需要关闭自动完成功能的具体表单字段上,添加autocomplete属性并将其设置为"new-password"。例如:
<input type="text" name="username" autocomplete="new-password">

这会告诉浏览器该字段可以自动完成,但只应提供新密码作为建议。


67. Label的作用是什么?是怎么用的?

用户点击"label"标签时,浏览器会自动将焦点置于input元素上。

  • id 绑定
<label for="username">Username:</label>
<input type="text" id="username" name="username">
  • 嵌套
<label>
  Username:
  <input type="text" name="username">
</label>

68. Doctype 是干什么的?

DOCTYPE是HTML文档中一个重要的声明,它告诉浏览器正在使用哪个HTML版本进行编写,并让浏览器以相应的标准模式来渲染页面。通常,DOCTYPE需要放在HTML文档的第一行。

DOCTYPE的全称为“Document Type Declaration”,它有两个作用:

  1. 声明文档类型:DOCTYPE告诉浏览器该文档使用哪种HTML版本进行编写,如HTML5、HTML 4.01、XHTML 1.0等。

  2. 触发标准模式:DOCTYPE还可以触发浏览器的标准模式(严格模式),这是一种更规范的渲染模式,它与浏览器的兼容模式(混杂模式)相对应。标准模式使得浏览器更加一致地解释和渲染页面,从而提高了跨浏览器兼容性。

以下是几种常见的DOCTYPE声明:

HTML5:

<!DOCTYPE html>

HTML 4.01 Strict:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

XHTML 1.0 Transitional:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

69. b 与 strong 的区别、i 与 em 的区别?

  1. b 与 strong 的区别:

b是HTML中的一种文本样式元素,通常用于将文本设置为加粗效果。它的作用仅仅是呈现出文字的视觉效果,没有任何语义含义。

strong是HTML中的一种语义元素,表示文本具有强调重点的意义。除了将文本设置为加粗外,还可以使用CSS样式对其进行进一步的调整和呈现。

  1. i 与 em 的区别:

i是HTML中的一种文本样式元素,通常用于将文本设置为斜体效果。它的作用与b类似,仅仅是为了呈现出文字的视觉效果,没有任何语义含义。

em是HTML中的一种语义元素,表示文本具有强调强调强调的语义含义。除了将文本设置为斜体外,还可以使用CSS样式对其进行进一步的调整和呈现。

总之,title、b、i等元素主要用于设置文本的样式效果,而h1、strong、em等元素则更多地关注文本的语义含义,这有助于提高文档的可读性、可访问性和搜索引擎优化效果。


70. 浏览器存储有哪些?

浏览器存储指的是在浏览器中保存和管理数据的技术。浏览器存储一般分为以下几种类型:

  1. Cookie

Cookie是一种小型的文本文件,可以由服务器发送给浏览器,并存储在用户的计算机上。它可以用于记录用户的登录状态、购物车信息等,以便下次访问时能够自动获取这些信息。Cookie的大小通常有限制,不同浏览器和服务器之间也存在差异,因此需要仔细管理。

  1. SessionStorage

SessionStorage是一种HTML5引入的API,用于将数据保存在浏览器会话期间。它与Cookie不同的是,SessionStorage存储的数据仅在当前会话期间有效,当用户关闭浏览器窗口时,存储的数据也会被删除。

  1. LocalStorage

LocalStorage也是一种HTML5引入的API,用于将数据保存在浏览器本地,即使用户关闭浏览器后,数据也能保留。LocalStorage的大小通常比Cookie和SessionStorage更大,可以存储数MB的数据。


71. Url 到浏览器的一个过程有哪些步骤?(一次完整的 HTTP 事务包括哪些步骤?)

  1. URL 解析:浏览器根据输入的 URL 进行解析,分析其中的协议(如 HTTP、HTTPS)、域名、路径等信息。

  2. DNS 解析:浏览器通过 DNS(Domain Name System)将域名解析成对应的 IP 地址,以便能够找到对应的服务器。

  3. 建立 TCP 连接:浏览器与服务器之间通过 TCP 协议建立连接,这个过程包括三次握手,确保双方能够互相通信。

  4. 发起 HTTP 请求:浏览器向服务器发送 HTTP 请求,包括请求的方法(GET、POST 等)、路径、请求头(如 Accept、User-Agent 等)以及请求体(对于 POST 请求)。

  5. 服务器处理请求:服务器接收到请求后,根据请求路径和方法执行相应的处理逻辑,可能涉及到查询数据库、处理业务逻辑等操作。

  6. 服务器响应:服务器将处理结果封装成 HTTP 响应,包括状态码、响应头(如 Content-Type、Content-Length 等)以及响应体(实际的返回数据)。

  7. 接收响应数据:浏览器接收到服务器的响应数据,开始解析处理响应内容。

  8. 渲染页面:如果响应是 HTML 内容,浏览器会解析 HTML、CSS 和 JavaScript,并渲染出页面。

  9. 关闭 TCP 连接:页面资源加载完成后,浏览器会关闭与服务器的 TCP 连接,释放网络资源。


72. JSON 和 JSONP 的区别?

JSON(JavaScript Object Notation)和JSONP(JSON with Padding)是两种用于在网络上传输数据的格式,它们之间有一些区别:

  1. JSON(JavaScript Object Notation):

    • JSON是一种轻量级的数据交换格式,用于在不同系统之间传输结构化数据。
    • JSON数据格式是纯粹的数据,通常由键值对组成,使用JavaScript的语法来描述数据结构。
    • JSON数据在传输过程中通常使用HTTP协议的请求和响应进行传输,可以被任何支持JSON格式解析的语言所解析和处理。
  2. JSONP(JSON with Padding):

    • JSONP是一种利用JSON的跨域技术,允许在客户端从不同域名下获取数据。
    • JSONP利用了<script>标签的跨域特性,在请求中指定一个回调函数的名称,服务器在返回数据时将数据作为参数传递给该回调函数并包裹在函数调用中,从而实现跨域数据获取。
    • JSONP只能用于GET请求,因为<script>标签无法发送POST请求。

总体来说,JSON是一种数据格式,用于在不同系统之间传输数据;而JSONP是一种利用JSON格式来进行跨域数据获取的技术,通过动态创建<script>标签来获取跨域数据。需要注意的是,由于JSONP存在安全性和可靠性问题,现在已经被CORS(Cross-Origin Resource Sharing)等更安全、更灵活的跨域解决方案所取代。


73. for循环 与 forEach循环的区别?

for循环和forEach循环都是用于遍历数组的,它们之间的区别主要包括以下几个方面:

  1. 语法: for循环语法比较复杂,需要手动索引到每一个元素;而forEach循环语法更为简单明了,只需要指定一个回调函数即可。

  2. 返回值: for循环没有返回值,只能通过定义变量进行操作;而forEach循环可以返回一个结果或者在回调函数中直接修改原数组。

  3. continue和break语句的使用: 在for循环中,可以使用continue和break语句来控制循环的流程;而在forEach循环中,无法使用这些语句。

  4. 性能: 在小型数组上,两种循环的性能几乎相同。但是在大型数组上,for循环比forEach循环快得多,因为forEach循环会在每次迭代时将回调函数压入调用堆栈,而for循环则不需要。

总体来说,for循环适合在需要使用break、continue等语句或者对数组进行大量操作的情况下使用;而forEach循环则适合在遍历数组时只需执行一些简单操作的情况下使用,同时代码更简洁易读。


74. 通过 new 的方式创建对象 和 通过字面量创建对象 的区别?

通过 new 的方式创建对象和通过字面量创建对象有以下区别:

  1. 语法: 通过 new 创建对象需要使用构造函数,而通过字面量创建对象直接使用大括号 {}

  2. 构造函数: 通过 new 创建对象时,需要定义一个构造函数来初始化对象的属性和方法。而通过字面量创建对象时,可以直接在对象字面量中定义属性和方法。

  3. 原型链: 通过 new 创建的对象会继承构造函数的原型链上的属性和方法,而通过字面量创建的对象只能继承默认的 Object 原型链上的属性和方法。

  4. 实例化: 通过 new 创建对象时,会实例化一个新的对象,并将构造函数中的属性和方法复制给该对象。而通过字面量创建对象时,直接创建一个新的对象。

  5. 性能: 通过 new 创建对象相对较慢,因为它需要实例化一个新的对象并执行构造函数。而通过字面量创建对象速度更快,因为它是直接创建一个新的对象。


75. 常见的浏览器内核有哪些?

  1. Trident 内核: 也称为 MSHTML,是微软公司的 Internet Explorer 浏览器所采用的内核。

  2. Gecko 内核: 是 Mozilla 公司的 Firefox 浏览器所采用的内核,也被一些其他浏览器所采用。

  3. WebKit 内核: 是苹果公司的 Safari 浏览器所采用的内核,也被谷歌公司的 Chrome 浏览器所采用。

  4. Blink 内核: 是由谷歌公司开发的一种浏览器内核,目前被谷歌公司的 Chrome 浏览器和 Opera 浏览器所采用。

除了上述几种主要的浏览器内核以外,还有一些其他的浏览器内核,如 Presto 内核(Opera 浏览器早期版本所采用的内核)、EdgeHTML 内核(微软公司的 Microsoft Edge 浏览器所采用的内核)等。随着浏览器技术的不断发展,浏览器内核也在不断优化和更新,未来可能会出现新的浏览器内核。


76. 为什么要初始化CSS样式

  1. 统一默认样式: 不同浏览器对于标签的默认样式有所不同,例如边距、内边距、字体大小等,通过初始化 CSS 样式可以消除这些差异,使页面在各种浏览器中表现一致。

  2. 提高可维护性: 初始化 CSS 样式可以减少在编写具体样式时需要考虑的因素,避免一些意外的样式问题以及浏览器兼容性的困扰,从而提高代码的可维护性。

  3. 优化用户体验: 统一的基础样式可以提高用户体验,使用户在不同浏览器下访问网页时获得一致的视觉感受,同时也能确保页面布局和元素的展示符合设计者预期。

  4. 减少重复工作: 通过初始化 CSS 样式,可以减少在项目中重复设置基础样式的工作量,提高开发效率。

  5. 避免样式冲突: 初始化 CSS 样式可以帮助规避一些样式冲突和意外的样式覆盖问题,确保设计的一致性和稳定性。


77. var const let 三者的区别?

  1. var

var是ES5及之前版本中声明变量的关键字,它具有以下特点:

  • 可以重复声明同一个变量;
  • 声明的变量作用域为函数作用域;
  • 如果没有使用var关键字声明变量,则该变量会被当做全局变量。
  1. let

let是ES6引入的声明变量的关键字,它与var相比有以下区别:

  • 不允许重复声明同一个变量;
  • 声明的变量作用域为块级作用域,即花括号{}内的范围;
  • 如果在同一作用域内使用let声明了一个变量,它会覆盖之前的同名变量。
  1. const

const也是ES6引入的声明变量的关键字,用于声明常量,它具有以下特点:

  • 声明的变量必须要进行初始化,且初始化后不能再次赋值;
  • 声明的变量作用域为块级作用域;
  • 对于引用类型的变量,const声明的是这个变量指向的内存地址不能改变,但是可以修改内存地址里的属性。

78. Promise构造函数是同步执行还是异步执行,then 方法呢?

console.log('Start');

const promise = new Promise((resolve, reject) => {
  console.log('Promise executor');
  resolve('Success');
});

promise.then((result) => {
  console.log('Promise resolved:', result);
});

console.log('End');

输出结果:

Start
Promise executor
End
Promise resolved: Success

在上面的例子中,Promise构造函数中的代码仍然会在主线程上同步执行,但then方法的回调函数会在当前任务队列的末尾以微任务的形式被添加,因此先输出"Start",然后输出"Promise executor",再输出"End"。最后,在下一个事件循环迭代开始之前,then方法的回调函数才会被执行,输出"Promise resolved: Success"。

这个例子展示了Promise构造函数和then方法在执行顺序上的差异。


79. Promise 有哪几种状态?

Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。

  • pending(进行中):Promise对象初始的状态是pending,表示异步操作还未完成。
  • fulfilled(已成功):当异步操作成功完成时,Promise的状态从pending转变为fulfilled。在这个状态下,Promise对象会执行then函数的第一个回调函数,并将异步操作的结果作为参数传递给该回调函数。
  • rejected(已失败):当异步操作失败时,Promise的状态从pending转变为rejected。在这个状态下,Promise对象会执行catch函数(或者then函数的第二个回调函数),并将异步操作的拒绝原因作为参数传递给该函数。

80. 使用箭头函数应注意什么?

  1. this 的指向: 箭头函数不绑定自己的 this 值,而是从定义它的作用域中继承 this 值。这意味着箭头函数内部的 this 与普通函数不同,它没有自己的 this 值,而是沿用外层作用域的 this 值。因此,在使用箭头函数时要注意其上下文的 this 绑定。

  2. 不适合作为构造函数: 箭头函数不能用作构造函数来创建对象实例,因为箭头函数没有自己的 this 值,无法通过 new 关键字调用。如果非要用箭头函数作为构造函数,会导致 TypeError。

  3. arguments 对象: 箭头函数没有自己的 arguments 对象,它会继承外层作用域的 arguments 对象。如果需要访问箭头函数内部的参数,可以使用 rest 参数(…args)或使用普通函数来获取 arguments 对象。

  4. 不绑定 super: 箭头函数也不能用来绑定 super 关键字,因为箭头函数没有自己的 super 关键字。如果在子类中需要引用父类的方法,应该使用普通函数。

  5. 单个表达式省略大括号: 如果箭头函数只有一条语句,可以省略大括号,并且该语句的结果会被隐式返回。但是如果有多条语句,就需要保留大括号并显式返回结果。


81. 什么是 async/await?

async/await 是 ES2017(也称为 ECMAScript 8)引入的一种异步编程方式。它使用 async 关键字定义一个异步函数,该函数内部可以使用 await 表达式来等待一个 Promise 对象的完成,进而避免了传统的回调地狱问题。

具体来说,使用 async/await 可以将异步代码以同步的方式表达,使得代码更加清晰易读,同时也更易于调试和维护。

以下是一个使用 async/await 的简单示例代码。其中,fetchData 函数是一个异步函数,它使用 fetch API 来从远程服务器获取数据,并返回一个 Promise 对象:

async function fetchData() {
  // 等待从远程服务器获取数据的 Promise 对象完成
  const response = await fetch('/api/data');

  // 等待将响应转换成 JSON 格式的 Promise 对象完成
  const data = await response.json();

  // 返回获取到的数据
  return data;
}

// 调用异步函数,并在 Promise 对象完成后打印结果
fetchData()
  .then(data => console.log(data))
  .catch(error => console.error(error));

在这个示例中,我们定义了一个名为 fetchData 的异步函数,它等待从服务器获取数据的 Promise 对象完成,并将响应转换成 JSON 格式的 Promise 对象完成,最后返回获取到的数据。

在主线程的 JavaScript 中,我们通过调用 fetchData 函数来发起异步请求,并使用 Promise 对象的 then 方法和 catch 方法来处理异步操作的结果。

需要注意的是,async/await 语法只是一种语法糖,它依然使用 Promise 对象来管理异步操作。因此,在使用 async/await 时仍然需要处理 Promise 对象的异常情况。


82. Vue 的双向绑定原理是什么?关键点在哪里?

Vue 的双向绑定原理是通过使用数据劫持结合观察者模式实现的。关键点在于以下几个方面:

  1. 数据劫持(Object.defineProperty):Vue 在初始化时会遍历数据对象,利用 Object.defineProperty 或者 Proxy 方法将数据对象的属性转换为 getter 和 setter,这样就能在属性被访问或修改时进行拦截和监听。

  2. 观察者模式:Vue 中有一个 Observer 观察者,它负责循环遍历数据对象的每个属性,并为每个属性创建对应的 Dep(依赖),同时还有一个 Watcher 观察者,它会收集属性的依赖关系,并在数据发生变化时通知相关的 Watcher 更新视图。

  3. 模板编译:Vue 的模板编译过程会解析模板中的指令和插值表达式,并为每个指令创建一个对应的 Watcher。当数据发生变化时,Watcher 会接收到通知,进而触发相应的更新操作。

  4. 依赖收集:在模板编译过程中,当解析到指令或插值表达式时,会建立起属性与 Watcher 之间的依赖关系。这样,当属性发生变化时,就可以通过依赖关系找到所有依赖该属性的 Watcher,并触发它们的更新操作。


83. Vue 的生命周期有哪些?它们每个阶段做什么操作?

  1. 创建阶段
    • beforeCreate:实例初始化之后,数据观测 (data observer) 和事件配置 (event/watcher setup) 之前被调用。在这个阶段,实例的数据对象 data 和方法 methods 已经初始化,但是尚未挂载到 DOM 上。数据和虚拟DOM树 还没有加载完成。
    • created:实例已经完成数据观测、属性和方法的运算,初始化事件,但尚未挂载到 DOM 上。在这个阶段,常常进行一些异步操作,如请求数据、监听事件等。数据已经加载好,虚拟DOM树没有加载完成。
  2. 挂载阶段
    • beforeMount:在挂载开始之前被调用,相关的 render 函数首次被调用。数据和虚拟DOM树已经都加载完成,但是这时数据没有渲染。
    • mounted:el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内。数据和虚拟DOM树已经都加载完成,也渲染完成。
  3. 更新阶段(多次)
    • beforeUpdate:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会导致重渲染。数据更新了,但页面还没有更新
    • updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁之后调用。页面也更新了。
  4. 销毁阶段
    • beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
    • destroyed:实例销毁后调用。该钩子被调用时,所有绑定和实例的指令都将被解绑,所有的事件侦听器都将被移除,所有的子实例也都将被销毁。

84. 父子组件生命周期执行顺序是怎么样的?

  • 创建、挂载阶段
    父beforeCreate->父created->父beforeMount->
    子beforeCreate->子created->子beforeMount->
    子mounted->父mounted
  • 更新阶段
    父beforeUpdate->子beforeUpdate->子updated->父updated
  • 销毁阶段
    父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

85. 组件通讯方式有哪些?

在 Vue 中,组件之间可以通过以下几种方式进行通信:

  1. Props/Attributes:使用 props 将数据从父组件传递给子组件。父组件通过属性绑定的方式将数据传递给子组件,在子组件内部通过 props 接收数据并进行使用。

  2. 事件:子组件可以通过 $emit 方法触发自定义事件,并通过事件参数传递数据给父组件。父组件通过 v-on@ 监听子组件的事件,并在事件处理函数中获取传递的数据。

  3. Vuex:Vuex 是 Vue 的官方状态管理库,用于在多个组件之间共享状态。通过定义全局的 state,可以在任何组件中访问和修改这些状态,实现组件之间的通信和共享数据。

  4. $refs:通过给组件设置 ref 属性,可以在父组件中通过 $refs 访问子组件实例。通过访问子组件的方法和属性,可以进行组件之间的直接通信。

  5. Provide/Inject:通过 provideinject 可以在祖先组件中提供数据,并在后代组件中注入数据。这种方式可以跨越多层嵌套关系,实现组件之间的非直接通信。


86. Vuex 有几个属性及作用?

  1. Statestate 是存储应用程序级别状态的对象。在 Vuex 中,所有组件都共享同一个状态树,可以通过 this.$store.state 来访问状态对象。State 的设计是响应式的,当 State 中的数据发生变化时,相关组件会自动更新。

  2. Gettersgetters 类似于组件中的计算属性,用于对 Store 中的数据进行一些计算操作。Getters 可以对 State 中的数据进行筛选、过滤、组合等操作,并将结果缓存起来,以提高性能。

  3. Mutationsmutations 是改变 Vuex Store 中状态的唯一途径。每个 Mutation 都是一个方法,接受 State 作为第一个参数,并可以接受额外的参数用于状态的修改。Mutations 必须是同步函数,用于记录每个状态变更的具体操作。

  4. Actionsactions 类似于 Mutations,但 Actions 可以包含异步操作。通过提交一个 Action,可以在 Action 内部执行异步操作,然后再提交一个 Mutation 来改变状态。Actions 可以包含多个 Mutation 的提交。

  5. Modulesmodules 允许将 Store 分割成模块,每个模块拥有自己的 State、Getters、Mutations 和 Actions。这样可以更好地组织大型应用的代码,并使代码结构更清晰。


87. Vue 的监听属性和计算属性有什么区别?

Vue的监听属性和计算属性都用于监测数据变化,但监听属性是一个函数,需要手动调用,每次都需要重新计算,而计算属性是一个属性,会自动计算并缓存结果,不需要重新计算

  1. 监听属性 (Watchers)
    • Watchers 允许你在数据变化时执行异步或耗时操作,或者在数据变化时执行自定义的逻辑。
    • 通过 vm.$watch 或在组件选项中使用 watch 对象来创建 Watchers。
    • Watchers 监听特定数据的变化,并在数据发生变化时执行回调函数。
    • Watchers 适用于需要执行异步操作、复杂逻辑或监听多个数据变化的情况。
  2. 计算属性 (Computed Properties)
    • 计算属性根据其依赖的数据动态计算新值,并将结果缓存起来,只有在依赖数据发生变化时才会重新计算。
    • 通过在组件选项中使用 computed 对象来定义计算属性。
    • 计算属性具有缓存机制,只有在依赖数据发生变化时才会重新计算,减少不必要的计算次数。
    • 计算属性适用于对数据进行转换、过滤、排序等操作,并且可以在模板中直接使用。

88. Vue 是什么?

Vue是一种用于构建用户界面的渐进式JavaScript框架。它专注于视图层,采用了组件化的开发方式,使得构建复杂的Web应用程序变得简单和高效。

  1. 渐进式:Vue被设计为渐进式的框架,可以逐步应用到现有的项目中,也可以作为一个独立的库使用。这意味着您可以根据需要逐步采用Vue的功能,而不必改变整个项目的架构。

  2. 响应式数据绑定:Vue使用双向数据绑定来实现数据与视图的自动同步。当数据发生变化时,视图会自动更新,反之亦然。这样可以让开发者轻松地管理和维护数据状态。

  3. 组件化开发:Vue将用户界面拆分为独立的可复用组件,每个组件都包含自己的模板、逻辑和样式。这种组件化的开发方式使得代码更加模块化、可维护性更高,并且提供了更好的复用性和扩展性。

  4. 虚拟DOM:Vue通过使用虚拟DOM来优化渲染性能。在数据发生变化时,Vue会生成一个虚拟DOM树,然后将其与实际DOM进行比对,只对有变化的部分进行更新,从而减少了DOM操作带来的性能开销。

  5. 简洁易学:Vue的API设计简洁明了,学习曲线较为平缓。它提供了大量的指令和工具,使得开发者可以更加高效地构建出功能丰富、交互流畅的应用程序。


89. Vue 常用的指令有哪些?

Vue.js 中常用的指令包括:

  1. v-if:根据表达式的真假值条件性地渲染元素。

    <div v-if="isTrue">条件为真时显示</div>
    
  2. v-for:基于数组或对象的数据源循环渲染元素。

    <ul>
      <li v-for="item in items" :key="item.id">{{ item.name }}</li>
    </ul>
    
  3. v-bind:动态地绑定一个或多个特性,或一个组件 prop 到表达式。

    <a v-bind:href="url">动态链接</a>
    
  4. v-on:绑定事件监听器,用于触发 JavaScript 方法或内联语句。

    <button v-on:click="handleClick">点击我</button>
    
  5. v-model:在表单控件元素上创建双向数据绑定。

    <input v-model="message" placeholder="输入内容">
    
  6. v-show:根据表达式的真假值条件性地显示元素。

    <div v-show="isShow">根据条件显示或隐藏</div>
    
  7. v-text:更新元素的 textContent。不能转义标签,只能渲染数据

    <span v-text="message"></span>
    
  8. v-html:更新元素的 innerHTML。可以转义标签和渲染数据

    <div v-html="htmlContent"></div>
    

这些指令是 Vue.js 中常用的核心指令,能够帮助开发者轻松地实现数据驱动的视图渲染和交互功能。除了以上列举的指令外,Vue.js 还提供了许多其他的指令和自定义指令的能力,开发者可以根据实际需求选择合适的指令来进行开发。


90. v-if 和 v-show 有什么区别?

  1. 初始化渲染: v-if 在初始渲染时会根据条件判断是否需要渲染对应的元素,如果条件为假,则该元素不会被渲染到 DOM 中。而 v-show 则会在初始渲染时直接渲染到 DOM 中,只是通过 CSS 的 display 属性控制该元素是否可见。

  2. 性能消耗: 当条件频繁切换时,v-show 的性能优于 v-if,因为 v-show 只是切换 CSS 的 display 属性,而 v-if 每次条件切换都需要重新渲染整个元素及其子组件。

  3. 适用场景: 如果需要在运行时频繁切换条件,则使用 v-show 可以获得更好的性能体验;如果条件不太可能改变,或者只在初始渲染时进行一次判断,则使用 v-if 更为合适。


91. v-for 为什么要加一个 key ?

  1. 提高性能:当数据发生变化时,Vue 会尽可能地复用已经存在的 DOM 元素,而不是销毁和重新创建。通过给每个节点添加唯一的 key,Vue 能够更快速准确地定位要更新、删除或插入的节点,从而提高页面更新的性能。

  2. 保持组件状态:在使用可复用的组件进行列表渲染时,带有相同 key 的组件会被复用,从而保持组件的状态,避免不必要的销毁和创建,提高了组件的复用性和性能。

  3. 避免出现错误:在没有为 v-for 循环的每个元素添加 key 时,可能会导致一些意外的行为或错误,例如列表渲染时的错位或重复渲染。


92. keep-alive是什么?有哪几个生命周期阶段?

keep-alive 是 Vue.js 的一个内置组件,用于在组件之间缓存和保留状态,以避免多次创建和销毁。

当一个组件被包裹在 <keep-alive> 标签中时,该组件会被缓存起来,而不是每次都重新渲染。这样可以提高组件的性能和响应速度,并且可以保留组件的状态,例如用户的输入、滚动位置等。

<keep-alive> 组件有以下几个生命周期阶段:

  1. activated:当缓存的组件被激活时触发。在组件首次渲染时,该生命周期钩子不会被调用。可以在这个阶段执行一些需要在组件激活时进行的操作,例如数据初始化、发送请求等。

  2. deactivated:当缓存的组件被停用时触发。在组件被销毁之前,先会触发该生命周期钩子。可以在这个阶段执行一些需要在组件停用时进行的操作,例如保存数据、清除定时器等。

注意,被 <keep-alive> 缓存的组件在切换时,不会触发常规的创建和销毁生命周期钩子,而是通过 activateddeactivated 钩子来表示组件的激活和停用。

使用 <keep-alive> 可以优化那些频繁切换或需要保持状态的组件,提高应用的性能和用户体验。


93. 常用伪元素有哪些?

常用的 CSS 伪元素包括 ::before::after::first-line::first-letter。这些伪元素可以用来在文档中的某些元素前后插入内容或样式,从而实现一些特殊的效果。

  1. ::before:用于在元素的内容之前插入内容,通常用于添加装饰性的内容或样式。

  2. ::after:用于在元素的内容之后插入内容,同样也常用于添加装饰性的内容或样式。

  3. ::first-line:用于选择元素的第一行文本,可以为其应用特殊的样式,例如改变字体、大小、颜色等。

  4. ::first-letter:用于选择元素的第一个字母,同样可以为其应用特殊的样式,比如改变字体、大小、颜色等。

这些伪元素可以通过 CSS 选择器来选择并定义样式,从而在页面中实现一些特殊的设计效果。例如,可以使用 ::before::after 来为元素添加装饰性的边框、图标或其他内容;使用 ::first-line::first-letter 来为文字段落的首行或首字母添加特殊的样式。

除了上述常用的伪元素外,还有一些其他的伪元素,如 ::selection 用于选择文本时的样式控制,::placeholder 用于 input 元素的占位符样式控制等。这些伪元素的灵活运用可以丰富页面的样式和交互效果。


94. Vue 中如何让 CSS 只在当前组件中起作用?

在 Vue 中,可以使用 <style> 标签的 scoped 属性来实现让 CSS 只在当前组件中起作用。


95. v-if 和 v-for 哪个优先级更高?

  • Vue2:v-for的优先级高于v-if
  • vue3:v-if的优先级高于v-for

96. 子组件可以直接改变父组件的数据吗?

在 Vue 中,子组件不能直接改变父组件的数据。这是因为 Vue 遵循单向数据流的原则,父组件通过 props 将数据传递给子组件,子组件可以修改 props 接收到的数据并将修改后的数据通过事件通知父组件。


97. 什么是 虚拟DOM 和 diff算法

虚拟 DOM(Virtual DOM)是指一个虚拟的内存数据结构,它是对真实 DOM 的抽象表示。在前端框架(如 Vue.js、React 等)中广泛使用虚拟 DOM 来提高性能和优化 DOM 操作。

当页面发生变化时,框架会先操作虚拟 DOM,而不是直接操作真实 DOM。通过比较新旧虚拟 DOM 的差异,框架能够高效地计算出最小的更新量,并将这些变化一次性批量更新到真实 DOM 上,从而减少对真实 DOM 的频繁操作,提高页面渲染性能。

虚拟 DOM 的工作流程通常是这样的:

  1. 初始化:页面首次渲染时,框架会根据组件结构生成虚拟 DOM。
  2. 更新:当状态发生变化时,框架会生成新的虚拟 DOM,并与之前的虚拟 DOM 进行比较。
  3. Diff 算法:通过比较新旧虚拟 DOM,找出两者之间的差异。
  4. 批量更新:将差异一次性更新到真实 DOM 上,以减少重绘和回流的次数,提高性能。

虚拟DOM的diff算法通常包括以下步骤:

  1. 树的遍历:对比过程从虚拟DOM树的根节点开始,深度优先遍历整棵树。

  2. 节点比较:对应位置的节点进行比较,判断节点类型是否相同(例如都是相同的标签),如果不同,则直接将旧节点替换为新节点;如果相同,则继续比较其属性和子节点。

  3. 属性比较:比较节点属性,找出需要更新的属性,将这些属性更新到真实DOM上。

  4. 子节点比较:递归比较子节点,找出需要插入、更新或删除的子节点,并将这些变更应用到真实DOM上。

通过以上方法,框架能够高效地计算出需要对真实DOM进行的最小变更,并且只对必要的部分进行更新,从而提升页面渲染性能。

需要注意的是,具体的diff算法实现可能因框架而异,例如React和Vue等框架可能会有不同的优化策略和差异对比方式,但总体思路是类似的。


98. vue.js 的两个核心是什么?

  1. 数据驱动:Vue.js 的数据驱动是指,当数据发生变化时,视图会自动更新。Vue.js 实现数据驱动的方式是通过双向绑定:将数据与视图进行绑定,当数据发生变化时,视图会随之更新;当用户操作视图时,数据也会相应地发生变化。这种方式使得开发者无需手动操作 DOM,只需要专注于处理数据的变化和逻辑。

  2. 组件化:Vue.js 的组件化是指,将页面拆分成多个独立、可复用的组件,并通过组合这些组件来构建整个应用。每个组件都包含自己的逻辑、样式和模板,可以接受和发送消息,可以嵌套其他组件中使用。这种方式能够提高应用的可维护性和复用性,同时也能够提高开发效率。


99. Vue 的导航守卫有哪些?

  1. 全局前置守卫 (beforeEach):在路由切换开始之前被调用,可以用于进行权限验证或其他全局的前置操作。
  2. 全局解析守卫 (beforeResolve):在组件被解析之后,导航被确认之前被调用。可以用于在路由切换时对组件进行进一步的处理。
  3. 全局后置钩子 (afterEach):在导航完成之后被调用,可以用于执行全局的后置操作或清理工作。
  4. 路由独享守卫 (beforeEnter):在单个路由配置中定义的守卫,只对该路由有效。
  5. 组件内的守卫
    • beforeRouteEnter:在路由进入组件之前被调用,可以访问组件实例 this,但此时不能保证组件已经加载完毕。
    • beforeRouteUpdate:在当前路由改变,但是组件被复用时被调用,可以访问组件实例 this
    • beforeRouteLeave:在离开当前路由时被调用,可以用于阻止路由离开或提示用户保存未保存的数据。

100. 当一个导航被触发时,Vue Router 的执行流程是什么?

  • 导航被触发
  • 在失活的组件里调用 beforeRouteLeave
  • 调用全局的 beforeEach
  • 在重用的组件里调用 beforeRouteUpdate
  • 在路由配置里调用 beforeEnter
  • 解析异步路由组件
  • 在被激活的组件里调用 beforeRouteEnter
  • 调用全局的 beforeResolve
  • 导航被确认
  • 调用全局的 afterEach
  • 触发 DOM 更新
  • 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

完结,撒花~

  • 27
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值