You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Symfony 4中Javascript函数未定义求助(Symfony Encore场景)

解决Symfony Encore中全局调用JS函数提示「function not defined」的问题

这个问题我之前开发Symfony项目时也踩过坑!核心原因是Symfony Encore基于Webpack打包,默认会把所有JS代码封装在模块的私有作用域里,你定义的openLoginModal函数只存在于这个模块内部,浏览器的全局window对象根本访问不到它,所以模板里的onclick会找不到函数。

下面给你几个可行的解决方案,按推荐程度排序:

方案1:用事件监听替代inline onclick(最推荐,符合现代JS实践)

尽量避免在HTML里写onclick这种内联事件,改用自定义data属性+事件委托的方式,既避免全局污染,代码也更易维护。

步骤:

  1. 修改模板中的元素,给它加一个自定义data属性:
<!-- 比如原来的按钮 -->
<button data-action="open-login-modal">打开登录弹窗</button>
  1. app.js里添加事件监听(放在$(function(){})里确保DOM加载完成):
/** 
 * Name: app.js 
 * Desc: Main application javascript 
 */ 
var $ = require('jquery'); 
require('bootstrap-sass'); 
require('../css/app.scss'); 

// Initialize tooltips 
$(function () { 
  $('[data-toggle="tooltip"]').tooltip();

  // 监听自定义data属性的点击事件
  $('body').on('click', '[data-action="open-login-modal"]', function() {
    $('#login-modal').modal('show');
  });
});

这里用body做事件委托,就算后续动态添加元素也能生效,比直接绑定元素更灵活。

方案2:将函数暴露到全局window对象(快速临时解决)

如果只是想快速解决问题,可以把函数挂载到全局的window对象上,这样浏览器就能在全局环境找到它:

修改app.js中的函数定义:

var openLoginModal = function(element){
  $('#login-modal').modal('show');
}

// 把函数暴露到全局window对象
window.openLoginModal = openLoginModal;

之后模板里的onclick="openLoginModal(this)"就能正常工作了。不过这种方式会污染全局命名空间,不推荐在大型项目中大量使用。

方案3:确认Encore打包后的JS已正确引入模板

最后别忘了检查模板里是否正确引入了Encore打包后的JS文件,要确保用Symfony的Twig函数引入:

{# 在模板的底部(</body>标签前)引入 #}
{{ encore_entry_script_tags('app') }}

如果JS文件引入位置不对(比如在元素之前加载),就算函数暴露到全局,DOM加载时也会找不到函数,所以尽量把JS放在页面底部。


内容的提问来源于stack exchange,提问作者Adam

火山引擎 最新活动