前端复习2

358 阅读15分钟

ES6

let和const的区别

相同:let跟const都没有变量提升,所以都存在暂时性死区问题(即在代码块内未定义变量之前使用变量会报错)。都不允许在相同作用域中重复声明一个变量。

区别:let可以先定义再初始化,const一旦定义就要初始化(本质上是指const指向的内存地址不可改动,例如const定义一个对象,表示栈中指针指向的堆中的地址不变,对象依然可以改变属性)

git

Git 基本命令

  • git init:在目录中创建新的 Git 仓库
  • git clone:拷贝一个 Git 仓库到本地,让自己能够查看该项目,或者进行修改
  • git add:将该文件添加到缓存
  • git status:用于查看项目的当前状态
  • git diff:查看执行 git status 的结果的详细信息
  • git commit-m:将缓存区内容添加到仓库中,提交注释
  • git reset HEAD:用于取消已缓存的内容
  • git rm: git rm -f:如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 git rm --cached:把文件从暂存区域移除,仍希望保留在当前工作目录中,仅从跟踪清单中删除
  • git mv:用于移动或重命名一个文件、目录、软连接
  • git branch:创建分支/列出分支
  • git checkout:切换分支
  • git merge:合并分支
  • git checkout -b:创建新分支并立即切换到该分支下,从而在该分支中操作
  • git branch -d:删除分支

框架

vue和react 的异同

运行时的性能

  • 在 React 应用中,当某个组件的状态发生变化时,它会以该组件为根,重新渲染整个组件子树。使用 PureComponent 和 shouldComponentUpdate 可以避免不必要的子组件的重渲染,需要保证该组件的整个子树的渲染输出都是由该组件的 props 所决定的。
  • 在 Vue 应用中,组件的依赖是在渲染过程中自动追踪的,所以系统能精确知晓哪个组件确实需要被重渲染。

组件方面

  • 什么是模块化:是从代码的角度进行分析的;把一些可复用的代码,抽离为单独的模块,便于项目的维护和开发;
  • 什么是组件化:是从UI界面的角度进行分析的;把一些可复用的UI元素,抽离成单独的组件;便于项目的维护和开发;
  • 组件化的好处:随着项目规模的增大,手里的组件越来越多,可以很方便的把现有组件凭借成一个完整的页面;
  • vue是如何实现组件化的:通过.vue文件,来创建对应的组件;① template结构;②script行为;③style样式;
  • React是如何实现组件化的: React有组件化概念,但是没有像vue那样的模板文件;在React中一切都是以JS来表现的;因此ES6和ES7(async和await)要会用,jsx语法;

状态管理

  • React状态管理redux: 把组件中的数据放到 Store 中,通过组件修改了 Store 中的数据,其他组件也会感知到数据的变化,从而做出更新,
  • vue状态管理vuex
    Vue 的路由库和状态管理库都是由官方维护支持且与核心库同步更新的。React 则是选择把这些问题交给社区维护,因此创建了一个更分散的生态系统。但相对的,React 的生态系统相比 Vue 更加繁荣。

改变数据方式

  • Vue 修改状态相比来说要简单许多,
  • React 需要使用 setState来改变状态,并且使用这个 API 也有一些坑点

前端路由

前端路由:本质就是监听 URL的变化,然后匹配路由规则,显示相应的页面,并且无须刷新页面。
后端路由,每次跳转到不同的URL,都要重新访问服务器。

SPA中前端路由跳转的两种实现方式:

  1. 修改 url 中 Hash
  2. 利用 H5 中的 history,HTML5提出了 pushState() 方法和 replaceState() 方法,这两个方法可以用来向历史栈中添加数据,模拟浏览历史和前进后退。 react中 this.props.history.push('路由地址')实现了编程式导航

