某腾喜欢问这些面试题

160 阅读15分钟

map和foreach reduce区别

  • map 方法创建新数组,每个元素经过处理后放入新数组,不改变原数组。
  • forEach 方法对数组中的每个元素执行指定的操作,没有返回值,改变原数组。
  • reduce 方法对数组进行累积计算,返回一个结果,可以指定初始值。

vue2 和 vue3 的区别:

Vue 3 是 Vue.js 框架的下一个主要版本,与 Vue 2 相比有一些重大改进和变化。以下是 Vue 2 和 Vue 3 之间的一些主要区别:

1.  性能提升:Vue 3 在性能方面进行了优化。通过使用 Proxy 代理对象替代了 Vue 2 中的
Object.defineProperty 来实现响应式数据,从而提高了初始化速度并减少了内存消耗。Vue 3 还引入了静态编译,可以在构建时对模板进行编译,提高了渲染速度。

2.  组合式 API:Vue 3 引入了 Composition API,它是一种基于函数的 API 风格,
可以更好地组织和复用组件逻辑。与 Vue 2 选项式 API 相比
,Composition API 更灵活且可维护性更好。
3.  更小的包大小:Vue 3 在体积方面进行了优化,移除了一些不常用的功能和依赖,
从而使最终生成的包更小。
4.  更好的 TypeScript 支持:Vue 3 对 TypeScript 的支持更加完善,
提供了更准确的类型推断和类型定义,以及更好的编辑器支持。
5.  更强大的工具链:Vue 3 与 Vue CLI 一起提供了更强大的工具链,
使开发者可以更轻松地进行构建、调试和测试。

需要注意的是,Vue 3 在某些方面与 Vue 2 不兼容,因此升级到 Vue 3 可能需要进行一些代码调整和迁移工作。同时,一些 Vue 2 的插件和库可能还没有适配到 Vue 3,因此在升级前需要确保相关依赖已经支持 Vue 3。

总体而言,Vue 3 在性能、开发体验和可维护性方面有所提升,但升级到 Vue 3 需要权衡现有项目的需求和工作量。

vue3 移除了哪些东西

以下是Vue 2中被Vue 3弃用的一些特性和API:

1. Filters(过滤器):在Vue 3中,过滤器被移除了。可以使用计算属性或方法来代替。

2. v-once指令:在Vue 3中,v-once指令被移除了。可以使用template标签或render函数来代替。

3. inline-template特性:在Vue 3中,inline-template特性被移除了。可以使用单文件组件或render函数来代替。

4. $els属性:在Vue 3中,$els属性被移除了。可以使用ref属性来代替。

5. $listeners属性:在Vue 3中,$listeners属性被移除了。可以使用v-on="$listeners"来代替。

6. $scopedSlots属性:在Vue 3中,$scopedSlots属性被重命名为$slots。可以使用v-slot指令来代替。

7. transition组件:在Vue 3中,transition组件被移除了。可以使用transition-group组件或CSS过渡来代替。

8. keep-alive组件:在Vue 3中,keep-alive组件的属性和事件被重命名了。activated事件被重命名为onActivated,deactivated事件被重命名为onDeactivated。include和exclude属性被重命名为includeInKeepAlive和excludeFromKeepAlive。

9. $on和$once方法:在Vue 3中,$on和$once方法被移除了。可以使用$emit方法和事件监听器来代替。

10. $dispatch和$broadcast方法:在Vue 3中,$dispatch和$broadcast方法被移除了。可以使用provide和inject来代替。

需要注意的是,虽然Vue 3移除了一些特性和API,但是大部分Vue 2的代码仍然可以在Vue 3中运行。如果需要迁移Vue 2项目到Vue 3,可以参考Vue 3官方文档中的迁移指南。

一 Vue的设计原理

