2023年高频前端面试项目考点(npm,git,webpack,TS4,sass,瀑布流,懒加载)

这篇具有很好参考价值的文章主要介绍了2023年高频前端面试项目考点(npm,git,webpack,TS4,sass,瀑布流,懒加载)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

合集:2023年最全前端面试题考点HTML5+CSS3+JS+Vue3+React18+八股文+手写+项目+笔试_参宿7的博客-CSDN博客

*表示回顾基础知识

项目为二面三面,面试官基本就是照着简历里面的项目技术点切入然后深入展开。

为了简洁,相关文章参考链接在标题里

目录

模块化规范

require与import的区别和使用

js的运行环境

浏览器

Node

特点

js包管理器

npm(Node Package Manager )

yarn(实际开发 包管理)

优势

用法区别

npx(Node Package Runner)单独执行包

nvm(Node Version Runner)版本切换

项目规范

命令(创建运行)

项目文件结构

package.json

package-lock.json

node_modules

git代码管理

常用命令

分支

git多人协同merge冲突

暂时保存更改

性能优化

webpack打包管理

原理

Babel

loader

plugin

loader和plugin的区别

热加载原理

TS4 加分项

类型

never,any,unknown

类型断言as与非空断言!

函数类型和void

泛型

应用

变量

 *类型注解

数组

函数

类型判断

is

Narrowing down sets

样式

Ant Design

Css、less、Sass (SCSS)

Sass

瀑布流

css

js

共性

问项目中有哪些难点,怎么解决的

代码遇到冲突怎么办

业务系统的搭建过程

复盘过程

拆分组件

如何实现自适应页面

*个性

介绍

实现功能

后端接口

登陆注册

*0.0.0.0,localhost,127.0.0.1

0.0.0.0

localhost

127.0.0.1

分页

弹窗组件modal

如何实现点击弹窗外面区域,弹窗消失

相关技术


模块化规范

一个模块是实现一个特定功能一组方法

  1. 由于函数具有独立作用域的特点,最原始的写法是使用函数来作为模块,几个函数作为一个模块,但是这种方式容易造成全局变量的污染,并且模块间没有联系
// 模块A
var ModuleA = {
  func1: function() {
    // ...
  },
  func2: function() {
    // ...
  }
};

// 模块B
var ModuleB = {
  func3: function() {
    // ...
  }
};

​​​​​​​

  1. 后面提出了对象,通过将函数作为一个对象的方法来实现,但是这种办法会暴露所 有的所有的模块成员,外部代码可以修改内部属性的值
  2. 现在最常用的是立即执行函数的写法,通过利用闭包来实现模块私有作用域的建立,同时不会对全局作用域造成污染
//IIFE(立即调用函数表达式)
//创建一个私有作用域,避免变量之间的冲突。然后,通过返回一个对象或函数来暴露模块的公共部分
// 模块A
var ModuleA = (function() {
  var privateVar = "private";

  function privateFunc() {
    // ...
  }

  return {
    publicVar: "public",
    publicFunc: function() {
      // ...
    }
  };
})();
  • ES6 :使用 import 和 export 的形式来导入导出模块。
  • CommonJS : require 来引入模块,通过 module.exports 定义模块的输出接口。

这种模块加载方案是服务器端的解决方案,它是以同步的方式来引入模块的,因为在服务端文件都存储在本地磁盘,所以读取非常快,所以以同步的方式加载没有问题。

但如果是在浏览器端,由于模块的加载是使用网络请求,因此使用异步加载的方式更加合适。

  • AMD :Asynchronous Module Definition,这种方案采用异步加载的方式来加载模块,模块的加载不影响后面语句的执行,所有依赖这个模块的语句都定义在一个回调函数里,等到加载完成后再执行回调函数require.js 实现了 AMD 规范。
  •  CMD :Common Module Definition,这种方案和 AMD 方案都是为了解决异步模块加载的问题,sea.js 实现了 CMD 规范。

AMD是预加载,CMD是懒加载。

AMD是提前执行,CMD是延迟执行。AMD在对应的加载之前导入,CMD在用的时候导入

​​​​​​​require与import的区别和使用

require/import

// CommonJS 的写法
const moduleA = require('moduleA');
const func1 = moduleA.func1;
const func2 = moduleA.func2;
// ES6 的写法
import { func1, func2 } from 'moduleA';

module.exports/export

// commonJS 的写法
var React = require('react');
var Breadcrumbs = React.createClass({
  render() {
    return <nav />;
  }
});
module.exports = Breadcrumbs;

