HTML-DOM模型

1.DOM模型

window对象下的document对象就是DOM模型。 DOM描绘了一个层次化的节点树,每一个节点就是一个html标签,而且每一个节点也是一个DOM对象。

2.操作DOM

2.1.获取DOM对象常用方法

获取DOM对象的常用方法有如下几种:

  1. getElementById() 通过元素的ID属性获取DOM对象,获取的是一个DOM对象
  2. getElementsByTagName() 通过元素的标签名获取DOM对象,获取的是一组DOM对象
  3. getElementsByClassName() 通过元素的class属性获取DOM对象,获取的是一组DOM对象
  4. getElementsByName() 通过元素的name属性获取DOM对象,获取的是一组DOM对象
	<p id="one">这是一个p标签</p><p class="first">这是一个p标签</p><p class="first">这是一个p标签</p><p name="username">这是一个p标签</p><p name="username">这是一个p标签</p><script>let oneObj = document.getElementById('one');oneObj.style.color = 'red';     //只有第一个p标签字体变红色let pArr = document.getElementsByTagName('p');console.log(pArr.length);       //获取所有p标签对象,是数组,长度为5let firstArr = document.getElementsByClassName('first');console.log(firstArr.length);   //获取所有class为first的对象,是数组,长度为2let userArr = document.getElementsByName('user');console.log(userArr.length);    //获取所有name属性为user的对象,是数组,长度为2</script>

上面代码中所涉及的知识点: 给DOM对象设置CSS样式的语法: DOM对象.style.样式属性名 = '样式值'

2.2.其它获取DOM对象的方法(扩展)

  1. document.documentElement 获取html对象
  2. document.body 获取body对象
  3. document.querySelector() 通过选择器获取一个DOM对象
  4. document.querySelectorAll() 通过选择器获取一组DOM对象
<div><p>这是一个p标签</p><p>这是一个p标签</p>
</div>
<script>let htmlObj = document.documentElement;htmlObj.style.backgroundColor = 'red';       //设置html背景色let bodyObj = document.body;bodyObj.style.fontSize = '36px';             //设置body中所有元素的字体大小let pObj = document.querySelector('div p');pObj.style.color = 'blue';                   //第一个p标签有效let pArr = document.querySelectorAll('div p');console.log(pArr.length);                    //数组长度为2
</script>

2.3.获取DOM对象的时机

  1. 要特别注意一点,javaScript代码要写在body的最后。因为,必须要保证html代码全部加载完毕之后,才执行javaScript代码,才能获取DOM对象。
  2. 如果一定要将javaScript代码放在html之前那么要做如下写法:
<script>//文档就绪函数window.onload = function(){var obj = document.getElementById("one");obj.innerHTML = 'hello world!';};
</script>
<p id="one"></p>

window.onload事件:浏览器完成页面加载(包括图片等资源)后立即触发,此事件的处理函数就叫做“文档就绪函数”。 如果使用window.onload事件的话,我们就可以将javaScript代码写在网页的任何一个部分,或者是任何一个外部js文件中。

2.4.操作DOM对象属性

操作DOM对象的属性,常用的都有两种方式:

  1. 通过DOM对象直接操作属性
<p>hello world</p>
<input type="text">
<script>document.getElementsByTagName('p')[0].title = 'aaaa';let userName = document.getElementsByTagName('input')[0];userName.value = 'zhangsan';userName.disabled = true;
</script>
  1. 通过DOM对象中封装的方法操作属性 setAttribute() 设置元素的属性值 getAttribute() 获取元素的属性值 removeAttribute() 移除元素的属性值
<p>hello world</p>
<input type="text">
<script>document.getElementsByTagName('p')[0].setAttribute('title','aaaa');let userName = document.getElementsByTagName('input')[0];userName.setAttribute('value','zhangsan');userName.setAttribute('disabled',true);userName.removeAttribute('disabled');console.log(userName.getAttribute('value'))
</script>

2.5.DOM对象中的常用属性

  1. innerHTML属性:用于设置或获取HTML 元素中的内容。
