Inhaltsverzeichnis
文件常识
文件权限
Wenn die Ausführungsberechtigung aufgehoben wird, kann nicht auf Dateien im Ordner zugegriffen werden und eine CD ist nicht möglich zum Ordner
Dateideskriptoren beginnen im Allgemeinen bei 3, 0/1/2 repräsentieren jeweils Standardeingabe/Standardausgabe/Fehlerausgabe Angemessen Dateien im Projekt%%PRE_BLOCK_0%%
Dateikopie
Datei-API
Pufferverwendung
Stream verwenden %%PRE_BLOCK_3%%
Datei-Upload
%%PRE_BLOCK_4%%" >Kleine Datei-Upload%%PRE_BLOCK_4%%
" >Große Datei-Upload
总结
Heim Web-Frontend js-Tutorial Lassen Sie uns ausführlich über das File-Modul in Node sprechen

Lassen Sie uns ausführlich über das File-Modul in Node sprechen

Apr 24, 2023 pm 05:49 PM
Frontend node.js

Lassen Sie uns ausführlich über das File-Modul in Node sprechen

Während wir über Stream/Buffer sprechen, haben wir bereits damit begonnen, require("fs") zu verwenden, um das Dateimodul einzuführen, um einige Vorgänge auszuführenrequire("fs")引入文件模块做一些操作了

文件模块是对底层文件操作的封装,例如文件读写/打开关闭/删除添加等等

文件模块最大的特点就是所有的方法都提供的同步异步两个版本,具有 sync 后缀的方法都是同步方法,没有的都是异步方法

文件常识

文件权限

因为需要对文件进行操作,所以需要设置对应的权限。【相关教程推荐:nodejs视频教程编程教学

Lassen Sie uns ausführlich über das File-Modul in Node sprechen

主要分为三种角色,文件所有者、文件所属组、其他用户

文件权限分为读、写、执行,分别于数字表示为4/2/1,没有权限的时候表示为0

如果取消了执行权限指,文件夹内任何文件都无法访问,也无法 cd 到文件夹

使用 Linux 命令ll

Das Dateimodul arbeitet weiter die zugrunde liegende Dateikapselung, wie z. B. Lesen/Schreiben/Öffnen/Schließen/Hinzufügen von Dateien usw.

Untitled 1.pngDas größte Merkmal des Dateimoduls ist, dass alle Methoden in zwei Versionen bereitgestellt werden:

synchrone

und

asynchrone