Vue 的设计原理主要包括响应式数据、组件化、虚拟 DOM、生命周期钩子和模板语法等。这些原理使得 Vue 在开发中能够提供高效、灵活和可维护的方式来构建用户界面。

  1. 响应式数据:Vue 使用了双向数据绑定的原理,通过 Object.defineProperty() 方法将数据对象的属性转化为 getter 和 setter,实现了数据的响应式更新。当数据发生变化时,相关的视图会自动更新。
  2. 组件化:Vue 将用户界面划分为一个个独立的组件,每个组件具有自己的状态和视图,组件可以嵌套和复用。这种组件化的设计使得代码的可维护性、可测试性和可复用性大大增强。
  3. 虚拟 DOM:Vue 通过使用虚拟 DOM 提高渲染性能。Vue 将组件的模板转换成虚拟 DOM,然后与之前的虚拟 DOM 进行比较,找出需要更新的部分,最后只更新实际需要改变的部分,减少了对真实 DOM 的操作,提高了性能。
  4. 生命周期钩子:Vue 组件具有生命周期钩子函数,可以在不同阶段执行相关操作。例如,在组件创建时执行初始化操作,在组件销毁时清理资源等。这些钩子函数提供了更好的控制组件的行为和交互。
  5. 模板语法:Vue 使用了简单且易于理解的模板语法,将 HTML 模板和 Vue 实例的数据进行绑定。通过在模板中使用指令和插值表达式,可以实现动态渲染和绑定数据。

二 vue 模板渲染的逻辑,是怎么把template渲染到界面上去的:

Vue 的模板渲染逻辑是先解析模板生成抽象语法树,然后根据抽象语法树生成渲染函数。 接着,创建虚拟 DOM,并执行渲染函数生成真实 DOM。 最后,根据虚拟 DOM 的变化进行局部更新,并将更新后的真实 DOM 挂载到容器中。 通过这个过程,Vue 实现了高效、灵活的模板渲染机制。

  1. 解析模板:首先,Vue 会将模板解析成抽象语法树(AST)。通过解析模板,Vue 可以了解模板的结构和内容,从而进行后续的渲染操作。
  2. 创建渲染函数:Vue 根据解析得到的抽象语法树,动态地生成一个渲染函数。这个渲染函数用于描述如何将模板渲染成最终的界面。
  3. 创建虚拟 DOM:在执行渲染函数之前,Vue 会先创建一个虚拟 DOM。虚拟 DOM 是一个轻量级的 JavaScript 对象,用于表示真实 DOM 的结构和属性。Vue 使用虚拟 DOM 来追踪界面的状态变化,并在需要更新界面时,对比新旧虚拟 DOM,找出差异并进行局部更新。
  4. 执行渲染函数:当需要渲染界面时,Vue 调用渲染函数,并将虚拟 DOM 作为参数传入。渲染函数会根据虚拟 DOM 的结构和属性生成真实 DOM。
  5. 更新界面:当界面的状态发生变化时,Vue 会进行重新渲染。Vue 会再次调用渲染函数,对比新旧虚拟 DOM 的差异,并更新需要更新的部分。
  6. 将界面挂载到容器中:最后,Vue 将生成的真实 DOM 挂载到指定的容器中,使界面呈现给用户。

三 promise有哪些方法

在 JavaScript 中,Promise 对象有以下几个常用的方法:

  1. Promise.then(onResolved, onRejected)

    • 该方法用来注册 Promise 对象的回调函数,当 Promise 对象解决(fulfilled)时会调用 onResolved 回调函数,当 Promise 对象拒绝(rejected)时会调用 onRejected 回调函数。
    • onResolved 和 onRejected 都是可选参数,可以是函数或者 null
    • 该方法返回一个新的 Promise 对象,用来实现链式调用。
  2. Promise.catch(onRejected)

    • 该方法用来注册 Promise 对象拒绝(rejected)时的回调函数。
    • 该方法相当于调用 Promise.then(null, onRejected),用来处理 Promise 对象拒绝的情况。
  3. Promise.finally(onFinally)

    • 该方法用来注册一个在 Promise 对象解决或拒绝后都会执行的回调函数。
    • 该方法的回调函数不接收任何参数,它只是在 Promise 对象最终状态确定后被调用。
    • 该方法返回一个新的 Promise 对象,该 Promise 对象的状态和值与原始 Promise 对象保持一致。
  4. Promise.resolve(value)

    • 该方法返回一个已解决(fulfilled)状态的 Promise 对象,解决值为指定的 value
    • 如果 value 是一个 Promise 对象,则直接返回该 Promise 对象;如果 value 是一个 thenable 对象,则会将其转换为 Promise 对象并返回;否则,返回一个已解决(fulfilled)状态的 Promise 对象,解决值为 value
  5. Promise.reject(reason)

    • 该方法返回一个已拒绝(rejected)状态的 Promise 对象,拒绝原因为指定的 reason

