当链接被点击时,JavaScript函数无法工作

11

我有一个非常简单的页面,带有侧边栏导航和一个iFrame用于加载内容。

我想通过点击侧边栏导航中的链接来更改iFrame的内容。我正在使用JavaScript来更改document.element的源(.src)。

我已经阅读了许多文章(StackOverflow),代码应该可以工作,但实际上却没有。

以下是我创建的HTML页面,它包括在script标签中的JS代码。

<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
<link href="css/default.css" rel="stylesheet" type="text/css">

<script type="text/javascript">
    function getContent{

        document.getElementById("contentFrame").src="LoremIpsum.html";  

    }
    </script>


</head>

<body>
<div class="sidebar"><h1>Technical Documentation</h1>
<ul>
    <li>Configuration Guides</li>
    <li>API Guides</li>
    <li><a href="" onclick='getContent()'> LoremIpsum</a></li>
</ul>
<!-- <button onclick="getContent()">Lorem Ipsum</button>    -->

</div>


<iframe class="content"  id="contentFrame" src="dummy.html">
</iframe>

</body>

3
尝试在JS函数声明中添加括号。将'function getContent{'改为'function getContent() {'。 - mrkd1991
看一下控制台,你会发现你有一个语法错误。 - Ibu
4个回答

31
你的问题是你忘了在函数名后面添加 ()
此外,还有几个要纠正的地方: 不要使用内联 HTML 事件属性(onclickonmouseover 等),因为它们:
  1. 创建难以阅读和调试的“意大利面代码”。
  2. 导致代码重复。
  3. 不具备良好的扩展性。
  4. 不遵循关注点分离的开发方法论。
  5. 会在回调函数中创建匿名全局包装函数,改变了this绑定。
  6. 不遵循W3C事件标准
  7. 不会将对 DOM 事件的引用传递给处理程序。

连MDN都同意

内联事件处理程序 - 不要使用这些

你可能在你的代码中也会看到这样的模式:

<button onclick="bgChange()">Press me</button> 

function bgChange() {   
  const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;  
  document.body.style.backgroundColor = rndCol; 
} 

在 Web 上注册事件处理程序的最早方法是使用事件处理程序 HTML 属性(或内联事件处理程序),就像上面显示的那样 - 属性值实际上是您希望在事件发生时运行的 JavaScript 代码。上面的示例调用了在同一页上定义的 script 元素中的函数,但您也可以直接将 JavaScript 插入到属性中,例如:
 <button onclick="alert('This is my old-fashioned event handler!');">Press me</button> 

你可以找到许多事件处理程序属性的HTML属性等效物;然而,你不应该使用它们——这被认为是一种不好的做法。如果你只是做一些很快的事情,使用事件处理程序属性可能看起来很简单,但它们很快就会变得难以管理和低效。
首先,将HTML和JavaScript混在一起并不是一个好主意,因为这样会变得难以阅读。将JavaScript与HTML分开是一种良好的实践,如果它在一个单独的文件中,你可以将其应用于多个HTML文档。
即使在一个文件中,内联事件处理程序也不是一个好主意。一个按钮还可以接受,但如果有100个按钮呢?你将不得不向文件中添加100个属性;它很快就会变成一个维护噩梦。使用JavaScript,你可以轻松地为页面上的所有按钮添加一个事件处理程序函数,无论有多少个按钮,可以像这样做:
const buttons = document.querySelectorAll("button");
 
for (const button of buttons) {   
  button.addEventListener("click", bgChange); 
} 

最后,许多常见的服务器配置将禁止内嵌 JavaScript,作为一种安全措施。 你永远不应该使用 HTML 事件处理程序属性-这些已过时,使用它们是不良实践。 相反,将所有工作都放在 JavaScript 中,并使用 .addEventListener() 来设置事件处理程序。
不要在可以使用按钮(或其他元素)的情况下使用超链接。如果你确实要使用超链接,你需要禁用其默认的导航行为,这可以通过将 href 属性设置为 # 而不是 "" 来实现。

// Place this code into a <script> element that goes just before the closing body tag (</body>).

// Get a reference to the button and the iframe
var btn = document.getElementById("btnChangeSrc");
var iFrame = document.getElementById("contentFrame");

// Set up a click event handler for the button
btn.addEventListener("click", getContent);

function getContent() {
  console.log("Old source was: " +  iFrame.src);
  iFrame.src="LoremIpsum.html";  
  console.log("New source is: " +  iFrame.src);
}
<div class="sidebar"><h1>Technical Documentation</h1>
<ul>
    <li>Configuration Guides</li>
    <li>API Guides</li>
</ul>
<button id="btnChangeSrc">Change Source</button>

</div>

<iframe class="content" id="contentFrame" src="dummy.html"></iframe>