// ES6 的写法
import React from 'react';
class Breadcrumbs extends React.Component {
  render() {
    return <nav />;
  }
};
export default Breadcrumbs;
  1. 规范:require是CommonJS,AMD规范的模块化语法,import是ECMAScript 6规范的模块化语法,如果要兼容浏览器的话必须转化成es5的语法;CommonJS模块默认export的是一个对象,即使导出的是基础数据类型
  2. 本质:require是赋值过程,其实require 的结果就是对象、数字、字符串、函数等,再把require的结果赋值给某个变量,引入复杂数据类型时,数据浅拷贝该对象。。import是解构过程。
  3. 加载:require是运行时加载,import是编译时加载;
  4. 位置:require可以写在代码的任意位置,import只能写在文件的最顶端且不可在条件语句或函数作用域中使用;
  5. 改变:require通过module.exports导出的不能再变,import通过export导出的值可以改变;
     

js的运行环境

脚本语言需要一个解析器才能运行,每一种解析器都是一个运行环境

JavaScript是脚本语言,在不同的位置有不一样的解析器,

浏览器

写入html的js语言,浏览器是它的解析器角色。

浏览器中的js的用途是操作DOM,浏览器就提供了document之类的内置对象。

Node

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,独立于浏览器的运行环境

nodejs中的js的用途是操作磁盘文件或搭建http服务器,nodejs就相应提供了fs,http等内置对象。

2023年高频前端面试项目考点(npm,git,webpack,TS4,sass,瀑布流,懒加载)

特点

  • 简单:javascript,json进行编码,
  • 强大:非阻塞IO,可以适应分块传输数据,较慢的网络环境,尤其擅长高并发访问
  • 轻量:node本身既是代码,又是服务器前后端使用统一语言;
  • 可扩展体:轻松应对多实例多服务器架构,同时有海量的第三方应用组件

js包管理器

npm(Node Package Manager )

是nodeJS的一个程序包管理和分发的管理工具,npm完全用 JavaScript 写成

允许用户从NPM服务器下载安装上传

安装
npm 使用 node 写的,同时也是 node 的包管理工具,

当安装了 node 就自动安装了npm,

只是 npm 版本更新比 node 快,更新 npm 指令用:

yarn(实际开发 包管理)

yarn由Facebook为解决npm的一些问题而创建的

优势

快速

  • 本地缓存+并行下载 - Yarn并行下载,还可以直接从硬盘缓存中读取包,因此可以显著提高速度。npm串行下载
  • 网络连接问题处理 - 当Yarn发现任何网络连接问题时,它会自动重试请求,保存响应并继续构建 - 这使得它更容易处理比npm更可靠且快速的环境。

稳定

  • 确定性安装 - Yarn能够在包含区别式锁文件(yarn.lock)的情况下进行精确的依赖项安装,每次运行生成相同的代码版本,与开发者上次运行相同。npm也有类似的功能,但是许多开发人员选择使用Yarn锁定其依赖关系以消除任何可能的不确定性。
  • 强制命令 - 通过添加--force标志,Yarn可以强制执行某些操作。这可能看起来像是一种强制手段,但它实际上是保证操作按期望进行的一种方法。npm也有许多命令选项,但是Yarn的操作强迫执行机制通常要好得多。

用法区别

  • 安装包
    • Yarn: yarn add
    • npm: npm install
  • 移除包
    • Yarn: yarn remove
    • npm: npm uninstall
  • 更新
    • Yarn: yarn upgrade
    • npm: npm update
npm install -g yarn

npx(Node Package Runner)单独执行包

npm install -g npx

nvm(Node Version Runner)版本切换

配置 .bash_profile 文件

  • 通过命令 touch .bash_profile ,创建文件夹 .bash_profile;

  • 通过命令 open .bash_profile,打开 .bash_profile 文件夹,把下面的内容复制进去;

  • 保存并关闭文件,然后输入 source .bash_profile 执行后重新启动终端,输入 nvm -v。检查是否可以正常显示版本号。

  • 坑1:安装 nvm 不需要单独安装 nodejs,如果装过了一定要卸载,否则报错;

  • 坑2:装完 nvm 手动配置.bash_profile 文件,网上教程不适用,不用 cd .nvm 才会成功

项目规范

整个项目不再使用class组件,统一使用函数式组件,并且全面用Hooks;

所有的函数式组件,为了避免不必要的渲染,全部使用memo进行包裹;

组件内部的状态,使用useState、业务数据全部放在redux中管理;

函数组件内部逻辑代码基本按照如下顺序编写代码:

组件内部state管理;

redux的hooks代码;

其他hooks相关代码(比如自定义hooks);

其他逻辑代码;

返回JSX代码;

redux代码规范如下:

redux目前我们学习了两种模式, 根据自己的情况选择普通模式还是rtk模式

每个模块有自己独立的reducer或者slice,之后合并在一起;

redux中会存在共享的状态、从服务器获取到的数据状态;

网络请求采用axios

对axios进行二次封装;

所有的模块请求会放到一个请求文件中单独管理;

项目使用AntDesign或者MUI(Material UI)