两种模式对比

  • Hash 模式只可以更改 # 后面的内容,History 模式可以通过 API 设置任意的同源 URL
  • History 模式可以通过 API 添加任意类型的数据到历史记录中,Hash 模式只能更改哈希值,也就是字符串
  • Hash 模式无需后端配置,并且兼容性好。History 模式在用户手动输入地址或者刷新页面的时候会发起 URL 请求,后端需要配置 index.html 页面用于匹配不到静态资源的时候

mvc与mvvm

MVC 是后端的分层开发概念
MVVM是前端视图层的概念,主要关注于视图层分离,也就是说:MVVM把前端的视图层,分为了 三部分 Model, View , VM ViewModel
Model 层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;
View 代表UI 组件,它负责将数据模型转化成UI 展现出来,
ViewModel 是一个同步View 和 Model的对象
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉

React

React的工作原理

通过创建虚拟DOM,当组件中的状态改变时,通过diff算法找旧VDOM与新的VDOM的最小差异,然后再把差异渲染出来

DOM/虚拟DOM的本质

DOM的本质:用JS对象表示页面上的元素并提供操作DOM对象的API; 虚拟DOM本质:程序员用JS对象模拟页面上的DOM元素和DOM嵌套关系;

diff算法

  1. tree diff 对树的分层比较,只对同一层级的节点进行比较,跨层级移动,直接销毁子树,在目的节点完全插入子树,这样只需对树进行一次遍历,便能完成整个DOM树的比较
  2. component diff 同一类型组件,按照tree diff进行同级比较,并且增加了shouldComponentUpdate钩子来判断组件虚拟DOM是否发生变化,无变化,不比较,从而节省diff时间
    不同类型组件,将组件标记为dirtycomponent,从而替换整个组件下的所有子节点
  3. element diff 对于同一层级的element,通过唯一id,可以优化其新增,修改,删除操作

为什么要有虚拟DOM

  • DOM 引擎、JS 引擎 相互独立,但又工作在同一线程(主线程) JS 代码调用 DOM API 必须挂起 JS 引擎、转换传入参数数据、激活 DOM 引擎,DOM 重绘后再转换可能有的返回值,最后激活 JS 引擎并继续执行。若有频繁的 DOM API 调用,且浏览器厂商不做“批量处理”优化, 引擎间切换的单位代价将迅速积累。若其中有强制重绘的 DOM API 调用,重新计算布局、重绘会引起更大的性能消耗
  • JS操作DOM是非常复杂,JS操作DOM越多,控制与页面的耦合度就越高,代码越难以维护

react特点

  1. 声明式设计
  2. 高效:通过对DOM的模拟,最大限度的减少与DOM的交互。
  3. 灵活:可以与已知的框架或库很好的配合。
  4. JSX:是js语法的扩展,不一定使用,但建议用。
  5. 组件:构建组件,使代码更容易得到复用,能够很好地应用在大项目的开发中。
  6. 单向响应的数据流:React实现了单向响应的数据流,从而减少了重复代码,这也是解释了它为什么比传统数据绑定更简单。

父子组件之间如何通信

父传子(组件嵌套浅):父组件定义一个属性,子组件通过this.props接收。

子传父:父组件定义一个属性,并将一个回调函数赋值给定义的属性,然后子组件进行调用传过来的函数,并将参数传进去,在父组件的回调函数中即可获得子组件传过来的值。

一些常用的生命周期函数

当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:

  • constructor():初始化组件的私有数据
  • static getDerivedStateFromProps():props变化时被调用,但是若是父组件重新渲染,也会被调用。它返回新的props值。
  • render()
  • componentDidMount()

组件更新的生命周期调用顺序如下:

  • static getDerivedStateFromProps():从props中获取state,意味着即使你的props没有任何变化,而是父state发生了变化,导致子组件发生了re-render,这个生命周期函数依然会被调用
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate():典型场景:获取render之前的dom状态
  • componentDidUpdate()

当组件从 DOM 中移除时会调用如下方法:

  • componentWillUnmount()

当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法:

  • static getDerivedStateFromError()
  • componentDidCatch()

高阶组件之间的逻辑复用

