AngularJS ngRoute切换视图时jQuery脚本失效问题求助
嘿,我明白你遇到的麻烦了——用AngularJS做SPA,切换回首页时jQuery的hover效果就失效,只有刷新才管用,还担心后续的样式动画也出问题对吧?咱们先搞清楚原因,再给你几个靠谱的解决方案。
问题根源
你写的$(document).ready()只会在页面首次加载完成时执行一次。而AngularJS通过ng-view动态加载模板(比如从Chatham页面切回首页时),这时候首页里的.wx图片是新插入DOM的,之前绑定的hover事件根本没作用在这些新元素上,所以就失效了。
而且在AngularJS项目里直接混用jQuery操作DOM,很容易踩这种动态元素的坑,咱们换更合适的方式来处理。
解决方案
方案1:用CSS伪类实现hover(最简单!)
其实根本不需要JS,直接用CSS的:hover伪类就能搞定,不管元素是静态还是动态加载的,CSS都会自动识别。
修改你的CSS代码,把原来的img样式改成针对.wx类,加上hover状态:
.wx { border: 6px solid red; border-radius: 20px; width: 500px; height: auto; transition: all 0.3s ease; /* 加个过渡动画,效果更丝滑 */ } .wx:hover { border-width: 10px; width: 600px; } /* 保留你原来的其他CSS */ .row { padding-bottom: 10px; padding-top: 10px; } body { background-color: black; } @keyframes slideOutLeft { to { transform: translateX(-100%); } } @keyframes scaleUp { from { opacity: 0.3; -webkit-transform: scale(0.8); } } .ng-enter { animation: scaleUp 0.5s both; }
然后直接删掉custom.js里的所有jQuery代码就行,完美解决问题,还不用操心动态元素的事儿。
方案2:用AngularJS指令处理(符合Angular设计理念)
如果以后需要更复杂的交互逻辑,推荐用AngularJS的自定义指令,这是Angular专门用来处理DOM交互的方式,能完美适配动态模板。
修改你的custom2.js,添加一个指令:
var app = angular.module("WXRisk", ["ngRoute", "ngAnimate"]); // 自定义wxHover指令,处理hover效果 app.directive('wxHover', function() { return { link: function(scope, element) { // 绑定鼠标进入事件 element.on('mouseenter', function() { element.css({ "border": "10px solid red", "width": "600px" }); }); // 绑定鼠标离开事件 element.on('mouseleave', function() { element.css({ "border": "6px solid red", "width": "500px" }); }); // 指令销毁时移除事件,避免内存泄漏 scope.$on('$destroy', function() { element.off('mouseenter mouseleave'); }); } }; }); // 路由配置不变,只是给img加上wx-hover指令 app.config(function($routeProvider){ $routeProvider .when("/", { template : "<div class='container'><div class='row'><div class='col-xl-6'><a href='#!Chatham'><img src='http://www.dishuser.com/TVMarkets/City%20Maps/Savannah.gif' class='img-fluid wx' wx-hover alt=''></a></div><div class='col-xl-6'><img src='http://www.dishuser.com/TVMarkets/City%20Maps/Savannah.gif' class='img-fluid wx' wx-hover alt=''></div></div><div class='row'><div class='col-xl-6'><img src='http://www.dishuser.com/TVMarkets/City%20Maps/Savannah.gif' class='img-fluid wx' wx-hover alt=''></div><div class='col-xl-6'><img src='http://www.dishuser.com/TVMarkets/City%20Maps/Savannah.gif' class='img-fluid wx' wx-hover alt=''></div></div></div>" }) .when("/Chatham", { template : "<a href='#/!'>CLICK</a>" }) .otherwise({ template : "<div class='container'><div class='row'><div class='col-xl-6'><a href='#!Chatham'><img src='http://www.dishuser.com/TVMarkets/City%20Maps/Savannah.gif' class='img-fluid wx' wx-hover alt=''></a></div><div class='col-xl-6'><img src='http://www.dishuser.com/TVMarkets/City%20Maps/Savannah.gif' class='img-fluid wx' wx-hover alt=''></div></div><div class='row'><div class='col-xl-6'><img src='http://www.dishuser.com/TVMarkets/City%20Maps/Savannah.gif' class='img-fluid wx' wx-hover alt=''></div><div class='col-xl-6'><img src='http://www.dishuser.com/TVMarkets/City%20Maps/Savannah.gif' class='img-fluid wx' wx-hover alt=''></div></div></div>" }); });
然后同样可以删掉jQuery代码,指令会在每个.wx元素渲染完成后自动绑定事件,不管路由怎么切换都能正常工作。
方案3:用jQuery事件委托(兼容现有代码)
如果不想改太多代码,也可以用jQuery的事件委托,把事件绑定到父元素上,利用事件冒泡来触发动态元素的事件。
修改custom.js里的代码:
// 替换原来的$(document).ready代码 $(document).on("mouseenter", ".wx", function(){ $(this).css("border", "10px solid red"); $(this).css("width", "600px"); }).on("mouseleave", ".wx", function(){ $(this).css("border", "6px solid red"); $(this).css("width", "500px"); });
这种方式不需要改模板,事件委托会监听document上的鼠标事件,只要.wx元素存在,就能触发hover效果,不管它是何时被添加到DOM的。
总结
优先推荐方案1(CSS伪类),最简单高效,完全没JS的问题;如果需要复杂交互再用方案2(Angular指令),符合Angular的设计思路;方案3适合临时兼容现有代码,但长期来看还是尽量减少jQuery和Angular的混用。
内容的提问来源于stack exchange,提问作者user9646948