这些是 Promise 对象的一些常用方法,它们可以帮助我们对异步操作进行处理和组合。此外,Promise 还有其他一些方法,如 Promise.allPromise.race 等,用于处理多个 Promise 对象的情况,你可以在相关的文档中了解更多信息。

四 code码100-500分别对应什么

100 - Continue 初始的请求已经接受,客户应当继续发送请求的其余部分。
200 - OK 一切正常,对GET和POST请求的应答
3xx - 重定向  有多重选择
301 永久
302 临时
4xx - 客户端错误 
400 - Bad Request 请求出现语法错误
401没有认证授权 比如 没有 携带token 或者 token过期
403 认证通过,但是没有指定的权限 比如 登录成功没有读写功能
404 - Not Found 无法找到指定位置的资源。
5xx - 服务器错误 

五 对于项目的源代码,你怎么研究

  1. 阅读文档:项目的文档通常提供了关于代码的详细说明和示例。通过仔细阅读文档,你可以了解代码的结构、功能和用法。
  2. 查看示例和案例:许多开源项目都提供了示例和案例,展示了如何使用项目的代码。你可以通过查看这些示例和案例来理解代码的实际用法和效果。
  3. 阅读源代码:如果项目是开源的,你可以通过查看项目的源代码来深入研究。使用代码编辑器打开项目的代码文件,逐行阅读和分析代码,理解其逻辑和实现方式。
  4. 参与讨论和社区:参与项目的讨论和社区可以帮助你与项目的贡献者和其他用户进行交流,了解他们的经验和见解。这样可以获得更多关于代码的背景信息和使用建议。

总之,研究项目的源代码需要进行深入的阅读、分析和实践。结合文档、示例和社区的帮助,你可以更好地理解和应用项目的代码。

六 项目打包用什么工具

打包项目用vueCli脚手架:当你完成项目开发并准备部署时,
可以使用以下命令将项目打包为生产环境可用的静态文件: npm run build

七 压缩js代码用什么插件:terser-webpack-plugin

1.  `terser-webpack-plugin`-   使用Terser对JS代码进行压缩和混淆。
-   Terser是一个由UglifyJS维护者开发的压缩工具,提供更好的压缩效果和更快的速度。
-   在Webpack 5及更高版本中,推荐使用`terser-webpack-plugin`来代替`uglifyjs-webpack-plugin`2. 项目上线优化:gzip压缩 ,采用compression-webpack-plugin,进行配置,主要配置,压缩率和体积大于多少的文件要压缩

    除了`uglifyjs-webpack-plugin`,还有一些其他插件也可以用来压缩JS代码,
例如`terser-webpack-plugin`和`babel-minify-webpack-plugin`等。
这些插件也可以通过类似的方式进行安装和配置。你可以根据自己的需求选择合适的插件。

这三个插件都是用于压缩JS代码的Webpack插件,但它们在实现方式和功能上有一些区别。
  1. uglifyjs-webpack-plugin

    • 使用UglifyJS对JS代码进行压缩和混淆。
    • 已经是一个相对老的插件,配置和使用相对简单。
    • 在Webpack 5及更高版本中,不再推荐使用uglifyjs-webpack-plugin,而是推荐使用terser-webpack-plugin
  2. babel-minify-webpack-plugin

    • 使用Babel和Babili对JS代码进行压缩和混淆。

    • Babili是由Babel团队开发的一个专门用于压缩JS代码的工具。

    • 在Webpack 4及更早版本中,可以使用babel-minify-webpack-plugin。但是在Webpack 5中,Babel团队已经停止了对此插件的维护和支持,推荐使用terser-webpack-plugin

    要在Vue项目中使用uglifyjs-webpack-plugin插件,需要进行以下步骤:

    1. 安装插件:在项目根目录下,使用npm或yarn命令安装uglifyjs-webpack-plugin插件:

    npm install uglifyjs-webpack-plugin --save-dev

    1. 配置插件:在vue.config.js文件中添加以下配置来启用uglifyjs-webpack-plugin插件: const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

    module.exports = { // ... configureWebpack: { plugins: [ new UglifyJsPlugin() ] } } 这样配置后,当你运行npm run build命令进行打包时, uglifyjs-webpack-plugin插件将自动对JS代码进行压缩和混淆。

综上所述,对于最新的Webpack版本,推荐使用terser-webpack-plugin来压缩JS代码。

八 打包去除console.log用什么插件

  1. terser-webpack-plugin:使用terser-webpack-plugin插件来代替uglifyjs-webpack-plugin,可以通过设置terserOptions中的compress选项的drop_consoletrue来去除console.log语句。示例配置如下:
const TerserPlugin = require('terser-webpack-plugin');
    module.exports = {
      // ...
      optimization: {
        minimizer: [
          new TerserPlugin({
            terserOptions: {
              compress: {
                drop_console: true,
              },
            },
          }),
        ],
      },
    };
  1. uglifyjs-webpack-plugin:使用uglifyjs-webpack-plugin插件配合uglifyjs压缩工具,可以通过设置uglifyOptions中的drop_console选项为true来去除console.log语句。示例配置如下:
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
  // ...
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        uglifyOptions: {
          compress: {
            drop_console: true,
          },
        },
      }),
    ],
  },
};