<p id="one"><span>这是一个段落</span>
</p>
<script>let obj = document.getElementById('one');console.log(obj.innerHTML);                  //<span>这是一个段落</span>obj.innerHTML = '<span>hello world!</span>';
</script>
  1. innerText属性:用于设置或获取HTML 元素中的纯文本
<p id="one"><span>这是一个段落</span>
</p>
<script>let obj = document.getElementById('one');console.log(obj.innerText);                  //这是一个段落obj.innerText = 'hello world!';
</script>
  1. className属性:用于设置或获取DOM对象的类样式
<div id="one" class="first"></div>
<script>let obj = document.getElementById('one');console.log(obj.className);                //firstobj.className = 'two';
</script>
  1. style属性:用于设置或获取DOM对象的style样式
<div id="one">我是一个div</div>
<script>let obj = document.getElementById('one');obj.style.width = '300px';obj.style.height = '200px';obj.style.backgroundColor = 'blue';obj.style.fontSize = '24px';obj.style.color = '#fff';obj.style.border = 'solid 10px red';obj.style.display = 'block';          //设置DOM对象的显示和隐藏
</script>

注意:

在使用javaScript操作DOM对象的CSS样式时,由于javaScript不能识别 ”-” 字符,所以,所有CSS样式的书写,要一律从xxxx-xxxx形式转换为xxxxXxxx的形式。

2.6.遍历DOM数组

在上面的例子中,都是使用getElementById获取一个DOM对象进行操作。 但在实际开发中,经常会同时操作多个DOM对象,此时,可以使用循环来遍历DOM数组。

<p>我是p标签</p>
<p>我是p标签</p>
<p>我是p标签</p>
<script>let arr = document.getElementsByTagName('p');for(let i=0;i<arr.length;i++){arr[i].style.color = 'red';arr[i].style.fontSize = '36px';}
</script>

3.代码调试

调试是指在一个脚本中找出并修复错误的过程。在浏览器中调试是开发过程中常见的操作,它可以帮助你查找和修复代码中的错误,也可以让我们一步步地跟踪代码以查看当前实际运行情况。在这里我们将会使用 Chrome(谷歌浏览器),因为它拥有足够多的功能,其他大部分浏览器的功能也与之类似。

3.1 打开浏览器的开发者工具

  • Google Chrome:右键点击页面任意位置,选择“检查”或按下Ctrl + Shift + ICmd + Option + I(Mac)或者使用快捷键 F12来打开开发者工具。然后切换到“Console”(控制台)选项卡。
  • Mozilla Firefox:同样,使用Ctrl + Shift + ICmd + Option + I(Mac)来打开开发者工具,然后切换到“Web Console”(Web控制台)选项卡。
  • Microsoft Edge:使用F12键或右键点击页面并选择“检查元素”打开开发者工具,然后切换到“Console”选项卡。

3.2 设置界面语言

3.3 重现错误

<html><head><title>Demo: 使用 Chrome DevTools 调试 JavaScript</title><meta name="viewport" content="width=device-width, initial-scale=1"><style>h1 {font-size: 1.5em}input, button {min-width: 72px;min-height: 36px;border: 1px solid grey;}label, input, button {display: block;}input {margin-bottom: 1em;}</style></head><body><h1>使用 Chrome DevTools 调试 JavaScript</h1><label for="num1">数字 1</label><input placeholder="数字 1" id="num1"><label for="num2">数字 2</label><input placeholder="数字 2" id="num2"><button>数字 1和数字 2相加 </button><p></p></body>
</html>
<script>function onClick() {if (inputsAreEmpty()) {label.textContent = 'Error: 有一个或者两个文本框值为空';return;}updateLabel();
}
function inputsAreEmpty() {if (getNumber1() === '' || getNumber2() === '') {return true;} else {return false;}
}
function updateLabel() {var addend1 = getNumber1();var addend2 = getNumber2();var sum = addend1 + addend2;label.textContent = addend1 + ' + ' + addend2 + ' = ' + sum;
}
function getNumber1() {return inputs[0].value;
}
function getNumber2() {return inputs[1].value;
}
var inputs = document.querySelectorAll('input');
var label = document.querySelector('p');
var button = document.querySelector('button');
button.addEventListener('click', onClick);</script>

运行结果:

