跳转到内容

JS相关知识7.0

JavaScript图片、文件夹上传到后台是什么类型

在 JavaScript 中,图片和文件夹上传到后台时,通常使用 multipart/form-data 格式。这种格式允许将文件和其他表单数据一起上传。以下是详细说明:

1. 文件上传的类型

  • multipart/form-data

    • 用于上传文件和其他表单数据。

    • 通过 <form> 表单或 FormData 对象实现。

  • application/json

    • 通常用于上传文本数据,不适合直接上传文件。

2. 使用 <form> 表单上传

<form action="/upload" method="post" enctype="multipart/form-data">
  <input type="file" name="file" multiple>
  <button type="submit">Upload</button>
</form>
  • 说明

    • enctype="multipart/form-data":指定表单数据编码类型。

    • multiple:允许选择多个文件。

3. 使用 FormData 对象上传

const fileInput = document.querySelector('input[type="file"]');
const formData = new FormData();

fileInput.addEventListener('change', function() {
  for (const file of fileInput.files) {
    formData.append('files', file); // 添加文件到 FormData
  }

  fetch('/upload', {
    method: 'POST',
    body: formData
  })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error));
});
  • 说明

    • FormData:用于构建表单数据,支持文件上传。

    • append:将文件添加到 FormData 中。

4. 文件夹上传

<input type="file" name="files" webkitdirectory multiple>
  • 说明

    • webkitdirectory:允许选择文件夹(仅支持部分浏览器)。

    • multiple:允许选择多个文件夹。

5. 后台处理

  • Node.js(使用 multer 中间件)
const express = require('express');
const multer = require('multer');
const app = express();

const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.array('files'), (req, res) => {
  console.log(req.files); // 上传的文件信息
  res.json({ message: 'Upload successful' });
});

app.listen(3000, () => console.log('Server running on port 3000'));
  • 说明

    • multer:用于处理 multipart/form-data 格式的文件上传。

    • upload.array('files'):处理多个文件上传。

总结

类型描述适用场景
multipart/form-data用于上传文件和表单数据文件上传、文件夹上传
FormData用于构建表单数据,支持文件上传通过 JavaScript 动态上传文件
multerNode.js 中间件,处理文件上传后台接收和处理文件

通过 multipart/form-data 格式和 FormData 对象,可以方便地实现文件和文件夹的上传功能。

Window.write和document.innerhtml区别

window.writedocument.innerHTML 是 JavaScript 中用于操作页面内容的两种方法,但它们的行为和用途有显著区别。以下是它们的详细对比:

1. window.write

  • 定义

    • window.writedocument.write 的别名,用于向文档中写入内容。
  • 行为

    • 如果文档已经加载完成,调用 document.write 会清空整个文档并重新写入内容。

    • 如果文档正在加载中,document.write 会将内容插入到当前文档流中。

document.write('<h1>Hello, World!</h1>');
  • 优点

    • 简单易用,适合快速测试。
  • 缺点

    • 会清空已加载的文档,导致页面内容丢失。

    • 不推荐在现代 Web 开发中使用。

2. document.innerHTML

  • 定义

    • document.innerHTMLElement.innerHTML 的误写,正确用法是 element.innerHTML,用于获取或设置元素的 HTML 内容。
  • 行为

    • 获取或设置指定元素的内部 HTML 内容。

    • 不会影响其他元素或文档结构。

document.getElementById('myDiv').innerHTML = '<p>Hello, World!</p>';
  • 优点

    • 精确控制特定元素的内容。

    • 不会影响文档的其他部分。

  • 缺点

    • 直接操作 HTML 字符串可能导致安全问题(如 XSS 攻击)。

3. 对比

特性document.writeelement.innerHTML
作用对象整个文档特定元素
行为清空文档或插入内容获取或设置元素的 HTML 内容
影响范围影响整个文档仅影响指定元素
安全性低,可能导致内容丢失低,可能导致 XSS 攻击
适用场景快速测试,不推荐用于生产环境动态更新页面内容

总结

  • document.write

    • 用于向文档中写入内容,但会清空已加载的文档。

    • 不推荐在现代 Web 开发中使用。

  • element.innerHTML

    • 用于获取或设置特定元素的 HTML 内容。

    • 适合动态更新页面内容,但需注意安全问题。