高阶组件适用于对多个不同的组件但是具有相同的逻辑处理(比如在一些生命周期函数中都挂载了一个更改监听器,侦听器都进行相同的操作,卸载时都删除监听器),这时候我们就可以使用高阶组件对组件的相同的逻辑进行复用。
高阶组件是一个函数组件,传进去的一个逻辑可以被复用的组件,称为被包装组件。返回一个新组件,称为容器组件。 将一些可以单独抽离的逻辑处理给写在容器组件里面。然后将被包装组件,传递给容器组件。被包装组件接收来自容器组件的所有 prop,同时也接收一个新的用于 render 的 data prop(data = this.setState.data)。

Hooks

动机:React 组件之间复用状态逻辑很难,虽然高阶组件可以实现。但是这类方案需要重新组织你的组件结构。Hook 使你在无需修改组件结构的情况下复用状态逻辑

Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数
Hook原理
hook的状态管理使用数组和指针,把钩子函数对数据的操作按顺序写入到数组中。但是在React 中是通过类似单链表的形式来代替数组的。通过 next 按顺序串联所有的 hook
举例hooks:
useState: 通过在函数组件里调用它来给组件添加一些内部 state
useEffect:用于在渲染结束之后执行某些操作(例如组件加载和更新后执行同样的操作。这是无需清除的副作用)。有些副作用可能需要清除,所以需要返回一个函数。useEffect 会在每次渲染后都执行。
useContext():共享状态钩子
hooks使用规则

  1. 只在最顶层调用,不能在循环、条件语句中使用,确保Hook在每一次渲染中都按照同样的顺序被调用。
  2. 只在react函数中调用hook

Vue

模块化

CommonJs/ES6/AMD模块的用法以及区别

  • RequireJS:是一个AMD框架,可以异步加载JS文件,按照模块加载方法,通过define()函数定义,第一个参数是一个数组,里面定义一些需要依赖的包,第二个参数是一个回调函数,通过变量来引用模块里面的方法,最后通过return来输出。 是一个依赖前置、异步定义的AMD框架(在参数里面引入js文件),在定义的同时如果需要用到别的模块,在最前面定义好即在参数数组里面进行引入,在回调里面加载

  • CMD:通过define()定义,没有依赖前置,通过require加载jQuery插件,CMD是依赖就近,在什么地方使用到插件就在什么地方require该插件,即用即返,这是一个同步的概念

  • commonJS的模块规范在Node中发扬光大,总的来说,它的特性有这几个:
    1.动态加载模块
    commonJS和es6的最大区别大概就在于此了吧,commonJS模块的动态加载能够很轻松的实现懒加载,优化用户体验。
    2.加载整个模块
    3.每个模块皆为对象
    4.值拷贝

  • es6 模块
    1.静态解析 即在解析阶段就确定输出的模块,所以es6模块的import一般写在被引入文件的开头。
    2.模块不是对象 在es6里,每个模块并不会当做一个对象看待
    3.加载的不是整个模块 在es6模块中经常会看见一个模块中有好几个export 导出
    4.模块的引用 es6模块中,导出的并不是模块的值拷贝,而是这个模块的引用 www.cnblogs.com/chinabin199…

webpack

treeshaking 原理

Tree-shaking是指在打包中去除那些引入了,但是在代码中没有被用到的那些死代码。
1、前提是使用 ES6的import 和 export在编译时完成模块加载。
2、webpack 4 正式版本扩展了未使用模块检测能力,通过 package.json 的 "sideEffects" 属性向 compiler 提供提示,表明项目中的哪些文件是 "pure(纯的 ES2015 模块)",由此,通过将mode选项设置为production,也可以利用uglifySPlugin插件,安全地删除文件中未使用的部分。

webpack打包原理

