$(document).ready AngularJS的替代品

时间:2017-05-04 11:57:20

标签: javascript jquery html angularjs gentelella

我正在使用名为Gentelella的模板,而我正在尝试将AngularJS实施到其中。但是,我遇到了某个Javascript文件的问题。在此文件的末尾,调用$(document).ready函数,该函数初始化在HTML代码中进行一些更改的Javascript代码。问题是在完全加载HTML之前,$(document).ready函数调用太早。

出现此问题可能是因为我使用ngRoute并将模板html文件注入index.html的ng-view。发生这种情况时,DOM可能已经在AngularJS注入模板(= HTML)之前宣布准备好文档。

基本上,一旦AngularJS注入模板,我只需要找到一种方法在Javascript文件中调用一些代码。

我附上了一些代码来深入了解这个问题:

custom.min.js的片段

$(document).ready(function () {
  init_sparklines(), init_flot_chart(), init_sidebar(), init_wysiwyg(), init_InputMask(), ...
});

main.js的片段:

.config(function($routeProvider, $httpProvider) {

  $routeProvider.when('/', {
    templateUrl : 'dash.html',
    controller : 'dash',
    controllerAs: 'controller'
  }).when('/login', {
    templateUrl : 'login.html',
    controller : 'navigation',
    controllerAs: 'controller'
  }).when('/plain_page', {
    templateUrl : 'plain_page.html',
    controller : 'dash',
    controllerAs: 'controller'
  }).otherwise('/');

  $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';

})

提前致谢!

5 个答案:

答案 0 :(得分:4)

许多jQuery插件依赖于1.绘制DOM的工作流程。 2.运行init()函数来设置针对这些DOM元素的代码。

该工作流在Angular中表现不佳,因为DOM不是静态的:Angular在其自己的生命周期中设置并销毁DOM节点,这可以覆盖在Angular之外进行的事件绑定或DOM更改。当您使用Angular时,文档就绪并不是特别有用,因为它表明Angular本身已准备好开始运行。

要有效地使用Angular,你必须养成只在实际需要时启动代码的习惯。因此,在document.ready上不是一大堆init_foo(); init_bar();,而是应该有一个带有自己的初始化代码的Foo指令,一个带有自己特定初始化代码的Bar指令,依此类推。这些指令中的每一个都应该只修改由该特定指令创建的DOM。这是确保您需要修改的DOM元素实际存在的唯一安全方法,并且您不会在指令之间创建冲突或意外的相互依赖性。

举一个例子:我猜测你的init_flot_chart()爬过DOM,寻找一个特定的元素,在其中绘制一个flot图表。而不是那种自上而下的方法,创建一个指令:

angular.module('yourApp')
  .directive('flotWrapper', function () {
    return {
      template: "<div></div>",
      scope: {
        data: '@'
      },
      link: function(scope, elem, attrs) {
        var options = {}; // or could pass this in as an attribute if desired
        $.plot(elem, scope.data, options); // <-- this calls flot on the directive's element; no DOM crawling necessary
      }
    };
});
你使用的

<flot-wrapper data="{{theChartData}}"></flot-wrapper>

...其中theChartData是一个对象,包含要在图表中绘制的任何数据。 (您可以添加其他属性以传入您喜欢的任何其他参数,例如flot选项,标题等。)

当Angular绘制flotWrapper指令时,它首先在指令模板中创建DOM元素,然后针对模板的根元素运行其link函数中的任何内容。 (flot库本身可以通过普通的旧<script>标记包含在内,因此当指令需要时,它的plot函数可用。)

(请注意,如果theChartData的内容发生变化,则不会自动更新;可以看到一个更精细的示例,该示例还会监视变化并做出适当的响应{。{3}}。

答案 1 :(得分:1)

当您使用ngRoute时,您的控制器将在加载页面时运行。 当控制器开始做你想做的任何事情时,你可以调用init()方法。

function MyCtrl($scope) {
    function init() {
        console.log('controller started!');
    }
    init();
}

作为旁注,这是John Papa Angular's guide中推荐的最佳做法。

另一种可能是使用ng-init指令,例如:

<div ng-controller="MyCtrl" ng-init="myFunction()">...</div>

答案 2 :(得分:0)

在最新版本的angular.js中有一个名为$postLink()的生命周期钩子,在此控制器的元素之后调用,并且它的子元素已被链接。与post-link函数类似,此挂钩可用于设置DOM事件处理程序并执行直接DOM操作。检查guide

答案 3 :(得分:-1)

$document.ready(function() {
  $scope.$on('$viewContentLoaded', function() {
    $timeout(function() {
      init_sparklines(), init_flot_chart(), init_sidebar(), init_wysiwyg(), init_InputMask(), ...
    })
  })
})

更新注意:sry家伙,这是不是一个严谨的解决方案,请参阅another answer我写的

答案 4 :(得分:-1)

这与角度消化周期有关,它是关于角度如何在引擎盖下工作,数据绑定等。有很好的教程解释这个。

要解决您的问题,请使用table(all.pos) # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 1 1 2 3 3 2 3 3 3 3 2 2 1 1 1 ,它将使代码在下一个周期执行:

$timeout