九 vue3 双向数据绑定原理

Vue 3中,双向数据绑定的原理与Vue 2有所不同。Vue 3中使用了Proxy对象来实现双向数据绑定。

Proxy对象是一种能够拦截并定制JavaScript操作的机制,它可以对目标对象进行拦截,并在拦截时执行自定义的操作。Vue 3利用Proxy对象来拦截数据对象,并在数据变化时更新相关的DOM。

当你在Vue 3中创建一个响应式对象时,Vue会使用Proxy包装这个对象。使用Proxy对象包装后,可以在访问和修改对象属性时进行拦截,从而实现双向绑定。

具体实现步骤如下:

1.  Vue会使用`reactive`函数将普通对象转换为响应式对象。`reactive`函数使用了Proxy对象来拦截对象的访问和修改操作。
1.  当你访问响应式对象的属性时,Proxy对象会触发`get`拦截器。在这个拦截器中,Vue会将属性与当前组件建立关联,并将该属性添加到依赖列表中。
1.  当你修改响应式对象的属性时,Proxy对象会触发`set`拦截器。在这个拦截器中,Vue会更新该属性的值,并通知相关的组件进行更新。
1.  当某个组件依赖的响应式对象发生变化时,Vue会通知该组件进行重新渲染。

需要注意的是,Vue 3中的双向数据绑定是通过Proxy对象的拦截功能实现的,而不是通过Object.defineProperty。这种改变带来了性能的提升,因为Proxy对象能够拦截更多类型的操作,并且在拦截时执行自定义操作。

十 vue3 proxy

Vue 3中,Proxy对象是用来代理目标对象的一个包装器。它可以拦截并定制JavaScript操作,
给开发者提供了对目标对象的访问、修改和删除的控制能力。

Vue 3使用Proxy对象来实现响应式系统,即实现双向数据绑定的核心机制。
当你创建一个响应式对象时,Vue会使用Proxy对象来包装这个对象,实现对对象属性的拦截。

Proxy对象的基本用法如下:const proxy = new Proxy(target, handler);
-   `target`:需要代理的目标对象,可以是任意JavaScript对象。
-   `handler`:一个包含各种拦截操作的处理程序对象。
处理程序对象中定义了一组拦截器(例如`get``set``deleteProperty`等),用来拦截对目标对象的操作。

对于Vue 3来说,它会使用Proxy对象的`get``set`拦截器来实现双向数据绑定。
当你访问响应式对象的属性时,会触发`get`拦截器,从而进行依赖收集;
当你修改响应式对象的属性时,会触发`set`拦截器,从而触发更新操作。

通过Proxy对象,Vue 3能够更准确地追踪对象属性的访问和修改,以及自动触发相关的更新操作,
实现了高效且精确的双向数据绑定。

十一 webpack用过哪些loader ?

 `babel-loader`:用于将ES6+的JavaScript代码转换为向后兼容的JavaScript代码,以便在旧版浏览器中运行。
 `css-loader`:用于加载处理CSS文件,使之能够在JavaScript代码中引入。
 `style-loader`:将CSS代码注入到HTML文档中的`<style>`标签中。
 `file-loader`:用于加载处理文件,例如图片、字体等,并返回文件的URL`url-loader`:类似于`file-loader`,但可以根据文件大小将文件转换为DataURL`sass-loader`:用于将Sass/SCSS样式文件转换为CSS`less-loader`:用于将Less样式文件转换为CSS`vue-loader`:用于解析和转换Vue单文件组件。
`ts-loader`:用于将TypeScript代码转换为JavaScript`eslint-loader`:用于在构建过程中运行ESLint进行代码检查。

