Angular面试题汇总系列一

news2024/11/27 7:06:27

1. 如何理解Angular Signal

Angular Signals is a system that granularly tracks how and where your state is used throughout an application, allowing the framework to optimize rendering updates.

什么是信号

信号是一个值的包装器,可以在该值发生变化时通知感兴趣的消费者。信号可以包含任何值,从简单的原语到复杂的数据结构。

信号的值总会通过 getter 函数读取,这使得 Angular 可以跟踪信号的使用位置。

信号可以是可写的或只读的。

可写信号

可写信号提供了一个 API 来直接更新它们的值。你可以通过使用信号的初始值调用 signal 函数来创建可写信号:

const count = signal(0);
// Signals are getter functions - calling them reads their value.
console.log('The count is: ' + count());

要更改可写信号的值,你可以直接 .set():

count.set(3);

或者使用 .update() 操作从前一个值计算出一个新值:

// Increment the count by 1.
count.update(value => value + 1);

在处理包含对象的信号时,有时直接改变该对象很有用。例如,如果对象是一个数组,你可能希望在不完全替换数组的情况下推送一个新值。要进行这样的内部更改,请使用 .mutate 方法:

const todos = signal([{title: 'Learn signals', done: false}]);

todos.mutate(value => {
  // Change the first TODO in the array to 'done: true' without replacing it.
  value[0].done = true;
});

计算信号

计算信号是从其他信号中派生出来的。可以使用 computed 并指定推导函数来定义一个:

const count: WritableSignal<number> = signal(0);
const doubleCount: Signal<number> = computed(() => count() * 2);

doubleCount 信号取决于 count。每当 count 更新时,Angular 知道任何依赖于 count 或 doubleCount 东西也需要更新。

计算信号都是惰性计算和记忆的

在第一次读取 doubleCount 之前,不会运行 doubleCount 的派生函数以计算其值。一旦计算出来,这个值就会被缓存起来,以后读取 doubleCount 将返回缓存的值而不用重新计算。

当 count 发生变化时,它会告诉 doubleCount 它的缓存值不再有效,并且该值只会在下一次读取 doubleCount 时重新计算。

因此,在计算信号中执行计算量大的推导(例如过滤数组)是相当安全的。

计算信号不是可写信号
你不能直接为计算信号赋值。比如,

doubleCount.set(3);

会产生编译错误,因为 doubleCount 不是 WritableSignal。

计算信号的依赖性是动态的

只能跟踪推导期间实际读取过的信号。例如,在此计算中,只会有条件地读取 count 信号:

const showCount = signal(false);
const count = signal(0);
const conditionalCount = computed(() => {
  if (showCount()) {
    return `The count is ${count()}.`;
  } else {
    return 'Nothing to see here!';
  }
});

读取 conditionalCount 时,如果 showCount 为 false,则没有读取 count 信号就返回了消息 “Nothing to see here!”。这意味着对 count 的更新不会导致重新计算。

如果稍后将 showCount 设置为 true 并再次读取 conditionalCount,则将重新执行派生并采用 showCount 为 true 的分支,返回显示 count 值的消息。对 count 的更改将使 conditionalCount 的缓存值无效。

请注意,可以删除和添加依赖项。如果 showCount 稍后再次设置为 false,则 count 将不再被视为 conditionalCount 的依赖项。

何时使用副作用

在大多数应用程序代码中很少需要副作用,但在特定情况下可能会有用。下面是一些需要以 effect 作为解决方案的例子:

  • 记录正在显示的数据及其更改时间,用于分析或作为调试工具

  • 在数据与 window.localStorage 之间保持同步

  • 添加无法用模板语法表达的自定义 DOM 行为

  • 对 canvas、图表库或其他第三方 UI 库执行自定义渲染

如何理解 Web Worker

在Angular中,Web Worker是一种运行在浏览器后台线程的JavaScript,它允许你执行任务而不会冻结用户界面。这对于执行密集型计算或长时间运行的任务特别有用,因为这些任务可能会阻塞主线程,导致用户界面变得不响应。
主线程与工作线程:

主线程:负责处理UI交互和DOM操作。
工作线程:运行Web Worker,处理后台任务,不会直接影响UI。
避免UI阻塞:
通过将计算密集型任务放在Web Worker中执行,可以避免主线程阻塞,从而提高应用的响应性和性能。

数据交换:
主线程和工作线程之间通过消息传递进行通信。你可以使用postMessage方法发送消息给Worker,Worker也可以通过postMessage向主线程发送消息。

创建Web Worker:
在Angular中,你可以创建一个服务来管理Web Worker。这个服务负责创建Worker实例,发送消息,并处理从Worker接收到的消息。

Angular服务中的Web Worker:
你可以使用@angular/platform-webworker和@angular/platform-webworker动态模块来创建专门的Worker应用程序或共享Worker。

示例:
以下是一个简单的Angular服务,演示如何使用Web Worker:

// worker.service.ts
import { Injectable } from '@angular/core';
import { Worker } from '@angular/platform-webworker';

@Injectable()
export class WorkerService {
  private worker: Worker;

  constructor() {
    this.worker = new Worker('./worker', { data: 'Hello, worker!' });
    this.worker.onMessage().subscribe(message => {
      console.log('Message from worker:', message);
    });
  }

  sendToWorker(data: any) {
    this.worker.postMessage(data);
  }
}

2 Web Worker 使用场景:

CPU密集型计算:
Web Worker允许在后台线程中运行CPU密集型计算,从而释放主线程以更新用户界面。这对于需要进行大量计算的应用,如生成CAD图纸或进行繁重的几何计算,非常有帮助

离线数据处理和缓存:
通过使用Web Worker和缓存,可以提高应用的性能和响应性。用户可以继续在页面上进行其他操作,而不会受到耗时计算的影响。同时,由于计算结果已经存储在缓存中,当用户需要再次获取时,可以快速地获取到,提高了应用的效率

大量数据计算:
对于需要处理大量数据的Web应用,例如数据分析工具或科学计算应用程序,可以使用Web Worker来处理这些数据。这样可以避免主线程阻塞,提高应用性能

图像处理和媒体编解码:
Web Worker在图像处理和媒体编解码方面也有广泛的应用。例如,可以创建一个Web Worker线程来处理图像调整大小、旋转、裁剪、滤镜等操作,而不阻塞主线程

实时数据推送和通知:
对于需要实时推送数据更新和通知的应用,可以使用Web Worker来处理实时数据的获取和处理任务。这样可以在后台线程中使用WebSocket、Server-Sent Events或定期轮询来获取实时数据,而不会影响主线程的用户交互

轮询服务器状态
有时,浏览器需要轮询服务器状态,以便第一时间得知状态改变。这个工作可以放在Web Worker里面,以避免阻塞主线程

文件数据处理
在某些应用中,可能需要处理大量文件数据,如保存文件数据到服务器。这些操作可以在Web Worker中进行,以避免阻塞用户界面

3. Angular 生命周期Hooks

Angular的生命周期钩子是组件或指令在其生命周期中经历的不同阶段的回调方法。理解这些钩子有助于我们更好地控制组件的行为。以下是Angular组件的生命周期钩子及其用途:

1. ngOnChanges

  • 触发时机: 当输入属性(通过@Input装饰器标记的属性)发生变化时。
  • 用途: 可以用来检测输入属性的变化,并执行相应的逻辑。
  • 操作示例: 重新计算数据、重新渲染视图、更新状态等。

2. ngOnInit

  • 触发时机: 组件或指令被初始化后,且第一次ngOnChanges之后。
  • 用途: 用于执行初始化逻辑,如订阅Observables、获取数据、设置初始状态等。
  • 操作示例: 发起HTTP请求、初始化表单、设置默认值等。

3. ngDoCheck

  • 触发时机: 每次变更检测运行时。
  • 用途: 用于检测Angular自身未检测到的变化,如第三方库的变化。
  • 操作示例: 手动检查变量的变化、执行自定义变更检测逻辑等。

4. ngAfterContentInit

  • 触发时机: 组件内容投影完成后。
  • 用途: 用于在内容投影完成后执行逻辑。
  • 操作示例: 初始化投影内容、设置初始状态等。