根据具体需求选择合适的方法,可以提高代码的可维护性和安全性。

JavaScript中call和apply的区别

在 JavaScript 中,callapply 都是用于显式绑定函数执行时的 this 值的方法。它们的主要区别在于 传递参数的方式

  1. call 方法
  • 作用:调用函数,并显式指定函数内部的 this 值,同时以 参数列表 的形式传递参数。

  • 语法

    javascript
    func.call(thisArg, arg1, arg2, ...);
    • thisArg:函数运行时 this 的值。
    • arg1, arg2, ...:传递给函数的参数列表。
  • 示例

    javascript
    function greet(name, age) {
        console.log(`Hello, ${name}! You are ${age} years old.`);
        console.log(this); // { country: "USA" }
    }
    
    const context = { country: "USA" };
    greet.call(context, "Alice", 25);
    // 输出:
    // Hello, Alice! You are 25 years old.
    // { country: "USA" }
  1. apply 方法
  • 作用:调用函数,并显式指定函数内部的 this 值,同时以 数组或类数组 的形式传递参数。

  • 语法

    javascript
    func.apply(thisArg, [argsArray]);
    • thisArg:函数运行时 this 的值。
    • argsArray:传递给函数的参数数组(或类数组对象)。
  • 示例

    javascript
    function greet(name, age) {
        console.log(`Hello, ${name}! You are ${age} years old.`);
        console.log(this); // { country: "Canada" }
    }
    
    const context = { country: "Canada" };
    greet.apply(context, ["Bob", 30]);
    // 输出:
    // Hello, Bob! You are 30 years old.
    // { country: "Canada" }
  1. callapply 的区别
特性callapply
参数传递方式参数列表 的形式传递数组或类数组 的形式传递
适用场景参数数量固定时使用参数数量不固定或动态时使用
  1. 使用场景

(1) call 的使用场景

  • 当参数数量固定且较少时,使用 call 更直观。
javascript
function add(a, b) {
    return a + b;
}
const result = add.call(null, 2, 3); // 5

(2) apply 的使用场景

  • 当参数数量不固定或动态时,使用 apply 更方便。
javascript
function sum() {
    return Array.from(arguments).reduce((acc, val) => acc + val, 0);
}
const numbers = [1, 2, 3, 4];
const result = sum.apply(null, numbers); // 10
  1. 实际应用

(1) 借用方法

  • 使用 callapply 可以借用其他对象的方法。
javascript
const obj1 = { name: "Alice" };
const obj2 = { name: "Bob" };

function greet() {
    console.log(`Hello, ${this.name}!`);
}

greet.call(obj1); // Hello, Alice!
greet.call(obj2); // Hello, Bob!

(2) 处理类数组对象

  • 使用 apply 可以将类数组对象(如 argumentsNodeList)转换为数组。
javascript
function logArguments() {
    const args = Array.prototype.slice.call(arguments);
    console.log(args);
}
logArguments(1, 2, 3); // [1, 2, 3]

总结

  • call:适合参数数量固定的场景,参数以列表形式传递。
  • apply:适合参数数量不固定或动态的场景,参数以数组形式传递。
  • 两者都可以显式绑定 this 值,是 JavaScript 中灵活调用函数的重要工具。

JavaScript添加 删除 替换 插入到某个节点的方法

在 JavaScript 中,操作 DOM 节点(添加、删除、替换、插入)是常见的任务。以下是常用的方法及其示例:

  1. 添加节点

(1) appendChild()

  • 将一个节点添加到指定父节点的子节点列表的末尾。

  • 语法

    javascript
    parentNode.appendChild(childNode);
  • 示例

    javascript
    const parent = document.getElementById("parent");
    const newChild = document.createElement("div");
    newChild.textContent = "New Child";
    parent.appendChild(newChild);

(2) insertBefore()

  • 将一个节点插入到指定父节点的某个子节点之前。

  • 语法

    javascript
    parentNode.insertBefore(newNode, referenceNode);
  • 示例

    javascript
    const parent = document.getElementById("parent");
    const newChild = document.createElement("div");
    newChild.textContent = "New Child";
    const referenceChild = document.getElementById("child");
    parent.insertBefore(newChild, referenceChild);
  1. 删除节点