首先,确保已经安装了`babel-loader``@babel/core`这两个依赖包。

接下来,在webpack配置文件中添加以下代码:
module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.js$/, // 匹配.js文件
        exclude: /node_modules/, // 排除node_modules目录
        use: {
          loader: 'babel-loader', // 使用babel-loader
          options: {
            presets: ['@babel/preset-env'] // 使用@babel/preset-env预设
          }
        }
      }
    ]
  }
  // ...
};
在这个示例中,我们使用了`test`选项来匹配文件的扩展名,`exclude`选项来排除不需要使用babel-loader处理的文件。然后,我们使用`use`选项指定了要使用的loader,即`babel-loader`,并传递了一些配置选项。

在`options`选项中,我们使用了`@babel/preset-env`来指定转换规则,这是一个常用的预设,用于将ES6+的JavaScript代码转换为向后兼容的JavaScript代码。

根据具体的项目需求,还可以添加其他的Babel插件和预设,以满足不同的转换需求。

十一 各种loader配置

以下配置可以同时处理JavaScript文件、CSS文件、Sass/SCSS文件、图片文件和字体文件,根据文件类型使用不同的loader进行处理。

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.js$/, // 匹配.js文件
        exclude: /node_modules/, // 排除node_modules文件夹
        use: ['babel-loader'] // 使用babel-loader
      },
      {
        test: /\.css$/, // 匹配.css文件
        use: ['style-loader', 'css-loader'] // 使用style-loader和css-loader
      },
      {
        test: /\.scss$/, // 匹配.scss文件
        use: ['style-loader', 'css-loader', 'sass-loader'] // 使用style-loader、css-loader和sass-loader
      },
      {
        test: /\.(png|jpg|gif|svg)$/, // 匹配图片文件
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192, // 图片小于8KB时转换为base64编码
              name: '[name].[ext]', // 输出文件名字和扩展名不变
              outputPath: 'images/' // 输出到images文件夹
            }
          }
        ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/, // 匹配字体文件
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]', // 输出文件名字和扩展名不变
              outputPath: 'fonts/' // 输出到fonts文件夹
            }
          }
        ]
      }
    ]
  }
  // ...
};

十二 要使用Webpack搭建一个前端框架,可以按照以下步骤进行:

1.  初始化项目:在项目文件夹中运行以下命令初始化一个新的npm项目。
npm init -y
2.  安装Webpack及相关插件:运行以下命令安装Webpack及其常用插件。
npm install 
webpack webpack-cli webpack-dev-server 
html-webpack-plugin clean-webpack-plugin --save-dev
3.  创建Webpack配置文件:在项目根目录下创建一个名为`webpack.config.js`的文件,并添加以下内容。
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      },
      // 添加其他需要的loader规则
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      filename: 'index.html'
    }),
    new CleanWebpackPlugin()
  ],
  devServer: {
    contentBase: './dist',
    port: 8080
  }
};
在上面的配置中,我们设置了入口文件为`src/index.js`,输出文件为`dist/bundle.js`。我们还添加了一些loader规则和插件,如Babel转译JavaScript、处理HTML文件等。

4.  创建必要的文件和文件夹:在项目根目录下创建一个名为`src`的文件夹,并在其中创建一个名为`index.js``index.html`的文件。
5.  编写代码:在`src/index.js`中编写你的前端代码。
6.  运行开发服务器:在项目文件夹中运行以下命令以启动开发服务器。
npx webpack serve
7.  打包项目:在项目文件夹中运行以下命令以打包项目。
npx webpack
以上步骤为使用Webpack搭建一个简单的前端框架提供了一个基本的指南。具体配置和使用方法可以根据项目需求进行调整和扩展。

十三 webpack 常用插件

Webpack有很多常用的插件,以下是一些常见的插件:

 HtmlWebpackPlugin:用于生成HTML文件,并将打包后的文件自动注入到HTML中。
 CleanWebpackPlugin:在每次构建之前清理output目录。
 MiniCssExtractPlugin:将CSS文件从打包的JavaScript文件中抽离出来,生成单独的CSS文件。
 OptimizeCSSAssetsPlugin:优化CSS文件,例如压缩和去除注释。
 UglifyJsPlugin:压缩JavaScript代码,减小文件体积。
 CopyWebpackPlugin:将文件从源目录复制到输出目录。
 DefinePlugin:在构建过程中定义全局常量。
 ProvidePlugin:在所有模块中注入某个模块,使其在应用中可直接使用。
 HotModuleReplacementPlugin:启用热模块替换,允许在运行时更新模块,而无需完全刷新页面。
 BundleAnalyzerPlugin:分析打包后的文件大小和依赖关系,帮助优化性能。

