2012-06-26 18 views
21

में "गणना की गई गुण" मैंने हाल ही में एक परियोजना के लिए एम्बर.जेएस पर एंगुलरजेएस चुना है, और मैं अब तक बहुत खुश हूं। एम्बर के बारे में एक अच्छी बात यह है कि स्वचालित डेटा बाइंडिंग के साथ "गणना गुण" के लिए इसका समर्थन किया गया है। मैं नीचे कोड के साथ कोणीय में कुछ समान करने में सक्षम हूं, लेकिन मुझे यकीन नहीं है कि ऐसा करने का सबसे अच्छा तरीका है या नहीं।AngularJS

// Controller 
angular.module('mathSkills.controller', []) 
    .controller('nav', ['navigation', '$scope', function (navigation, $scope) { 
    // "Computed Property" 
    $scope.$watch(navigation.getCurrentPageNumber, function(newVal, oldVal, scope) { 
     scope.currentPageNumber = newVal; 
    }); 
    $scope.totalPages = navigation.getTotalPages(); 
    }]); 

// 'navigation' service 
angular.module('mathSkills.services', []) 
    .factory('navigation', function() { 
    var currentPage = 0, 
     pages = []; 

    return { 
     getCurrentPageNumber: function() { 
     return currentPage + 1; 
     }, 
     getTotalPages: function() { 
     return pages.length; 
     } 
    }; 
    }); 

// HTML template 
<div id=problemPager ng-controller=nav> 
    Problem {{currentPageNumber}} of {{totalPages}} 
</div> 

मैं जब भी navigation सेवा में परिवर्तन की currentPage उपरोक्त कोड सिद्ध अद्यतन करने के लिए यूआई के लिए करना चाहते हैं।

क्या यह AngularJS में इस समस्या को हल करने का सबसे अच्छा तरीका है? $watch() का उपयोग करने के लिए क्या (महत्वपूर्ण) प्रदर्शन प्रभाव हैं? क्या ऐसा कुछ कस्टम इवेंट्स और $emit() या $broadcast() का उपयोग करके बेहतर किया जाएगा?

उत्तर

22

मुझे लगता है कि मुझे जवाब मिला। अपने स्वयं जवाब काम करता है

// Controller 
angular.module('mathSkills.controller', []) 
    .controller('nav', ['navigation', '$scope', function (navigation, $scope) { 
    // Property is now just a reference to the service's function. 
    $scope.currentPageNumber = navigation.getCurrentPageNumber; 
    $scope.totalPages = navigation.getTotalPages(); 
    }]); 

// HTML template 
// Notice the first binding is to the result of a function call. 
<div id=problemPager ng-controller=nav> 
    Problem {{currentPageNumber()}} of {{totalPages}} 
</div> 
+0

बेहतर वास्तव में है कि लेकिन, आप क्यों चिपके रहते है सब कुछ एक साथ हो सकता है कि आप अपने मॉड्यूल को अलग करने की कोशिश करनी चाहिए और? आपके नियंत्रक घोषणाएं? – Nimaen

+1

खैर, मॉड्यूल नियंत्रक के लिए मॉड्यूल है; शीर्ष स्तर नियंत्रक को रखने के बजाय। – ithkuil

24

है, यह वास्तव में गणना गुण को लागू नहीं करता है: इस उदाहरण में नाटकीय रूप से करने के लिए सरल किया जा सकता। बाध्यकारी होने के लिए बाध्यकारी को मजबूर करने के लिए आपने अपने बाध्यकारी में एक फ़ंक्शन को कॉल करके समस्या को हल किया। मुझे 100% यकीन नहीं है कि यह सभी मामलों में काम करेगा, और लालच में कुछ परिस्थितियों में अवांछित प्रदर्शन विशेषताओं हो सकती है।

मैं एक अभिकलन गुण डब्ल्यू/क्या EmberJS है के लिए इसी तरह की निर्भरता के लिए एक समाधान तक काम किया:

function ngCreateComputedProperty($scope, computedPropertyName, dependentProperties, f) { 
    function assignF($scope) { 
    var computedVal = f($scope); 
    $scope[computedPropertyName] = computedVal; 
    }; 

    $scope.$watchCollection(dependentProperties, function(newVal, oldVal, $scope) { 
    assignF($scope); 
    }); 
    assignF($scope); 
}; 

// in some controller... 
ngCreateComputedProperty($scope, 'aSquared', 'a',  function($scope) { return $scope.a * $scope.a }); 
ngCreateComputedProperty($scope, 'aPlusB', '[a,b]', function($scope) { return $scope.a + $scope.b }); 

यह लाइव देखें:। http://jsfiddle.net/apinstein/2kR2c/3/

यह है कि $ गुंजाइश ध्यान देने योग्य है $ watchCollection कुशल है - - मैंने सत्यापित किया है कि "असाइनएफ()" को केवल एक बार बुलाया जाता है भले ही एकाधिक निर्भरता एक साथ बदल जाती है (उसी $ लागू चक्र)। "

+1

उत्कृष्ट। बस आप किस कस्टम ऑब्जेक्ट को घोषित करते हैं (उदाहरण में वैश्विक वस्तु की तुलना में)? कोणीय में इसके लिए एक अनुशंसित अभ्यास है? – CodeToad

4

ध्यान दें कि ECMAScript 5 के साथ आप अब भी कुछ इस तरह कर सकते हैं:।

// Controller 
angular.module('mathSkills.controller', []) 
    .controller('nav', function(navigation, $scope) { 
    $scope.totalPages = navigation.getTotalPages(); 
    Object.defineProperty($scope, 'currentPageNumber', { 
     get: function() { 
     return navigation.getCurrentPageNumber(); 
     } 
    }); 
    ]); 

//HTML 
<div ng-controller="nav">Problem {{currentPageNumber}} of {{totalPages}}</div>