(1) removeChild()

  • 从父节点中移除指定的子节点。

  • 语法

    javascript
    parentNode.removeChild(childNode);
  • 示例

    javascript
    const parent = document.getElementById("parent");
    const child = document.getElementById("child");
    parent.removeChild(child);

(2) remove()

  • 直接从 DOM 中移除当前节点。

  • 语法

    javascript
    node.remove();
  • 示例

    javascript
    const child = document.getElementById("child");
    child.remove();
  1. 替换节点

(1) replaceChild()

  • 用新节点替换父节点中的某个子节点。

  • 语法

    javascript
    parentNode.replaceChild(newNode, oldNode);
  • 示例

    javascript
    const parent = document.getElementById("parent");
    const oldChild = document.getElementById("child");
    const newChild = document.createElement("div");
    newChild.textContent = "New Child";
    parent.replaceChild(newChild, oldChild);

(2) replaceWith()

  • 用新节点替换当前节点。

  • 语法

    javascript
    oldNode.replaceWith(newNode);
  • 示例

    javascript
    const oldChild = document.getElementById("child");
    const newChild = document.createElement("div");
    newChild.textContent = "New Child";
    oldChild.replaceWith(newChild);
  1. 插入节点

(1) insertAdjacentElement()

  • 在相对于当前元素的指定位置插入一个新元素。

  • 语法

    javascript
    element.insertAdjacentElement(position, newElement);
  • 参数

    • position:插入位置,可以是以下值之一:
      • "beforebegin":在当前元素之前插入。
      • "afterbegin":在当前元素的第一个子元素之前插入。
      • "beforeend":在当前元素的最后一个子元素之后插入。
      • "afterend":在当前元素之后插入。
  • 示例

    javascript
    const target = document.getElementById("target");
    const newElement = document.createElement("div");
    newElement.textContent = "New Element";
    target.insertAdjacentElement("beforeend", newElement);

(2) insertAdjacentHTML()

  • 在相对于当前元素的指定位置插入 HTML 字符串。

  • 语法

    javascript
    element.insertAdjacentHTML(position, htmlString);
  • 示例

    javascript
    const target = document.getElementById("target");
    target.insertAdjacentHTML("beforeend", "<div>New Element</div>");

总结

操作方法描述
添加appendChild()在父节点末尾添加子节点
insertBefore()在指定子节点前插入新节点
删除removeChild()移除指定子节点
remove()直接移除当前节点
替换replaceChild()用新节点替换指定子节点
replaceWith()用新节点替换当前节点
插入insertAdjacentElement()在指定位置插入新元素
insertAdjacentHTML()在指定位置插入 HTML 字符串

通过掌握这些方法,可以灵活地操作 DOM 节点,实现动态的页面更新和交互。

清除浮动有哪些方法,哪种方法最优

清除浮动是解决父元素高度塌陷问题的关键方法。以下是常用的清除浮动方案及其优缺点分析,最后会给出最优方案建议:

一、清除浮动的常见方法

1. 空 div + clear: both

html
<div class="parent">
  <div class="float-left"></div>
  <div class="float-left"></div>
  <div style="clear: both;"></div> <!-- 清除浮动的空 div -->
</div>
  • 优点:简单直接,兼容性好。
  • 缺点:添加无意义的空标签,破坏 HTML 语义化。

2. 父元素设置 overflow 属性

css
.parent {
  overflow: auto; /* 或 overflow: hidden */
}
  • 原理:触发 BFC(块级格式化上下文),强制父元素包裹浮动内容。
  • 优点:代码简洁,无需额外标签。
  • 缺点:可能隐藏内容(overflow: hidden)或显示滚动条(overflow: auto)。

