阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > <script>-客户端脚本

<script>-客户端脚本

作者:陈川 阅读数:10795人阅读 分类: HTML

<script> 标签是 HTML 中用于嵌入或引用客户端脚本的核心元素,通常用于实现动态交互、数据操作或第三方功能集成。它支持多种属性和加载方式,直接影响脚本的执行时机和行为。

<script> 标签的基本语法

<script> 标签的常规写法分为两种:内联脚本和外部脚本。内联脚本直接将代码写在标签内,而外部脚本通过 src 属性引入外部文件。

<!-- 内联脚本示例 -->
<script>
  console.log('内联脚本执行');
</script>

<!-- 外部脚本示例 -->
<script src="app.js"></script>

未指定 type 属性时,默认值为 text/javascript。现代开发中通常省略 type,因为 JavaScript 已是默认脚本语言。

关键属性解析

src 属性

用于引用外部脚本文件,可以是绝对路径或相对路径。例如:

<script src="https://example.com/library.js"></script>
<script src="/local/path/app.js"></script>

asyncdefer

控制脚本的加载和执行时机:

  • async:异步加载,下载完成后立即执行,不保证顺序。
    <script async src="script1.js"></script>
    <script async src="script2.js"></script>
    <!-- script2.js 可能先于 script1.js 执行 -->
    
  • defer:延迟到文档解析完成后按顺序执行。
    <script defer src="vendor.js"></script>
    <script defer src="app.js"></script>
    <!-- 保证 vendor.js 在 app.js 前执行 -->
    

type 的特殊值

除常规的 MIME 类型外,还可使用模块化脚本:

<script type="module">
  import { utils } from './utils.js';
  console.log(utils.version);
</script>

脚本加载策略

阻塞渲染问题

默认情况下,浏览器解析到 <script> 时会暂停 HTML 解析,立即执行脚本。将脚本放在 <body> 末尾可减少影响:

<body>
  <!-- 页面内容 -->
  <script src="app.js"></script>
</body>

动态加载脚本

通过 DOM API 动态插入脚本:

const script = document.createElement('script');
script.src = 'dynamic.js';
document.head.appendChild(script);

实际应用场景

数据埋点

异步加载统计脚本以避免影响主线程:

<script async src="https://analytics.example.com/tracker.js"></script>

第三方库集成

使用 defer 确保依赖顺序:

<script defer src="jquery.min.js"></script>
<script defer src="plugin-depends-on-jquery.js"></script>

性能优化实践

  1. 代码拆分:按需加载非关键脚本
    if (userNeedsFeature) {
      import('./heavy-module.js').then(module => {
        module.init();
      });
    }
    
  2. Intersection Observer 懒加载
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const script = document.createElement('script');
          script.src = entry.target.dataset.src;
          document.body.appendChild(script);
          observer.unobserve(entry.target);
        }
      });
    });
    observer.observe(document.querySelector('[data-src]'));
    

安全注意事项

内容安全策略 (CSP)

通过 HTTP 头限制脚本来源:

Content-Security-Policy: script-src 'self' https://trusted.cdn.com

防止 XSS

避免拼接 HTML 插入脚本:

// 危险示例
document.write(`<script>alert("${userInput}")</script>`);

// 安全做法
const el = document.createElement('div');
el.textContent = userInput;
document.body.appendChild(el);

兼容性与现代实践

传统浏览器降级

使用 nomodule 为不支持 ES6 的浏览器提供回退:

<script type="module" src="modern.js"></script>
<script nomodule src="legacy.js"></script>

预加载关键资源

通过 <link rel="preload"> 提前加载:

<link rel="preload" href="critical.js" as="script">

调试技巧

源代码映射

通过 sourcemap 调试压缩代码:

<script src="app.min.js"></script>
<!-- 同时存在 app.min.js.map -->

错误捕获

全局监听脚本错误:

window.addEventListener('error', (e) => {
  console.error('脚本加载失败:', e.filename);
});

与其他技术的协作

与 Web Workers 配合

将计算密集型任务移出主线程:

// main.js
const worker = new Worker('worker.js');
worker.postMessage(data);

// worker.js
self.onmessage = (e) => {
  const result = heavyComputation(e.data);
  self.postMessage(result);
};

服务器端渲染 (SSR) 注意事项

避免重复执行客户端脚本:

<script data-ssr="true">
  window.APP_DATA = JSON.parse('{{serverData|escapejs}}');
</script>

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益,请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