前端框架相关的前置知识点

#2024/08/10 #前端/前端框架

目录

1. 何为前端框架

  • umi 算是框架,内置了路由、构建、流水线部署等
  • Angular 是框架
  • Next.js :基于 React 的,支持 SSR、SSG的服务端框架

2. 前端库与前端框架的区别?

  • 框架:React(虽然有时被称为库,但因其生态系统更像框架)、Angular 、Vue.js
  • 库:
    • 提供特定功能的工具集,比如 jQuery、Lodash、Moment.js

严格说,React 和 Vue 都不算是框架,而算是

3. 现代前端框架的实现原理

现代前端框架的核心实现原理是通过组件化、虚拟DOM和响应式系统等,实现高效的声明式UI渲染和状态管理

  • 其实就是围绕 UI = f(state) 展开的
    • UI 依赖与宿主环境的渲染引擎
    • f 是框架本身的运行机制
    • state 当前视图的动态
  • 至于组件化、VDom、响应式等都是手段和一些关键模块

4. 现代前端框架的核心模块组成有哪些?

  1. 组件化
    • 前端框架通常以组件为基础构建应用程序。组件是封装了 UI 和逻辑的独立单元,可以重复使用
  2. 虚拟 DOM
    • 虚拟 DOM 是内存中的一个轻量级表示,用于优化实际 DOM 操作。
  3. 响应式系统
    • 现代框架提供自动化的响应式数据绑定,确保当应用状态变化时,UI 会自动更新。
    • 实现:
      • Vue:使用 Proxy 和 Object.defineProperty 来检测数据变更。
      • React:通过状态(state)管理系统更新,通常结合 setState 或 hooks
  4. 单向数据流
    • 通过单向数据流来管理组件之间的数据传递,以确保应用的数据流动方向明确,易于跟踪和调试。
    • 实现:通常采用状态管理库(如 Redux、Vuex),管理全局应用状态,并通过严格的操作步骤来更新状态。
  5. 模板和声明式渲染
    • 使用模板来描述 UI,提供声明式的视图定义。
    • 实现:模板语法被编译为渲染函数,将数据映射到 UI 组件。
  6. 路由管理
    • 实现单页应用(SPA)的视图切换,方便在不同页面之间导航。
    • 实现:框架提供路由功能(如 React Router、Vue Router),匹配路径并渲染相应组件。
  7. 生命周期管理
    • 提供钩子函数,允许开发者在组件特定的生命周期阶段执行代码。
    • 实现:通过生命周期方法(React 的 componentDidMount、useEffect,Vue 的 created、mounted 等)来获取个性化控制。
  8. 性能优化
    • 现代框架通过多种技术优化性能,如懒加载、代码分割等。
    • 实现:框架提供内置的工具和约定,以减少初始加载时间和优化更新性能。
  9. 跨平台渲染: -支持服务器端渲染(SSR)、静态站点生成(SSG)、以及与移动和桌面平台(如 React Native)集成。 -实现在:抽象出渲染层,并提供多平台兼容的实现
  10. 事件处理
    • 管理和优化事件绑定
    • 实现: 事件委托,统一管理事件监听

5. 如何描述 UI

5.1. 方式一:声明式描述 UI - 模板

主流其实都是模板来描述,无论是 jsx 或者模板引擎都是模板

  • JSX 也是一种特殊的模板,兼顾以下两个特性
    • 强逻辑表达
    • UI 描述丰富性
  • 模板,即声明式描述 UI
    • 代表
      • HTML
      • php smarty
      • jsp 等等
      • ejs
    • 主要问题是逻辑表达性弱了些

举例:声明式描述 UI

  • 比如 <div class='btn' id='test' @click="handle"> button </div>, 包含信息 tag名,属性,事件,层级关系

5.2. 方式二:JavaScript 对象

使用 JavaScript对象 来描述 UI,如下代码

const title = {
    tag: 'h1', // tag 名称
    props:{
	    // 属性与事件
	    onClick:handler
	}
	children:[
      // 子节点
      {tag: 'span'}
  ]
}

5.2.1. V-DOM

虚拟 DOM 描述 UI,比如 vue 中的 渲染函数 - h ,如下代码:

import {h} from "vue";
export default{
    render(){
    
        // 虚拟 DOM
        return h('h1',{ onClick: fn }); 
        
        // 或者直接返回 js 对的
        return {
            tag: 'h1', // tag 名称
            props:{ // 属性与事件
                onClick:handler
            }
            children:[ // 子节点
                {tag: 'span'}
            ]
        }
    }
}

h 返回的其实就是 js 对象h 函数就是辅助创建虚拟 DOM 的工具函数而已,所以他俩其实是一个东西

5.3. 两种方式的对比

  • 哪种方式更灵活呢?
    • 答案是:JavaScript 对象(或虚拟 DOM ) 的方式,
      • 比如表现 H1-H6 ,使用 tag:H${index} 即可
      • 又比如说,jsx的方式实现 递归树,更方便
  • 那种方式更直观呢?当然是 模板

6. 数据 与 UI

简单说,前端框架需要数据驱动 UI 渲染,即数据变化了,UI 视图跟着一起变化

7. 什么是副作用

指的是在组件渲染过程中,那些会影响到组件之外的其他部分的操作,比如

  • 发起网络请求(如 API 调用)
  • 修改 DOM(直接操作,而非通过框架的渲染机制)
  • 设置定时器或间隔器,如 setTimeout 或 setInterval
  • 订阅外部事件
  • 修改全局变量
  • 写入本地存储,如修改 localStorage 或 sessionStorage
  • 日志记录等

比如:访问/修改 localStorage(副作用)