递归地构建一个模块之间依赖关系图(dependency graph),然后将所有这些模块打包成一个或多个 bundle。
打包过程可以拆分为四步:
1、利用babel完成代码转换,并生成单个文件的依赖图谱 (转为Ast->遍历Ast->调用ImportDeclaration通过import引入的模块)
2、从入口开始递归分析,并生成项目的依赖图谱
3、将各个引用模块打包为一个立即执行函数,立即执行函数的参数是modules。modules是一个对象, 这个对象的 key 为引用模块的地址, value 是引用的模块的函数代码
立即执行函数返回__webpack_require__ 函数 ,把 modules 里面的的 key 传递给 __webpack_require__函数
再看 __webpack_require__函数,webpack_require 实际返回的就是modules对象中的 value 对应的函数,并且调用了入口文件里面的函数,

(function(modules) {
    var installedModules = {}
    function __webpack_require__(moduleIid) {

    }
    return __webpack_require__(__webpack_require__.s = "./src/index.js")
})({
    "./src/index.js": (function(module, exports) {
                            eval("console.log('test webpack entry')");
                    })
})

4、将最终的bundle文件写入bundle.js中
blog.csdn.net/weixin_4452…
segmentfault.com/a/119000000…

为什么要用webpack打包

  • (1)为什么打包
    前端产品的交付是基于浏览器,这些资源是通过增量加载的方式运行到浏览器端,打包是在开发环境组织好这些碎片化的代码和资源,并且保证他们在浏览器端快速、优雅的加载和更新

  • (2) 为啥用webpack
    ① 模块化开发(import,require),避免了作用域问题,
    ② 预处理(Less,Sass,ES6,TypeScript……),loader 可以使你在 import 或"加载"模块时预处理文件
    ③ 主流框架脚手架支持(Vue,React,Angular)
    ④ 庞大的社区(资源丰富,降低学习成本 juejin.cn/post/684490…

webpack优化

体积:按需加载,tree-shaking
速度:

  • 优化loader,减小loader的搜索范围。
  • HappyPack 插件可以将 Loader 的同步执行转换为并行的
  • resolve.alias 可以通过别名的方式来映射一个路径,能让 Webpack 更快找到路径

模块热更新原理

runtime:webpack 用来连接模块化应用程序所需的加载和解析逻辑的代码。 manifest :指模块的详细要点,作用:管理所有所需模块之间的交互 runtime 会通过 manifest 来找到对应的模块解析和加载。 无论你选择哪种 模块语法, import 或 require 语句都会转换为__webpack_require__ 方法,此方法指传入的是moduleId。通过使用 manifest 中的数据,runtime 将能够检索这些标识符,找出每个标识符背后对应的模块。 热更新原理 webpack在编译的时候会加一小段HMR runtime的代码进bundle里面,这一段代码运行在你的APP中。当编译结束后Webpack不会退出而是监听源代码的变化,如果检测到了源代码变化,Webpack会重新编译发生变化的模块(不会全部重新编译)。

loader

用来预处理非JS文件 babel-loader 用babel来转换ES6文件到ES5
style-loader 将css添加到DOM的内联样式标签style里
css-loader 允许将css文件通过require的方式引入,并返回css代码
less-loader 处理less
sass-loader 处理sass
file-loader 分发文件到output目录并返回相对路径
url-loader 和file-loader类似,但是当文件小于设定的limit时可以返回一个Data Url
html-minify-loader 压缩HTML

plugin

插件以各种方式自定义 webpack 构建过程。插件接口功能极其强大。
html-webpack-plugin 简单创建 HTML 文件,用于服务器访问
clean-webpack-plugin
ModuleConcatenationPlugin内置在生产模式中,实现预编译功能。 webpack内置UglifyJs-webpack-Plugin 压缩优化js文件
webpack内置模块热更新插件HotModuleReplacementPlugin。 webpack-dev-server是webpack官方提供的一个小型Express服务器实现模块热更新 CommonsChunkPlugin 提取 chunks 之间共享的通用模块
DefinePlugin 创建允许在编译时配置的全局常量
extract-text-webpack-plugin 将js文件中引用的样式单独抽离成css文件