角度范围。$ parent是null,bug还是功能?

时间:2014-01-28 11:20:05

标签: angularjs

我编写了以下代码,该代码是一个以无限自动滚动方式显示来自服务器的数据的指令,即缩略图会自动向上滚动,每次拇指离开视图时,都会从服务器加载新的缩略图。

如果用户指向拇指,则自动滚动停止,直到用户移除鼠标。

这样可行(只要用户没有指向拇指),但由于某种原因,在自动滚动停止后&重启,它工作几秒钟,然后它因为范围。$ parent为空而中断

var wmApp = angular.module("wmApp");

wmApp.directive("wmThumb", function($rootScope, $http) {

    return {

        link: function(scope, element, attrs) {
            $rootScope.autoscroll = 1;
            w = $('.content').width();
            h = $('.content').height();
            eWidth = w * 0.2;
            eHeight = h * 0.25;
            growWidth = w * 0.4;
            element.width(eWidth);
            $(".bands-thumb").css("right", 0);

            contain = element.parents(".thumbs-container");
            element.css("margin", w * 0.01);
            contain.height(h * 0.9);
            contain.width(growWidth + 20);
            contain.css("margin", w * 0.02);
            $(".thumb-body", element).height(eHeight);
            $(".thumb-pImg", element).height(eHeight);
            $(".thumb-pImg img", element).width(eWidth);
            $(".thumb-title", element).width(eWidth);


            var startAutoScroll = function(elem) {

                if ($rootScope.autoscroll <= 0 
                    || elem.height() == 0 /* elem is out of view*/
                    ) 
                    return;
                var position = elem.position();

                if (position.top < -elem.height()) {
                    //debugger;
                    // $rootScope.autoscroll--;
                    scope.$parent.bands.splice(0,1);
                    page = scope.$parent.bandsPage;

                    //$http.post('ui/list/Band', page).success(function(response) {
                    $.post('ui/list/Band', page, function  (response) {
                        scope.$parent.bandsPage.count++;
                        scope.$parent.bands = scope.$parent.bands.concat(response);
                        // $rootScope.autoscroll++;
                        scope.$parent.$digest();
                    });


                } else {
                    elem.animate({
                        top: "-=5"
                    }, 20, 'linear', function() {
                        startAutoScroll(elem);
                    });
                }
            };

            setTimeout(function() {
                ep= element.prev();
                if (!ep.hasClass('node-thumb'))
                    t = 0;
                else {
                    p  = ep.position();
                    t = p.top;
                    t = t + element.height() + 5;
                }

                element.css("top", t + "px");

                setTimeout(function() {
                    startAutoScroll(element);
                }, 20);
            }, 100);

            growBody = growWidth - eWidth - 10;
            element.bind("mouseenter", function() {
                $(this).animate({
                    width: growWidth + 'px',
                }, 100);
                $(".thumb-body", element).show(100).animate({
                    width: growBody + 'px',
                }, 100);
                element.css("z-index", 100);

                $rootScope.autoscroll--; // fix bug when jumping from each other

            });

            element.bind("mouseleave", function(event) {
                $(this).animate({
                    width: eWidth + 'px',
                }, 100);
                $(".thumb-body", element).hide(100).animate({
                    width: '0px',
                }, 100);
                element.css("z-index", 1);
                setTimeout(function() {
                    $rootScope.autoscroll++;
                    $(".node-thumb").each(function(i, e) {
                        e = $(e);
                        startAutoScroll(e);
                    });
                }, 200);

            });
            setTimeout(function () {
                element.show();
                // // fit image id H is small
                img = $(".thumb-pImg img", element);
                imgH = $(img).height();
                if (imgH < eHeight)
                    $(img).height(eHeight);
            },100);

        }

    };


});