// 这个组件将用户名存储在浏览器的 localStorage 中,这是一个影响外部环境的操作。
function RememberMe({ username }) {
 
 useEffect(() => {
   localStorage.setItem('username', username);
 }, [username]);
 
 return <div>Remembering {username}</div>;
}

相对比的,纯函数或者没有副作用代表不会影响到它本身以外的任何东西,比如

// 这个组件只是单纯地渲染文本,不会影响其他任何东西。
function Welcome(props) {
 return <h1>Hello, {props.name}</h1>;
}

副作用不是简单的渲染操作,而是会影响组件外部状态或环境的操作。

在现代前端框架中,妥善管理这些副作用是保证应用稳定性和性能的关键。

8. 说说前面提的 Vue 的 h 函数

h函数用于创建虚拟 DOM 节点的一个函数,通常在渲染函数中使用

h 函数本质上是一个创建虚拟 DOM 节点的工厂函数。它的作用可以类比为用 JavaScript 来写 HTML。

简单来说:

  • 作用:创建虚拟 DOM 节点
  • 使用场景:当你需要用 JavaScript 来精确控制渲染内容时
  • 基本语法:h(标签或组件, 属性对象, 子节点)

一个简单的例子:

// HTML: <div class="greeting">Hello, World!</div>
h('div', { class: 'greeting' }, 'Hello, World!')

// HTML: <button onClick="alert('Hi')">Click me</button>
h('button', { onClick: () => alert('Hi') }, 'Click me')

// 嵌套使用
h('div', [
  h('h1', 'Title'),
  h('p', 'Paragraph')
])

8.1. 主要用途

  1. 创建虚拟 DOM:
    • h 函数通过 JavaScript 对象来描述 DOM 结构,这对于动态创建组件结构、进行复杂的条件渲染等场景十分有用。
  2. 渲染函数中使用:
    • 在需要完全控制渲染逻辑时,h 函数可以与渲染函数一起使用,以构建组件的虚拟 DOM 树。
  3. 支持 JSX 语法:
    • 在使用 JSX 语法时,JSX 会被编译成 h 函数调用。

8.2. 常见的 h 函数参数

  • 第一个参数:标签名称、组件类型或异步组件(可以是字符串或组件变量)。
  • 第二个参数(可选):一个数据对象,包括属性、class、事件等。
  • 第三个参数(可选):子节点,可以是字符串、数组或更多 h 函数调用。

8.3. 示例

import { h } from 'vue';

export default {
  render() {
    return h('div', { class: 'container' }, [
      h('h1', 'Hello World'),
      h('p', 'This is a paragraph.'),
      h(MyButton, { onClick: this.handleClick }, 'Click Me')
    ]);
  },
  methods: {
    handleClick() {
      alert('Button clicked!');
    }
  }
}

在这个例子中,h 函数用于创建一个 div 包含一个标题、一个段落和一个自定义按钮组件。这种方式提供了非常灵活的界面渲染能力,可以在不依赖模板的情况下,直接使用 JavaScript 表达业务逻辑。

9. 聊聊前端框架中的一些编译技术或编译策略

代码编译技术或者策略,对应用程序的性能和开发体验有重要影响,还直接影响开发效率和调试能力。选择合适的编译策略通常需要权衡开发体验、应用性能和部署环境等多个因素。

9.1. JIT(Just-in-Time)编译:即时编译、运行时编译

JIT 编译是在运行时进行的编译。代码在执行时被动态编译为机器码。

特点:

  • 灵活性高:可以根据运行时的情况进行优化。
  • 启动时间较长:因为需要在运行时编译。
  • 内存占用较大:需要保存原始代码和编译后的代码。

应用:

  • 在浏览器中广泛使用,如 V8 引擎(Chrome)。
  • Angular 的开发时模式默认使用 JIT。

优势:

  • 开发过程中更快的构建时间。
  • 易于调试,因为源代码和运行代码之间有直接对应关系。

9.2. AOT(Ahead-of-Time):预编译

AOT 编译是在构建阶段就将代码编译为机器码或更低级的代码。

特点:

  • 更快的启动时间:因为代码已经预先编译。
  • 更小的包体积:不需要包含编译器。
  • 更好的安全性:源代码不暴露在客户端。

应用:

  • Angular 生产模式默认使用 AOT。
  • React 的 Prepack 是一种 AOT 优化工具。

优势:

  • 更快的首次加载和渲染速度。
  • 在构建时就能发现某些类型的错误。

9.3. 增量编译(Incremental Compilation)

只重新编译发生变化的部分(增量部分),而不是整个应用。

特点:

  • 加快开发中的编译速度。
  • 在大型项目中特别有效。

应用:

  • TypeScript 和许多现代构建工具支持增量编译。

9.4. 懒加载(Lazy Loading)

  • 不是的编译技术,是一种编译策略
  • 定义
    • 按需加载代码块,而不是一次性加载整个应用
  • 特点:
    • 改善初始加载时间。
    • 减少不必要的网络传输。
  • 应用:
    • Angular、React Router 等都支持路由级别的懒加载

9.5. Tree Shaking

  • 定义:移除未使用的代码(死代码消除)。
  • 特点:
    • 减小最终的包大小。
    • 通常与 ES6 模块和 AOT 编译结合使用。
  • 应用:
    • Webpack、Rollup 等构建工具支持 Tree Shaking。

9.6. 源码映射(Source Mapping)

  • 定义:在生产环境中将压缩和转换后的代码映射回原始源代码。
  • 特点:
    • 便于在生产环境中进行调试。
    • 通常与 AOT 编译结合使用。

9.7. 选择

  • 开发期间,快速迭代和调试需求往往让 JIT 更受青睐。
  • 生产环境,启动性能和安全性通常使 AOT 成为更好的选择