3
如果使用内联HTML事件属性是如此糟糕,那么告诉我:为什么所有现代框架(如angular、react、vue等)都设计为在其HTML模板中使用内联事件?对于小型纯JS项目,使用内联HTML事件是可以接受的(因为它们很小、简单且易于控制),但对于更大的项目,最好使用一些现代框架而不是纯js。 - Kamil Kiełczewski
6
@KamilKiełczewski您的观点在许多论坛上已经被反复提出。这源于基本的误解和错误等值观。框架必须具有与原生代码的“钩子”,因此它们提出了内联方式来实现这一点,但是渲染后的代码不包含这些内联钩子。我不讨论框架,我讨论不会转换成其他任何东西的原始代码。您说小项目使用内联事件处理程序可以接受是没有道理的。无论规模如何,内联事件处理程序都是不好的。 - Scott Marcus
5
好的,那是你的观点,你有权这么认为。我教授这些内容从它被发明以来,后来又教了2万多名学生,我的观点是,只要你理解什么是框架以及它如何实现其功能,理解用框架编码与用原生JS编码采取不同的方法并没有任何问题。我看到的不好习惯是培训过程中跳过这个主题,直接深入编码而没有区分两者之间的差别。理解各自的最佳实践并不需要太高深的知识。 - Scott Marcus
1
各种机制都可以导致作者提供的可执行代码在文档的上下文中运行。这些机制包括但可能不限于:[...] 事件处理程序,无论是通过使用addEventListener()在DOM中注册,还是通过显式事件处理程序内容属性、事件处理程序IDL属性或其他方式注册。强调添加。EHCA不属于DOM规范;它们属于HTML规范,因此指向DOM事件是直接无关和有点误导的(如前所述)。 - wtr
1
感谢尊重的聊天。对于未来的访客,有一些其他声音与@ScottMarcus的看法不同; 请考虑这些声音:https://dev59.com/KWcs5IYBdhLWcg3wtmWf#26439633,https://softwareengineering.stackexchange.com/a/225013/143891,https://dev59.com/-2025IYBdhLWcg3wqn0N#dp-dEYcBWogLw_1bL46k,https://dev59.com/KWcs5IYBdhLWcg3wtmWf#U6WeEYcBWogLw_1by53h,https://dev59.com/fGw05IYBdhLWcg3w6GLH#JxsBoYgBc1ULPQZF8ZZg - wtr
显示剩余23条评论

2
这是一个语法错误。无论函数参数如何,都需要加括号。不过,把 script 标签放在 body 标签底部是个好习惯。

1
您的函数声明存在语法错误(缺少括号):
function getContent {
   document.getElementById("contentFrame").src="LoremIpsum.html";
}

应该是:

应该是:

function getContent() {
   document.getElementById("contentFrame").src="LoremIpsum.html";
}

你还需要防止链接的默认事件。

<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
<link href="css/default.css" rel="stylesheet" type="text/css">

<script type="text/javascript">
    function getContent(event) {
       event.preventDefault();
       document.getElementById("contentFrame").src="LoremIpsum.html";
    }
    </script>


</head>

<body>
<div class="sidebar"><h1>Technical Documentation</h1>
<ul>
    <li>Configuration Guides</li>
    <li>API Guides</li>
    <li><a href="#" onclick='getContent(event)'> LoremIpsum</a></li>
</ul>
<!-- <button onclick="getContent()">Lorem Ipsum</button>    -->

</div>


<iframe class="content"  id="contentFrame" src="dummy.html">
</iframe>

</body>


为了防止链接导航,您可以将 href 设置为 #。无需 JavaScript。 - Scott Marcus
好的,我倾向于避免像这样内联JavaScript,并且更喜欢使用event.preventDefault() - Rob M.
将值设置为#不会内联JavaScript。这根本没有任何JavaScript。 - Scott Marcus
我知道这点,我是指onclick='getContent(event)' - Rob M.
是的,同意(我在我的回答中详细讨论了这个问题)。但是,你对我的评论的回复并不是关于我评论的最初内容的。 - Scott Marcus
显示剩余2条评论

0

你可以使用javascript:void(0)。

    <a href="javascript:void(0)" onclick='getContent(event)'> LoremIpsum</a>

或者在JavaScript中返回false。

     <script type="text/javascript">
function getContent(){

    document.getElementById("contentFrame").src="LoremIpsum.html";
    return false;

}
</script>

1
哦不,不要提倡使用javascript:void(0)(现在已经不是1997年了)!而且,如果你真的要这样做,仅仅添加return false到函数中是不够的。你还需要将onclick属性设置为onclick="return getContent()",并且event参数不会被传递给getContent,而是会被传递给包装它的匿名全局包装函数。请参阅我的答案以获取更多有关为什么这样做是不好的详细信息。 - Scott Marcus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接