在本例中,1 + 2 的结果是 12。应该是 3。

3.4 调试并修复错误

3.4.1 熟悉“来源”面板界面

开发者工具提供了许多不同的工具来处理不同的任务,例如更改 CSS、分析网页加载性能以及监控网络请求。您可以在 Sources 面板中调试 JavaScript。

  1. 按 Command+Option+J (Mac) 或 Control+Shift+J(Windows、Linux)打开开发者工具。此快捷方式可打开控制台面板,并点击来源标签页。

2、Sources 面板界面包含 3 个部分:

  1. 文件导航器窗格。此处列出了网页请求的每个文件。
  2. 代码编辑器窗格。在文件导航器窗格中选择文件后,此处会显示该文件的内容。
  3. JavaScript 调试窗格。用于检查网页 JavaScript 的各种工具。如果开发者工具窗口较宽,此窗格会显示在 Code Editor 窗格的右侧。

3.4.2 使用断点暂停代码

调试这类问题的常用方法是在代码中插入大量 console.log() 语句,以便在脚本执行时检查值。由于前端代码相对比较简单,函数的代码量较少,这也是目前非常有效的做法。

function updateLabel() {var addend1 = getNumber1();console.log('addend1:', addend1);var addend2 = getNumber2();console.log('addend2:', addend2);var sum = addend1 + addend2;console.log('sum:', sum);label.textContent = addend1 + ' + ' + addend2 + ' = ' + sum;
}

console.log() 方法可以完成工作,但断点可以更快地完成工作。通过断点,您可以在代码执行过程中暂停代码,并在该时刻检查所有值。与 console.log() 方法相比,断点具有一些优势:

  • 使用 console.log() 时,您需要手动打开源代码,找到相关代码,插入 console.log() 语句,然后重新加载页面,才能在控制台中查看这些消息。使用断点,您甚至无需了解代码的结构即可暂停相关的代码。
  • 在 console.log() 语句中,您需要明确指定要检查的每个值。使用断点,开发者工具会及时显示所有变量的值。有时,有些变量在您不知情的情况下会影响您的代码。

简而言之,与 console.log() 方法相比,断点可以帮助您更快地查找和修复 bug。

如果您退一步想一想应用的工作原理,可以有据地猜测,系统会在与 Add Number 1 and Number 2 按钮关联的 click 事件监听器中计算不正确的总和 (5 + 1 = 51)。因此,您可能需要在 click 监听器执行前后暂停代码。事件监听器断点可让您实现以下目的:

  1. JavaScript 调试窗格中,点击事件监听器断点以展开该部分。开发者工具会显示一系列可展开的事件类别,例如 AnimationClipboard
  2. 点击鼠标事件类别旁边的展开 。 开发者工具会显示鼠标事件列表,例如 clickmousedown。每个事件旁都有一个复选框。
  3. 选中 click 复选框。开发者工具现已设置为在执行任何 click 事件监听器时自动暂停。
  4. 返回演示,再次点击 Add Number 1 and Number 2(添加编号 1 和编号 2)。开发者工具会暂停演示,并在 Sources 面板中突出显示一行代码。在以下代码行上,开发者工具应暂停:

注意:如果您是在其他代码行暂停,请按 Resume Script Execution 图标 ,直到暂停位置正确。

事件监听器断点只是开发者工具中提供的众多断点类型之一。您需要记住所有不同的类型,因为每种类型最终都可以帮助您尽快调试不同的场景。如需了解每种类型的使用时机和使用方式,请参阅使用断点暂停代码。

3.4.3.单步调试代码

导致 bug 的一种常见原因是脚本执行顺序有误。您可以通过单步调试代码一次一行地检查代码执行情况,并弄清楚代码的执行顺序与预期不同。立即试用:

  1. 在开发者工具的 Sources 面板中,点击 Step into next function call 图标

    ,以一次一行的形式逐步执行 onClick() 函数。开发者工具会突出显示下面这行代码:
