学习目标
完成本单元后,您将能够:
- 描述JavaScript和浏览器之间的交互。
- 解释Web API的角色。
- 使用基本的文档对象模型API。
- 描述闪电组件抽象DOM的方式。
JavaScript在浏览器中的工作方式
您刚刚了解了一些JavaScript运行时引擎和语言。您还学到了一些编写JavaScript的人都应该知道的东西。在本模块中,我们重点介绍JavaScript与浏览器之间的关系,特别关注您的网页在JavaScript中的外观。
JavaScript运行时不是浏览器,也不是浏览器JavaScript
因此,JavaScript运行时引擎可以在许多不同的地方运行,但是最常托管在浏览器中。那么JavaScript和浏览器之间有什么区别?
浏览器的主要工作是充当Web服务器的客户端。它使用几种协议(通常为HTTP / HTTPS)之一通过Internet请求资源。服务器将其中的一些资源传递给服务器后,浏览器需要对其进行处理。至少将HTML和CSS渲染到页面中。当资源包含一些JavaScript时,浏览器将到达JavaScript运行时引擎以解析,评估和执行该代码。
同样,在执行脚本时,它也可以返回到浏览器以执行诸如修改网页,与本地环境交互或与其他Web资源交互的操作。
为了使这些交互有效,浏览器会显示API。实际上,人们认为客户端JavaScript的很大一部分实际上就是这些API。
Web API
标准品
能够与浏览器进行交互的API并不奇怪。就像任何其他编程语言或平台界面API与其在其上运行的环境进行交互一样,您的浏览器也是如此。
虽然超过一半的浏览器互联网 流量来自Google Chrome浏览器,但大约另外30%来自其他五个浏览器。这强调了Web标准对于这些API的重要性,因此JavaScript可以编写一次并可以在任何地方运行。
将Web API添加到图片
以前,我们创建了JavaScript运行时的图片。
- 请求使用单个线程在堆栈上执行。
- 一个请求将保留线程,直到该线程执行完该请求的所有同步逻辑为止。
- 新请求将排队,直到线程准备就绪。
- 事件循环在下一个排队的请求可用时将其移入堆栈。
现在,我们将Web API添加到JavaScript图片中。这些扩展了核心JavaScript语言。它们显示界面,这些界面执行了许多对于现代Web用户体验至关重要的工作。例如,浏览器API可以:
- 与浏览器中呈现的当前页面的结构进行交互(文档对象模型或DOM API)
- 在不离开当前页面的情况下执行对服务器的异步请求(Fetch API)
- 与音频,视频和图形进行交互
- 与显示在浏览器上的设备功能进行交互(地理位置,设备方向,客户端数据存储)
在大多数情况下,正是这些API向队列添加了新请求。
注意
我们正在避开JavaScript生态系统的重要组成部分:抽象或扩展浏览器功能的第三方API和JavaScript库。这些在野外使用JavaScript方面起着重要作用。
就我们在Salesforce中的目的而言,我们涵盖了我们的JavaScript框架:Lightning Component Framework。具体来说,当谈论Lightning Platform上的JavaScript时,此模块介绍了Lightning Web组件开发模型。
举个例子。您在带有表单的网页上有一个注释列表。您填写表单上的某些字段,单击按钮以保存该数据,然后将新项添加到列表中。为了好玩,我们还说您将在本地缓存此新记录,以加快涉及该记录的将来请求。
这个简单的用例将与以下浏览器API交互
- 提取API(以保存记录)
- DOM API(用于将新项目添加到HTML列表中)
- 客户端数据存储(用于本地缓存数据)
让我们深入了解DOM API,因为它代表了用户在JavaScript中看到的内容。
文档对象模型
DOM:您的JavaScript页面
当请求页面然后由浏览器接收时,浏览器将解析HTML并创建该页面的描述或模型。此模型用于在浏览器的视口中绘制页面。它也通过DOM浮出水面。
将DOM视为一棵树。它始于浏览器显示功能的根:窗口。从那里开始,页面被封装在中window.document
,页面的主体位于window.document.body
。然后,树会扇动到页面上所表示的每一位内容。大多数网页都有一个非常复杂的树,其中许多节点最终以叶节点作为层次结构中最细化的部分结束。
作为一个API,DOM是巨大的,它使您可以触摸树的每个部分。它还具有许多优化与DOM交互的方法。看一下jsbin.com 上的这个简单 示例。它 包括:
- 输入字段
- 添加项目按钮
- 无序列表
每次单击按钮时,代码都会到达输入字段,读取其值,将其转换为文本节点,创建一个新li
元素,将文本节点插入该li
节点,最后将新的li
-and-text节点粘贴到的ul
。
注意
为了获得更多乐趣,并且如果您想实践到目前为止讨论的一些原理,请查看是否可以修改jsbin以执行以下操作。
- 检查文本输入中是否有数据
- 如果不是,请不要在列表中添加新的li
- 添加新li后,清除文本输入
如果悬念杀死了您,请查看修改后的 代码。
如您所见,仅此简单示例就需要开发人员执行一系列手动步骤。而且它甚至不会在服务器上存储任何数据,也不会以任何其他方式与服务器交互。因此,JavaScript库(reactjs,jQuery)和框架(Angular,vuejs)已成为交互式页面的标准。这样的框架会抽象化并简化DOM交互,并且通常会自动对缺少的功能应用polyfill。闪电组件框架没有什么不同。
使用Shadow DOM封装
DOM API丰富而灵活。使用相对简单的JavaScript,很容易对UI调用的外观,行为和动作进行更改。
但是有一个陷阱。DOM模型使得难以封装UI部分并保护它们免受意外(或有目的和恶意)更改的影响。
因此,开发了Shadow DOM标准。Shadow DOM在UI功能的特定部分周围创建边界。该边界可防止父母更改孩子的元素或CSS。它还会强制跨边界传播的所有事件重新确定其目标范围,从而阻止父级跨越阴影DOM边界。
Lightning组件框架:Aura组件和Lightning Web组件
从Spring ’19版本(API版本45.0)开始,您可以使用两个编程模型来构建Lightning组件:Lightning Web组件模型和原始的Aura组件模型。闪电Web组件是使用HTML和现代JavaScript构建的自定义HTML元素。闪电Web组件和Aura组件可以在页面上共存和互操作。此内容仅涵盖Lightning Web Components。
闪电Web组件和DOM
注意
从现在开始,每个单元都有一个相似的部分,并带有一些示例,以说明与Lightning Web Components的关联。如果您想应用所学内容,现在是开始在Trailhead上使用Lightning Web Components Basics 模块的好时机 。
自动DOM更新
Lightning组件的基本价值在于构建由Salesforce数据驱动的自定义UI。这与DOM操作有关,因为DOM本身是由Salesforce数据驱动的。
该组件以最简单的形式演示了该原理。
这是此组件的代码。
// JavaScript Module: demo.js
import { LightningElement } from 'lwc';
export default class Demo extends LightningElement {
text = 'This text came from a JS prop';
}
<!-- HTML Template: demo.html -->
<template>
<lightning-card title="Basic DOM Example" icon-name="utility:hierarchy">
<div class="slds-card__body slds-card__body-inner">
<p>
<lightning-formatted-text value={text}></lightning-formatted-text>
</p>
</div>
</lightning-card>
</template>
首先介绍一下上下文:每个Lightning Web组件都需要一个JavaScript模块。如果组件包含要呈现给用户的任何元素,则也需要HTML模板。大多数组件在捆绑中都包含一个JavaScript和一个HTML文件。
Lightning Web Components使将数据呈现到UI变得毫不费力。例如,上面的代码使用JavaScript属性text
存储硬编码的字符串。在<lightning-formatted-text>
标记中,value
属性的text
属性绑定到JavaScript text
属性,从而在UI中呈现数据。
但是,如果您希望用户交互时更改UI,该怎么办?我们可以扩展这个例子来做到这一点。
这是代码。
// JavaScript Module demo2.js
import { LightningElement, track } from 'lwc';
export default class Demo2 extends LightningElement {
@track text = '';
handleChange(event){
this.text = event.target.value;
}
}
<!-- HTML Template demo2.html -->
<template>
<lightning-card title="Basic DOM Example" icon-name="utility:hierarchy">
<div class="slds-card__body slds-card__body-inner">
<p>
<lightning-formatted-text value={text}></lightning-formatted-text>
</p>
<p>
<lightning-input onchange={handleChange} label="Input Text" value={text}></lightning-input>
</p>
</div>
</lightning-card>
</template>
如果text
再次查看该属性,则会看到我们添加了一些新行为。通过使用@track
,我们利用了称为装饰器的相对较新的JavaScript功能。此装饰器将功能附加到属性,以确保在其值更改时重新呈现组件的DOM。
在模板中,我们添加了一个<lightning-input>
。尽管绑定text
属性是显示数据的关键,但请注意该onchange
属性。handleChange
现在已由change
事件触发已添加到JavaScript模块的功能。用户对值的每次修改都会更新的值text
。文本更新时,DOM也更新。
尽管这是一个人为的示例,但它说明了Lightning Web Components如何显示使隐式DOM更改易于实现为开发人员的功能。
显式DOM操作
在构建Lightning Web组件时,手动DOM操作不应该是您的首要策略,但是更复杂的组件可能需要您这样做。这是一个更高级的主题,但是在签署DOM之前值得先了解一下它的工作原理。
有条件的渲染
编写Lightning Web组件时,可以显式定义UI的部分,这些部分仅在满足某些条件时才呈现。您可以通过在嵌套 标记中添加if:true
or if:false
指令来实现template
。
//conditionalButton.js
import { LightningElement, track } from 'lwc';
export default class ConditionalButton extends LightningElement {
@track show = true;
handleClick(){
this.show = !this.show;
}
}
//conditionalButton.html
<template>
<lightning-card title="Conditional Rendering with Button" icon-name="utility:hierarchy">
<div class="slds-card__body slds-card__body-inner">
<p>
<template if:true={show}>
Peek-a-boo!
</template>
<template if:false={show}>
I'm hiding!
</template>
</p>
<p>
<lightning-button onclick={handleClick} variant="neutral" label="Switch"></lightning-button>
</p>
</div>
</lightning-card>
</template>
在此代码示例中,文本Peek-a-boo!该show
属性值为时出现true
。当show设置为时false
,我隐藏的文本!出现。单击该按钮可切换show
属性的值。
手动操作DOM的其他方法
在某些情况下,可以使用显示CSS样式来操作DOM元素的显示。尽管此方法在Lightning Web Components中照常工作,但超出了此特定模块的范围。