第2章:HTML中的JavaScript [一起学前端]

200 阅读7分钟

第2章:HTML中的JavaScript [一起学前端]

作者是位前端切图仔,本系列旨在从头开始学习前端,巩固前端基础。同时分享学习笔记供广大同学讨论,如有编写错误或者描述问题,还请大家多多指点。


2.1 <script>元素

将JavaScript插入HTML的主要方法是使用

  • async:可选。标识应该立即开始下载脚本,但不能阻止其他页面动作,比如下载资源或等待其他脚本加载。只对外部脚本文件有效。这个属性很有用,在加载外部资源或者优化网站加载速度的时候很有效。

  • charset:可选。使用src属性指定的代码字符集。这个属性很少使用,因为大多数浏览器不在乎它的值。

  • crossorigin:可选。配置相关请求的CORS(跨源资源共享)。默认不使用CORS。

    • 值”anonymous“配置文件请求不必设置凭据标示

    • 值”use-credentials“设置凭据标示,意味着出站请求会包含凭据这里可以使用浏览器加载下跨站资源,比如CDN,很明显能看到没有携带cookie

  • defer:可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效。和async属性一样,可以用在网站优化中

  • integrity:可选。用来验证资源完整性,类似MD5摘要算法。防止外部文件被修改导致页面被攻击,比如加载外部CDN资源,签名生成算法可以参照MDN

  • language:废弃

  • src:可选。表示包含要执行的代码的外部文件

  • type:可选。代替language,现在比较常用的应该是module 用来加载ES6模块

当然使用script标签的时候,也可以使用行内代码进行编写。

在使用行内JavaScript编写代码时,要注意代码中不能出现字符串。比如下面的代码会导致浏览器报错

<script>
    function sayScript(){
        console.log("</script>"); // 这里会报错,解决方法,使用转义字符处理下 \/
    }
</script>

另外script标签是成对出现的,自闭和标签在某些场景下可以使用,比如XHTML文档中,但是大部分还是需要成对出现,避免浏览器不识别。

注意:按照管理,外部JavaScript文件的扩展名是js。这不是必须的,因为浏览器不会检查所包含JavaScript文件的扩展名。这就为使用服务器脚本语言动态生成JavaScript代码,或者在浏览器中将JavaScript扩展语言转译为JavaScript提供了可能性。不过要注意,服务器经常会根据文件扩展来确定响应的正确MIME类型。如果不打算使用.js扩展名,一定要确保服务器能返回正确的MIME类型。

2.1.1 标签位置

过去,所有script元素都被放在页面的head标签内,现代Web应用程序通常将所有JavaScript引用放在body元素中的页面内容后面。

上面是书上的描述,但是现在应该是反的了

  • 以前使用jQuery进行开发的时候,页面基本上都是CSS加HTML进行编写,这个时候脚本确实需要放在页面底部,这样用户可以先看到页面的布局,然后再加载动画,交互和请求的JS

  • 但是现在都是VUE react这种脚手架工具,压根就不会生成html结构,页面只剩下了JS文件,放到哪里都没区别,body里面只有一个app

2.1.2 推迟执行脚本

defer属性会让脚本延迟到整个页面都解析完毕后再运行。因此,在Script元素上设置defer属性,相当于告诉浏览器立即下载,但延迟执行。

2.1.3 异步执行脚本

从改变脚本处理方式上看,async属性和defer类似。当然,它们两者也都只适用于外部脚本,都会告诉浏览器离职开始下载。不过,与defer不同的是,标记为async的脚本并不保证能按照它们出现的次序执行。

2.1.4 动态加载脚本

let script = document.createElement('script');
script.src = 'aaaa.js';
document.head.appendChild(script);

当然,在把HTMLElement元素添加到DOM且执行到这段代码之前不会发送请求。默认情况下,以这种方式创建的属性。不过这样做可能会有问题,因为所有浏览器都支持async属性。因此,如果要统一动态脚本的加载行为,可以明确将其设置为同步加载:

script.async=false;

以这种方式获取的资源对浏览器预加载器是不可见的。这会严重影响它们在资源队列中的优先级。根据应用程序的工作方式以及怎么使用,这种方式可能会严重影响性能。要想让预加载器知道这些动态请求文件的存在,可以在文档头部显示声明它们

<link rel="preload" href="aaaa.js">

2.1.5 XHTML中的变化

这章主要讲解了语法的区别,其中type是必须的,里面还有一些语法的解释问题,比如< 可以使用一些hack语法进行处理,比如

<script type="text/javascript">
    //<![CDATA[
        function compare(a,b){
            if(a<b){ ... }
       }
    // ]]>
</script>

2.2 行内代码与外部文件

虽然可以直接在HTML文件中嵌入JavaScript代码,但通常认为最佳实践是尽可能将JavaScript代码放在外部文件中。不过这个最佳实践并不是明确的强制性规则。推荐使用外部文件的理由如下。

  • 可维护性。JavaScript代码如果分散到很多HTML页面,会导致维护困难,而用一个目录保存所有JavaScript文件,则更容易维护,这样开发者就可以独立于使用它们的HTML页面来编辑代码

  • 缓存。浏览器会根据特定的设置缓存所有外部链接的JavaScript文件,这意味着如果两个页面都用到同一个文件,则该文件只需下载一次。这最终意味着页面加载更快

  • 适应未来。通过把JavaScript放到外部文件中,就不必考虑用XHTML或前面提到的注释黑科技。包含外部JavaScript文件的语法在HTML和XHTML中是一样的

在初次请求时。如果浏览器支持SPDY/HTTP2,就可以从同一个地方取得一批文件,并将它们逐个放到浏览器缓存中。从浏览器角度看,通过SPDY/HTTP2获取所有这些独立的资源与获取一个大JavaScript文件的延迟差不多

个人认为也就是说现在浏览器对于多文件下载或者单个大文件下载并没有特别大的区别

2.3 文档模式

这里说的是在网页的头部,可以使用doctype来进行文档模式的声明,不过现在都被HTML5的规范统一了,下面是一些旧版本的声明

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"

2.4 元素

针对早期浏览器不支持JavaScript的问题,需要一个页面优雅降级的处理方案。最终,元素出现,被用于给不支持JavaScript的浏览器提供替代内容。

比如现在使用VUE 或者react打包之后的index.html 中还是能看到这个代码的影子,就是为了告诉用户当前浏览器不支持JS

当然也不一定是浏览器不支持JS,也可能是用户手动禁用了脚本支持

Q&A

  • script 标签如果既有src 又有行内代码,哪个生效呢?(建议手动试试)

  • 为了方式脚本堵塞页面,有哪些解决办法?至少三种

  • 为什么标签可以在不支持JS的浏览器上显示?在支持JS的浏览器不显示呢?