Préface
Tout d'abord, ne parlons pas de la création du projet de base d'AngularJS. Il est préférable d'utiliser l'outil d'échafaudage Yeoman pour le générer directement. S'il n'y a pas un tel environnement, bien sûr, vous pouvez également présenter le projet en téléchargeant vous-même le fichier AngularJS.
Exemple détaillé Explication
main.js est le fichier JS principal du projet. Tous les JS sont écrits dans ce fichier. Après initialisation, le code JS du fichier est le suivant
Angular .Module ('CalculatorApp', ['nganimate', 'ngcookies', 'ngresource', 'ngoute', 'ngsanitize', 'ngtouch']) .Contrller ('mainctrl', fonction ($ scope) {$ scope.result = "; $ scope.data = {Scope). "1": ["ac", "+/-", "%", "÷"], "2": ["7", "8", "9", "×"], "3": ["4", "5", "6", "-"], "4": ["1", "2", "3", "+"], "5": ["0", "," = "];Le résultat ici est utilisé pour lier les résultats du calcul en liaison bidirectionnelle, et les données sont les nombres et les symboles sur le clavier de la calculatrice.
Tous les codes CSS liés à ce projet sont les suivants:
* {margin: 0; rembourrage: 0;} corps {padding-top: 20px; Padding-Bottom: 20px;} H1 {Text-Align: Centre; Couleur: # 3385ff;}. Main {margin: 20px auto; Border: 1px solide # 202020; Border-Bottom: Aucun; Largeur: 60%; Hauteur: 600px;}. Result {affichage: bloc; Largeur: 100%; hauteur: 30%; Contexte: # 202020; Dimensionnement en boîte: Border-Box; Border: aucun; rembourrage: 0; marge: 0; redimensionner: aucun; Couleur: #FFF; taille de police: 80px; Texte-aligne: à droite; hauteur de ligne: 270px; débordement: caché; Background-Clip: Border-Box;}. Row {hauteur: 14%; Contexte: # d7d8da; Dimensionnement en boîte: Border-Box; Border-Bottom: 1px solide # 202020; débordement: caché;}. Col {hauteur: 100%; Dimensionnement en boîte: Border-Box; Border-droite: 1px solide # 202020; flottant: à gauche; Couleur: # 202020; taille de police: 28px; Texte-aligne: Centre; LINE-HEIGHT: 83PX;}. NORMAL {largeur: 25%;}. End-No {largeur: 25%; Border-droite: aucun; Contexte: # F78E11; couleur: #fff;}. zéro {width: 50%;}. History {background: # 3385ff; Couleur: #FFF; taille de police: 22px; Texte-aligne: Centre;}Ensuite, la disposition HTML est la suivante:
<corps ng-app = "calculatApp"> <h1> Calculatrice pour iOS8 </h1> <hr /> <p> {{history.join ("" ")}} </p> <v> <textarea ng-model =" result "> </ textArea> <div ng-repeat =" item in data "> <div ng-repeat =" a élément " ng-class = "showClass ($ index, a)" ng-Click = "showResult (a)"> {{a}} </div> </div> </div> </body> Ici, la balise P de l'historique des classes est utilisée pour afficher l'enregistrement d'entrée, ce qui signifie que toutes les touches que vous appuyez sur lui seront affichées pour consulter facilement les résultats. L'histoire est un tableau sous la portée actuelle, qui sera expliquée plus tard. Ici, une TextArea est utilisée comme écran d'affichage pour les résultats du calcul, principalement pour utiliser la fonction de liaison bidirectionnelle. Dans le même temps, chaque clé et élément d'interface de la calculatrice sont générés par boucle sur l'objet de données. showClass est une méthode ci-dessous Scope, qui est utilisée pour obtenir les attributs de classe des éléments d'affichage de l'interface irrégulière. Il sera expliqué plus tard. showResult est la principale méthode pour répondre à la clé. Toutes nos réponses aux clés sont obtenues via cette méthode, et nous expliquerons en détail plus tard.
Le code de la méthode ShowClass est le suivant:
// Afficher le style de calculatrice $ scope.showclass = function (index, a) {if (a == 0) {return "zero"; } return index == 3 || a == "="? "End-No": "Normal"; };Cette méthode traite principalement de la dernière colonne de chaque ligne à afficher en orange et les clés qui affichent 0 doivent occuper deux cellules pour un traitement spécial.
Jusqu'à présent, l'interface de calculatrice a été entièrement implémentée
Les rendus sont les suivants:
Ce qui suit doit réaliser la réponse aux clés. Les clés comprennent les clés numériques, les clés de l'opérateur et les clés AC. Chaque pression de touche aura des réponses différentes et il existe un lien entre les clés.
Afin de rendre le code plus facile à expliquer, une méthode est utilisée pour donner le code de la méthode ShowResult dans les segments, puis l'expliquer en détail.
Tout d'abord, nous devons ajouter plusieurs variables pour le contrôle et le stockage.
// la pile des nombres utilisés pour le calcul $ Scope.num = []; $ scope.history = []; // l'opérateur Stack $ scope.opt = []; // Le résultat du calcul de la calculatrice $ scope.result = ""; // le résultat de la calculatrice $ scope.result = ""; // Cela signifie s'il faut recommencer à afficher. Le vrai signifie ne pas s'afficher à nouveau. Faux moyens pour effacer la sortie actuelle et redéposer le nombre $ scope.flag = true; // Cela signifie si l'opérateur peut être entré maintenant. Si cela peut être vrai, sinon il est faux $ scope.isopt = true;
Le tableau Num est en fait une pile, utilisée pour recevoir les numéros saisis par l'utilisateur. L'utilisation spécifique sera expliquée plus tard. Le tableau d'historique est toutes les clés entrées par l'utilisateur. Chaque fois que vous appuyez dessus, les symboles ou les nombres sur la touche sont mis dans la pile, puis il est affiché sur l'interface en temps réel en utilisant la liaison. Le tableau OPT est une autre pile utilisée pour recevoir l'entrée de l'opérateur par l'utilisateur. L'utilisation spécifique sera expliquée plus tard. Le drapeau est un drapeau. Lorsque cela est vrai, cela signifie que le numéro appuyé lors de la pressage du numéro fait partie du numéro actuellement affiché et doit être affiché derrière. Par exemple, l'interface actuelle s'affiche 12, puis la pression 3 sera jugée. Si c'est vrai, 123 sera affiché. Sinon, l'interface sera effacée et 3.Sopt est un autre drapeau. Il s'agit principalement d'empêcher l'utilisateur de l'entrée illégale des opérateurs pendant le processus d'entrée. Par exemple, l'utilisateur entre 1 + 2 + succession. Lorsque l'entrée est entrée ici, l'entrée ci-dessous doit être un nombre, mais l'utilisateur entre un opérateur. En jugeant ce drapeau, la calculatrice ignorera cet opérateur illégal et gardera l'entrée encore 1 + 2 +.
Le code suivant est donné dans les segments et le code complet est de les connecter ensemble.
$ scope.init = function () {$ scope.num = []; $ scope.opt = []; $ scope.history = []; $ scope.flag = true; $ scope.isopt = true; }; $ scope.showResult = fonction (a) {$ scope.history.push (a); var reg = // d / ig, regdot = //. / ig, regabs = /// ig; // Si cliquez sur un nombre si (reg.test (a)) {// éliminer le gel if ($ scope.isopt == false) {$ scope.isopt = true; } if ($ scope.result! = 0 && $ scope.flag && $ scope.result! = "error") {$ scope.result + = a; } else {$ scope.result = a; $ scope.flag = true; }} La méthode init est utilisée pour initialiser certaines variables et drapeaux pour les retourner à leur état d'origine. showResult est la principale méthode d'affichage de l'interface pour répondre aux opérations utilisateur. Le code ci-dessus est une branche IF dans cette méthode, indiquant que si l'entrée de l'opérateur est entrée, alors si l'entrée de l'opérateur a été gelée (l'opérateur n'est pas actuellement autorisé à être entré, et il sera ignoré après la saisie), puis lors de la saisie de l'opérateur, l'état de congélation est non bloqué pour que la pile de l'opérateur soit entrée à la prochaine fois que l'opérateur sera entré. Si le résultat actuellement affiché n'est pas vide et que le numéro appuyé fait partie du numéro actuellement affiché et qu'aucune erreur ne se produit, le résultat affiché est que le numéro actuellement appuyé est connecté à la fin du numéro actuellement affiché. Sinon, cela signifie que le numéro que vous entrez la prochaine fois doit être affiché après ce numéro lors de la rediffusion.
Code JS (suite)
// Si vous cliquez sur ACELS IF (A == "AC") {$ SCOPE.RESULT = 0; $ scope.init (); }Si le clic cliqué signifie l'initialisation, laissez le résultat de l'affichage être 0 et tous les états sont effacés.
Code JS (suite)
// Si vous cliquez sur un point décimal else if (a == ".") {If ($ scope.result! = "" &&! Regdot.test ($ scope.result)) {$ scope.result + = a; }}Si le clic est un point décimal, laissez le point décimal être connecté à la fin de l'écran actuel si l'affichage actuel n'est pas vide et qu'il n'y a pas de point décimal dans le résultat de l'affichage actuel.
Code JS (suite)
// si vous cliquez sur un opérateur inverse else if (regabs.test (a)) {if ($ scope.result> 0) {$ scope.result = "-" + $ scope.result; } else {$ scope.result = math.abs ($ scope.result); }}Si le clic est une opération inverse, le résultat de l'affichage actuel sera inversement
Code JS (suite)
// si vous cliquez sur un signe de pourcentage else if (a == "%") {$ scope.result = $ scope.format (nombre ($ scope.result) / 100); } Si vous cliquez sur un signe en pourcentage, divisez le résultat affiché actuel par 100, puis affichez-le. Voici une fonction format
Le code est le suivant:
// Format Result Output $ scope.format = function (num) {var regnum = /. {10,} / ig; if (regnum.test (num)) {if (//./. test (num)) {return num.toexponential (3); } else {return num.toexponential (); }} else {return num; }}} else {return num; }}Sa fonction principale est que la calculatrice fournie avec iOS8 n'affichera pas beaucoup de chiffres à l'infini. S'il dépasse 10 chiffres (y compris des points décimaux), des calculs scientifiques seront utilisés pour afficher. Pour plus de simplicité, lorsque vous utilisez des calculs scientifiques pour afficher les résultats contenant des points décimaux et dépassant 10 chiffres, laissez-le conserver l'affichage de 3 chiffres après le point décimal.
JS Code (la pièce ShowResult est connectée)
// Si l'opérateur cliqué et le résultat d'affichage actuel ne sont pas vides et l'erreur else if ($ scope.checkoperator (a) && $ scope.result! = "" && $ scope.result! = "Error" && $ scope.isopt) {$ scope.flag = false; $ scope.num.push ($ scope.result); $ Scope.Operation (a); // Après avoir cliqué sur l'opérateur une fois, vous devez ignorer la situation où l'opérateur est à nouveau cliqué. $ scope.isopt = false; }Cette branche est la branche la plus complexe, ce qui signifie que si l'entrée est un opérateur, l'opération doit être effectuée. Pour saisir cette branche, vous devez d'abord définir FALL sur FALSE, qui consiste à saisir le numéro la prochaine fois, ce qui consiste à réintégrer le numéro au lieu de saisir le résultat de l'affichage actuel.
Ensuite, laissez le numéro actuellement affiché comme le nombre en cours de calcul pour saisir d'abord la pile de numéro. operation est la méthode de fonctionnement. Parce qu'un opérateur a été cliqué cette fois, la prochaine fois que vous cliquez dessus, vous devez ignorer cet opérateur et définir ISOPT sur FALSE.
Le code d'opération est le suivant
// Comparez la priorité de l'opérateur d'entrée actuellement et de l'opérateur de l'opérateur supérieur de la pile // Si la priorité de l'opérateur supérieur est petite, l'opérateur actuel est mis sur la pile et ne le calcule pas. // Sinon, l'opérateur supérieur est mis sur la pile, et la pile de nombres est placée sur la pile pour deux éléments successivement et calculez // puis l'opérateur actuel est mis sur la pile. $ scope.Operation = fonction (courant) {// Si la pile de l'opérateur est vide, mettez directement l'opérateur actuel sur la pile if (! $ Scope.opt.length) {$ scope.opt.push (courant); retour; } Var Operator, à droite, à gauche; var lastOpt = $ scope.opt [$ scope.opt.length-1]; // Si la priorité actuelle de l'opérateur est supérieure au dernier opérateur, seule la pile est entrée si ($ scope.ispri (courant, lastOpt)) {$ scope.opt.push (courant); } else {operator = $ scope.opt.pop (); droit = $ scope.num.pop (); Left = $ scope.num.pop (); $ scope.calculate (gauche, opérateur, droite); $ scope.Operation (courant); }};Cette méthode accepte l'opérateur d'entrée actuellement en tant que paramètre. L'idée principale est qu'un opérateur est actuellement reçu. Si la pile de l'opérateur est vide, l'opérateur actuel sera placé sur la pile, et il n'est plus nécessaire de faire autre chose dans ce cas. Si la pile de l'opérateur actuel n'est pas vide, l'élément supérieur de la pile d'opérateur actuel est apparu, de sorte que l'opérateur actuellement reçu et l'opérateur supérieur ont la priorité (la priorité de la multiplication et de la division est supérieure à l'addition et à la soustraction, et que l'opérateur supérieur a la priorité de la même priorité car elle est d'abord entrée). La méthode ISPRI est utilisée pour déterminer la priorité et recevoir deux paramètres. Le premier est l'opérateur actuellement reçu et le second est l'opérateur haut de gamme de la pile. Si l'opérateur actuel a une priorité plus élevée en fonction des règles mentionnées ci-dessus, l'opérateur sera directement mis sur la pile. Si la priorité de l'opérateur actuel est plus petite que le haut de l'opérateur de pile, vous devez effectuer des calculs et modifier l'affichage de la calculatrice. Les deux éléments en haut de la pile du numéro d'opération sont apparus à leur tour, car les deux numéros de fonctionnement d'une opération, puis le haut de la pile de la pile de l'opérateur est apparu comme l'opérateur de cette opération, et la méthode de calcul est appelée pour la méthode de calcul de l'opération.
Le code de la méthode est le suivant
// responsable du calcul de la fonction de résultat $ scope.calculate = fonction (gauche, opérateur, droite) {commutateur (opérateur) {case "+": $ scope.result = $ scope.format (nombre (gauche) + nombre (droite)); $ scope.num.push ($ scope.result); casser; cas "-": $ scope.result = $ scope.format (nombre (gauche) - nombre (droite)); $ scope.num.push ($ scope.result); casser; cas "×": $ scope.result = $ scope.format (nombre (gauche) * numéro (à droite)); $ scope.num.push ($ scope.result); casser; cas "÷": if (droit == 0) {$ scope.result = "error"; $ scope.init (); } else {$ scope.result = $ scope.format (nombre (gauche) / numéro (droite)); $ scope.num.push ($ scope.result); } casser; par défaut: pause; }};Cette méthode accepte trois paramètres, le numéro de fonctionnement de gauche, l'opérateur moyen et le numéro de fonctionnement droit, et modifie le résultat pour afficher le résultat après avoir ajouté, soustrayant, multiplication et fonctionnement de la division, et met le résultat de calcul dans la pile du numéro de calcul. Ici, il est nécessaire de noter que si le calcul est la division et que le diviseur est 0, une erreur se produit, des erreurs d'affichage et tous les états sont effacés, sinon le calcul est normal.
Une fois une opération terminée, les états de la pile de l'opérateur et de la pile de nombres seront modifiés et la valeur de courant de la clé actuelle n'a pas été placée dans la pile. Par conséquent, le processus ci-dessus doit être répété pour la comparaison prioritaire, puis l'opération est effectuée. En fait, il s'agit d'un processus récursif jusqu'à ce que la pile de l'opérateur soit vide ou que la priorité de l'opérateur actuel soit plus élevé que le haut de l'opérateur de la pile de l'opérateur. La méthode ISPRI est utilisée pour déterminer la priorité de l'opérateur.
Le code est le suivant:
// juger si l'opérateur actuel a une priorité plus élevée que le dernier, s'il est renvoyé vrai // sinon, renvoie false $ scope.ispri = fonction (current, dernier) {if (current == dernier) {return false; } else {if (current == "×" || current == "÷") {if (last == "×" || last == "÷") {return false; } else {return true; }} else {return false; }}};Les règles de jugement ont été décrites plus tôt.
De plus, il existe une méthode checkOperator , qui est de déterminer si le symbole d'entrée est les quatre symboles de l'opérateur de l'addition, de la soustraction, de la multiplication et de la division.
Le code est le suivant:
// juger si le symbole actuel est un symbole opérable $ scope.checkoperator = function (opt) {if (opt == "+" || opt == "-" || opt == "×" || opt == "÷") {return true; } return false; }Si c'est le cas, renvoyez vrai, sinon renvoyez false.
Jusqu'à présent, il y a toujours une branche avec entrée égale au nombre qui n'a pas
Le code est le suivant (connecté à la méthode ShowResult)
// Si le clic est le signe égal else if (a == "=" && $ scope.result! = "" && $ scope.result! = "Error") {$ scope.flag = false; $ scope.num.push ($ scope.result); while ($ scope.opt.length! = 0) {var operator = $ scope.opt.pop (); var droit = $ scope.num.pop (); var left = $ scope.num.pop (); $ scope.calculate (gauche, opérateur, droite); }}};Si l'entrée est un signe égal, définissez d'abord l'indicateur sur FALSE, permettant à l'interface de rediger la prochaine fois que vous entrez le numéro, et le numéro actuellement affiché doit être placé dans la pile comme numéro de calcul. Ensuite, vous devez effectuer des opérations d'empilement continu jusqu'à ce que la pile de l'opérateur soit vide avant de pouvoir s'arrêter.
Résumer
Ce qui précède est le code et le processus principal de l'implémentation. Puisqu'il existe de nombreux codes de branche, toutes les branches sont données en même temps et ne peuvent pas être décrites en détail. Par conséquent, la méthode ShowResult est séparée, qui peut ne pas être adaptable. Étant donné que l'écriture était précipitée et n'a pas pris trop de temps à tester, il peut y avoir des bugs, veuillez les signaler. Dans le même temps, en raison de niveaux limités, cette méthode peut ne pas être la meilleure. Bienvenue pour donner un meilleur plan pour communiquer et apprendre ensemble ~~ Ce qui précède est le contenu complet de cet article. J'espère que cela apportera une aide à l'étude ou au travail de chacun.