其他规范在项目中根据实际情况决定和编写

命令(创建运行)

npm run start 来运行启动项目并打开页面
npx create-react-app my-app //创建项目
cd my-app
npm start

安装命令:

npx create-react-app 项目名称 --template typescript     
 

项目文件结构

主要开发代码在src目录下。App.js为组件,index.js为入口模块,index.css为全局样式文件。

2023年高频前端面试项目考点(npm,git,webpack,TS4,sass,瀑布流,懒加载)

package.json

配置jsconfig.json:这个文件在Vue通过脚手架创建项目时自动生成, React是没有自动生成

package.json相当于说明书,其重点字段:

{
  "name": "react-ts-app",
  "version": "0.1.0",
  "private": true,//是否私有,设置为 true 时,npm 拒绝发布
  "dependencies": {//生产环境下,项目运行所需依赖
    "@ant-design/icons": "^4.8.0",
     ...
    "@types/node": "^16.18.6",
    "@types/react": "^18.0.26",
    "@types/react-dom": "^18.0.9",
    "antd": "^5.0.4",
    "axios": "^1.2.1",
    "classnames": "^2.3.2",
    "lodash": "^4.17.21",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-redux": "^8.0.5",
    "react-router-dom": "^6.4.4",
    "react-scripts": "5.0.1",
    "redux": "^4.2.0",
    "redux-persist": "^6.0.0",
    "sass": "^1.56.1",
    "typescript": "^4.9.3",
    "web-vitals": "^2.1.4"
  },
  "scripts": {//执行npm脚本命令简写,比如“start" : "react-scripts start",执行npm start就是运行“react-scripts start"
    "start": "SET PORT=8080 && react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
....
  "devDependencies": {//开发环境下,项目所需依赖
    "@types/lodash": "^4.14.191"
  }
}

package-lock.json

用一句话来概括很简单,就是锁定安装时的包的版本号,并且需要上传到git,以保证其他人在npm install时大家的依赖能保证一致。

node_modules

2023年高频前端面试项目考点(npm,git,webpack,TS4,sass,瀑布流,懒加载)

是安装node后用来存放用包管理工具下载安装的的文件夹。比如webpack、gulp、grunt这些工具。

git代码管理

常用命令

git init 初始化git仓库

git status 查看文件状态

git add 文件列表 追踪文件

git commit -m 提交信息 向仓库中提交代码

git log 查看提交记录

分支

1.分支明细

(1)主分支(master):第一次向 git 仓库中提交更新记录时自动产生的一个分支。

(2)开发分支(develop):作为开发的分支,基于 master 分支创建。

(3)功能分支(feature):作为开发具体功能的分支,基于开发分支创建

2.分支命令

(1)git branch 查看分支

(2)git branch 分支名称 创建分支

(3)git checkout 分支名称 切换分支

(4)git merge 来源分支 合并分支 (备注:必须在master分支上才能合并develop分支)

(5)git branch -d 分支名称 删除分支(分支被合并后才允许删除)(-D 强制删除)

git多人协同merge冲突

是当前修改是左箭头方向,传入的是右箭头的方向,

中间用等于号分割,等号上边是当前修改(本地),下边是传入的修改(线上的代码)。

两人同时提交可能会出现冲突,解决办法是手动修改冲突

暂时保存更改

存储临时改动:git stash(藏匿)

恢复改动:git stash pop

  • 应用场景:

对于多人并行开发,维护同一仓库工作场景,经常会出现文件合并冲突的情况

  • 作用:

能够将所有未提交的修改(工作区和暂存区)保存至堆栈中,用于后续恢复当前工作目录。

git add

只是把文件加到 git 版本控制

性能优化

压缩js,css,js分包,优化图片(webp),开启gzip(后端开启),配置缓存(强制缓存协商缓存),使用cdn,
webpack分包,减少重绘回流

webpack打包管理

它将根据模块的依赖关系进行静态分析,然后将这些模块( js、css、less )按照指定的规则生成对应的静态资源减少了页面的请求。Webpack是以公共JS的形式来书写脚本的,方便旧项目进行代码迁移

2023年高频前端面试项目考点(npm,git,webpack,TS4,sass,瀑布流,懒加载)

原理

Webpack通过一个给定的主文件(如:index.js)开始找到项目的所有依赖文件,

使用loaders处理它们,plugin可以压缩代码和图片

把所有依赖打包成一个 或多个bundle.js文件(捆bundle)浏览器可识别的JavaScript文件。

Babel

JavaScript 编译器

将es6、es7、es8等语法转换成浏览器可识别的es5或es3语法,即浏览器兼容的语法,比如将箭头函数转换为普通函数

将jsx转换成浏览器认的js

loader

webpack只认识JS和JSON,所以Loader相当于翻译官,将其他类型资源进行预处理,最终变为js代码。

  • less-loader:将less文件编译成css文件(开发中,会使用less预处理器编写css样式,使开发效率提高)
  • css-loader:将css文件变成commonjs模块(模块化的规范)加载到js中,模块内容是样式字符串
  • style-loader:创建style标签,将js中的样式资源插入标签内,并将标签添加到head中生效
  • ts-loader:打包编译Typescript文件

plugin

Plugin解决loader 无法实现的事情,比如打包优化代码压缩等。

  • html-webpack-plugin 处理html资源,默认会创建一个的HTML,自动引入打包输出的所有资源(js/css)
  • mini-css-extract-plugin 打包过后的css在js文件里,该插件可以把css单独抽出来
  • clean-webpack-plugin 每次打包时候,CleanWebpackPlugin 插件就会自动把上一次打的包删除

loader和plugin的区别

2023年高频前端面试项目考点(npm,git,webpack,TS4,sass,瀑布流,懒加载)

运行时机
1.loader运行在编译阶段
2.plugins 在整个周期都起作用

热加载原理

浏览器热更新:开发时能够在浏览器页面实时看到我们代码的变化产生效果的流程。

热加载是通过内置的 HotModuleReplacementPlugin 实现的

2023年高频前端面试项目考点(npm,git,webpack,TS4,sass,瀑布流,懒加载)

  1. 构建 bundle 的时候,监听文件变化。
  2. 文件修改会触发 webpack 重新构建
  3. 服务器通过向浏览器发送更新消息
  4. 浏览器通过 jsonp 拉取更新的模块文件,
  5. jsonp 回调触发模块热替换逻辑

TS4 加分项

类型

never,any,unknown

never类型表示永不存在的值的类型,当一个值不存在的时候就会被自动类型推断成never类型。

出问题的时候会被自动转成never。

any类型表示任意类型,而unknown类型表示为未知类型,是any类型对应的安全类型。

类型断言as与非空断言!

当 TypeScript 推断出来类型并不满足需求,需要手动指定一个类型,强制说明类型,让TS编译不报错

let a: unknown = 'hello';
a = 123;
(a as []).map(()=>{})    // success

因为b可能是字符串也可能是undefined,所以b.length的时候就会报错,这样我们可以采用非空断言来告诉TS,这个b肯定不是undefined,所以b只能是字符串,那么b.length就不会报错了。

let b: string|undefined = undefined;
b!.length   // success

函数类型和void

function foo(n: number, m?: string): number{
   return 123;
}
foo(123, 'hello');
foo(123);     // success

当函数没有returnreturn undefined的时候返回void类型。

let foo = function(){   // void
}let foo = function(): undefined{   // undefined 不能不写return的
}  // error

泛型

泛型是指在定义函数、接口、类时,未指定其参数类型,只有在运行时传入才能确定。泛型简单来说就是对类型进行传参处理。

应用

变量

 *类型注解

类型注解:把变量空间与类型空间结合在一起

type关键字+类型别名

let a: string = 'hello'

//也可以通过类型别名进行连接
type A = string
let a: A = 'hello'

数组

let arr: Array<number> = [1, 2, 3];
//自定义MyArray实现
type MyArray<T> = T[];
let arr2: MyArray<number> = [1, 2, 3];

函数

function foo(n: number, m?: string): number{
   return 123;
}
foo(123, 'hello');
foo(123);     // success

function foo<T>(n: T){
}
foo<string>('hello');
foo(123);   // 泛型会自动类型推断

class Foo {
  //第一种写法
  //username: string = 'xiaoming';
  //第二种写法
  // username: string;
  // constructor(){
  //   this.username = 'xiaoming';
  // }
  //第三种写法
  username: string;
  constructor(username: string){
    this.username = username;
  }
}

interface A {
  username: string
  age: number
  showName(n: string): string
}

class Foo implements A {
  username: string = 'xiaoming'
  age: number = 20
  gender: string = 'male'  
  showName = (n: string): string => {
    return n
  }
}

class Foo {
  ...
  showAge = (n: number): number => {
    return n;
  }
}

class Foo<T> {
  username!: T;  //不给初始值可通过非空断言
}
let f = new Foo<string>();
f.username = 'hello';

class Foo<T> {
  username!: T
}
class Baz extends Foo<string> {}
let f = new Baz()
f.username = 'hello'

类型判断

is

is 让 ts 分辨类型

function toUpperCase(x: unknown) {
  if(isString(x)) {
    x.toUpperCase(); // ⚡️ x is still of type unknown
  }
}
  • 但是由于这个检验函数(isString)被包裹在 toUpperCase()函数中,ts 在判断的时候还是抛出了错误提示

  • 使用 is ,这里让我们主动明确的告诉 ts ,在 isString() 这个函数的参数是一个 string。

// !!! 使用 is 来确认参数 s 是一个 string 类型
function isString(s): s is string {
  return typeof s === 'string';
}

Narrowing down sets

function pipsAreValid(pips: number) {
  // we check for every discrete value, as number can 
  // be something between 1 and 2 as well.
  return pips === 1 || pips === 2 || pips === 3 ||
    pips === 4 || pips === 5 || pips === 6;
}

function evalThrow(count: number) {
  if (pipsAreValid(count)) {
    // my types are lying 😢
    switch (count) {
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
        console.log('Not today');
        break;
      case 6:
        console.log('Won!');
        break;
      case 7:
        // TypeScript does not complain here, even though
        // it's impossible for count to be 7
        console.log('This does not work!');
        break;
    }
  }
}

count 是一个 number 类型,输入的参数是没有问题的。

在我们校验它的时候,count不再是一个 number 类型,而是变成了一个 1-6 number 的特殊类型。

ts 为了防止类型溢出,使用了联合类型把原来 number 类型变成 1-6的数字(缩小了范围)

改变处
// 主动使用联合类型确保我们的输入是 1-6的数字
type Dice = 1 | 2 | 3 | 4 | 5 | 6;

function pipsAreValid(pips: number): pips is Dice {
改变处
  return pips === 1 || pips === 2 || pips === 3 ||
    pips === 4 || pips === 5 || pips === 6;
}

function evalThrow(count: number) {
  if (pipsAreValid(count)) {
    // count is now of type Dice 😎
    switch (count) {
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
        console.log('Not today');
        break;
      case 6:
        console.log('Won!');
        break;
      case 7:
        // TypeScript errors here. 7 is not in the union type of 
        // Dice
        console.log('This does not work!');
        break;
    }
  }
}

样式

Ant Design

Css、less、Sass (SCSS)

less, sass, scss都是css预处理语言(也是对应的文件后缀名)。

CSS 预处理器为 CSS 增加一些编程的特性,无需考虑浏览器的兼容性问题,

可以在 CSS 中使用变量、简单的逻辑程序、函数(如变量$main-color)等等在编程语言中的一些基本特性,可以让 CSS 更加简洁、适应性更强、可读性更佳,更易于代码的维护等诸多好处。

开发时用预处理语言,在打包上线时,用webpack再配合loader工具给转成css给浏览器使用。

Sass

瀑布流

描述:页面元素的宽度按照屏幕分辨率进行适配调整,但整体布局不变。主要特征是像瀑布一样往下流,有规律的无限遍历模块。(阿里、字节考过)

2023年高频前端面试项目考点(npm,git,webpack,TS4,sass,瀑布流,懒加载)

css

给图片添加样式让图片等宽并同行显示。

1、首先我们定义一个container容器来装所有图片,在这个容器中用box容器装box-img容器再装入每张图片,这样方便之后样式的编写。

2、使图片同行显示--给box容器使用float:left;属性

3、让图片等宽显示--给box-img容器设置width:150px;,img标签设置width:100%;继承父容器box-img高度的100%

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>waterFall</title>
    <script src="./index.js"></script>
</head>
<style>
<!--清除浏览器自带样式-->
    *{
        margin: 0;
        padding: 0;
    }
<!--overflow: hidden触发BFC-->
    .container {
        overflow: hidden;
        position: relative;
    }
<!--float: left同行显示-->
    .box{
        float: left;
        padding: 5px;
    }
<!--图片等宽-->
    .box-img{
        width: 150px;

        padding: 5px;
        border: 1px solid #484848;
        box-shadow: 0 0 5px #484848;
    }
<!--图片占满父容器-->
    .box-img img{
        width: 100%;
    }
</style>
<body>
    <div id="container">
        <div class="box">
            <div class="box-img">
                <img src="./img/1.jpg" alt="">
           </div>
        </div>
        /*.......后面接39个box,此处省略*/
    </div>
    
</body>
</html>

js

1、首先用window.οnlοad=function(){}来实现页面加载完毕后立即执行的功能

调用imgLocation('container','box')函数来呈现最终效果,

传入的实参是父容器'container',装图片的子容器'box'。

window.onload=function() {
    imgLocation('container','box')
}

2、实现imgLocation()函数功能

1)首先我们得 获取所有要摆放的图片,并将其存入一个数组

