我使用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() {
});
}
}
答案 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();
});
}
有关详细信息,请参阅