我的问题:

  1. 根据角度最佳实践,有更好的方法吗?
  2. 为什么范围。$ parent节点变为空?它是一个错误还是一个功能?
  3. 我该如何解决这个问题?
  4. 仅供参考:这是一个有效的代码 - 我使用rootScope而不是范围。$ parent

    var wmApp = angular.module("wmApp");
    
    wmApp.directive("wmThumb", function($rootScope, $http, $timeout) {
    
        return {
    
            link: function(scope, element, attrs) {
                w = $('.content').width();
                h = $('.content').height();
                eWidth = w * 0.2;
                eHeight = h * 0.25;
                growWidth = w * 0.4;
                element.width(eWidth);
                $(".bands-thumb").css("right", 0);
    
                contain = element.parents(".thumbs-container");
                element.css("margin", w * 0.01);
                contain.height(h * 0.9);
                contain.width(growWidth + 20);
                contain.css("margin", w * 0.02);
                $(".thumb-body", element).height(eHeight);
                $(".thumb-pImg", element).height(eHeight);
                $(".thumb-pImg img", element).width(eWidth);
                $(".thumb-title", element).width(eWidth);
    
    
                var startAutoScroll = function(elem) {
                    if ($rootScope.autoscroll <= 0 
                        || elem.height() == 0 /* elem is out of view*/
                        ) 
                        return;
                    var position = elem.position();
    
                    if (position.top < -elem.height()) {
                        $rootScope.bands.splice(0,1);
                        page = $rootScope.bandsPage;
    
                        $.post('ui/list/Band', page, function  (response) {
                            $rootScope.bandsPage.count++;
                            $rootScope.bands = $rootScope.bands.concat(response);
                            $rootScope.$digest();
                        });
    
    
                    } else {
                        elem.animate({
                            top: "-=5"
                        }, 20, 'linear', function() {
                            startAutoScroll(elem);
                        });
                    }
                };
    
                $timeout(function() {
                    ep= element.prev();
                    if (!ep.hasClass('node-thumb'))
                        t = 0;
                    else {
                        p  = ep.position();
                        t = p.top;
                        t = t + element.height() + 5;
                    }
    
                    element.css("top", t + "px");
    
                    $timeout(function() {
                        startAutoScroll(element);
                    }, 20);
                }, 100);
    
                growBody = growWidth - eWidth - 10;
                element.bind("mouseenter", function() {
                    $(this).animate({
                        width: growWidth + 'px',
                    }, 100);
                    $(".thumb-body", element).show(100).animate({
                        width: growBody + 'px',
                    }, 100);
                    element.css("z-index", 100);
    
                    $rootScope.autoscroll--; // fix bug when jumping from each other
    
                });
    
                element.bind("mouseleave", function(event) {
                    $(this).animate({
                        width: eWidth + 'px',
                    }, 100);
                    $(".thumb-body", element).hide(100).animate({
                        width: '0px',
                    }, 100);
                    element.css("z-index", 1);
                    $timeout(function() {
                        $rootScope.autoscroll++;
                        $(".node-thumb").each(function(i, e) {
                            e = $(e);
                            startAutoScroll(e);
                        });
                    }, 200);
    
                });
                $timeout(function () {
                    element.show();
                    // // fit image id H is small
                    img = $(".thumb-pImg img", element);
                    imgH = $(img).height();
                    if (imgH < eHeight)
                        $(img).height(eHeight);
                },100);
    
            }
    
        };
    
    
    });
    

2 个答案:

答案 0 :(得分:3)

您询问了最佳做法。为了使指令更灵活和可重用,建议不要硬编码从父作用域明确继承的$ scope链。例如,我注意到你正在查询band和bandsPage。您可以使用范围隔离将父范围中的变量映射到指令的隔离范围,而不是依赖父范围和继承来实现此目的:

return {
   scope: {
       bands: "=", 
       bandsPage: "="
   },
   link: etc. etc. 
}

这会设置双向数据绑定,因此您可以像这样“映射”:

<myDirective bands="bands" bandsPage="bandsPage" ...> 

这样,无论您是在父作用域还是子作用域中,都无需捕获作用域值。它可以在链接时使用,但是在任何时候使用该指令时你想要的是什么,并且范围隔离将自动为你的指令创建一个范围,该范围映射到你指定的继承属性,同时将你的代码与你不相关的无关属性隔离开来。需要。

您可以在此处的“隔离指令范围”部分了解更多信息:view-source:http://docs.angularjs.org/guide/directive#

答案 1 :(得分:0)

如果指令定义对象(DDO)的$parent字段为假,则不会设置scope成员。

  return {
    controller: 'myController',
    link: function(scope, elm, attrs) {
        // scope.$parent not set

  return {
    scope: true,
    controller: 'myController',
    link: function(scope, elm, attrs) {
        // scope.$parent is set

这是因为scope是私有范围的标志,因此,如果为false,则指令范围===控制器范围,因此$ parent范围是冗余的而不是设置。

scope设置为true时,即使有$parent成员,它的引用也不等于控制器范围,因此没有共享。

如果将scope设置为定义getter属性的对象,则通过视图进行范围共享。

  .controller('versionCntrlr', ['$scope', function($scope) {
    $scope.scopeVersion = '0.2';

  // ...

 .directive(    

  // ...

  return {
    scope: { ver: '='},
    controller: 'myController',
    link: function(scope, elm, attrs) {

在视图中......

<span app-version ver="{{scopeVersion}}"></span>

因此,在这种情况下,您可以向控制器作用域添加一个值,它可供视图使用,由数据绑定提供,然后可以传递给指令。

似乎还有很多不同的替代排列,它们很奇怪,有时也很有用,但我猜这些排列应该是预期的。