我无法理解如何在AngularJS中使用MVC。 我正在写一个简单的标签手风琴。
假设我有这种HTML结构:
<my-tabs>
<tab title="Tab One">
<div>content 1</div>
</tab>
<tab title="Tab Two">
<div>Tab 2 content</div>
</tab>
<tab title="Tab Three">
<div>Tab 3 content</div>
</tab>
</my-tabs>
这是我的JS。我有主要指令和子指令:
directive("myTabs", function () {
return {
restrict: "E",
transclude: true,
replace: true,
scope: {},
template:
"<ul></ul>",
link: function (scope, element, attrs) {
var arrayOfTabs = element.find("li");
},
controller: function () {}
};
})
.directive('tab', function () {
return {
require: "^myTabs",
restrict: "E",
transclude: true,
replace: true,
scope: {
title: "@"
},
template:
"<li>" +
" <h1 class='title'>{{title}}</h1>" +
" <div class='content' ng-transclude></div>" +
"</li>",
link: function (scope, element, attrs) {
scope.openTab = function()
{
var contentWidth = element.attr("content-width");
element.css('width', contentWidth);
}
scope.closeTab = function ()
{
var contentWidth = element.attr("content-width");
element.css('width', tabCloseWidth);
}
}
};
})
我真正不明白的是: tab指令只能打开/关闭它自己,而myTabs指令是打开所选择的指令并关闭所有其他指令的指令。但是 - 他们如何沟通?我不希望“tab”在每个选择上触发事件,告诉“myTabs”打开选定的选项卡并关闭所有其他选项。对于这两个指令,必须有比$ watch或$ on / $ broadcast更好的方式来互相交流吗?我在这里想念的是什么?当用户点击标签时,我想让“myTabs”控制并设置打开哪个标签以及关闭哪个标签,但他怎么知道?每个人都有孤立的范围。
答案 0 :(得分:1)
指令之间有一些沟通方式:
你想要使用的东西并不容易,但让我解释一下:
link
方法的第4个参数,您可以访问指令的控制器myTabsController
添加方法,通过传递选项卡的范围将每个选项卡注册到数组中。 (我首先认为这是不好的做法,但我已经检查过angular-ui-bootstrap手风琴的源代码,他们也是这样做的。所以这应该没问题。)open
方法中,您可以调用closeOthers
的{{1}}方法并传递当前打开的标签(=范围),然后它将使用{{1}关闭其他元素} loop。请查看下面的演示或此jsfiddle。
myTabsController
angular.forEach
angular.module('demoApp', [])
.controller('MainController', function($scope) {
$scope.open = true;
$scope.oneAtATime = true;
})
.constant('tabsConfig', {
closeOthers: true
})
.directive("myTabs", function() {
return {
restrict: "E",
transclude: true,
replace: true,
scope: {
},
template: "<ul ng-transclude></ul>",
link: function(scope, element, attrs) {
//var arrayOfTabs = element.find("li");
},
controller: function($scope, $attrs, tabsConfig) {
this.tabs = [];
this.addTab = function(tab) {
this.tabs.push(tab);
};
this.closeOthers = function(openTab) {
var closeOthers = angular.isDefined($attrs.closeOthers) ?
$scope.$eval($attrs.closeOthers) : tabsConfig.closeOthers;
if (closeOthers) {
angular.forEach(this.tabs, function(tab) {
if (!angular.equals(tab, openTab)) {
//console.log(tab);
tab.closeTab();
}
});
}
};
}
};
})
.directive('tab', function() {
return {
require: "^myTabs",
restrict: "E",
transclude: true,
replace: true,
scope: {
title: "@",
open: '='
},
template: '<li ng-click="toggle()">' +
" <h1 class='title'>{{title}}</h1>" +
" <div class='content' ng-transclude></div>" +
"</li>",
link: function(scope, element, attrs, myTabsCtrl, ngTransclude) {
myTabsCtrl.addTab(scope);
//console.log('ctrl', myTabsCtrl);
//console.log(scope.open);
if (!scope.open) {
closeTab();
}
scope.toggle = function() {
//scope.open = !scope.open;
if (scope.open) {
closeTab();
} else {
openTab();
myTabsCtrl.closeOthers(scope);
}
};
scope.openTab = openTab;
scope.closeTab = closeTab;
function openTab() {
/*var contentWidth = element.attr("content-width");
element.css('width', contentWidth);*/
element.find('div').css('display', 'block');
scope.open = true;
}
function closeTab() {
/*
var contentWidth = element.attr("content-width");
element.css('width', tabCloseWidth);*/
element.find('div').css('display', 'none');
scope.open = false;
}
}
};
});
答案 1 :(得分:0)
您需要了解angularjs中的范围 - https://docs.angularjs.org/guide/scope。
现在两个指令都有'隔离'范围scope: {}
意味着他们'彼此不了解'除了'myTabs'可以使用属性'title'将标题传递给'tab'这一事实。
这应该解释您需要知道的所有https://github.com/angular/angular.js/wiki/Understanding-Scopes