这只是一些常见的Webpack插件,还有很多其他插件可根据具体需求选择使用。可以通过在项目的`webpack.config.js`中的`plugins`选项中配置这些插件。

十四 webpack的工作流程

1.所有的文件从入口文件出发,根据入口文件的依赖关系,找到所有的模块, 2. 调用各种loader进行处理,常处理的文件类型有 img,js json css 字体,或其他的 3.如果处理不了的就调用babel进行语法兼容转换,babel-loader core(IE浏览器无法兼容[es6]) preset(预设置), es6转es5,像里面的promise,Generator map,这些都转换成es5语法 4. 在这个过程中还有一些像html模板,压缩或其他的一些东西,功能性的, 可能需要调用plugin插件,htmlwebpackplugin 5. 根据出口的路径编译打包多个chunk,如果把css 或者 js这些模块都摘出去了, 需要单个打包,就打包了多个chunk,最后统一生成一个列表输出到bundle中,这就是打包的工作原理。 6. 工程化,就是一种思想,让项目按照标准化,模块化,自动化方式进行编码, 这就是工程化,现在用的最好的就是美团,vue+anguage+西瓜ui+electronic

十五 生命周期

Webpack的生命周期分为三个阶段:初始化阶段,编译阶段和输出阶段。

  1. 初始化阶段:

    • beforeRun:在开始构建之前触发。
    • run:开始构建时触发。
    • watchRun:在使用webpack --watch进行持续构建时触发。
  2. 编译阶段:

    • normalModuleFactory:解析和创建模块之前触发。
    • contextModuleFactory:创建上下文模块之前触发。
    • beforeCompile:在开始编译之前触发。
    • compile:创建新的编译实例时触发。
    • thisCompilation:在每次新的编译开始之前触发。
    • compilation:创建新的编译实例时触发。
    • make:在编译构建过程中触发。
    • afterCompile:编译完成之后触发。
  3. 输出阶段:

    • emit:在将输出资源写入磁盘之前触发。
    • afterEmit:在将输出资源写入磁盘之后触发。
    • done:构建完成时触发。
    • failed:构建失败时触发。

在每个阶段,Webpack都提供了一些钩子函数,开发者可以注册自定义的插件来扩展Webpack的功能。这些插件可以在对应的钩子函数中执行自定义逻辑,例如处理特定的文件、优化打包结果、生成统计信息等。

十六 0.5px像素会不会生效,如何实现0.5像素

.element { transform: scale(0.5, 0.5); /* 将元素水平和垂直方向上缩小为原始大小的一半 */ }

十七 原生js发请求的步骤,如何知道请求是否完成

请求基本流程:创建XHR实例对象 => 发送数据 => 接收数据

请求基本流程:创建 new XMLHttpRequest()实例对象 => 
调用xhr对象上的 open() 方法,创建一个请求=> 
第一个参数(必填): 请求类型(主要两个POST,GET)
第二个参数(必填): 请求的URL地址
第三个参数(默认true): 是否异步发送请求(true:异步请求;false:同步请求)
根据项目需求,加上请求头
// 设置content-Type,后端传给前端为JSON格式数据
xmlHttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
// 这个是用来解决跨域
xmlHttp.setRequestHeader("Access-Control-Allow-Origin", "*");
最后就是发送请求啦
// get请求中send()方法里面的参数传值为null
xmlHttp.send(null)
// post请求中send()方法里面的参数传值为json格式
xmlHttp.send("{"test":123}")

请求发送出去后,客户端需要接收服务器响应回来的数据
readyState里面状态码含义
0: 还未创建请求,即未调用 open() 方法
1: 已调用 open() 方法,但未发送 send() 方法
2: 已调用 send() 方法,但未接收到响应
3: 已接收到部分响应
4: 已接收到全部的响应
如果readyState === 4 且 status === 200 就是成功,两个可以分开判断,先判断readyState在进行status判断

十八 vue生命周期

