我正在使用Angular 1.5.8构建天气应用程序,并且需要让用户能够在英制和公制测量之间来回切换温度和风速。
切换选项和所有天气信息(从外部API获取)都位于单独的指令中,但我想过将临时和风速数据移动到与切换选项相同的指令,然后使用$ broadcast或$ emit显示天气指令中的数据和转换。这是最好的方法吗?如果没有,会是什么?
切换位置的指令:
app.directive('topBar', topBar);
function topBar() {
return {
template:
'<div class="changeTemp" ng-click="vm.changeTempUnit()">' +
'<span ng-class="vm.fahrClass">°F</span>' +
'<span>/</span>' +
'<span ng-class="vm.celsClass">°C</span>' +
'</div>',
restrict: 'E',
scope: {},
controller: TopBarController,
controllerAs: 'vm'
};
}
function TopBarController() {
var vm = this;
vm.celsClass = 'unselected';
vm.changeTempUnit = changeTempUnit;
vm.fahrClass = 'selected';
vm.temp;
vm.windSpeed;
function changeTempUnit() {
if (vm.fahrClass === "selected") {
vm.fahrClass = 'unselected'; //F unselected
vm.celsClass = 'selected'; //C selected
vm.temp = Math.round((vm.temp - 32) * 5 / 9); //Celsius
vm.windSpeed = (vm.speed * 0.44704).toFixed(0); // M/S
} else if (vm.celsClass === 'selected') {
vm.celsClass = 'unselected'; //C unselected
vm.fahrClass = 'selected'; //F selected
vm.temp = Math.round(vm.temp * 1.8 + 32); //Fahren
vm.windSpeed = (vm.speed / 0.44704).toFixed(0); //MPH
}
}
}
天气显示的指令
app.directive('weather', weather);
function weather() {
return {
template:
'<div>' +
'Temp: {{vm.temp}}°' + '<br>' +
'Wind Speed: {{vm.windSpeed}}' +
'</div>',
restrict: 'E',
scope: {},
controller: WeatherController,
controllerAs: 'vm'
};
}
WeatherController.$inject = ['weatherService'];
function WeatherController(weatherService) {
var vm = this;
vm.temp;
vm.windSpeed;
activate();
function activate() {
return weatherService.getWeather().then(function(data) {
weatherInfo(data);
});
}
function weatherInfo(data) {
vm.temp = Math.round(data.main.temp); //Fahren
vm.windSpeed = (data.wind.speed).toFixed(0); //MPH
}
}
答案 0 :(得分:0)
我的第一个建议是使用AngularJs 1.5 + component
api。组件假设您已经选择了几个指令定义对象值。
如果您对这些问题的回答是肯定的,那么您应该使用component
api。
将<top-bar>
转换为组件将如下所示
app.component('topBar', {
template:
'<div class="changeTemp" ng-click="$ctrl.changeTempUnit()">' +
'<span ng-class="$ctrl.fahrClass">°F</span>' +
'<span>/</span>' +
'<span ng-class="$ctrl.celsClass">°C</span>' +
'</div>',
controller: TopBarController,
bindings: {}
});
function TopBarController() {
...
}
注意模板如何使用$ctrl
来引用控制器而不是vm
。对于组件,$ctrl
是默认值。
emit
和broadcast
,这可能是使用它们的理想场所!但如果你能避免它们,那么就不要依赖它们。
这是一个选项
<强>顶栏强>
app.component('topBar', {
template:
'<div class="changeTemp" ng-click="$ctrl.changeTempUnit()">' +
'<span ng-class="$ctrl.fahrClass">°F</span>' +
'<span>/</span>' +
'<span ng-class="$ctrl.celsClass">°C</span>' +
'</div>',
controller: ['conversionService', TopBarController],
bindings: {
}
})
function TopBarController(conversionService) {
var vm = this;
vm.celsClass = 'unselected';
vm.changeTempUnit = changeTempUnit;
vm.fahrClass = 'selected';
function changeTempUnit() {
if (vm.fahrClass === "selected") {
vm.fahrClass = 'unselected'; //F unselected
vm.celsClass = 'selected'; //C selected
conversionService.selectedUnit = conversionService.tempUnits.celsius;
} else if (vm.celsClass === 'selected') {
vm.celsClass = 'unselected'; //C unselected
vm.fahrClass = 'selected'; //F selected
conversionService.selectedUnit = conversionService.tempUnits.farhenheit;
}
}
}
<强> ConversionService 强>
app.service('conversionService', function() {
var service = this;
service.tempUnits = {
farhenheit: 'farhenheit',
celsius: 'celsius'
};
service.selectedUnit = 'farhenheit';
service.convertTemperature = function(temp, tempUnit) {
if (service.selectedUnit === tempUnit) {
return temp;
} else if (service.selectedUnit === service.tempUnits.farhenheiht) {
return Math.round(temp * 1.8 + 32);
} else if (service.selectedUnit === service.tempUnits.celsius) {
return Math.round((temp - 32) * 5 / 9);
} else {
throw Error("Invalid unit");
}
}
});
<强>天气强>
app.component('weather', {
template:
'<div>' +
'Temp: {{ $ctrl.getTemp() }}°' +
'<br>' +
'Wind Speed: {{ $ctrl.windSpeed }}' +
'</div>',
controller: ['conversionService', 'weatherService', WeatherController],
bindings: {}
});
function WeatherController(conversionService, weatherService) {
var ctrl = this;
ctrl.temp;
ctrl.windSpeed;
ctrl.conversionService = conversionService;
activate();
function getTemp() {
return ctrl.conversionService.convertTemperature(ctrl.temp, ctrl.conversionService.tempUnits.farhenheit);
}
function activate() {
return weatherService.getWeather()
.then(weatherInfo);
}
function weatherInfo(data) {
ctrl.temp = Math.round(data.main.temp); //Fahren
ctrl.windSpeed = (data.wind.speed).toFixed(0); //MPH
}
}
由于当ng-click
之类的指令评估其绑定表达式时,Angular会进行脏检查,因此<weather>
的模板也将被检查并且表达式
{{ $ctrl.conversionService.convertTemperature($ctrl.temp, $ctrl.conversionService.tempUnits.farhenheit) }}
将被评估。