【问题标题】:Dynamic html link tag using external javascript library使用外部 javascript 库的动态 html 链接标签
【发布时间】:2022-04-30 02:39:50
【问题描述】:

这个问题与之前的一个帖子有关:Check if user is using browser located in China or not

我正在加载一个外部 js 库来评估我想在我的标题中加载哪个 css。按照上述帖子的接受答案,我在我的 HTML 头中加载了 userinfo.io API,然后对接收到的数据进行评估。这是我所做的:

<head>

...

<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/userinfo/1.0.0/userinfo.min.js"></script>

<script type="text/javascript">
    UserInfo.getInfo(function(data) {
       // the "data" object contains the info
       if (data.country.code == 'CN') {
          // Load fallback fonts
          document.write('<link href="http://fonts.useso.com/css?family=Source+Sans+Pro:200,400,700|Dancing+Script:400,700|PT+Serif|Open+Sans:400,300,700" rel="stylesheet" type="text/css">');
       } else {
          // Load google fonts
          document.write('<link href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,400,700|Dancing+Script:400,700|PT+Serif|Open+Sans:400,300,700" rel="stylesheet" type="text/css">');
       }
    }, function(err) {
       // the "err" object contains useful information in case of an error
    });
</script>

</head>

在Firefox中调试js,可以看到库加载成功。首先发生的是,我收到一条错误消息“参考错误:未定义用户信息”。我在我的 html 头中对行的顺序进行了一些操作(当然还有一些 css 包含,一些元标记和标题)。放完

<head>

<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/userinfo/1.0.0/userinfo.min.js"></script>

...

<script type="text/javascript">
    UserInfo.getInfo(function(data) {
       // the "data" object contains the info
       if (data.country.code == 'CN') {
          // Load fallback fonts
          document.write('<link href="http://fonts.useso.com/css?family=Source+Sans+Pro:200,400,700|Dancing+Script:400,700|PT+Serif|Open+Sans:400,300,700" rel="stylesheet" type="text/css">');
       } else {
          // Load google fonts
          document.write('<link href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,400,700|Dancing+Script:400,700|PT+Serif|Open+Sans:400,300,700" rel="stylesheet" type="text/css">');
       }
    }, function(err) {
       // the "err" object contains useful information in case of an error
    });
</script>

</head>

作为head标签内的第一行,它开始真正识别对象UserInfo及其方法getInfo()。同时,当我将线路放回原来的位置时(例如在第一个代码sn-p中),它也可以识别该功能。这种行为不知何故让我想知道在加载 html 页面时如何在 head 标记中执行 javascript。是否有可能在加载库之前偶尔调用该方法?

无论如何,现在当它成功导入 userinfo.io 库时,该站点不再正确加载。看看我看到的浏览器控制台:

查看我页面的源代码,我只看到正确加载的链接标签,但页面的其余部分丢失了。

我的猜测是这样的:

我不能在 head 标签中使用document.write(),因为它会干扰页面加载。页面成功加载后,我更有可能应该通过getElementById() 访问和修改链接标签。所以我实际上会用 jQuery 的 ready() 函数来触发它,以确保库已成功加载?如果您对这些想法发表任何评论,我将不胜感激。

