在1.5

时间:2017-01-16 10:58:32

标签: javascript angularjs ecmascript-6

我使用Angularjs组件和ES6构建一个也使用d3js的应用程序。我使用属性指令进行DOM操作。由于组件具有范围,我试图在链接功能中访问它并在内部使用$ watch。我怀疑的是,我试图观察和访问的变量都在$ scope内。$ ctrl。在这种情况下访问它们的正确方法是什么?

模板

<div class="card">
    <svg network-svg>
    </svg>
</div>

组件

export const NetworkComponent = {

    template,
    controller: class NetworkComponent {

        constructor(CommService) {
            'ngInject'
            this.comm = CommService;
            this.physicalTree = new NodeTree('physical');
            this.virtualTree = new NodeTree('virtual');
            this.pVisible = true;
        }
    }
}

指令 当前指令的代码,但返回未定义。

export const NetworkSvg = () => {

    return {
        restrict: 'A',
        link($scope, $element, $attrs) {
            $scope.$watch('virtualTree', function() {

            });

            $scope.$watch('physicalTree', function() {

            });
     }
}

3 个答案:

答案 0 :(得分:0)

我发现了一个语法错误: 你可以用这个替换指令代码......并尝试

<Style TargetType="{x:Type c:MyBorder}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type c:MyBorder}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <!-- Label. -->
                    <Border Padding="3,0" Margin="0,-16,0,0" HorizontalAlignment="Right"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="White">
                        <TextBlock Foreground="Black" Text="{TemplateBinding Label}" />
                    </Border>
                    <!-- Content inside Border. -->
                    <Border Grid.Row="1"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}">
                        <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Stretch" />
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

答案 1 :(得分:0)

在我看来,如果你明确依赖它们将属性传递给你的指令会更清楚。 e.g。

<svg network-svg virtual-tree="virtualTree" physical-tree="physicalTree">

然后,您就可以在链接函数的$attrs属性中访问这些值,以及控制器上的范围。

答案 2 :(得分:0)

$ctrl对象是范围的属性。只需在手表中使用它:

export const NetworkSvg = () => {

    return {
        restrict: 'A',
        link: ($scope, $element, $attrs) => {
            //$scope.$watch('virtualTree', function() {
            $scope.$watch('$ctrl.virtualTree', function(newValue) {
                 console.log(newValue);    
            });

            //$scope.$watch('physicalTree', function() {
            $scope.$watch('$ctrl.physicalTree', function(newValue) {
                 console.log(newValue);    
            });
         }
     }
}

在幕后,AngularJS框架在实例化组件的控制器时使用controller as $ctrl。控制器的this上下文设置为组件范围的$ctrl属性。

  

因此,使用$scope.$ctrl.physicalTree访问它并没有坏处吗?

作为稳健设计的问题,最好避免将模型变量名称硬连接到自定义指令中。而是使用属性来定义名称:

export const NetworkSvg = () => {

    return {
        restrict: 'A',
        link: (scope, element, attrs) => {
            //scope.$watch('virtualTree', function() {
            //scope.$watch('$ctrl.virtualTree', function() {
            scope.$watch(attrs.virtualTree, function(newValue) {
                console.log(newValue);    
            });

            //scope.$watch('physicalTree', function() {
            //scope.$watch('$ctrl.physicalTree', function() {
            scope.$watch(attrs.physicalTree, function(newValue) {
                console.log(newValue);
            });
        }
    }
}

然后使用属性来定义接线:

 <my-component virtual-tree="$ctrl.virtualTree"
               physical-tree="$ctrl.physicalTree" ></my-component>

这也是一个更加通用的指令,其中布线是清晰的。

  

我很难使用这个解决方案,因为就我所尝试和阅读而言,通过属性执行此操作时传递的值只是字符串文字。我怎么会传递对象?

在幕后,$watch使用scope.$eval来评估角度表达。其他代码也可以使用它:

例如:

<div my-event="$ctrl.handle($event)"></div>

JS:

link: (scope,elem,attrs) => {
    elem.on("someEvent", function(e) {
        scope.$eval(attrs.myEvent({$event: e});
        scope.$apply();
    });
}

有关详细信息,请参阅