function imgLocation(parent,content){
    //得到父容器
    var cparent=document.getElementById(parent)
    //cparent下的所有的第一层的子容器 box
    var ccontent=getChildElement(cparent,content)//数组,40个div
}

//取到父容器中的某一层子容器
function getChildElement(parent,content){
    var contentArr=[]
    var allContent=parent.getElementsByTagName('*')//通过标签来选中得到一个数组
    //遍历allContent把其中类名为content的容器都存到contentArr数组中
    for(var i=0;i<allContent.length;i++){
        if(allContent[i].className==content){    //当前这个容器的类名是否为content
            contentArr.push(allContent[i])
        }
    }
    return contentArr;

}

2)得到这个数组后,找出从谁开始是需要被摆放位置的

首先获取视窗的宽度每张图片的宽度

将两者相除向下取整可得到第一行可以放置图片的数量,

自然也就知道了我们需要操作的那张图片的序号

    //从谁开始是需要被摆放位置的
    var winWidth=document.documentElement.clientWidth;//视窗宽度
    var imgWidth=ccontent[0].offsetWidth;//图片宽度

    var num=Math.floor(winWidth/imgWidth)//第一行能放几张图

3)得到需要被摆放位置的图片序号后,确定其摆放位置

定义一个存储高度的数组,对前一行元素的高度进行遍历存入数组,