5. ngAfterContentChecked

  • 触发时机: 每次变更检测运行后,内容投影检查完成后。
  • 用途: 用于在内容投影检查完成后执行逻辑。
  • 操作示例: 更新投影内容的状态、执行额外的检查等。

6. ngAfterViewInit

  • 触发时机: 组件视图初始化完成后。
  • 用途: 用于在视图初始化完成后执行逻辑。
  • 操作示例: 初始化视图、设置初始状态、操作DOM等。

7. ngAfterViewChecked

  • 触发时机: 每次变更检测运行后,视图检查完成后。
  • 用途: 用于在视图检查完成后执行逻辑。
  • 操作示例: 更新视图的状态、执行额外的检查等。

8. ngOnDestroy

  • 触发时机: 组件或指令被销毁前。
  • 用途: 用于执行清理工作,如取消订阅、清理定时器等。
  • 操作示例: 取消HTTP请求、清理DOM监听器、释放资源等。

示例代码

import { Component, OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy, Input } from '@angular/core';

@Component({
  selector: 'app-lifecycle',
  template: `<p>Current value: {{ value }}</p >`
})
export class LifecycleComponent implements OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy {
  @Input() value: string;

  constructor() {
    console.log('Constructor called');
  }

  ngOnChanges(changes: SimpleChanges): void {
    console.log('ngOnChanges called', changes);
  }

  ngOnInit(): void {
    console.log('ngOnInit called');
  }

  ngDoCheck(): void {
    console.log('ngDoCheck called');
  }

  ngAfterContentInit(): void {
    console.log('ngAfterContentInit called');
  }

  ngAfterContentChecked(): void {
    console.log('ngAfterContentChecked called');
  }

  ngAfterViewInit(): void {
    console.log('ngAfterViewInit called');
  }

  ngAfterViewChecked(): void {
    console.log('ngAfterViewChecked called');
  }

  ngOnDestroy(): void {
    console.log('ngOnDestroy called');
  }
}

总结

  • ngOnChanges: 输入属性变化时调用。
  • ngOnInit: 初始化完成后调用。
  • ngDoCheck: 每次变更检测时调用。
  • ngAfterContentInit: 内容投影完成后调用。
  • ngAfterContentChecked: 内容投影检查完成后调用。
  • ngAfterViewInit: 视图初始化完成后调用。
  • ngAfterViewChecked: 视图检查完成后调用。
  • ngOnDestroy: 销毁前调用。

4. 如何理解Angular中的依赖注入

依赖注入(DI)是 Angular 中的基本概念之一。DI 被装配进 Angular 框架,并允许带有 Angular 装饰器的类(例如组件、指令、管道和可注入对象)配置它们所需的依赖项。

DI 系统中存在两个主要角色:依赖使用者和依赖提供者。

Angular 使用一种称为 Injector 的抽象来促进依赖消费者和依赖提供者之间的互动。当有人请求依赖项时,注入器会检查其注册表以查看那里是否已有可用的实例。如果没有,就会创建一个新实例并将其存储在注册表中。Angular 会在应用的引导过程中创建一个应用范围的注入器(也称为“根”注入器),并会根据需要创建任何其它注入器。在大多数情况下,你都不需要手动创建注入器,但应该知道有这样一个连接提供者和消费者的层次。

本主题介绍了某个类如何作为依赖项的基本场景。Angular 还允许你使用函数、对象、基本类型(例如字符串或 Boolean)或任何其他类型作为依赖项。

提供依赖项

假设有一个名为 HeroService 的类需要用作组件中的依赖项。

第一步是添加 @Injectable 装饰器以表明此类可以被注入。

@Injectable()
class HeroService {}

下一步是提供它,以便让其在 DI 中可用。可以在多种地方提供依赖项:

在组件级别,使用 @Component 装饰器的 providers 字段。在这种情况下,HeroService 将可用于此组件的所有实例以及它的模板中使用的其他组件和指令。例如:

@Component({
  selector: 'hero-list',
  template: '...',
  providers: [HeroService]
})
class HeroListComponent {}

当你在组件级别注册提供者时,该组件的每个新实例都会获得一个新的服务实例。

