AngularJS面板首次打开可找元素,再次打开失效问题求助
问题
点击特定项目后页面右侧弹出面板,打开面板时会执行AngularJS代码查找ID为view-link的元素,但仅首次打开面板能找到该元素,关闭后重新打开就找不到,必须刷新页面才能恢复。开发者工具控制台里用相同语法能正常查到元素,试过通过判断href是否存在重新查找,问题依旧。
面板加载的HTML代码
<a id="view-link" href="https://www.google.com">https://www.google.com</a>
我的AngularJS控制器代码
var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { console.log('widget load!!!'); var link_element = null; var link_element_2 = null; console.log(link_element); var youtube_link = null; console.log(youtube_link); link_element = angular.element(document.getElementById('view-link')); console.log('link_element IS'); console.log(link_element); if(link_element.attr('href') == undefined) { console.log('In if case'); link_element_2 = angular.element(document.getElementById('view-link')); console.log('link_element_2 IS'); console.log(link_element_2); } $scope.controllerActive = true; $scope.$on("$destroy", function() { $scope.controllerActive = false; console.log("Controller destroyed"); }); });
解决方案
为啥会出现这种情况?
其实是控制器初始化和DOM元素加载的顺序没对上:第一次开面板时,刚好元素先加载完,控制器才执行查找,所以能找到;关了再开,控制器可能在view-link还没渲染到页面里就跑了查找代码,自然查不到。而且面板关闭时如果DOM被删掉,重新打开是新生成的DOM,但控制器没重新触发查找逻辑。
给你几个靠谱的修复办法:
办法1:用$timeout等DOM渲染完再查
Angular里的$timeout会把代码放到DOM更新完之后执行,哪怕设0毫秒也管用,能保证元素已经存在:
var app = angular.module('myApp', []); app.controller('myCtrl', function($scope, $timeout) { console.log('widget load!!!'); var link_element = null; // 等DOM渲染完再找元素 $timeout(function() { link_element = angular.element(document.getElementById('view-link')); console.log('link_element IS'); console.log(link_element); // 这里写拿到元素后的处理逻辑 }, 0); $scope.controllerActive = true; $scope.$on("$destroy", function() { $scope.controllerActive = false; console.log("Controller destroyed"); }); });
办法2:用Angular数据绑定,别直接碰DOM
Angular本来就是数据驱动的,最好别手动查DOM。把链接的内容绑定到控制器的变量里,省心又靠谱:
<!-- 面板里的HTML改成这样 --> <a id="view-link" href="{{linkHref}}">{{linkText}}</a>
var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { // 直接在控制器里给变量赋值就行 $scope.linkHref = "https://www.google.com"; $scope.linkText = "https://www.google.com"; $scope.controllerActive = true; $scope.$on("$destroy", function() { $scope.controllerActive = false; console.log("Controller destroyed"); }); });
办法3:绑面板打开事件,打开时再查
如果你的面板有打开的回调(比如组件自带的onOpen方法),把查找元素的代码放到这个回调里,确保面板完全打开、元素已经加载好再执行:
var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { console.log('widget load!!!'); var link_element = null; // 假设面板打开时会调用这个方法(根据你用的组件调整) $scope.onPanelOpen = function() { link_element = angular.element(document.getElementById('view-link')); console.log('link_element IS'); console.log(link_element); }; $scope.controllerActive = true; $scope.$on("$destroy", function() { $scope.controllerActive = false; console.log("Controller destroyed"); }); });
额外提醒
- 尽量用Angular自带的
angular.element('#view-link')代替document.getElementById,如果用的是jqLite(Angular内置的轻量jQuery),记得要通过父元素find,比如angular.element(document.body).find('#view-link')。 - 检查面板关闭时的逻辑:如果面板是被从DOM里删掉而不是隐藏,重新打开时要确保控制器重新初始化,或者查找逻辑能重新跑一遍。
内容的提问来源于stack exchange,提问作者staymini
相关产品推荐
相关产品推荐