1. 主要是从组件的创建到销毁的过程,系统4个阶段分别是:
   创建 beforeCreate, created
   挂载 beforeMount, mounted
   更新 beforeUpdate, updated
   销毁 beforeDestroy,destroyed
   
   beforeCreate:初始化实例,进行数据观测,可以加loading事件
   
        created:完成数据初始化 data\methods\watch,里面的方法和数据可以访问,
                 可以进行异步请求和结束loading事件
                 DOM没有挂载,如果需要修改就放在Nexttick回调函数里
                 
    beforeMount:完成DOM阶段初始化,但并没有挂载到el选项上
    
        mounted:完成DOM挂载渲染,可以在这里操作DOM,双向数据绑定
                 发送请求,请求数据(created也可以发送请求,请求数据,
                 但是没有dom,所以一般不会再create发送请求)
                 
   beforeUpdate:可以访问dom,删除一些数据监听器,更新数据必须是被渲染在模板上的(el template render之一),此时view还没有更新
                 若在beforeUpdate中再次修改数据,不会再触发更新方法
                 
         update:数据更新后,完成view的重新渲染,
                 不再在这里继续修改数据,否则会在此触发更新方法(beforeUpdate/update)
                 
   beforeDestroy: 实例销毁前,删除一些提示操作
   
         destroy: 销毁后,实例被删除,监听 组件 子组件 不能操作任何东西

  1.1 为什么要在created中获取数据,而不是在mounted中去获取?
    因为前端都是 先是获取到数据再到页面渲染,而不是数据页面又请求数据,
    如果在这里获取一次数据会造成重绘回流,性能不太好。在mounted主要是用来获取dom的,
    比如点击了某个按钮跳转到某个导航栏目,就先获取到偏移量数据再去跳转。
    
2. 一旦进入组件或进入页面 会执行 前4个生命周期
    beforeCreate, created
    beforeMount, mounted
    
3. 如果使用了keep-alive 缓存组件,会多出两个生命周期
    activated  deactivated
    
4. 如果使用keep-alive 第一次进入组件会执行5个生命周期
    beforeCreate, created
    beforeMount, mounted
    activated
    
5. 如果使用keep-alive 第二次或第N次进入组件,每次都会执行一个生命周期,
     activated
 
6. 生命周期原理:mvvm


vue3使用生命周期需要单独从vue中引用,并且只能在setup函数内调用
Vue3 的生命周期比较多。
setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method
onBeforeMount() : 组件挂载到节点上之前执行的函数。
onMounted() : 组件挂载完成后执行的函数。
onBeforeUpdate(): 组件更新之前执行的函数。
onUpdated(): 组件更新完成之后执行的函数。
onBeforeUnmount(): 组件卸载之前执行的函数。
onUnmounted(): 组件卸载完成后执行的函数。
onActivated(): 被包含在中的组件,会多出两个生命周期钩子函数。被激活时执行。
onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行。
onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数(以后用到再讲,不好展
现)。


Vue2--------------vue3
beforeCreate  -> setup()
created       -> setup()
beforeMount   -> onBeforeMount
mounted       -> onMounted
beforeUpdate  -> onBeforeUpdate
updated       -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed     -> onUnmounted
activated     -> onActivated
deactivated   -> onDeactivated
errorCaptured -> onErrorCaptured

十九 微前端的工作原理

微前端是一种将前端应用程序拆分成更小、更易于维护和开发的独立部分的架构风格。它的工作原理可以概括如下:

拆分应用:将单体应用程序拆分为多个小型的独立应用,每个应用负责处理特定的功能模块或页面。

独立开发和部署:每个独立应用可以由不同的团队开发和维护,并且可以单独部署。这样可以提高开发效率和降低部署复杂性。

应用集成:将这些独立应用集成到一个整体中,以提供统一的用户体验。这可以通过以下几种方式实现:

基座应用:创建一个基座应用,作为主要的容器,负责加载和渲染各个独立应用,并提供公共的布局和导航等功能。

前端路由:使用前端路由将不同的独立应用程序连接起来,实现不同应用之间的页面切换和跳转。

跨域通信:不同的独立应用可能存在跨域问题。可以使用诸如iframe、postMessage等技术来实现应用之间的通信。

共享状态:为了实现应用之间的数据共享,可以使用共享状态管理工具(例如Redux、Mobx等)或通过消息总线等方式来进行数据传递和同步。