在 NgModule 级别,要使用 @NgModule 装饰器的 providers 字段。在这种情况下,HeroService 可用于此 NgModule 或与本模块位于同一个 ModuleInjector 的其它模块中声明的所有组件、指令和管道。当你向特定的 NgModule 注册提供者时,同一个服务实例可用于该 NgModule 中的所有组件、指令和管道。要理解所有边缘情况,参见多级注入器。例如:

@NgModule({
  declarations: [HeroListComponent]
  providers: [HeroService]
})
class HeroListModule {}

在应用程序根级别,允许将其注入应用程序中的其他类。这可以通过将 providedIn: ‘root’ 字段添加到 @Injectable 装饰器来实现:

@Injectable({
  providedIn: 'root'
})
class HeroService {}

当你在根级别提供服务时,Angular 会创建一个 HeroService 的共享实例,并将其注入到任何需要它的类中。在 @Injectable 元数据中注册提供者还允许 Angular 通过从已编译的应用程序中删除没用到的服务来优化应用程序,这个过程称为摇树优化(tree-shaking)。

注入依赖项

注入依赖项的最常见方法是在类的构造函数中声明它。当 Angular 创建组件、指令或管道类的新实例时,它会通过查看构造函数的参数类型来确定该类需要哪些服务或其他依赖项。例如,如果 HeroListComponent 要用 HeroService,则构造函数可以如下所示:

@Component({})
class HeroListComponent {
  constructor(private service: HeroService) {}
}

当 Angular 发现一个组件依赖于一项服务时,它会首先检查注入器中是否已有该服务的任何现有实例。如果所请求的服务实例尚不存在,注入器就会使用注册的提供者创建一个,并在将服务返回给 Angular 之前将其添加到注入器中。

当所有请求的服务都已解析并返回时,Angular 就可以用这些服务实例为参数,调用该组件的构造函数。
在这里插入图片描述
在这里插入图片描述

指定提供者令牌

如果你用服务类作为提供者令牌,则其默认行为是注入器使用 new 运算符实例化该类。

在下面这个例子中,Logger 类提供了 Logger 的实例。

providers: [Logger]

但是,你可以将 DI 配置为使用不同的类或任何其他不同的值来与 Logger 类关联。因此,当注入 Logger 时,会改为使用这个新值。

实际上,类提供者语法是一个简写表达式,可以扩展为由 Provider 接口定义的提供者配置信息。

在这种情况下,Angular 将 providers 值展开为完整的提供者对象,如下所示:

[{ provide: Logger, useClass: Logger }]

展开后的提供者配置是一个具有两个属性的对象字面量:

provide 属性包含一个令牌,该令牌会作为定位依赖值和配置注入器时的键。

第二个属性是一个提供者定义对象,它会告诉注入器如何创建依赖值。提供者定义对象中的键可以是以下值之一:

  • useClass - 此选项告诉 Angular DI 在注入依赖项时要实例化这里提供的类

  • useExisting - 允许你为令牌起一个别名,并引用任意一个现有令牌。

  • useFactory - 允许你定义一个用来构造依赖项的函数。

  • useValue - 提供了一个应该作为依赖项使用的静态值。

5 Angular常见指令有哪些

NgIf:
用于根据条件包含或排除一个元素。

<div *ngIf="condition">Content to show when condition is true.</div>

NgForOf:
用于基于一个数组或可迭代对象来重复元素。

<ul>
  <li *ngFor="let item of items">{{ item }}</li>
</ul>

NgSwitch:
用于在多个条件之间切换显示不同的内容。

<div [ngSwitch]="condition">
  <ng-container *ngSwitchCase="'case1'">Case 1</ng-container>
  <ng-container *ngSwitchDefault>Default case</ng-container>
</div>

NgClass 和 NgStyle:
用于动态添加或移除CSS类和样式。

<div [ngClass]="{'active': isActive, 'disabled': isDisabled}"></div>
<div [ngStyle]="{'color': color, 'font-size': size}"></div>

NgModel:
用于实现双向数据绑定,通常与表单控件一起使用。

<input type="text" [(ngModel)]="name">

FormsModule:
提供了NgModel以及其他表单相关的指令,需要在模块中导入。

import { FormsModule } from '@angular/forms';
@NgModule({
  imports: [FormsModule]
})