if (inputsAreEmpty()) {

  1. 点击 Step over next function call【跳过下一个函数调用】 图标

    。 开发者工具会执行 inputsAreEmpty(),而不会进入它。请注意开发者工具如何跳过几行代码。这是因为 inputsAreEmpty() 的求值结果为 false,所以 if 语句的代码块未执行。

相比之下,

这就是单步调试代码的基本思路。

3.4.4 设置代码行断点

代码行断点是最常见的断点类型。如果您想在执行到某一行代码时暂停,请使用代码行断点。

使用代码行断点之前,首先您应该先对自己的代码进行简要评估,按照业务的执行顺序,估计出错误代码的范围,一般代码行断点设在此范围之前。

  1. 请查看 updateLabel() 中的最后一行代码:
label.textContent = addend1 + ' + ' + addend2 + ' = ' + sum;
  1. 在代码左侧,您可以看到这行代码的行号,即 53。点击 53。开发者工具会在 53 上方显示一个蓝色图标。这意味着这行代码上有一个代码行断点。现在,开发者工具始终会在执行这行代码之前暂停。

  1. 点击继续执行脚本

    。脚本会继续执行,直到第 32 行。在第 29、30 和 31 行,开发者工具以内嵌方式显示 addend1、addend2 和 sum 的值。

在此示例中,开发者工具在第 53 行代码行断点处暂停。

3.4.5 检查变量值

addend1、addend2 和 sum 的值看起来很可疑。它们是用英文引号引起来的,这意味着它们是字符串。这是一个很好的假设,可以解释错误的原因。现在可以收集更多信息了。开发者工具提供了许多用于检查变量值的工具。

方法 1:Scope【本地】 窗格

在某行代码上暂停时,Scope 【本地】窗格会显示当前定义的局部和全局变量,以及每个变量的值。其中还会显示闭包变量(如果适用)。双击变量值即可对其进行修改。如果未在任何代码行暂停,则 Scope 【本地】窗格为空。

方法 2:监视表达式

监视表达式标签页可让您监控变量的值随时间的变化。顾名思义,监视表达式不仅限于变量。您可以将任何有效的 JavaScript 表达式存储在监视表达式中。立即试用:

  1. 点击观看标签页。
  2. 点击添加表达式

  3. 输入 typeof sum。
  4. 按 Enter 键。开发者工具会显示 typeof sum: "string"。冒号右侧的值是监视表达式的结果。

上面的屏幕截图显示了创建 typeof sum 监视表达式后的 Watch Expression 窗格(右下角)。如果开发者工具窗口较大,Watch Expression 窗格位于右侧,在 Event Listener Breakpoints 窗格的上方。

就像猜测一样,sum 的求值结果本应是数字,而实际结果却是字符串。现在,您已确认这是导致 bug 的原因。

方法 3:控制台

除了查看 console.log() 消息之外,您还可以使用控制台对任意 JavaScript 语句求值。在调试方面,您可以使用控制台测试 bug 的潜在解决方法。立即试用:

  1. 如果您尚未打开控制台抽屉式导航栏,请按 Esc 将其打开。它会在开发者工具窗口底部打开

  1. 在控制台中,输入 parseInt(addend1) + parseInt(addend2)。此语句之所以有效,是因为您暂停了 addend1 和 addend2 在范围内的代码行。

注意:需要根据提示输入:允许粘贴

  1. 按 Enter 键。开发者工具会评估语句并输出 3,这是您希望演示生成的结果。

上面的屏幕截图显示了评估 parseInt(addend1) + parseInt(addend2) 后的 Console 抽屉式导航栏。

3.4.6 应用解决方案

您已找到该 bug 的修复方案。接下来就是尝试通过修改代码并重新运行演示来尝试修复。您无需离开开发者工具即可应用修复。您可以直接在开发者工具界面中修改 JavaScript 代码。立即试用:

  1. 点击继续执行脚本

  1. 代码编辑器中,将第 53 行 var sum = addend1 + addend2 替换为 var sum = parseInt(addend1) + parseInt(addend2)。
  2. 按 Command + S (Mac) 或 Ctrl + S(Windows、Linux)以保存更改。
  3. 点击 停用断点

    。 其颜色会变为蓝色,表示处于活动状态。完成此设置后,开发者工具会忽略您已设置的任何断点。

  1. 尝试使用不同的值测试演示。演示现在会正确计算。

注意:此工作流只会修复在浏览器中运行的代码。它不会为访问您的网页的所有用户修正代码。为此,您需要修正服务器上的代码。不过,您可以在开发者工具中修改文件,并通过工作区将文件保存到来源中。

要点:从 Chrome 105 版开始,您可以实时修改已暂停的函数。

3.5 小结

Chrome提供了强大的开发者工具,使开发者能够在浏览器中调试和优化代码。除了前文外,还包括:条件断点、XHR断点、代码搜索、性能分析、网络面板、代码预处理器、移动设备模拟以及Remote Debugging等等,请大家在平时的开发过程中,注重积累。

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

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

相关文章

无线麦克风哪个好,麦克风哪个品牌音质最好,领夹麦克风推荐

​无线领夹麦克风作为直播、视频录制等场景必备的设备之一&#xff0c;用起来很方便&#xff0c;功能多样且易于操作&#xff0c;在音频设备领域占据着重要地位。但当前市场乱象较为严重&#xff0c;有许多商家纷纷打起价格战&#xff0c;忽视了产品质量&#xff0c;造成耐用性…

李沐 多层感知机【动手学深度学习v2】

学习XOR 同或操作&#xff1a;相同为1&#xff0c;不同为0。 先进入蓝色和黄色分类器&#xff0c;最后进入灰色分类器来得到最终的结果。 单隐藏层 输入为x1~x4&#xff0c;加入隐藏层后&#xff0c;x1~x4需要先进入h1~h5&#xff0c;该隐藏层再作为输入&#xff0c;连接下一层…

【24华为杯数模研赛赛题思路已出】国赛E题思路丨附参考代码丨免费分享

2024年华为杯研赛E题解题思路 E题 高速公路应急车道紧急启用模型 问题1 1. 某路段&#xff08;长度约5000m&#xff0c;行车道2应急车道1&#xff09;上有四个视频观测点&#xff08;见示意图1&#xff09;。请基于该路段四个视频数据解决如下问题&#xff1a; &#xff08;…

任天堂发言人:不会透露起诉《幻兽帕鲁》开发商细节

任天堂在昨天突然宣布将起诉《幻兽帕鲁》开发商 Pocketpair&#xff0c;除了引起许多玩家不满外&#xff0c;更多的是所有人的疑惑&#xff1a;因为实际上大家内心里觉得任天堂出手是理所当然的&#xff0c;但是为什么是在游戏发布数月后才选择起诉&#xff1f;此次诉讼是“专利…

解决引入ethereumjs-wallet报错Uncaught ReferenceError: process is defined

最近在学习web3.0开发DApp的视频教程&#xff0c;遇到用助记词生成秘钥对报错Uncaught ReferenceError: process is defined。具体报错如下截图&#xff1a; 在网上搜了好几个小时都没找到解决方法。突然在学习的视频论坛找到有哥们说是引入的包不兼容问题导致报这个错。我试了…

集合框架(一):Collection集合的遍历方式

一.迭代器遍历Collection集合 package com.njau.d2_collection_traverse;import java.util.ArrayList; import java.util.Collection; import java.util.Iterator;/*** 目标&#xff1a;Collection集合的遍历方式一&#xff1a;使用迭代器Iterator对象遍历Collection集合*/ pub…

嵌入式常用硬件电路设计及分析 — 通信篇

目录 一、简介 二、RS232通信 1、硬件电路设计 2、硬件电路设计分析 &#xff08;1&#xff09;常规电路 &#xff08;2&#xff09;EMC设计使用注意事项 3、DB9接头定义 三、RS485通信 1、硬件电路设计 2、硬件电路设计分析 &#xff08;1&#xff09;自动收发电路…

【C++】C++入门概念(一)

C关键字 C总计63个关键字&#xff0c;C语言32个关键字 ps&#xff1a;下面我们只是看一下C有多少关键字&#xff0c;不对关键字进行具体的讲解。后面我们学到以后再详细讨论。 命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、…

神州数码社招校招入职北森测评笔试:语言理解、图形推理、材料计算

神州数码入职测评使用的是北森CATA-能力倾向计算机自适应测评 国内唯一被国际计算机自适应测验协会(IACAT)收录产品&#xff0c;基于企业大量招聘下对认知能力考察的需求&#xff0c;通过最新的测评技术手段&#xff0c;快速高效,评价候选人的认知能力&#xff0c;平均作答时…

Linux环境Docker安装Mongodb

Linux环境Docker安装Mongodb 环境要求拉取指定版本镜像创建映射目录&#xff08;相当于数据存放于容器外&#xff0c;容器被删除不会影响数据&#xff09;启动容器 进入mongo命令行为指定db创建新用户查看mongodb的容器id进入命令行查看所有db切换db为指定db创建新用户使用新账…

CZ 即将回归,这四个月币安疯狂上币用意何在?

随着币安创始人赵长鹏&#xff08;CZ&#xff09;即将在2024年9月29日刑满释放&#xff0c;市场上对于他的回归以及币安未来战略方向的讨论愈演愈烈。自今年4月&#xff0c;CZ因违反美国反洗钱法被判四个月监禁后&#xff0c;币安并没有停下发展的步伐&#xff0c;反而在CZ缺席…

【python设计模式7】行为型模式2

目录 策略模式 模板方法模式 策略模式 定义一个个算法&#xff0c;把它们封装起来&#xff0c;并且使它们可以相互替换。本模式使得算法可独立于使用它的客户而变化。角色有&#xff1a;抽象策略、具体策略和上下文。 from abc import abstractmethod, ABCMeta from datetim…

2024华为杯C题详细完整思路和视频讲解

文章目录 一、背景问题描述数据描述问题问题一&#xff1a; 励磁波形分类问题二&#xff1a; 斯坦麦茨方程&#xff08;Steinmetz-equation&#xff09;修正问题三&#xff1a; 磁芯损耗因素分析问题四问题五 参考文献补充磁芯损耗分离模型磁芯损耗经验计算模型 特别注意事项问…

毕业设计选题:基于ssm+vue+uniapp的捷邻小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…

稀土抗菌剂:厨房用品中的安全卫士

稀土抗菌剂的抗菌机制是基于稀土的光催化半导体特性&#xff0c;通过光生氧自由基ROS机理杀灭细菌&#xff1b;稀土化合物与细菌表面静电结合&#xff0c;造成直接的杀灭&#xff1b;稀土化合物破坏细胞膜通透性&#xff0c;造成破损导致细胞质流出杀灭细菌;稀土离子跨膜后与细…

使用Lantern和LangChain构建RAG应用:一步步指南

使用Lantern和LangChain构建RAG应用&#xff1a;一步步指南 在本文中&#xff0c;我们将介绍如何使用Lantern和LangChain创建一个高效的RAG&#xff08;检索增强生成&#xff09;应用。我们将详细讲解环境设置&#xff0c;数据库配置&#xff0c;代码实现&#xff0c;以及如何…

表盘针头位置检测系统源码分享

表盘针头位置检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

【软设】 系统开发基础

【软设】 系统开发基础 一.软件工程概述 &#xff08;了解一下大概的流程就行&#xff09; 1. 可行性分析与项目开发计划 目的&#xff1a;评估项目的经济性、技术性和运营性&#xff0c;判断项目是否值得投资和开发。确定开发时间、预算、所需资源等。 可行性分析&#xff…

Spring Boot框架在心理教育辅导系统中的应用案例

目 录 摘 要 I ABSTRACT II 1绪 论 1 1.1研究背景 1 1.2设计原则 1 1.3论文的组织结构 2 2 相关技术简介 3 2.1Java技术 3 2.2B/S结构 3 2.3MYSQL数据库 4 2.4Springboot框架 4 3 系统分析 6 3.1可行性分析 6 3.1.1技术可行性 6 3.1.2操作可行性 6 3.1.3经济可行性 6 3.1.4法律…

Transformer模型-7- Decoder

概述 Decoder也是N6层堆叠的结构&#xff0c;每层被分3层: 两个注意力层和前馈网络层&#xff0c;同Encoder一样在主层后都加有Add&Norm&#xff0c;负责残差连接和归一化操作。 Encoder与Decoder有三大主要的不同&#xff1a; 第一层 Masked Multi-Head Attention: 采用…