gpt4 book ai didi

javascript - Angular 组件/指令的 $postLink 运行得太早

转载 作者:IT王子 更新时间:2023-10-29 03:19:17 27 4
gpt4 key购买 nike

更新:我悬赏这个问题。我不是在寻找黑客或解决方法。我正在寻找一种官方方式来访问 Angular 组件中的 dom,并解释为什么我看到的行为($postLink 运行到早期)似乎与官方文档相矛盾。
官方文档状态 ( here ):

$postLink() - Called after this controller's element and its children have been linked. Similar to the post-link function this hook can be used to set up DOM event handlers and do direct DOM manipulation

原始问题:我这里有一个问题的例子 -> http://plnkr.co/edit/rMm9FOwImFRziNG4o0sg?p=preview

我正在使用一个 Angular 组件,我想修改 post 链接函数中的 dom,但它不起作用,似乎该函数运行得太早,在模板实际在 dom 中准备好之前 Angular 处理。

在 html 页面中,我有这个:

<my-grid grid-id="'foo'"></my-grid>

组件定义为:

appModule.component('myGrid',{
controller: gridController,
bindings: {
"gridId": "<",
},
templateUrl: 'gridTemplate'
});

在组件模板中我有这个:

<table id='{{$ctrl.gridId}}'>
...

(毫无疑问,绑定(bind)本身有效。最终,在 html 中,表格的 id 正如预期的那样是“foo”)。

在 Controller 中,我有这样的东西:

function gridController($scope, $compile, $attrs) {
console.log ("grid id is: " + this.gridId); // 'foo'

this.$postLink = function() {
var elem = document.getElementById(this.gridId);
// do something with elem, but elem is null
}
}

我在调试时看到的是,当$postLink函数执行时,表在dom中但它的id属性仍然是{{$ctrl.gridId}}而不是 foo,所以 document.getElementById() 什么也找不到。这似乎与文档形成对比。
我错过了什么?是否有不同的方式来访问组件中的 dom?

更新2:今天我发现指令的常规链接功能也出现了同样的问题,它不仅限于组件。因此,显然我误解了“直接进行 DOM 操作”的含义 - 链接函数在与 dom 分离的元素上运行,因此将 document 对象与选择器一起使用是无用的。

最佳答案

有关$postLink() 的文档是正确的。它在其 Controller 的元素及其子元素已链接后调用。这并不意味着您会立即看到指令的结果。也许它正在调用 $http 并在结果到达后插入结果。也许它正在注册一个观察者,该观察者反过来设置结果,就像大多数 Angular 的内置指令一样

你的情况的根本问题是你想在编译插值之后执行 DOM 操作,或者更好的是,在他们注册的观察者有时间运行一次之后。

不幸的是,没有官方方式来做到这一点。尽管如此,还是有一些方法可以实现这一点,但您不会在文档中找到它们。

在编译插值后运行函数的两种流行方式是:

  • 立即使用 $timeout(因为它默认为 0):$timeout(function() {/* Your code goes here */});

  • 使用由 Angular's jqLite 提供的 .ready()

在您的情况下,一旦具有给定 ID 的元素存在,您最好使用观察者运行函数:

var deregistrationFn = $scope.$watch(() => {
return document.getElementById(this.gridId);
}, (newValue) => {
if (newValue !== null) {
deregistrationFn();

// Your code goes here
}
});

最后,在我看来,我相信每当您需要等待插值被编译,或者某些指令插入它们的值时,您就没有遵循Angular 的构建方式。在您的情况下,为什么不创建一个新组件 myGridTable 需要 myGrid 作为父级,并在其中添加其适当的逻辑。这样,每个组件的职责都得到了更好的定义,并且更容易测试。

关于javascript - Angular 组件/指令的 $postLink 运行得太早,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37146700/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com