NgTemplateOutlet:
用于插入一个模板到指定的位置。

<ng-template let-item="item">
  <div>{{ item }}</div>
</ng-template>
<ng-container *ngTemplateOutlet="template; context: { $implicit: context }"></ng-container>

NgComponentOutlet:
用于动态创建组件实例。

<ng-component-outlet [component]="dynamicComponent"></ng-component-outlet>

NgIfElse:
与NgIf一起使用,用于提供条件为假时的备用内容。

<div *ngIf="condition; else elseBlock">True</div>
<ng-template #elseBlock>False</ng-template>

AsyncPipe:
用于订阅可观察对象,并自动清理订阅。

<div>{{ (data$ | async)?.property }}</div>

NgNonBindable:
用于跳过元素及其子元素的Angular绑定。

<span ngNonBindable>{{ '{' }}{{ value }}{{ '}' }}</span>

NgContent:
用于在组件中分配内容(使用标签)。

NgHost:
用于在创建组件时指定宿主元素。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2248268.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SAR ADC系列15:基于Vcm-Base的开关切换策略

VCM-Based开关切换策略&#xff1a;采样~第一次比较 简单说明: 电容上下极板分别接Vcm&#xff08;一般Vcm1/2Vref&#xff09;。采样断开瞬间电荷锁定&#xff0c;进行第一次比较。 当VIP > VIN 时&#xff0c;同时 减小VIP 并 增大VIN 。P阵列最高权重电容从Vcm(1/2Vref)…

实现Excel文件和其他文件导出为压缩包,并导入

导出 后端&#xff1a; PostMapping("/exportExcelData")public void exportExcelData(HttpServletRequest request, HttpServletResponse response, RequestBody ResData resData) throws IOException {List<Long> menuIds resData.getMenuIds();List<Co…

某车企ASW面试笔试题

01--背景 去年由于工作岗位的动荡&#xff0c;于是面试了一家知名车企&#xff0c;上来进行了一番简单的介绍之后&#xff0c;被告知需要进入笔试环节&#xff0c;以往单位面试都是简单聊聊技术问题&#xff0c;比如对软件开发的流程或者使用的工具等待问题的交流&#xff0c;…

计算(a+b)/c的值

计算&#xff08;ab&#xff09;/c的值 C语言代码C语言代码Java语言代码Python语言代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 给定3个整数a、b、c&#xff0c;计算表达式(ab)/c的值&#xff0c;/是整除运算。 输入 输入仅一行&…

【在Linux世界中追寻伟大的One Piece】多线程(二)

目录 1 -> 分离线程 2 -> Linux线程互斥 2.1 -> 进程线程间的互斥相关背景概念 2.2 -> 互斥量mutex 2.3 -> 互斥量的接口 2.4 -> 互斥量实现原理探究 3 -> 可重入VS线程安全 3.1 -> 概念 3.2 -> 常见的线程不安全的情况 3.3 -> 常见的…

【NLP高频面题 - 分布式训练】ZeRO1、ZeRO2、ZeRO3分别做了哪些优化?

【NLP高频面题 - 分布式训练】ZeRO1、ZeRO2、ZeRO3分别做了哪些优化&#xff1f; 重要性&#xff1a;★★ NLP Github 项目&#xff1a; NLP 项目实践&#xff1a;fasterai/nlp-project-practice 介绍&#xff1a;该仓库围绕着 NLP 任务模型的设计、训练、优化、部署和应用&am…

AIGC--AIGC与人机协作:新的创作模式

AIGC与人机协作&#xff1a;新的创作模式 引言 人工智能生成内容&#xff08;AIGC&#xff09;正在以惊人的速度渗透到创作的各个领域。从生成文本、音乐、到图像和视频&#xff0c;AIGC使得创作过程变得更加快捷和高效。然而&#xff0c;AIGC并非完全取代了人类的创作角色&am…

C++11特性(详解)

目录 1.C11简介 2.列表初始化 3.声明 1.auto 2.decltype 3.nullptr 4.范围for循环 5.智能指针 6.STL的一些变化 7.右值引用和移动语义 1.左值引用和右值引用 2.左值引用和右值引用的比较 3.右值引用的使用场景和意义 4.右值引用引用左值及其一些更深入的使用场景分…

