【问题标题】:Wait for DOM to be ready on an AngularJS directive等待 DOM 在 AngularJS 指令上准备就绪
【发布时间】:2014-03-29 07:28:18
【问题描述】:

我正在为我的 Angular 网站构建一个“导游”。

我四处寻找选项,Intro.js 似乎是最合适的。它已经准备好 Angular 指令和一切:Angular Intro.js

一切都按预期进行,直到我不得不向 first(并且只有第一个)添加一个由 ng-repeat 绑定注入的 DOM 对象的步骤。我给所有 ng-repeat 项目一个唯一的 ID(通过 $index),但 Intro.js 只是没有承认它。

我猜 Intro 正在尝试通过指定的 ID 查找 DIV,但由于 ng-repeat 尚未完成,因此没有该名称的 DIV。

我做了一个 plunker,您可以在其中看到它正在处理静态内容,但无法识别 ng-repeat 中的对象。

相关代码:

HTML:

<!-- Works -->
<div id="static">This is static content.</div>

<!-- Doesnt work -->
<div id="item{{$index}}" ng-repeat="item in items">
    {{ item.name }}
</div>

角度控制器:

  $scope.IntroOptions = {
        steps:[
        {
            element: document.querySelector('#static'),
            intro: "This is static content"
        },
        {
            /** ID "item0" belongs to the first element on the ng-repeat **/
            element: document.querySelector('#item0'),
            intro: "Doesnt work!"
        }
        ],
        showStepNumbers: false,
        exitOnOverlayClick: true,
        exitOnEsc:true,
        nextLabel: '<strong>NEXT!</strong>',
        prevLabel: '<span style="color:green">Previous</span>',
        skipLabel: 'Exit',
        doneLabel: 'Thanks'
    };

Plunkerhttp://plnkr.co/edit/kE8P5Kq2Y5CVWEYgyBIo?p=preview

  • 假设上面的原因是它不起作用的原因,我该怎么做 让指令等待 DOM “就绪”?

  • 如果我的假设是错误的,那为什么它不起作用呢?

【问题讨论】:

  • 总是在问题中发布相关代码in,不要只是链接。链接烂了。
  • document.querySelector 是控制器中的脏代码。创建一个指令来操作 DOM。

标签: javascript jquery angularjs angularjs-directive intro.js


【解决方案1】:

我最初尝试的最无能的方法是包装动态内容:

<div id="dynamic">
    <div id="item{{$index}}" ng-repeat="item in items">
        {{ item.name }}
    </div>
</div>

作用域变量就变成了

$scope.IntroOptions = {
    steps:[
    {
        element: document.querySelector('#static'),
        intro: "This is static content"
    },
    {
        element: document.querySelector('#dynamic'),
        intro: "This is dynamic content"
    }
    ],
// ... cut ...

看起来您的原始代码正在死锁:视图取决于数据($scope.items),而数据取决于视图(IntroOptions)

【讨论】:

  • 这只会突出显示所有项目周围的 DIV。我只想强调第一个。我意识到我没有在这个问题上说清楚,对此感到抱歉。我对其进行了编辑以澄清这一点。
  • 好的,现在我明白了。我会再弄乱代码。
【解决方案2】:

您可以观察 $rootScope 将广播的 $viewContentLoaded 事件。

【讨论】:

    【解决方案3】:

    我知道这已经很老了,但是如果有人偶然发现了这个答案,最好的办法是使用getter,它会在需要访问该属性的那一刻进行评估:

    $scope.IntroOptions = {
        steps:[
        {
            element: document.querySelector('#static'),
            intro: "This is static content"
        },
        {
            /** ID "item0" belongs to the first element on the ng-repeat **/
            get element(){return document.querySelector('#item0')},
            intro: "Doesnt work!"
        }
        ],
        showStepNumbers: false,
        exitOnOverlayClick: true,
        exitOnEsc:true,
        nextLabel: '<strong>NEXT!</strong>',
        prevLabel: '<span style="color:green">Previous</span>',
        skipLabel: 'Exit',
        doneLabel: 'Thanks'
    };
    

    【讨论】:

      【解决方案4】:
      .directive('onLastRepeat', function() {
          return function(scope, element, attrs) {
              if (scope.$last) setTimeout(function(){
                  scope.$emit('onRepeatLast', element, attrs);
              }, 50);
      };});
      

      像这样使用这个指令:

      <div id="item{{$index}}" ng-repeat="item in items" on-last-repeat>
          {{ item.name }}
      </div>
      

      在您的控制器中等待完成循环并调用 introjs

      $scope.$on('onRepeatLast', function (eve, elem) {
      //call intro
      });
      

      【讨论】:

        猜你喜欢
        • 2021-08-09
        • 1970-01-01
        • 1970-01-01
        • 2019-07-22
        • 2022-10-23
        • 1970-01-01
        • 1970-01-01
        • 2019-07-09
        • 2023-04-01
        相关资源
        最近更新 更多