Methoden mit Das Synchronisierungssuffix umfasst alle synchronen Methoden, ohne alle asynchronen Methoden Da Sie die Datei bearbeiten müssen, müssen Sie die entsprechenden Berechtigungen festlegen. [Empfohlene verwandte Tutorials: nodejs-Video-Tutorial, Programmierunterricht

Lassen Sie uns ausführlich über das File-Modul in Node sprechen

Es ist hauptsächlich in drei Rollen unterteilt: Dateibesitzer, Dateibesitzergruppe, andere BenutzerUntitled 2.png

Die Dateiberechtigungen sind in Lesen und Schreiben unterteilt , Die Ausführung wird jeweils als 4/2/1 in Zahlen ausgedrückt und als 0, wenn keine Berechtigung vorliegt

Wenn die Ausführungsberechtigung aufgehoben wird, kann nicht auf Dateien im Ordner zugegriffen werden und eine CD ist nicht möglich zum Ordner

Verwenden Sie den Linux-Befehlll, um die Berechtigungen von Dateien/Ordnern im Verzeichnis anzuzeigen

Das erste d stellt den Ordner dar, - stellt die Datei dar, gefolgt von den Berechtigungen des Datei // TODO: Was stellt @ dar

Dateiidentifikation

Untitled 3.png

In Node repräsentiert das Identifikationsbit die Betriebsmethode der Datei, lesbar/schreibbar/lesbar und beschreibbar usw., die angeordnet und kombiniert werden kann

Untitled 4.png

Untitled 5.png

Dateideskriptor

in Wie im vorherigen Inhalt erwähnt, weist das Betriebssystem jeder geöffneten Datei eine numerische Kennung zu, die als Dateideskriptor bezeichnet wird, und verwendet diese Werte, um bestimmte Dateien zu verfolgen.

Dateideskriptoren beginnen im Allgemeinen bei 3, 0/1/2 repräsentieren jeweils Standardeingabe/Standardausgabe/Fehlerausgabe Angemessen Dateien im Projekt
const fs = require("fs");
const path = require("path");
const { promisify } = require("util");
const reg = new RegExp("(.ts[x]*|.js[x]*|.json)$");
const targetPath = path.resolve(__dirname, "../mini-proxy-mobx");

const readDir = (targetPath, callback) => {
    fs.readdir(targetPath, (err, files) => {
        if (err) callback(err);
        files.forEach(async (file) => {
            const filePath = path.resolve(__dirname, `${targetPath}/${file}`);
            const stats = await promisify(fs.stat)(filePath);
            if (stats.isDirectory()) {
                await readDir(filePath);
            } else {
                checkFile(filePath);
            }
        });
    });
};
const checkFile = (file) => {
    if (reg.test(file)) {
        console.log(file);
    }
};

readDir(targetPath, (err) => {
    throw err;
});

Dateikopie

Problem: Sie müssen den Inhalt von Datei 1 in Datei 2 kopieren

Datei-API

Sie können fs.readFile verwenden, um den Dateiinhalt zu lesen, und dann Verwenden Sie fs.writeFile, um eine neue Datei zu schreiben

const fs = require("fs");
const path = require("path");

const sourceFile = path.resolve(__dirname, "../doc/Mobx原理及丐版实现.md");
const targetFile = path.resolve(__dirname, "target.txt");

fs.readFile(sourceFile, (err, data) => {
    if (err) throw err;
    const dataStr = data.toString();
    fs.writeFile(targetFile, dataStr, (err) => {
        if (err) throw err;
        console.log("copy success~");
        process.exit(1);
    });
});

Pufferverwendung

Verwenden Sie die Methode fs.open, um die Datei zu öffnen, den Dateideskriptor abzurufen, und rufen Sie dann die Methode fs.read/fs.write auf, um eine bestimmte Datenmenge zu lesen und an einen bestimmten Speicherort zu schreiben

const copyFile = (source, target, size, callback) => {
    const sourceFile = path.resolve(__dirname, source);
    const targetFile = path.resolve(__dirname, target);

    const buf = Buffer.alloc(size);
    let hasRead = 0; // 下次读取文件的位置
    let hasWrite = 0; // 下次写入文件的位置
    fs.open(sourceFile, "r", (err, sourceFd) => {
        if (err) callback(err);
        fs.open(targetFile, "w", (err, targetFd) => {
            if (err) throw callback(err);
            function next() {
                fs.read(sourceFd, buf, 0, size, hasRead, (err, bytesRead) => {
                    if (err) callback(err);
                    hasRead += bytesRead;
                    if (bytesRead) {
                        fs.write(targetFd, buf, 0, size, hasWrite, (err, bytesWrite) => {
                            if (err) callback(err);
                            hasWrite += bytesWrite;
                            next();
                        });
                        return;
                    }
                    fs.close(sourceFd, () => { console.log("关闭源文件"); });
                    fs.close(targetFd, () => { console.log("关闭目标文件"); });
                });
            }
            next();
        });
    });
};

Stream verwenden
const fs = require("fs");
const path = require("path");
const readStream = fs.createReadStream(
    path.resolve(__dirname, "../doc/Mobx原理及丐版实现.md")
);
const writeStream = fs.createWriteStream(path.resolve("target.txt"));
readStream.pipe(writeStream);

Datei-Upload

Untitled 6.png

Hauptschritte

  1. 前端接收大文件,并进行切片处理
  2. 将每份切片进行上传处理
  3. 后端接收到所有的切片,存储所有切片到一个文件夹中
  4. 将文件夹中的切片做合并,并对切片做删除
  5. 再次上传统一文件时,能够快速上传

具体实现

  1. 前端切片

    const BIG_FILE_SIZE = 25 * 1024 * 1024;
    const SLICE_FILE_SIZE = 5 * 1024 * 1024;
    
    const uploadFile = async () => {
        if (!fileList?.length) return alert("请选择文件");
        const file = fileList[0];
        const shouldUpload = await verifyUpload(file.name);
        if (!shouldUpload) return message.success("文件已存在,上传成功");
        if (file.size > BIG_FILE_SIZE) {
            // big handle
            getSliceList(file);
        }
        // // normal handle
        // upload("/uploadSingle", file);
    };
    const getSliceList = (file: RcFile) => {
        const sliceList: ISlice[] = [];
        let curSize = 0;
        let index = 0;
        while (curSize < file.size) {
            sliceList.push({
                id: shortid.generate(),
                slice: new File(
                    [file.slice(curSize, (curSize += SLICE_FILE_SIZE))],
                    `${file.name}-${index}`
                ),
                name: file.name,
                sliceName: `${file.name}-${index}`,
                progress: 0,
            });
            index++;
        }
        uploadSlice(sliceList);
        setSliceList(sliceList);
    };

    file 是一种特殊的 Blob 对象,可以使用 slice 进行大文件分割

    Untitled 7.png

  2. 上传切片

    const uploadSlice = async (sliceList: ISlice[]) => {
      const requestList = sliceList
          .map(({ slice, sliceName, name }: ISlice, index: number) => {
              const formData = new FormData();
              formData.append("slice", slice);
              formData.append("sliceName", sliceName);
              formData.append("name", name);
              return { formData, index, sliceName };
          })
          .map(({ formData }: { formData: FormData }, index: number) =>
              request.post("/uploadBig", formData, {
                  onUploadProgress: (progressEvent: AxiosProgressEvent) =>
                      sliceUploadProgress(progressEvent, index),
              })
          );
      await Promise.all(requestList);
    };

    根据切片构建每个切片的 formData,将二进制数据放在 slice 参数中,分别发送请求。

    onUploadProgress 来处理每个切片的上传进度

    // Client
    const storage = multer.diskStorage({
      destination: async function (req, file, cb) {
          const name = file?.originalname.split(".")?.[0];
          const SLICE_DIR = path.join(UPLOAD_DIR, `${name}-slice`);
          if (!fs.existsSync(SLICE_DIR)) {
              await fs.mkdirSync(SLICE_DIR);
          }
          // 设置文件的存储目录
          cb(null, SLICE_DIR);
      },
      filename: async function (req, file, cb) {
          // 设置文件名
          cb(null, `${file?.originalname}`);
      },
    });
    
    // Server
    router.post(
        "/uploadBig",
        async (ctx, next) => {
            try {
                await next();
                const slice = ctx.files.slice[0]; // 切片文件
                ctx.body = {
                    code: 1,
                    msg: "文件上传成功",
                    url: `${RESOURCE_URL}/${slice.originalname}`,
                };
            } catch (error) {
                ctx.body = {
                    code: 0,
                    msg: "文件上传失败",
                };
            }
        },
        multerUpload.fields([{ name: "slice" }])
    );
  3. 切片合并

    当我们所有的切片上传成功之后,我们依旧希望是按着原始文件作为保存的,所以需要对切片进行合并操作

    // Client
    const uploadSlice = async (sliceList: ISlice[]) => {
    		// ...和上述 uploadSlice 一致
    		mergeSlice();
    };
    
    const mergeSlice = () => {
        request.post("/mergeSlice", {
            size: SLICE_FILE_SIZE,
            name: fileList[0].name,
        });
    };
    
    // Server
    router.post("/mergeSlice", async (ctx, next) => {
        try {
            await next();
            const { size, name } = ctx.request.body ?? {};
            const sliceName = name.split(".")?.[0];
            const filePath = path.join(UPLOAD_DIR, name);
            const slice_dir = path.join(UPLOAD_DIR, `${sliceName}-slice`);
            await mergeSlice(filePath, slice_dir, size);
            ctx.body = {
                code: 1,
                msg: "文件合并成功",
            };
        } catch (error) {
            ctx.body = {
                code: 0,
                msg: "文件合并失败",
            };
        }
    });
    
    // 通过 stream 来读写数据,将 slice 中数据读取到文件中
    const pipeStream = (path, writeStream) => {
        return new Promise((resolve) => {
            const readStream = fs.createReadStream(path);
            readStream.on("end", () => {
                fs.unlinkSync(path);   // 读取完成之后,删除切片文件
                resolve();
            });
            readStream.pipe(writeStream);
        });
    };
    
    const mergeSlice = async (filePath, sliceDir, size) => {
        if (!fs.existsSync(sliceDir)) {
            throw new Error("当前文件不存在");
        }
        const slices = await fs.readdirSync(sliceDir);
        slices.sort((a, b) => a.split("-")[1] - b.split("-")[1]);
        try {
            const slicesPipe = slices.map((sliceName, index) => {
                return pipeStream(
                    path.resolve(sliceDir, sliceName),
                    fs.createWriteStream(filePath, { start: index * size })
                );
            });
            await Promise.all(slicesPipe);
            await fs.rmdirSync(sliceDir);  // 读取完成之后,删除切片文件夹
        } catch (error) {
            console.log(error);
        }
    };
  4. 上传文件校验

    当我们上传一个文件的时候,先去判断在服务器上是否存在该文件,如果存在则直接不做上传操作,否则按上述逻辑进行上传

    // Client
    const verifyUpload = async (name: string) => {
        const res = await request.post("/verify", { name });
        return res?.data?.data;
    };
    
    const uploadFile = async () => {
        if (!fileList?.length) return alert("请选择文件");
        const file = fileList[0];
        const shouldUpload = await verifyUpload(file.name);
        if (!shouldUpload) return message.success("文件已存在,上传成功");
        if (file.size > BIG_FILE_SIZE) {
            // big handle
            getSliceList(file);
        }
        // // normal handle
        // upload("/uploadSingle", file);
    };
    
    // Server
    router.post("/verify", async (ctx, next) => {
        try {
            await next();
            const { name } = ctx.request.body ?? {};
            const filePath = path.resolve(UPLOAD_DIR, name);
            if (fs.existsSync(filePath)) {
                ctx.body = {
                    code: 1,
                    data: false,
                };
            } else {
                ctx.body = {
                    code: 1,
                    data: true,
                };
            }
        } catch (error) {
            ctx.body = {
                code: 0,
                msg: "检测失败",
            };
        }
    });

    上述直接使用文件名来做判断,过于绝对,对文件做了相关修改并不更改名字,就会出现问题。更应该采用的方案是根据文件相关的元数据计算出它的 hash 值来做判断。

    const calculateMD5 = (file: any) => new Promise((resolve, reject) => {
        const chunkSize = SLICE_FILE_SIZE
        const fileReader = new FileReader();
        const spark = new SparkMD5.ArrayBuffer();
        let cursor = 0;
        fileReader.onerror = () => {
            reject(new Error(&#39;Error reading file&#39;));
        };
        fileReader.onload = (e: any) => {
            spark.append(e.target.result);
            cursor += e.target.result.byteLength;
            if (cursor < file.size) loadNext();
            else resolve(spark.end());
            
        };
        const loadNext = () => {
            const fileSlice = file.slice(cursor, cursor + chunkSize);
            fileReader.readAsArrayBuffer(fileSlice);
        }
        loadNext();
    });

    本文所有的代码可以github上查看

    总结

    本文从文件常识/常用的文件 API 入手,重点讲解了 Node 中 File 的相关实践,最后使用相关内容实现了大文件上传。

    更多node相关知识,请访问:nodejs 教程

    Das obige ist der detaillierte Inhalt vonLassen Sie uns ausführlich über das File-Modul in Node sprechen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

PHP-Tutorial
1510
276
PHP und Vue: eine perfekte Kombination von Front-End-Entwicklungstools PHP und Vue: eine perfekte Kombination von Front-End-Entwicklungstools Mar 16, 2024 pm 12:09 PM

PHP und Vue: eine perfekte Kombination von Front-End-Entwicklungstools In der heutigen Zeit der rasanten Entwicklung des Internets ist die Front-End-Entwicklung immer wichtiger geworden. Da Benutzer immer höhere Anforderungen an das Erlebnis von Websites und Anwendungen stellen, müssen Frontend-Entwickler effizientere und flexiblere Tools verwenden, um reaktionsfähige und interaktive Schnittstellen zu erstellen. Als zwei wichtige Technologien im Bereich der Front-End-Entwicklung können PHP und Vue.js in Kombination als perfekte Waffe bezeichnet werden. In diesem Artikel geht es um die Kombination von PHP und Vue sowie um detaillierte Codebeispiele, die den Lesern helfen sollen, diese beiden besser zu verstehen und anzuwenden

Erkundung der Front-End-Technologie der Go-Sprache: eine neue Vision für die Front-End-Entwicklung Erkundung der Front-End-Technologie der Go-Sprache: eine neue Vision für die Front-End-Entwicklung Mar 28, 2024 pm 01:06 PM

Als schnelle und effiziente Programmiersprache erfreut sich Go im Bereich der Backend-Entwicklung großer Beliebtheit. Allerdings assoziieren nur wenige Menschen die Go-Sprache mit der Front-End-Entwicklung. Tatsächlich kann die Verwendung der Go-Sprache für die Front-End-Entwicklung nicht nur die Effizienz verbessern, sondern Entwicklern auch neue Horizonte eröffnen. In diesem Artikel wird die Möglichkeit der Verwendung der Go-Sprache für die Front-End-Entwicklung untersucht und spezifische Codebeispiele bereitgestellt, um den Lesern ein besseres Verständnis dieses Bereichs zu erleichtern. In der traditionellen Frontend-Entwicklung werden häufig JavaScript, HTML und CSS zum Erstellen von Benutzeroberflächen verwendet

Ist Django Front-End oder Back-End? Hör zu! Ist Django Front-End oder Back-End? Hör zu! Jan 19, 2024 am 08:37 AM

Django ist ein in Python geschriebenes Webanwendungs-Framework, das Wert auf schnelle Entwicklung und saubere Methoden legt. Obwohl Django ein Web-Framework ist, müssen Sie zur Beantwortung der Frage, ob Django ein Front-End oder ein Back-End ist, ein tiefes Verständnis der Konzepte von Front-End und Back-End haben. Das Front-End bezieht sich auf die Schnittstelle, mit der Benutzer direkt interagieren, und das Back-End bezieht sich auf serverseitige Programme. Sie interagieren mit Daten über das HTTP-Protokoll. Wenn das Front-End und das Back-End getrennt sind, können die Front-End- und Back-End-Programme unabhängig voneinander entwickelt werden, um Geschäftslogik bzw. interaktive Effekte sowie den Datenaustausch zu implementieren.

Erfahrungsaustausch in der C#-Entwicklung: Fähigkeiten zur kollaborativen Front-End- und Back-End-Entwicklung Erfahrungsaustausch in der C#-Entwicklung: Fähigkeiten zur kollaborativen Front-End- und Back-End-Entwicklung Nov 23, 2023 am 10:13 AM

Als C#-Entwickler umfasst unsere Entwicklungsarbeit in der Regel die Front-End- und Back-End-Entwicklung. Mit der Weiterentwicklung der Technologie und der zunehmenden Komplexität von Projekten wird die gemeinsame Entwicklung von Front-End und Back-End immer wichtiger und komplexer. In diesem Artikel werden einige kollaborative Front-End- und Back-End-Entwicklungstechniken vorgestellt, um C#-Entwicklern dabei zu helfen, die Entwicklungsarbeit effizienter abzuschließen. Nach der Festlegung der Schnittstellenspezifikationen ist die gemeinsame Entwicklung von Front-End und Backend untrennbar mit dem Zusammenspiel der API-Schnittstellen verbunden. Um den reibungslosen Ablauf der kollaborativen Front-End- und Back-End-Entwicklung sicherzustellen, ist es am wichtigsten, gute Schnittstellenspezifikationen zu definieren. Bei der Schnittstellenspezifikation handelt es sich um den Namen der Schnittstelle

Häufig gestellte Fragen von Front-End-Interviewern Häufig gestellte Fragen von Front-End-Interviewern Mar 19, 2024 pm 02:24 PM

In Front-End-Entwicklungsinterviews decken häufige Fragen ein breites Themenspektrum ab, darunter HTML/CSS-Grundlagen, JavaScript-Grundlagen, Frameworks und Bibliotheken, Projekterfahrung, Algorithmen und Datenstrukturen, Leistungsoptimierung, domänenübergreifende Anfragen, Front-End-Engineering, Designmuster sowie neue Technologien und Trends. Interviewerfragen sollen die technischen Fähigkeiten, die Projekterfahrung und das Verständnis des Kandidaten für Branchentrends beurteilen. Daher sollten Kandidaten in diesen Bereichen umfassend vorbereitet sein, um ihre Fähigkeiten und Fachkenntnisse unter Beweis zu stellen.

Django: Ein magisches Framework, das sowohl Front-End- als auch Back-End-Entwicklung bewältigen kann! Django: Ein magisches Framework, das sowohl Front-End- als auch Back-End-Entwicklung bewältigen kann! Jan 19, 2024 am 08:52 AM

Django: Ein magisches Framework, das sowohl Front-End- als auch Back-End-Entwicklung bewältigen kann! Django ist ein effizientes und skalierbares Webanwendungs-Framework. Es unterstützt mehrere Webentwicklungsmodelle, einschließlich MVC und MTV, und kann problemlos hochwertige Webanwendungen entwickeln. Django unterstützt nicht nur die Back-End-Entwicklung, sondern kann auch schnell Front-End-Schnittstellen erstellen und durch die Vorlagensprache eine flexible Ansichtsanzeige erreichen. Django kombiniert Front-End-Entwicklung und Back-End-Entwicklung zu einer nahtlosen Integration, sodass sich Entwickler nicht auf das Lernen spezialisieren müssen

Kombination von Golang- und Front-End-Technologie: Entdecken Sie, welche Rolle Golang im Front-End-Bereich spielt Kombination von Golang- und Front-End-Technologie: Entdecken Sie, welche Rolle Golang im Front-End-Bereich spielt Mar 19, 2024 pm 06:15 PM

Kombination von Golang und Front-End-Technologie: Um zu untersuchen, welche Rolle Golang im Front-End-Bereich spielt, sind spezifische Codebeispiele erforderlich. Mit der rasanten Entwicklung des Internets und mobiler Anwendungen ist die Front-End-Technologie immer wichtiger geworden. Auch in diesem Bereich kann Golang als leistungsstarke Back-End-Programmiersprache eine wichtige Rolle spielen. In diesem Artikel wird untersucht, wie Golang mit Front-End-Technologie kombiniert wird, und sein Potenzial im Front-End-Bereich anhand spezifischer Codebeispiele demonstriert. Die Rolle von Golang im Front-End-Bereich ist effizient, prägnant und leicht zu erlernen

Das Verständnis der Hauptfunktion von React: Die Frontend -Perspektive Das Verständnis der Hauptfunktion von React: Die Frontend -Perspektive Apr 18, 2025 am 12:15 AM

Zu den Hauptfunktionen von React gehören komponentiertes Denken, Staatsmanagement und virtuelles DOM. 1) Die Idee der Komponentierung ermöglicht es, die Benutzeroberfläche in wiederverwendbare Teile aufzuteilen, um die Lesbarkeit und Wartbarkeit der Code zu verbessern. 2) Das staatliche Management verwaltet dynamische Daten durch Status und Requisiten und ändert sich auslösen UI -Updates. 3) Aktualisieren Sie die Benutzeroberfläche virtuelle DOM -Optimierungsleistung durch die Berechnung des Mindestbetriebs der DOM -Replik im Speicher.

See all articles