【问题讨论】:

    标签: javascript html css


    【解决方案1】:

    document.write() 是一个非常危险的功能(对网页而言)。您应该更具体地说明您想在哪里写东西(而不是整个文档!)。因此,在您的 HTML 中,您可以指定一个空的 div 块,并为其分配一个 id:

    <div id="writehere"></div>
    

    然后在你的 JavaScript 中你会做这样的事情:

    var place;  //global variable
    

    在一些页面初始化函数中这样做:

    place=document.getElementById("writehere");
    

    之后,您可以随心所欲地进行所有写作,例如:

    place.innerHTML += "Special output text<br />";
    

    你甚至可以重写它(修改innerHTML时使用“=”而不是“+=”)。

    我承认我可能错过了您在问题中提出的要点之一。我现在得到的印象是您想在加载过程中指定要加载的页面的额外内容,并且不一定总是相同的额外内容。我不确定head 部分是否是尝试这样做的正确位置,因为我不知道强制浏览器关注head 部分中新添加的link 项目。我知道它可以关注一些事情,就像在这个例子中一样(虽然代码由与body 标签关联的onload 事件调用,但将一个图标放入浏览器选项卡或左上角-浏览器窗口的一角):

    var hd, itm;
    
    hd = document.getElementById('ID_of_Head');
    itm = document.createElement('link');
    itm.id = 'whatever';
    itm.rel = 'shortcut icon';
    itm.type = 'image/png';
    itm.href = 'desired URL'; //OOPS; my comment below wrongly says 'src' property
    hd.appendChild(itm);
    //you can now re-use the 'itm' variable to specify another link, if you wish
    

    appendChild() 函数可能足以触发浏览器关注新添加的链接,在这种情况下,这可能是通用的,而不仅仅是针对这个特定示例。另一方面,我没有尝试添加多个links;有可能一次只能“关注”其中一个。但是,在这种情况下,仍然有一种方法,涉及一系列函数,每个函数都指定在head 中仅添加一个link。在每个函数结束时,你会这样做:

    setTimeout('nextlinkfunc();', 200);  //give each function a different name!
    

    当当前的link-adding 函数结束时,它会设置一个计时器,让浏览器有机会关注刚刚添加的link。 200 毫秒(1/5 秒)后,计时器触发指定的下一个函数——您可以在其中指定将另一个 link 添加到 head。该函数的最后一件事将是另一个 setTimeOut() 到第三个函数,具有自己的唯一名称.... 一个变体可能是一个更复杂的单个函数,其中一个参数用于指定正在进行哪个“调用”到函数(当然,第一次调用函数必须指定参数值1):

    //Note need to declare the global 'hd' and 'itm' variables,
    // and set the 'hd' variable, before calling this function the first time
    function nextlinkfunc(p)
    { itm = document.createElement('link');
      //more stuff as previously presented
      switch(p++)
      { case 1: //Note each 'case' block could have extra 'conditional' code
          itm.href = "URL_of_1st_link";
          break;
        case 2: //Conditional code can encompass many different combinations of URLs
          itm.href = "URL_of_2nd_link";
          break;
        //etc
      }
      hd.appendChild(itm);
      if(p<max_number_of_links_you_want_to_add)
        setTimeout('nextlinkfunc('p');', 200);
    }
    

    【讨论】:

    • 首先,你能具体说明一下“危险函数”是什么意思吗?其次,我同意这将适用于
      ,但我的问题与 -tag 有关。我相信我不能为其分配“id”,因为“id”未列在 -tag 属性中(c.f. w3schools.com/tags/tag_link.asp
    • 你是说我应该把 放在
      里面,例如:
      ... ?
    • document.write() 能够用您使用document.write() 编写的内容替换网页上的所有内容——包括包含document.write() 的JavaScript 代码。我会称这对网页来说是“危险的”。关于用div标签在head标签内做事,我不知道做不到。另一方面,你可以给head标签一个ID,用document.getElementById()获取它,然后使用appendChild()函数指定添加一个link标签。实验!
    • 您链接的页面上描述的link 标签确实支持“全局属性”,其中包括ID。向下滚动该页面足够远以查看。因此,您可能不需要div 块或appendChild() 函数;只需设置link 标记的innerHTML(或者,也许最简单的是,link 标记的src 属性)。
    【解决方案2】:

    好的,这很好用!谢谢。

    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/userinfo/1.0.0/userinfo.min.js"></script>
    
    <script type="text/javascript">
      UserInfo.getInfo(function(data) {
    
        var elHead, elLink;
    
        elLink = document.createElement('link');
        elLink.rel = 'stylesheet';
        elLink.type = 'text/css';
    
        if (data.country.code == 'CN') {
          elLink.href = 'http://fonts.useso.com/css?family=Source+Sans+Pro:200,400,700|Dancing+Script:400,700|PT+Serif|Open+Sans:400,300,700';
        }else{
          elLink.href = 'http://fonts.google.com/css?family=Source+Sans+Pro:200,400,700|Dancing+Script:400,700|PT+Serif|Open+Sans:400,300,700';
        }
    
        elHead = document.getElementsByTagName("head")[0];
    
        elHead.appendChild(elLink);
    
      }, function(err) {
    
      });
    </script>
    
    ...
    
    <body onload="UserInfo.getInfo();">
    

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多
      热门标签