当遍历到需要被摆放位置的图片时,

Math.min()方法获取前一行高度最矮的元素高度,并用indexOf()方法获取到其下标

再对我们所操作的这个图片容器的样式调整
position:absolute;绝对定位

top值设置为前一行高度最矮的图片高度minHeight

left值设置为单张图片宽度这张图片的下标minIndex

最后,摆放好图片后,还要更新摆放的那一列的高度

    //操作num+1张图
    var BoxHeightArr=[]
    for(var i=0;i<ccontent.length;i++){
        //前num张只要计算高度
        if(i<num){
            BoxHeightArr[i]=ccontent[i].offsetHeight
        }
        else{
            //我们要操作的box  :ccontent[i]
            var minHeight=Math.min.apply(null,BoxHeightArr)//apply:把最小值这个方法借给它用
            var minIndex=BoxHeightArr.indexOf(minHeight)//返回数组下标
            ccontent[i].style.position='absolute'//style设置样式
            ccontent[i].style.top=minHeight+'px'
            ccontent[i].style.left=imgWidth*minIndex+'px'

            //更新最矮的那一列的高度
            BoxHeightArr[minIndex]+=ccontent[i].offsetHeight
        }
    }

共性

问项目中有哪些难点,怎么解决的

代码遇到冲突怎么办