3. 伪元素法(.clearfix

css
.clearfix::after {
  content: "";
  display: block;
  clear: both;
}
/* 兼容旧浏览器(可选) */
.clearfix {
  zoom: 1;
}
html
<div class="parent clearfix">
  <div class="float-left"></div>
  <div class="float-left"></div>
</div>
  • 优点:语义化好,无冗余标签,广泛使用。
  • 缺点:需为父元素添加额外类名。

4. 父元素浮动(不推荐)

css
.parent {
  float: left; /* 父元素自身浮动 */
}
  • 缺点:可能导致布局连锁反应,影响其他元素。

5. 使用 display: flow-root(现代方案)

css
.parent {
  display: flow-root;
}
  • 原理:直接创建 BFC,无需副作用。
  • 优点:语义清晰,无冗余代码。
  • 缺点:兼容性稍差(不支持 IE11 及以下)。

二、最优方案推荐

推荐方案:伪元素法(.clearfix

  • 原因
    1. 语义化:无需添加无意义的空标签。
    2. 兼容性:支持所有浏览器(搭配 zoom: 1 兼容 IE6/7)。
    3. 灵活性:可复用 .clearfix 类,适合复杂项目。

替代方案:display: flow-root(现代项目首选)

  • 条件
    1. 项目无需支持 IE11 及以下浏览器。
    2. 希望代码更简洁,无副作用。

三、各方案对比表

方法语义化兼容性副作用代码简洁性
div + clear添加空标签
overflow内容截断/滚动条
伪元素法(.clearfix
父元素浮动布局连锁反应
display: flow-root⚠️无(需兼容性处理)

四、总结

  • 传统项目:使用 伪元素法(.clearfix,兼容性好且无副作用。
  • 现代项目:优先选择 display: flow-root,代码简洁高效。
  • 避免使用:空 div 和父元素浮动,前者破坏语义,后者导致布局问题。

根据项目需求选择最适合的方案即可!

DOM怎样添加、移除、移动、复制、创建和查找节点

以下是 JavaScript 中 DOM 节点操作的常见方法,涵盖创建、添加、移除、移动、复制和查找节点的详细说明及示例:

一、创建节点

  1. 创建元素节点
javascript
// 创建新的 <div> 元素
const newDiv = document.createElement('div');
  1. 创建文本节点
javascript
// 创建文本内容
const newText = document.createTextNode('Hello World!');
  1. 创建带属性的节点
javascript
const newImg = document.createElement('img');
newImg.src = 'image.jpg';
newImg.alt = '示例图片';

二、添加节点

  1. 追加到父节点末尾
javascript
const parent = document.getElementById('parent');
parent.appendChild(newDiv); // 将 newDiv 添加到 parent 末尾
  1. 插入到指定位置
javascript
const referenceNode = document.getElementById('child1');
parent.insertBefore(newDiv, referenceNode); // 在 referenceNode 前插入
  1. 直接插入 HTML(现代方法)
javascript
parent.insertAdjacentHTML('beforeend', '<p>插入的内容</p>');
// 可选位置:'beforebegin', 'afterbegin', 'beforeend', 'afterend'

三、移除节点

  1. 通过父节点移除子节点
javascript
parent.removeChild(childNode); // 传统方法
  1. 直接移除自身(现代方法)
javascript
childNode.remove(); // 直接调用节点的 remove() 方法

四、移动节点

  1. 移动现有节点到新位置
javascript
const newParent = document.getElementById('newParent');
newParent.appendChild(childNode); // 从原位置移除,添加到新位置
  1. 示例:交换两个节点的位置
javascript
const node1 = document.getElementById('node1');
const node2 = document.getElementById('node2');
const parent = node1.parentNode;
parent.insertBefore(node2, node1); // 将 node2 移到 node1 前面

五、复制节点

  1. 浅拷贝(不复制子节点)
javascript
const clonedNode = node.cloneNode(false); // 只复制节点本身
  1. 深拷贝(复制节点及其子节点)
javascript
const clonedNode = node.cloneNode(true); // 复制节点及所有子节点

六、查找节点

  1. 通过 ID 查找
javascript
const element = document.getElementById('myId');
  1. 通过类名查找
javascript
const elements = document.getElementsByClassName('myClass'); // 返回动态集合
  1. 通过标签名查找
javascript
const elements = document.getElementsByTagName('div'); // 返回动态集合
  1. 通过 CSS 选择器查找
javascript
// 返回第一个匹配元素
const element = document.querySelector('.myClass');
// 返回所有匹配元素(静态集合)
const elements = document.querySelectorAll('div.highlight');
  1. 层级关系查找
javascript
// 父节点
const parent = node.parentNode;

// 子节点集合(包含文本节点)
const children = node.childNodes;

// 仅元素子节点
const elementChildren = node.children;

// 前后兄弟节点
const nextSibling = node.nextElementSibling;
const prevSibling = node.previousElementSibling;

七、综合示例

html
<div id="container">
  <p class="text">原始段落</p>
</div>
javascript
// 创建新节点
const newParagraph = document.createElement('p');
newParagraph.textContent = '新段落';

// 添加到容器末尾
document.getElementById('container').appendChild(newParagraph);

// 移除原始段落
const oldParagraph = document.querySelector('.text');
oldParagraph.remove();

// 复制节点并插入到前面
const clonedParagraph = newParagraph.cloneNode(true);
document.getElementById('container').prepend(clonedParagraph);

八、最佳实践

  1. 优先使用 querySelectorquerySelectorAll:更灵活且支持复杂选择器。
  2. 操作前检查节点是否存在:避免 null 错误。
    javascript
    const node = document.getElementById('myId');
    if (node) {
      node.remove();
    }
  3. 批量操作使用文档片段:减少重绘次数。
    javascript
    const fragment = document.createDocumentFragment();
    for (let i = 0; i < 10; i++) {
      const div = document.createElement('div');
      fragment.appendChild(div);
    }
    document.body.appendChild(fragment);

通过掌握这些方法,你可以高效地操作 DOM 节点,实现动态的页面交互!

src与href的区别

在 HTML 中,src(Source)和 href(Hypertext Reference)是两个常见的属性,但它们的用途和行为有本质区别:

1. 核心定义

  • src 表示 “引入资源”,用于替换当前元素的内容或直接嵌入外部资源。 常见场景:<script><img><iframe><audio><video>

    html
    <script src="app.js"></script>  <!-- 加载并执行 JS -->
    <img src="image.jpg">          <!-- 加载并显示图片 -->
  • href 表示 “建立关联”,用于定义当前文档与外部资源的链接关系。 常见场景:<a><link><area>

    html
    <a href="page.html">链接</a>     <!-- 跳转到其他页面 -->
    <link href="style.css" rel="stylesheet"> <!-- 关联 CSS 文件 -->

2. 关键区别

特性srchref
作用直接嵌入资源,替换当前元素内容建立关联,不替换当前内容
加载行为阻塞性加载(如 JS 会阻塞 HTML 解析)非阻塞性加载(如 CSS 并行加载)
语义资源是当前文档的一部分资源与当前文档是关联关系
典型标签<script><img><iframe><a><link><area>

3. 具体场景分析

(1) <script> 标签

  • 使用 src 引入外部 JS 文件,文件内容会替代标签内的代码
    html
    <!-- 正确 -->
    <script src="app.js"></script>
    
    <!-- 错误:同时写 src 和内部代码时,内部代码会被忽略 -->
    <script src="app.js">
      console.log("这段代码不会执行!");
    </script>

(2) <link> 标签

  • 使用 href 关联 CSS 文件,浏览器会加载但不会替换标签本身
    html
    <link href="style.css" rel="stylesheet">

(3) <a> 标签

  • 使用 href 定义超链接,点击后跳转到目标 URL:
    html
    <a href="https://example.com">访问网站</a>

(4) <img> 标签

  • 使用 src 加载图片资源,图片会替代 <img> 标签的位置
    html
    <img src="photo.jpg" alt="示例图片">

4. 加载行为差异

  • src 的阻塞性: 浏览器遇到 src 属性时会暂停解析 HTML,直到资源加载并执行完成(如 JS 文件)。

    html
    <!-- 页面会等待 app.js 加载执行完成后,再继续渲染 -->
    <script src="app.js"></script>
  • href 的非阻塞性: 浏览器遇到 href 属性时会并行加载资源,不会阻塞 HTML 解析(如 CSS 文件)。

    html
    <!-- 页面继续渲染,同时加载 style.css -->
    <link href="style.css" rel="stylesheet">

5. 常见误区

(1) 混淆 <link><script>

  • 错误
    html
    <link src="style.css"> <!-- 应用 href,而非 src -->
    <script href="app.js"></script> <!-- 应用 src,而非 href -->

(2) 误用 <a> 标签的 src

  • 错误
    html
    <a src="page.html">点击</a> <!-- 应用 href -->

总结

场景使用 src使用 href
资源类型直接嵌入内容(JS、图片、框架等)关联外部资源(CSS、超链接等)
是否替换元素内容
加载行为阻塞非阻塞
典型标签<script><img><iframe><a><link><area>

简单记忆

  • src“拿来用”(替换当前内容),如脚本、图片。
  • href“指向它”(建立关联),如超链接、样式表。