AngularJS骰子应用:实现rollDice函数独立调用的OOP改造
嘿,我完全懂你现在的困扰!多个骰子组共用同一个控制器里的状态,点一个按钮另一个也跟着变,这确实是AngularJS新手很容易踩的坑。咱们用面向对象的思路来封装一下,就能彻底解决这个问题啦~
核心问题分析
你现在的控制器里,$scope.dice、$scope.marked这些状态都是全局(相对于控制器)的变量,所有骰子组共用同一套数据,自然会互相影响。解决思路就是把每个骰子组的状态和对应的方法封装成独立的对象,让每个组拥有自己的专属数据和行为。
下面给你两种常用的实现方案,按需选择:
方案1:用Factory封装骰子组对象
这种方式适合在同一个控制器里管理多个独立的骰子实例,把骰子的逻辑封装成可实例化的类,每个实例都是完全独立的。
代码实现
首先创建一个DiceSet工厂,封装状态和方法:
angular.module('diceApp', []) .factory('DiceSet', function() { // 定义骰子组构造函数 function DiceSet(numDice, sides) { this.numDice = numDice; this.sides = sides; this.dice = Array(numDice).fill(0); // 存储骰子结果 this.marked = Array(numDice).fill(false); // 存储骰子标记状态 } // 掷骰子方法:只掷未标记的骰子 DiceSet.prototype.rollDice = function() { this.dice = this.dice.map((val, index) => { return this.marked[index] ? val : Math.floor(Math.random() * this.sides) + 1; }); }; // 标记/取消标记骰子方法 DiceSet.prototype.markDice = function(index) { this.marked[index] = !this.marked[index]; }; // 检查标记骰子的逻辑(示例:返回标记数量) DiceSet.prototype.checkMarkedDice = function() { return this.marked.filter(isMarked => isMarked).length; }; return DiceSet; }) .controller('DiceController', function($scope, DiceSet) { // 创建两个独立的骰子组实例 $scope.diceGroup1 = new DiceSet(4, 6); $scope.diceGroup2 = new DiceSet(3, 6); });
对应的HTML模板,每个组绑定自己的实例:
<div ng-controller="DiceController"> <!-- 第一组:4d6 --> <div> <button ng-click="diceGroup1.rollDice()">Roll 4d6</button> <div ng-repeat="die in diceGroup1.dice track by $index"> <span ng-click="diceGroup1.markDice($index)" ng-class="{'marked': diceGroup1.marked[$index]}" > {{die}} </span> </div> <p>Marked dice: {{diceGroup1.checkMarkedDice()}}</p> </div> <!-- 第二组:3d6 --> <div> <button ng-click="diceGroup2.rollDice()">Roll 3d6</button> <div ng-repeat="die in diceGroup2.dice track by $index"> <span ng-click="diceGroup2.markDice($index)" ng-class="{'marked': diceGroup2.marked[$index]}" > {{die}} </span> </div> <p>Marked dice: {{diceGroup2.checkMarkedDice()}}</p> </div> </div>
为什么能解决问题?
每个DiceSet实例都有自己的dice和marked数组,方法也是属于实例的,两个骰子组完全独立,不会再互相干扰。
方案2:用Directive创建可复用骰子组件
如果想把骰子组做成可复用的独立组件(比如在页面多个地方使用),用Directive的隔离作用域更合适,这也是AngularJS组件化的标准做法。
代码实现
angular.module('diceApp', []) .directive('diceSet', function() { return { restrict: 'E', // 作为标签使用 scope: { numDice: '@', // 接收外部传入的骰子数量 sides: '@' // 接收外部传入的骰子面数 }, template: ` <button ng-click="rollDice()">Roll {{numDice}}d{{sides}}</button> <div ng-repeat="die in dice track by $index"> <span ng-click="markDice($index)" ng-class="{'marked': marked[$index]}" > {{die}} </span> </div> <p>Marked dice: {{checkMarkedDice()}}</p> `, controller: function($scope) { // 初始化数据 $scope.numDice = parseInt($scope.numDice); $scope.sides = parseInt($scope.sides); $scope.dice = Array($scope.numDice).fill(0); $scope.marked = Array($scope.numDice).fill(false); // 掷骰子方法 $scope.rollDice = function() { $scope.dice = $scope.dice.map((val, index) => { return $scope.marked[index] ? val : Math.floor(Math.random() * $scope.sides) + 1; }); }; // 标记骰子方法 $scope.markDice = function(index) { $scope.marked[index] = !$scope.marked[index]; }; // 检查标记骰子 $scope.checkMarkedDice = function() { return $scope.marked.filter(isMarked => isMarked).length; }; } }; });
HTML使用起来超级简洁,直接复用组件:
<dice-set num-dice="4" sides="6"></dice-set> <dice-set num-dice="3" sides="6"></dice-set>
为什么能解决问题?
Directive的scope: {}创建了隔离作用域,每个<dice-set>标签都有自己独立的状态和方法,完全不会和其他组件共享数据,完美实现了组件的独立性和复用性。
内容的提问来源于stack exchange,提问作者DuFuS
相关产品推荐
相关产品推荐

