Я пытаюсь найти лучшее решение для использования ui-router
вместе с angular components
.
Рассмотрим две простые компоненты:
app.component('componentOne', {
template: '<h1>My name is {{$ctrl.name}}, I am {{$ctrl.age}} years old.</h1>',
bindings : {
name : '@',
age : '@'
}
}
);
app.component('componentTwo', {
template: '<h1>I am component 2</h1>'
});
Прямо сейчас я указываю компонент и его параметр, используя свойство template
:
app.config(function($stateProvider, $urlRouterProvider ){
$stateProvider
.state('component1', {
url: "/component1",
template: "<component-one name=\"foo\" age=\"40\"></component-one>"
})
.state('component2', {
url: "/component2",
template: "<component-two></component-two>"
})
});
Хотя это работает нормально, у меня есть компоненты с arround десять привязок, что делает конфигурацию ui-router
очень неудобной.
Я попытался использовать свойство component
но это не работает для меня вообще. Единственное другое решение, которое я нашел, - указать родителя с использованием свойства require
и опустить привязки - но это мне не подходит... Есть ли лучший способ сделать это?
Вот plnkr.
component:
UI-Router component:
маршрутизация существует в UI-Router 1. 0+ (в настоящее время 1.0.0-beta.1)
Здесь обновленный плункер: https://plnkr.co/edit/VwhnAvE7uNnvCkrrZ72z?p=preview
Чтобы связать статические данные с компонентом, используйте component
и блок разрешения, который возвращает статические данные.
$stateProvider.state('component1', {
url: "/component1",
component: 'componentOne',
resolve: { name: () => 'foo', age: () => 40 }
})
Чтобы привязать значения async, используйте решение, которое возвращает обещания для данных. Обратите внимание, что одно решение может зависеть от другого решения:
$stateProvider.state('component1Async', {
url: "/component1Async",
component: "componentOne",
resolve: {
data: ($http) => $http.get('asyncFooData.json').then(resp => resp.data),
name: (data) => data.name,
age: (data) => data.age
}
});
Вы упомянули, что у вас есть 10 привязок к компоненту. В зависимости от структуры данных, которые вы связываете, вы можете использовать JavaScript для построения блока resolve
(в конце концов, это "просто javascript")
var component2State = {
name: 'component2',
url: '/component2',
component: 'componentTwo',
resolve: {
data: ($http) => $http.get('asyncBarData.json').then(resp => resp.data)
}
}
function addResolve(key) {
component2State.resolve[key] = ((data) => data[key]);
}
['foo', 'bar', 'baz', 'qux', 'quux'].forEach(addResolve);
$stateProvider.state(component2State);
Одна из альтернатив, которую вы можете попробовать, - переопределить шаблон пользовательскими свойствами состояний в событии $stateChangeStart
.
Выполните блок, подобный этому, для достижения такого поведения.
app.run(function($rootScope){
//listen to $stateChangeStart
$rootScope.$on("$stateChangeStart",function(event, toState, toParams, fromState, fromParams, options){
//if the component attribute is set, override the template
if(toState.component){
//create element based on the component name
var ele = angular.element(document.createElement(camelCaseToDash(toState.component)));
//if there is any binding, add them to the element attributes.
if(toState.componentBindings){
angular.forEach(toState.componentBindings,function(value,key){
ele.attr(key,value)
})
}
//you may also do something like getting bindings from toParams here
//override the template of state
toState.template = ele[0].outerHTML;
}
})
//convert camel case string to dash case
function camelCaseToDash(name) {
return name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
})
И с этим теперь вы можете иметь свойство component
в своей конфигурации состояния.
app.config(function($stateProvider, $urlRouterProvider ){
$stateProvider
.state('component1', {
url: "/component1",
component:"componentOne",
componentBindings:{
name:"foo",
age:"40",
}
})
.state('component2', {
url: "/component2",
component:"componentTwo",
})
});
Вот рабочий плункер.
Тем не менее у вас может быть большая функция конфигурации, но это будет выглядеть не так уж неудобно.
Кроме того, вы можете переместить свои привязки на уровень вниз и создать объект, который будет единственным привязкой. Если 10 привязок - это то, что вас беспокоит.