前端集合(一)

54 阅读14分钟

1、pinia和vuex的区别

答:Pinia和Vuex都是Vue.js的状态管理库。它们的主要区别如下:

  1. 数据响应式:
    Pinia使用Vue 3 Composition API提供的reactive函数实现数据响应式,而Vuex使用自己的state对象和Vue的响应式系统。这意味着在使用Pinia时,您可以像编写Vue组件一样编写存储库,而且代码更简洁易懂。
  2. 模块化:
    在Vuex中,状态是通过store模式组织在一起的,每个store模块都包含自己的状态、mutations、actions和getters。相比之下,Pinia将状态存储在单独的存储库中,每个存储库只包含该存储库自己的状态和操作。这使得在大型应用程序中,每个功能模块都可以拥有自己的状态管理。
  3. 插件系统:
    Vuex提供了许多插件,例如logger、devtools等。Pinia本身没有提供插件系统,但它使用Vue插件API提供了机制来注册全局插件。
  4. TypeScript支持:
    虽然Vuex支持TypeScript,但Pinia是为TypeScript设计的,并且在TypeScript应用程序中具有更好的类型推断和提示。

总之,Pinia和Vuex都是出色的状态管理工具,根据您的具体需求,选择适合您的工具即可。如果您喜欢使用Vue 3的Composition API,并希望编写模块化的存储库,则可以试用Pinia;如果您已经熟悉Vuex并喜欢其插件系统,则可以继续使用Vuex。

2、css实现DOM节点的水平居中有几种方式

答:有以下几种方式可以使用CSS实现DOM节点的水平居中:

  1. text-align: center;
    对于内联元素,可以将其父容器的text-align属性设置为center实现水平居中。例如,可以将包含文本的p元素置于其父容器中并添加如下样式:
.parent {
  text-align: center;
}
  1. margin: auto;
    对于块级元素,可以将其左右margin值都设置为auto实现水平居中。例如,可以将一个div元素的宽度设为固定值,并将其左右margin值设置为auto来使其水平居中:
.center {
  width: 200px;
  margin: 0 auto;
}
  1. display: flex;
    使用flex布局是另一种实现元素水平居中的好方法,它可以让其子元素在其主轴上居中。例如,可以将一个div元素的display属性设置为flex,并将其子元素的justify-content属性设置为center来使其水平居中:
.parent {
  display: flex;
  justify-content: center;
}
  1. position + transform;
    设置相对于父元素绝对定位,然后通过translateX(-50%)来使其水平居中。例如,可以将一个绝对定位的div元素的left和top属性都设置为50%,并使用translateX(-50%)来使其水平居中:
.center {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translateX(-50%);
}
  1. table + margin: 0 auto;
    使用table布局,通过将table元素的margin设置为“0 auto”来使其在父容器中水平居中。例如,可以将一个table元素放置在一个div元素中,并将table元素的margin属性设置为0 auto来使其水平居中:
复制代码.parent {
  text-align: center;
}
.center {
  display: table;
  margin: 0 auto;
}
  1. line-height;
    对于单行内联元素(如文字),可以设置其所在容器的line-height属性等于容器的高度,从而使其水平居中。例如,可以将一个包含文本的span元素放置在一个div元素中,并将div元素的height和line-height属性都设置为相同的固定值来使其水平居中:
复制代码.parent {
  height: 50px;
  line-height: 50px;
  text-align: center;
}
.center {
  display: inline-block;
}

需要注意的是,以上方法中有些只适用于特定的情况,因此需要根据实际情况选择适合的方法来实现元素的水平居中。

3、typeof和instanceof区别

答:typeof和instanceof是JavaScript中用于判断数据类型的操作符,它们之间有以下区别:

  1. typeof是一个操作符,用于检测给定变量或表达式的数据类型。它返回一个字符串,表示被检测值的数据类型。typeof可以检测出基本数据类型(如字符串、数字、布尔值等),以及函数和对象(包括数组、日期等),但不能检测出null和undefined的具体类型。
  2. instanceof是一个操作符,用于检测对象是否是指定构造函数的实例。它通过检查对象的原型链来判断对象是否是由指定构造函数创建的。当一个对象是指定构造函数的实例时,instanceof返回true;否则返回false。instanceof只能用于检测对象是否是某个构造函数的实例,而不能用于基本数据类型的检测。

简单来说,typeof用于检测数据类型(包括基本数据类型和函数、对象的数据类型),返回一个字符串;而instanceof用于检测对象是否是指定构造函数的实例,返回一个布尔值。

示例:

复制代码var str = "Hello";
console.log(typeof str);  // 输出: "string"

var arr = [1, 2, 3];
console.log(typeof arr);  // 输出: "object"

var date = new Date();
console.log(typeof date);  // 输出: "object"

console.log(arr instanceof Array);  // 输出: true
console.log(date instanceof Date);  // 输出: true
console.log(str instanceof String);  // 输出: false(因为str是字符串字面量,不是String对象的实例)