通信与协作:不同的独立应用可能需要进行通信和协作。可以使用事件总线、发布-订阅模式等方式实现应用之间的解耦和交互。

通过以上的工作原理,微前端可以实现应用的解耦、独立开发和部署,提高团队的协作效率和应用的可扩展性。同时,它也可以帮助组织更好地管理和维护复杂的前端应用。

二十 mixin和组件定义相同的属性名和方法,会有什么问题

当在 Vue 中使用 mixin 和组件定义相同的属性名和方法时,会出现以下问题:

命名冲突:如果 mixin 和组件定义相同的属性名或方法名,可能会导致命名冲突。当组件使用 mixin 时,
属性或方法的定义会被 mixin 中的定义覆盖,可能会导致组件中原本的逻辑出现问题或失效。

重复调用:如果 mixin 和组件都定义了同名的生命周期钩子函数,那么这个生命周期钩子函数会被重复调用。
例如,如果 mixin 和组件都定义了 created 钩子函数,那么 created 钩子函数会被调用两次,从而可能导致意外的行为。

代码维护困难:如果 mixin 和组件都定义相同的属性名和方法名,那么在代码维护和调试时会变得困难。
例如,当出现 bug 时,需要确认是 mixin 中的定义还是组件中的定义出现了问题,增加了代码的复杂性和难以维护性。

为避免以上问题,建议在使用 mixin 时,确保 mixin 中的属性名和方法名与组件中的定义不冲突。
可以通过给 mixin 中的属性和方法添加特定的前缀或命名空间,或者使用不同的命名约定来避免冲突。另外,在组件中可以通过 $options 对象来判断属性或方法是否属于 mixin,以避免重复调用。



1. 什么是混入
		
    封装了可复用功能
    混入本身可以包含组件中script标签的任意内容:data、生命周期、methods、computed...
		
		注意:当前组件有data:{a:1} ,在混入中可以直接使用this.a ,相当于组件和混入的js文件是混在一起的
  
2. 混入使用场景:你在什么地方用过混入,为什么用混入
		
		小程序全局开启分享功能,那么分享功能是生命周期 而 混入可以使用生命周期,那么直接弄一个全局混入就可以了

3. 混入的方式
		
		全局混入==》main.js
		局部混入==》某一个.vue中
	
4. 混入缺点

	不好维护:因为混入进来的值,当前组件查找不到来源

5. 全局混入和Vue.prototype.xxx区别

	Vue.prototype.xxx  ==》 Vue这个构造函数的原型中添加的方法
	全局混入            ==》 直接给这个构造函数添加的方法

6. 混入和普通工具类区别
	
	普通的数据类:是没有组件的data、methods、生命周期...,混入是有的

二十:垂直水平居中的方法

算法题:

console.log(1);
let a = setTimeout(() => {console.log(2)}, 0);
console.log(3);
Promise.resolve(4).then(b => {
console.log(b);
clearTimeout(a);
});
console.log(5);

输出顺序:1 3 5 4

排序法
function thirdMax(nums) {
  nums.sort((a, b) => b - a);
  return nums[2] !== undefined ? nums[2] : nums[0];
}

集合法
function thirdMax(nums) {
  const set = new Set(nums);
  const sortedNums = Array.from(set).sort((a, b) => b - a);
  return sortedNums[2] !== undefined ? sortedNums[2] : sortedNums[0];
}

function thirdMax(nums) {
  let max1 = -Infinity;
  let max2 = -Infinity;
  let max3 = -Infinity;

  for (let num of nums) {
    if (num > max1) {
      max3 = max2;
      max2 = max1;
      max1 = num;
    } else if (num < max1 && num > max2) {
      max3 = max2;
      max2 = num;
    } else if (num < max2 && num > max3) {
      max3 = num;
    }
  }

  return max3 !== -Infinity ? max3 : max1;
}

// 示例用法
console.log(thirdMax([3, 2, 1])); // 输出 1
console.log(thirdMax([1, 2])); // 输出 2
console.log(thirdMax([2, 2, 3, 1])); // 输出 1


封装 loading 

在vue全局install了方法==>$loading

在Vue3中的setup写法是没有this的,所以要获取全局vue的某一个方法,需要在组件中:
	
import { getCurrentInstance } from 'vue';
let app = getCurrentInstance();
app.appContext.config.globalProperties.$loading;

在全局install中,的方法,导入.vue文件,创建在body中,那么这样就可以在某个组件中直接使用了。