HTML

前言

对于script标签,对于一个前端开发工程师来说,不会陌生,反而熟悉,因为只要写纯静态html,想要写点脚本,那么就需要在页面顶部或者body底部插入script标签,比较熟悉的有src,和type属性,来看看这个type属性。

1、type

MDN:该属性定义script标签元素包含或src应用的脚本语言,属性的值为MIME类型(Multipurpose Internet Mail Extensions Type,多用途互联网邮件扩展类型)也叫媒体类型
支持的MIME类型包括text/javascripttext/ecmascriptapplication/javascript,和application/ecmascriptapplication/jsonmodule
大部分媒体类型是服务端通过http协议告知客户端(浏览器)的,准确的来说,是服务端通过Content-type这个响应头来告诉浏览器接收到的响应体的媒体类型到底是什么。
这个媒体类型决定了服务端返回的内容(响应体)究竟该如何被浏览器解析处理,比如:Content-type: text/html,此时浏览器将会将响应的内容当做一个html文件来解析处理。
在script标签中如果没有定义这个type属性,脚本会被视为javascript,会被浏览器解析。

2、type=""text/javascript

平时写script标签的时候,一些编辑器如果安装emmet插件,就会自动的提升将这个type="text/javascript"属性带上

  1. <script type="text/javascript"></script>

这个是可以省略的,加上的话是html4and xHTML,而忽略的话表示是HTML5的写法,也就是说,在最新的语法规则里,把这个type="text/javascript"自动给加上了的。
当在script标签上定义了type="text/javascript",此时浏览器会将里面的内容当做javascript来执行,所以写在里面的代码,要符合js语法的规范,否则就会报错。

  1. <script type="text/javascript">
  2. // 这里面书写形式得符合Js语法的一个规范,否则的话就会报错
  3. console.log(name); // 会报错,因为没有定义name这个变量,就直接读取这个变量的,这个变量不存在
  4. // 正确的写法
  5. var name = "itclan.cn"
  6. console.log(name);
  7. </script>

在阅读有些网站源码的时候,在script标签上除了type="text/javascript",还会看到一个就是application/json
比如:Nextjs官网,打开console,Elelement或netWork,直接搜索即可。

3、application/json

看到这个type值,会想到服务端请求头会返回一个响应头

  1. Content-Type: application/json;

type="text/javascript",是让浏览器把标签里面的内容当做js来执行,那这里的application/json

  1. <script type="application/json">
  2. const nameStr = "it";
  3. console.log(nameStr);
  4. </script>

这个时候刷新页面,打开控制台,it,不会被输出,控制台一片空白,没有报错,也没有输出任何内容
如果写成type="text/javacript"script里面的内容就会被浏览器当做js来执行,因此一开始的js执行了就会输出it
scripttype属性为application/json时浏览器则不会把script里面的内容当做js来执行,那如果把标签里面内容修改为json格式呢

  1. <script type="application/json">
  2. {
  3. "data": [
  4. {
  5. "a": 1,
  6. "b": 2
  7. },
  8. {
  9. "c": 3,
  10. "d": 4
  11. }
  12. ],
  13. "total": 100
  14. }
  15. </script>

会发现控制台没有任何变化,也不会报错,但是想要获取里面的内容,给这个script标签添加上个id

  1. <script id="json-script" type="application/json">
  2. {
  3. "data": [
  4. {
  5. "a": 1,
  6. "b": 2
  7. },
  8. {
  9. "c": 3,
  10. "d": 4
  11. }
  12. ],
  13. "total": 100
  14. }
  15. </script>

然后再通过一段js去获取这个标签里面的内容再转成json:

  1. <script>
  2. const node = document.getElementById("json-script");
  3. const jsonStr = JSON.parse(node.innerText);
  4. console.log(jsonStr);
  5. </script>

那如果书写的时候不符合json的语法,或者说故意破坏json的语法呢? 比如先破坏json的语法,然后不获取也不解析:
如果写的不是json格式,那么在解析json的时候,就会报错,必须得遵循json语法
也就是说,浏览器不会把里面的内容当做js去解析,它会把里面的内容当做数据块,而不会被当做是js执行

4、application/json应用场景

大家平时写一些临时活动页面,在页面上展示固定数据的时候,有的产品经理对前端提出了这么一个需求就是
页面中的数据和图片,以及信息,希望是能够通过配置而成,然后通过Ajax请求

  1. 方法1-在文件外部创建一个js文件,加载数据,然后写到html页面上
  2. 方法2-把数据对象写成一json,然后请求该json文件,动态的插入到页面结构中
  3. 方法3-script上定义**type="application/json"**,把配置对象选项写在里面

    1. <script id="_json_data" type="application/json">
    2. {
    3. "data": [
    4. {
    5. "name": "川川",
    6. "desc": "it"
    7. },
    8. {
    9. "name": "iT",
    10. "desc": "https://it.cn"
    11. }
    12. ],
    13. "total": 100
    14. }
    15. </script>

    然后再通过js去获取,关键代码如下

    1. const jsonScriptNode = document.getElementById('_json_data');
    2. const jsonStr = jsonScriptNode.innerText;
    3. const json = JSON.parse(jsonStr);

    这样可以避免使用js加载数据时多余的网络请求,同时语义也更加的明确,定义在一个文件里,可以减少文件的请求

    5、type="module"

    平时写纯静态页时,不会用到,但是大家使用vue-cli,vite都使用得最多的模块化,importexport使用比较频繁
    新建一个目录,里面有module.html文件,如下所示

    1. project
    2. |--public
    3. | |--js
    4. | | |--a-module.js
    5. | |--module.html

    如下是a-module.js代码

    1. export const func = () => {
    2. console.log("https://it.cn");
    3. }

    如下是module.html代码

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>Document</title>
    8. </head>
    9. <body>
    10. <script type="module">
    11. import { func } from "./js/a-module.js"
    12. func()
    13. </script>
    14. </body>
    15. </html>

    如果是直接从本地环境直接打开的话,会直接报一个跨域的错

    1. Access to script at 'file:///D:/it/%E6%8A%80%E6%9C%AF%E6%96%87%E7%AB%A0/Vue%E6%8A%80%E6%9C%AF%E6%96%87%E7%AB%A0/03-script%E4%B8%AD%E7%9A%84type/project/public/js/a-module.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.
    2. a-module.js:1 Failed to load resource: net::ERR_FAILED

    这是因为script[type="module"]会受到cors策略的限制,直接在浏览器中打开文件用的是file协议,而只有http,data,chrome,chrome-extension,chrome-untrusted,https这几个协议才能使用
    遇到这种问题,本地搭建一个服务就可以了,可以用express写一个后端服务文件,用node起得
    这里使用的是在vscode中安装一个live-server插件,起一个本地服务的,比较简单粗暴
    这里有怎么使用安装的
    在实际项目开发中,模块化的开发,在vite中已经引入了的,而在vue2项目里,很多依赖webpack打包工具,工程化的项目,使用这种type="module"兼容性是有待考量的,之所以使用webpack,他会处理成IIFE形式的代码,同时辅以babel将Es6 的代码转为更具兼容性的Es5的代码,既提升了编程体验,同时还兼顾了兼容性问题

    总结

    这里只是在一些开源的项目代码里看到了type="application/json",一时好奇,所以就总结记录了一下
    在实际开发中,平时写静态页,如果想配置成动态的数据,这种方式是可以的,减少文件的请求