console.log(arr instanceof Object);  // 输出: true(数组也是对象)
console.log(date instanceof Object);  // 输出: true(日期对象也是对象)
console.log(str instanceof Object);  // 输出: false(字符串不是对象)

需要注意的是,typeof对于null的返回值是"object",这是一个历史遗留问题。而instanceof对于null的检测会返回false。

4、浏览器输入url,到看到页面会发生什么

答:当在浏览器中输入一个URL并按下回车键时,通常会经历以下步骤:

  1. URL解析:浏览器会解析输入的URL,将其分解为协议(如HTTP、HTTPS)、域名(或IP地址)和路径等部分。
  2. DNS解析:浏览器将解析出来的域名部分发送给DNS服务器,以获取该域名对应的IP地址。如果DNS缓存中存在对应的记录,则直接返回IP地址;否则,会进行递归查询,直至找到对应的IP地址。
  3. 建立TCP连接:浏览器使用取得的IP地址与服务器建立TCP连接。这是通过三次握手来确保客户端和服务器之间建立可靠的连接。
  4. 发送HTTP请求:浏览器向服务器发送HTTP请求,以获取所需的资源。请求包括请求头(包含方法、URL、协议版本等信息)和请求体(一般用于POST请求)。
  5. 服务器处理请求:服务器接收到请求后,会根据请求的路径、方法等信息进行处理。服务器可能会查询数据库、处理业务逻辑,并最终生成相应的HTTP响应。
  6. 接收响应内容:浏览器接收到服务器发回的HTTP响应。响应包括响应头(包含状态码、内容类型等信息)和响应体(实际返回的数据)。
  7. 渲染页面:浏览器开始解析响应内容,并根据其中的HTML、CSS和JavaScript等资源构建DOM树、CSSOM树和渲染树。然后,浏览器会将渲染树绘制到屏幕上,展示给用户。
  8. 关闭TCP连接:当所有资源都加载完成后,浏览器会关闭与服务器之间的TCP连接。但通常情况下,浏览器会保持TCP连接的复用,以便快速请求其他资源。

以上过程是简化的描述,实际情况还可能涉及到缓存机制、重定向、安全认证等。不同浏览器和网络环境也可能有细微差别,但大体流程是相似的。

5、函数式编程的副作用是什么

答:函数式编程强调函数的纯粹性,即函数的输出仅由输入决定,没有任何副作用。副作用指的是函数除了返回值之外对程序其他部分产生的影响。函数式编程的目标是尽量减少副作用的存在,使函数更加可预测、可测试和可复用。

然而,在实际编程中,有些任务难以避免副作用的产生,比如与外部世界进行交互(如读写文件、发送网络请求)、修改共享状态(如全局变量)等。这些副作用可能导致代码的不确定性、难以理解和难以调试。

一些常见的副作用包括:

  1. 修改共享状态:当函数直接或间接地修改共享状态(全局变量、对象属性等),会引入不可预测的变化,从而增加了代码的复杂性。
  2. I/O操作:涉及到与外部世界的交互,比如读写文件、发送网络请求,这些操作会受到外部环境的影响,难以控制和预测。
  3. 异步操作:在处理异步操作时,为了处理回调函数或者Promise的结果,往往需要改变函数的执行流程,这也是副作用的一种表现。
  4. 异常处理:处理异常时,可能会修改程序状态或者引发其他副作用。

副作用的存在不一定是完全不可避免的,但函数式编程通过提倡将副作用局限在必要的最小范围内,尽量将可变状态和副作用隔离起来,从而提高代码的可读性、可测试性和可维护性。为了应对副作用,函数式编程常常使用纯函数、不可变数据和函数组合等技术手段。

6、为什么 vue2监听不到数据变化

答:在Vue 2中,数据的变化监听主要依赖于Object.defineProperty这个方法来实现。它通过劫持对象属性的getter和setter函数,在数据发生变化时触发相应的回调函数。

然而,Object.defineProperty只能劫持对象的属性,而不能直接劫持整个对象或数组。这就导致了一个常见的问题:当你给对象或数组中新增或删除属性时,Vue2无法自动检测到这些变化。

解决这个问题的常用方法是使用Vue提供的特定方法来操作数据,例如Vue.set()Array.prototype.splice()。这些方法会通过特殊的逻辑来更新Vue的响应式系统,从而能够正确地监听到数据的变化。

另外,如果你需要监听一个嵌套对象的属性变化,Vue2并不能自动劫持嵌套对象的属性。为了解决这个问题,你需要使用深度监听(deep watch)或者使用Vue提供的工具类Vue.$set()来手动设置嵌套属性的响应式。

总结起来,如果你在Vue2中遇到监听不到数据变化的情况,有以下几个可能原因:

  1. 使用了Object.defineProperty之外的方式修改数据,例如直接赋值或使用非响应式的数组方法。
  2. 嵌套对象的属性变化没有被正确地劫持,需要使用深度监听或Vue.$set()来手动设置响应式。
  3. 数据在监听之前就已经被修改,导致监听无法生效。