React中事件处理和合成事件:理解与使用

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

大数据新视界 -- 大数据大厂之 Hive 数据桶:优化聚合查询的有效手段(下)(10/ 30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

基于FPGA的信号DM编解码实现,包含testbench和matlab对比仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 1.编码器硬件结构 2.解码器硬件结构 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) FPGA测试结果如下&#xff1a; matlab对比仿真结果如下&#xff1a; 2.算法运行软…

鸿蒙中拍照上传与本地图片上传

1.首页ui import { picker } from kit.CoreFileKit; import fs from ohos.file.fs; import request from ohos.request; import { promptAction } from kit.ArkUI; import { cameraCapture } from ./utils/CameraUtils; import { common } from kit.AbilityKit; import { Imag…

【算法】连通块问题(C/C++)

目录 连通块问题 解决思路 步骤&#xff1a; 初始化&#xff1a; DFS函数&#xff1a; 复杂度分析 代码实现&#xff08;C&#xff09; 题目链接&#xff1a;2060. 奶牛选美 - AcWing题库 解题思路&#xff1a; AC代码&#xff1a; 题目链接&#xff1a;687. 扫雷 -…

人工智能 实验2 jupyter notebook平台 打印出分类器的正确率

实验2 jupyter notebook平台 【实验目的】掌握jupyter notebook平台的使用方法 【实验内容】上传文件到jupyter notebook平台&#xff0c;学会编辑运行ipynb文件 【实验要求】写明实验步骤&#xff0c;必要时补充截图 安装Anaconda。 2、 将BreadCancer.zip上传到jupyter no…

【贪心算法第五弹——300.最长递增子序列】

目录 1.题目解析 题目来源 测试用例 2.算法原理 3.实战代码 代码解析 注意本题还有一种动态规划的解决方法&#xff0c;贪心的方法就是从动态规划的方法总结而来&#xff0c;各位可以移步博主的另一篇博客先了解一下&#xff1a;动态规划-子序列问题——300.长递增子序列…

Spring Boot——统一功能处理

1. 拦截器 拦截器主要用来拦截用户的请求&#xff0c;在指定方法前后&#xff0c;根据业务需要执行设定好的代码&#xff0c;也就是提前定义一些逻辑&#xff0c;在用户的请求响应前后执行&#xff0c;也可以在用户请求前阻止其执行&#xff0c;例如登录操作&#xff0c;只有登…

【2024】前端学习笔记19-ref和reactive使用

学习笔记 1.ref2.reactive3.总结 1.ref ref是 Vue 3 中用来创建响应式引用的一个函数&#xff0c;通常用于基本数据类型&#xff08;如字符串、数字、布尔值等&#xff09;或对象/数组的单一值。 ref特点&#xff1a; ref 可以用来创建单个响应式对象对于 ref 包裹的值&…

javaweb-day01-html和css初识

html:超文本标记语言 CSS&#xff1a;层叠样式表 1.html实现新浪新闻页面 1.1 标题排版 效果图&#xff1a; 1.2 标题颜色样式 1.3 标签内颜色样式 1.4设置超链接 1.5 正文排版 1.6 页面布局–盒子 &#xff08;1&#xff09;盒子模型 &#xff08;2&#xff09;页面布局…

3mf 格式详解,javascript加载导出3mf文件示例

3MF 格式详解 3MF&#xff08;3D Manufacturing Format&#xff09;是一种开放标准的文件格式&#xff0c;专门用于三维制造和打印。3MF 格式旨在解决 STL 格式的局限性&#xff0c;提供更丰富和灵活的数据表示。3MF 文件是一种 ZIP 文件&#xff0c;其中包含了描述三维模型的…

音视频流媒体直播/点播系统EasyDSS互联网视频云平台介绍

随着互联网技术的飞速发展&#xff0c;音视频流媒体直播已成为现代社会信息传递与娱乐消费的重要组成部分。在这样的背景下&#xff0c;EasyDSS互联网视频云平台应运而生&#xff0c;它以高效、稳定、便捷的特性&#xff0c;为音视频流媒体直播领域带来了全新的解决方案。 1、产…