Laravel 5.6:需单独引入JQuery吗?app.js中是否已包含?
首先明确一点:Bootstrap 4的折叠功能能正常使用,说明jQuery确实已经被包含在你的项目里了——因为Bootstrap的JS组件完全依赖jQuery才能运行,没有jQuery的话折叠功能根本无法工作。
那为什么你的内联脚本会报“jQuery is not defined”呢?问题出在你给app.js加的defer属性上:
原因详解
defer属性的作用是告诉浏览器:先完成HTML的解析和DOM构建,再执行这个脚本,而且脚本会按它们在页面中出现的顺序执行。
你的内联脚本是直接写在视图里的(没有加defer),浏览器解析到这个脚本时会立即执行,而这时候带有defer的app.js还没开始加载/执行,里面的jQuery自然还没被定义,所以就报错了。
而Bootstrap的代码能正常运行,是因为Laravel默认的app.js里已经正确引入了jQuery和Bootstrap,并且它们的执行顺序是jQuery在前、Bootstrap在后——当app.js最终执行时,jQuery已经存在,所以Bootstrap的组件能正常工作。
解决方法
这里有几个靠谱的方案,按推荐程度排序:
1. 把内联脚本放到页面底部(推荐)
将你的脚本移到</body>标签之前,这样浏览器会先完成DOM解析,也会等带有defer的app.js执行完毕,再运行你的脚本:
<!-- 页面内容 --> <script type="text/javascript"> jQuery(document).ready(function(){ jQuery( "#ddtype" ).change(function() { alert( "Handler for .change() called." ); }); }); </script> </body>
2. 将代码整合到Laravel Mix的打包流程中
如果你的JS代码不止这一段,更推荐把它放到单独的JS文件里,然后通过Laravel Mix打包,这样Mix会自动处理依赖顺序:
- 在
resources/js目录下新建custom.js,写入你的代码:jQuery(document).ready(function(){ jQuery( "#ddtype" ).change(function() { alert( "Handler for .change() called." ); }); }); - 在
resources/js/app.js里引入这个文件:require('./bootstrap'); require('./custom'); // 新增这一行 - 运行打包命令:
npm run dev
这样打包后的app.js会确保jQuery先加载,再执行你的自定义代码,就不会有问题了。
3. 去掉app.js的defer属性(不推荐)
直接把<script src="{{ asset('js/app.js') }}" defer></script>里的defer去掉,这样app.js会同步加载执行,你的内联脚本就能找到jQuery了。但这种方法会阻塞页面渲染,影响加载性能,所以不建议使用。
4. 监听DOMContentLoaded事件
在你的内联脚本里监听DOMContentLoaded事件,确保代码在DOM和延迟脚本都加载完成后执行:
<script type="text/javascript"> document.addEventListener('DOMContentLoaded', function() { jQuery( "#ddtype" ).change(function() { alert( "Handler for .change() called." ); }); }); </script>
不过这个方法本质和第一种类似,只是写法不同。
内容的提问来源于stack exchange,提问作者NoNice