业务系统的搭建过程

复盘过程

拆分组件

复用和业务逻辑拆分

如何实现自适应页面

说到媒体查询和多个样式表
React如何实现动画的(数字不断变大的动画)

最后是用库实现的

*个性

介绍

打卡考勤项目

实现功能

后端接口

  1. Navicat创建数据库和空表
  2. 加载MySQL等模块
  3. 创建MySQL连接池(设置服务器地址host,服务器端口号port) 和 服务器对象server
  • 3306是MySQL的默认端口
  • 默认的服务端口就是8080
  • 跨源资源共享CORS
  • Origin字段用来说名本次请求来自哪个源,服务器根据这个值,决定是否同意这次请求。

    如果Origin指定的源不在允许范围之内,服务器就会返回一个正常的HTTP回应,然后浏览器发现头信息中没有包含Access-Control-Allow-Origin 字段,就知道出错啦,然后抛出错误

// 加载Express模块
const express = require('express');
 
// 加载MySQL模块
const mysql = require('mysql');

...

// 创建MySQL连接池
const pool = mysql.createPool({
  host: '127.0.0.1', //MySQL服务器地址
  port: 3306, //MySQL服务器端口号

  user: 'root', //数据库用户的用户名
  password: '', //数据库用户密码
  database: 'reg_log', //数据库名称
  connectionLimit: 20, //最大连接数
  charset: 'utf8' //数据库服务器的编码方式
});
 
// 创建服务器对象
const server = express();

// 加载CORS模块
const cors = require('cors');

// 使用CORS中间件
server.use(cors({
  origin: ['http://localhost:8080', 'http://127.0.0.1:8080']
}));

登陆注册

*0.0.0.0,localhost,127.0.0.1

网络需求 数据传输 访问 性质
localhost 不联网 不使用网卡,不受防火墙和网卡限制 本机访问 域名,默认是指向 127.0.0.1
127.0.0.1 不联网 网卡传输,受防火墙和网卡限制 本机访问 环回地址
本机IP 联网 网卡传输 ,受防火墙和网卡限制 本机or外部访问 本机对外放开访问的 IP 地址

0.0.0.0

  • 服务器中:0.0.0.0表示本机上的任意ip地址
  • 路由中:0.0.0.0表示的是默认路由,即当路由表中没有找到完全匹配的路由的时候所对应的路由。表示”任意IPV4主机”。
  • 当一台主机还没有被分配一个IP地址的时候,用于表示主机本身

localhost

localhost是个域名而不是一个ip地址。可修改。

用于指代 this computer 或者 this host,可以用它来获取运行在本机上的网络服务

在大多数系统中,localhost被指向了 IPV4 的 127.0.0.1 和 IPV6 的 ::1,这就是把localhost与127.0.0.1等同的原因。