希望以上解释可以帮助你理解为什么Vue2有时候无法监听到数据变化。如果还有其他问题,请随时提问。

7、vite配置参数

答:在Vite中,你可以通过在项目根目录下创建一个名为vite.config.js(或者vite.config.ts)的文件来配置相关参数。下面是一些常用的Vite配置选项:

  1. root:指定项目的根目录,默认为当前工作目录。
  2. base:指定输出的静态资源的基础路径,默认为/
  3. publicDir:指定公共静态资源目录,默认为public
  4. build.outDir:指定构建输出目录,默认为dist
  5. build.assetsDir:指定构建输出的静态资源子目录,默认为assets
  6. build.sourcemap:是否生成源代码映射文件,默认为true
  7. build.minify:是否启用代码压缩,默认为true
  8. build.rollupOptions:用于配置Rollup的选项,例如添加额外的插件等。
  9. server.host:指定开发服务器的主机地址,默认为localhost
  10. server.port:指定开发服务器的端口号,默认为3000
  11. server.proxy:用于配置开发服务器的代理规则,用于处理跨域请求。
  12. plugins:用于加载Vite插件。

你可以根据具体需求在vite.config.js中进行配置。下面是一个示例:

复制代码// vite.config.js

export default {
  root: './src',
  base: '/',
  publicDir: 'public',
  build: {
    outDir: 'dist',
    assetsDir: 'assets',
    sourcemap: true,
    minify: true
  },
  server: {
    host: 'localhost',
    port: 3000,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        rewrite: path => path.replace(/^/api/, '')
      }
    }
  },
  plugins: []
};

以上是一些常见的Vite配置参数,具体的配置选项可以根据你的项目需求进行调整。如果你需要更详细的配置信息,建议查阅Vite官方文档的配置部分 vitejs.dev/config/

8、为什么要从vue2升级到vue3

答:升级到Vue 3有以下几个主要的好处和原因:

  1. 更好的性能:Vue 3在性能方面进行了一系列的优化,包括更快的渲染速度、更小的包体积、更高效的响应式系统等,可以提供更好的用户体验。
  2. 更好的开发体验:Vue 3引入了一些新的特性和 API,例如Composition API、Teleport、Suspense等,这些新特性使得代码组织更灵活、可重用性更高,提供了更好的开发体验和更方便的调试工具。 2.1 Composition API(组合式API):Composition API是Vue 3中新增的一种逻辑组织方式。它通过将逻辑相关的代码封装到一个独立的函数中,实现代码的组合和复用。相比于Vue 2中的Options API,Composition API更加灵活,可以更好地应对复杂的业务需求。通过Composition API,开发者可以更方便地组合逻辑相关的代码,并且可以更好地重用组合函数。 2.2 Teleport:Teleport是Vue 3中新增的一个特性,用于在DOM中进行跨组件的传送(即传送到另一个目标容器中)。通过Teleport,可以将组件的内容渲染到DOM中的任意位置,而不仅仅局限于组件所在的父级元素内部。这使得开发者能够更灵活地布局和组织组件,提供更好的用户体验。 2.3 Suspense:Suspense是Vue 3中引入的一个新特性,用于处理异步组件的加载状态。通过Suspense,可以在组件树中指定一个区域,并在该区域内等待异步组件的加载完成。在异步组件加载期间,可以显示自定义的加载状态或占位内容,提高用户体验。一旦异步组件加载完成,Suspense会自动渲染该组件,并替换掉之前的占位内容。
  3. 更好的类型支持:Vue 3通过TypeScript重新实现了整个代码库,提供了更好的类型支持,可以帮助开发者在编码过程中更早地捕捉到错误,并提供更好的代码提示和自动补全。
  4. 更好的可组合性:Vue 3的Composition API(组合式API)可以让开发者更方便地组合逻辑相关的代码,将组件内部的逻辑进行封装和复用,使得代码结构更清晰、可读性更强,可以更好地应对复杂的业务需求。
  5. 更好的扩展性:Vue 3对于自定义指令、自定义渲染器等方面进行了改进和扩展,为开发者提供了更多的自定义能力,可以更灵活地满足不同场景下的需求。

需要注意的是,升级到Vue 3可能需要对现有代码进行一些调整和修改,因为Vue 3在某些方面与Vue 2有一些不兼容的变化。因此,在升级之前,建议先仔细阅读Vue 3官方文档中的迁移指南,了解迁移过程中需要做的改动和注意事项 v3.vuejs.org/guide/migra…

综上所述,升级到Vue 3可以带来更好的性能、开发体验、类型支持、可组合性和扩展性,提升项目的质量和开发效率。但在升级之前,需要仔细评估和规划,确保能够平稳地进行迁移并获得预期的收益。