127.0.0.1

本机地址,主要用于测试

(127.x.x.x)是本机回送地址(Loopback Address),即主机IP堆栈内部的IP地址,主要用于网络软件测试以及本地机进程间通信,无论什么程序,一旦使用回送地址发送数据,协议软件立即返回,不进行任何网络传输。

示例都使用端口3000作为HTTP服务器的默认监听端口。

3000 是整数。 0 ~ 1023 (常用端口)49152 ~ 65535 号端口是动态端口


//用户注册接口
server.post('/register', (req, res) => {
  //console.log(md5('12345678'));
  // 获取用户名和密码信息
  let username = req.body.username;
  let password = req.body.password;
  
  //以username为条件进行查找操作,以保证用户名的唯一性
  let sql = 'SELECT COUNT(id) AS count FROM reg_log WHERE username=?';
  pool.query(sql, [username], (error, results) => {
    if (error) throw error;
    let count = results[0].count;
    if (count == 0) {
      // 将用户的相关信息插入到数据表
      sql = 'INSERT reg_log(username,password) VALUES(?,MD5(?))';

      pool.query(sql, [username, password], (error, results) => {
        if (error) throw error;
        res.send({
          message: 'ok',
          code: 200
        });
      })
    } else {
      res.send({
        message: 'user exists',
        code: 201
      });
    }
  });
});
 
// 用户登录接口
server.post('/login', (req, res) => {
  //获取用户名和密码信息
  let username = req.body.username;
  let password = req.body.password;
   // SQL语句
  let sql = 'SELECT id,username FROM reg_log WHERE username=? AND password=MD5(?)';
  pool.query(sql, [username, password], (error, results) => {
    if (error) throw error;
    if (results.length == 0) { //登录失败
      res.send({
        message: 'login failed',
        code: 201
      });
    } else { //登录成功
      res.send({
        message: 'ok',
        code: 200,
        result: results[0]
      });
    }
  });
 
// 指定服务器对象监听的端口号
server.listen(3000, () => {
  console.log('server is running...');
})

注册页,使用token,能避免CSRF攻击Cross-site request forgery。JSON Web Token(JWT)

​//注册
checkForm() {
      // 点击注册按钮后调用此方法,验证用户名、密码、二次密码是否均正确,正确则发送axios请求
      if (this.checkName() && this.checkPwd() && this.checkrePwd()) {
        console.log(`验证成功,执行注册业务......`);
        // 发送注册(post)请求
        this.axios
          .post("/register", `username=${this.name}&password=${this.pwd}`)
          .then((result) => {
            console.log(result);
            if (result.data.code == 200) {
              // 弹窗提示注册成功
               ...
              // 注册成功后直接跳转到登录页
              this.$router.push("/login");
            } else if (result.data.code == 201) {
              ...
            }
          });
      }
//登陆
 checkForm() {
      // 点击登录按钮后调用此方法,同时验证用户名和密码
      if (this.checkName() && this.checkPwd()) {
        // 发送登录(post)请求
        this.axios
          .post("/login", `username=${this.name}&password=${this.pwd}`)
          .then((result) => {
            console.log(result);
            if (result.data.code == 200) {
              // 弹窗提示登录成功
              this.$toast({
                message: `欢迎您 ${this.name}`,
                position: "bottom",
                duration: 3000,
              });
             ...
            } else {
              this.$toast({
                message: "登录失败,请检查您的用户名和密码",
                position: "bottom",
                duration: 3000,
              });
            }
          });
      }

分页

currentPage(当前页码)、total(总条数)、pageSize(每页展示的数据量)
所有的数据请求回后,通过arr.slice(开始索引,结束索引)来进行截取每一页的数据;

假设当前页是currentPage = 1,pageSize = 5,那么应该从(currentPage-1)*pageSize开始截取,到currentPage*pageSize结束

弹窗组件modal

.modal {
    display: none; /* 默认隐藏 */
    position: fixed; /* 固定定位 */
    z-index: 1; /* 设置在顶层 */
    ...
    overflow: auto; 
}
// 点击按钮打开弹窗
btn.onclick = function() {
    modal.style.display = "block";
}

如何实现点击弹窗外面区域,弹窗消失

事件委托,往上遍历target的父元素如果有弹窗的id就不做反应,如果没有就触发消失

相关技术

主要目的是为了巩固基础知识,和适应大型项目的需求文章来源地址https://www.toymoban.com/news/detail-425586.html

  • 框架,选择了React,说说其不同....,Router,Redux基本使用
  • 保持TS限定类型的习惯,减少报错,说下区别和原因及其常用,
  • 使用懒加载,组件库按需加载,优化性能,
  • 使用ant-design做ui,学会利用API,省去设计样式的时间,实现样式和行为分离
  • webpack打包

到了这里,关于2023年高频前端面试项目考点(npm,git,webpack,TS4,sass,瀑布流,懒加载)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AJAX入门到实战,学习前端框架前必会的(ajax+node.js+webpack+git)(五)—— 项目-新闻头条-数据管理平台-ajax综合案例前端

    愿许秋风知我意,解我心中意难平。 推荐使用, 每个程序员都有自己的管理方式。 HTML结构: 1.为什么要提取公共前缀地址(基地址),因为公司业务可能会更换服务器,如果你不想一条一条地修改请求地址的话。 后续使用axios时,url不需要再写前缀。 2.请求成功与失败 成

    2024年01月25日
    浏览(52)
  • ChatGPT给出的前端面试考点(html+css+JS)

    HTML HTML是什么,它的主要作用是什么? 什么是DOCTYPE,为什么在HTML文档中使用它? HTML5相对于之前的HTML版本有哪些主要的新特性? 解释语义化HTML的概念。为什么要使用语义化标签? 如何在HTML中嵌入JavaScript和CSS? 什么是表单,如何在HTML中创建一个表单? 什么是响应式图片

    2024年01月21日
    浏览(62)
  • 【前端笔记】前端包管理工具和构建打包工具介绍之npm、yarn、webpack、vite

    NPM(Node Package Manager)是node包管理器,是node.js默认采用的软件包管理系统,使用JavaScript语言编写。包管理可以理解为依赖管理,有一个npm包管理仓库,当我们执行npm命令的时候,就可以直接从npm仓库中下载对应的依赖包,类似于后端开发中的POM。 node.js中就已经安装了NPM,所

    2024年02月02日
    浏览(43)
  • 【前端工程化面试题】使用 webpack 来优化前端性能/ webpack的功能

    这个题目实际上就是来回答 webpack 是干啥的,你对webpack的理解,都是一个问题。 (1)对 webpack 的理解 webpack 为啥提出 + webpack 是啥 + webpack 的主要功能 前端开发通常是基于模块化的,为了提高开发效率,webpack 是一个基于模块的构建工具,是一个用于 js 应用程序的静态模块

    2024年02月20日
    浏览(58)
  • 前端面试题-webpack

    1.webpack是什么? 模块打包工具,用于将前端资源,如JavaScript、css、图片等打包成可以在浏览器运行的静态资源。可以将多个模块打包成一个或多个bundle。 主要功能: 模块化:可以将多个模块打包成一个或多个bundle,方便管理维护。 自动化:可以自动处理和编译JavaScript等文

    2024年01月17日
    浏览(38)
  • 前端Webpack面试题

    备注:本文是总结他人资料,供面试背诵使用 ​ 开发时,我们会使用框架 (React、Vue) ,ES6 模块化语法,Less/Sass 等 CSS 预处理器等语法进行开发,这样的代码要想在浏览器运行必须经过编译成浏览器能识别的 JS、CSS语法才能运行。所以我们需要打包工具帮我们做完这些事。除

    2024年02月13日
    浏览(34)
  • 2023年高级系统架构设计师 如何备考?

    高级架构有一定的难度,但是值得挑战一下 新版《系统架构设计师考试大纲》出版了! 可以去官网看看 系统架构设计师是软考的高级科目之一,系统架构设计师一年只有一次考试机会,是在下半年11月份考试 考试科目分为 :综合题(选择题)、案例分析题、论文题 其中综

    2024年02月07日
    浏览(54)
  • 前端面试的话术集锦第 7 篇:高频考点(浏览器渲染原理 & 安全防范)

    这是记录 前端面试的话术集锦第七篇博文——高频考点(浏览器渲染原理 安全防范) ,我会不断更新该博文。❗❗❗ 注意:该章节都是⼀个⾯试题。 1.1.1 浏览器接收到HTML⽂件并转换为DOM树 当我们打开⼀个⽹⻚时,浏览器都会去请求对应的 HTML ⽂件。虽然平时我们写代码时

    2024年02月03日
    浏览(58)
  • 2023年高性价比笔记本电脑选购推荐

    用免费公开视频,卷飞培训班哈人!打死不报班,赚钱靠狠干!只要自己有电脑,前后项目都能搞!N年苦学无人问,一朝成名天下知! 毕竟钱是你自己的,没有人会购买自己不喜欢的产品。还有就是任何人都不会是永远的真理。只写给那些真心需要学习的人。对于大部分的

    2024年02月12日
    浏览(66)
  • 前端面试的话术集锦第 5 篇:高频考点( 类型转换 & 深浅拷贝 & 模块化机制等)

    这是记录 前端面试的话术集锦第五篇博文——高频考点(类型转换 深浅拷贝 模块化机制等) ,我会不断更新该博文。❗❗❗ typeof 对于原始类型来说,除了 null 都可以显示正确的类型:

    2024年02月09日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包