Prefácio
Primeiro de tudo, não vamos falar sobre a criação do projeto básico do AngularJS. É melhor usar a ferramenta de andaimes para gerá -la diretamente. Se não houver esse ambiente, é claro, você também poderá apresentar o projeto baixando o arquivo AngularJS.
Exemplo detalhado Explicação
Main.js é o principal arquivo JS do projeto. Todos os JS estão escritos neste arquivo. Após a inicialização, o código JS do arquivo é o seguinte
Angular .Module ('CalculateApp', ['Nganimate', 'NgCookies', 'Ngresource', 'Ngroute', 'Ngsanitize', 'ngTouch']) .Controller ('Mainctrl', function ($ scope) {$ scope.Result = "; "1":["AC","+/-","%","÷"], "2":["7","8","9","×"], "3":["4","5","6","-"], "4":["1","2","3","+"], "5":["0",","="] }; });O resultado aqui é usado para vincular o cálculo resulta em ligação bidirecional e os dados são os números e símbolos no teclado da calculadora.
Todos os códigos CSS relacionados a este projeto são os seguintes:
*{margem: 0; preenchimento: 0;} corpo {cadding-top: 20px; Botting-Bottom: 20px;} H1 {Text-Align: Center; Cor:#3385ff;}. Main {margem: 20px Auto; fronteira: 1px Solid #202020; Bottom de fronteira: Nenhum; largura: 60%; Altura: 600px;}. Resultado {display: block; largura: 100%; altura: 30%; Antecedentes:#202020; Timing de caixa: caixa de fronteira; fronteira: nenhuma; preenchimento: 0; margem: 0; redimensionar: nenhum; Cor: #FFF; tamanho de fonte: 80px; Alinhamento de texto: à direita; altura da linha: 270px; estouro: oculto; clipe de fundo: border-box;}. Linha {altura: 14%; Antecedentes: #d7d8da; Timing de caixa: caixa de fronteira; Bottom de fronteira: 1px Solid #202020; Overflow: Hidden;}. Col {Hight: 100%; Timing de caixa: caixa de fronteira; Fronteira: 1px Solid #202020; flutuar: esquerda; Cor: #202020; Size de fonte: 28px; Alinhamento de texto: centro; altura da linha: 83px;}. Normal {largura: 25%;}. end-no {width: 25%; Right-Right: Nenhum; Antecedentes: #F78E11; cor: #fff;}. zero {width: 50%;}. history {background: #3385ff; Cor: #FFF; Size da fonte: 22px; Alinhamento de texto: centro;}Então o layout HTML é o seguinte:
<corpo ng-app = "calculatepp"> <h1> calculadora para iOS8 </h1> <hr/> <p> {{history.join ("")}} </p> <div> <textarea ng-model = "resultado"> </textarea> <div ng-repeat = "item em dados" ng-class = "showclass ($ index, a)" ng-click = "showResult (a)"> {{a}} </div> </div> </div> </body> Aqui, a tag P do histórico de classe é usada para exibir o registro de entrada, o que significa que todas as teclas que você pressiona serão exibidas para facilitar a visualização dos resultados. A história é uma matriz abaixo do escopo atual, que será explicado mais tarde. Aqui, uma textarea é usada como tela de exibição para os resultados do cálculo, principalmente para usar o recurso de ligação bidirecional. Ao mesmo tempo, cada tecla e elemento de interface da calculadora são gerados ao loop sobre o objeto de dados. showClass é um método abaixo do escopo, usado para obter os atributos de classe dos elementos irregulares da exibição da interface. Será explicado mais tarde. showResult é o principal método de resposta à chave. Todas as nossas respostas às chaves são obtidas através deste método, e explicaremos em detalhes posteriormente.
O código do método Showclass é o seguinte:
// Mostrar estilo de calculadora $ scope.showclass = function (index, a) {if (a == 0) {return "zero"; } Return Índice == 3 || a == "="? "End-No": "Normal"; };Esse método lida principalmente com a última coluna de cada linha a ser exibida como laranja e as teclas que exibem 0 devem ocupar duas células para processamento especial.
Até agora, a interface da calculadora foi totalmente implementada
As renderizações são as seguintes:
O seguinte precisa realizar a resposta às chaves. As teclas incluem teclas numéricas, teclas do operador e teclas AC. Cada pressionamento de teclas terá respostas diferentes e há uma conexão entre as teclas.
Para facilitar a explicação do código, um método é usado para fornecer o código do método ShowResult nos segmentos e depois explicá -lo em detalhes.
Primeiro de tudo, precisamos adicionar várias variáveis para controle e armazenamento.
// a pilha de números usados para cálculo $ scope.num = []; $ scope.history = []; // a pilha do operador $ scope.opt = []; // o resultado do cálculo da calculadora $ scope.result = ""; // o resultado da calculadora $ scope.result = ""; // significa se deve começar a exibir novamente. Verdadeiro significa não exibir novamente. Falso significa limpar a saída atual e redisplay o número $ scope.flag = true; // significa se o operador pode ser inserido agora. Se puder ser verdadeiro, caso contrário, é falso $ scope.isot = true;
A matriz NUM é na verdade uma pilha, usada para receber os números inseridos pelo usuário. O uso específico será explicado mais tarde. A matriz de histórico é todas as chaves inseridas pelo usuário. Cada vez que você o pressionar, os símbolos ou números na chave são colocados na pilha e, em seguida, ela é exibida na interface em tempo real usando a ligação. A matriz OPT é outra pilha usada para receber a entrada do operador pelo usuário. O uso específico será explicado mais tarde. Bandeira é uma bandeira. Quando é verdade, significa que o número pressionado durante a pressão do número faz parte do número exibido atualmente e precisa ser exibido por trás dele. Por exemplo, a interface atual é exibida 12 e, em seguida, pressione 3 será julgada. Se verdadeiro, 123 será exibido. Caso contrário, a interface será limpa e 3.IsOpt é outro sinalizador. É principalmente para impedir que o usuário tenha informações ilegais de operadores durante o processo de entrada. Por exemplo, o usuário entra 1+ 2+ em sucessão. Quando a entrada é inserida aqui, a entrada abaixo deve ser um número, mas o usuário entra em um operador. Ao julgar esse sinalizador, a calculadora ignorará esse operador ilegal e manterá a entrada ainda 1+2+.
O código a seguir é fornecido nos segmentos e o código completo é conectá -los.
$ scope.init = function () {$ scope.num = []; $ scope.opt = []; $ scope.history = []; $ scope.flag = true; $ scope.isot = true; }; $ scope.showResult = function (a) {$ scope.history.push (a); var reg = // d/ig, regdot = //./ig, regabs = /// ig; // se clicar em um número se (reg.test (a)) {// elimine o congelamento if ($ scope.isot == false) {$ scope.isot = true; } if ($ scope.result! = 0 && $ scope.flag && $ scope.result! = "erro") {$ scope.result += a; } else {$ scope.result = a; $ scope.flag = true; }} O método init é usado para inicializar algumas variáveis e sinalizadores para devolvê -las ao seu estado original. showResult é o principal método de exibir a interface para responder às operações do usuário. O código acima é uma ramificação IF nesse método, indicando que, se a entrada do operador for inserida, se a entrada para o operador tiver sido congelada (o operador não poderá ser inserido no momento e será ignorado após a entrada do número, quando a pilha de operador será inserida. Se o resultado atualmente exibido não estiver vazio e o número pressionado fará parte do número exibido atualmente e nenhum erro ocorre, o resultado exibido é que o número atualmente pressionado está conectado ao final do número atualmente exibido. Caso contrário, isso significa que o número inserido na próxima vez precisa ser exibido após esse número ao redisplay.
Código JS (continuação)
// se você clicar em CA else se (a == "AC") {$ scope.result = 0; $ scope.init (); }Se o CA clicado, significa inicialização, que o resultado seja 0 e todos os estados sejam limpos.
Código JS (continuação)
// Se você clicar em um ponto decimal mais se (a == ".") {If ($ scope.result! = "" &&! Regdot.test ($ scope.result)) {$ scope.result+= a; }}Se o clique for um ponto decimal, deixe o ponto decimal estar conectado ao final do visor atual se o visor atual não estiver vazio e não houver ponto decimal no resultado da exibição atual.
Código JS (continuação)
// Se você clicar em um operador inverso se (regabs.test (a)) {if ($ scope.result> 0) {$ scope.result = "-"+$ scope.result; } else {$ scope.result = math.abs ($ scope.result); }}Se o clique for uma operação inversa, o resultado atual será inversamente
Código JS (continuação)
// se você clicar em um sinal percentual mais se (a == "%") {$ scope.result = $ scope.format (número ($ scope.result)/100); } Se você clicar em um sinal percentual, divida o resultado atual exibido por 100 e depois o exibir. Aqui está uma função format
O código é o seguinte:
// Resultado do formato Saída $ scope.format = function (num) {var regnum =/. {10,}/ig; if (regnum.test (num)) {if (//./. test (num)) {return num.toexponencial (3); } else {return num.toexponencial (); }} else {return num; }}} else {return num; }}Sua principal função é que a calculadora que vem com iOS8 não exibirá muitos dígitos infinitamente. Se exceder 10 dígitos (incluindo pontos decimais), os cálculos científicos serão usados para exibir. Por simplicidade, ao usar cálculos científicos para resultados de exibição contendo pontos decimais e excedendo 10 dígitos, deixe -o manter a exibição de 3 dígitos após o ponto decimal.
Código JS (parte do showResult está conectado)
// Se o operador clicado e o resultado atual não estarão vazios e erros se ($ scope.checkoperator (a) && $ scope.result! = "" && $ scope.result! = "Error" && $ scope.isot) {$ scope.flag = false; $ scope.num.push ($ scope.result); $ SCOPE.OPERAÇÃO (A); // Depois de clicar no operador uma vez, você precisa ignorar a situação em que o operador é clicado novamente. $ scope.isot = false; }Esta filial é a ramificação mais complexa, o que significa que, se a entrada for um operador, a operação deverá ser executada. Para inserir nesta ramificação, você precisa definir o sinalizador como False primeiro, que é inserir o número da próxima vez, que é reentrar o número em vez de inserir o resultado da exibição atual.
Em seguida, deixe o número atualmente exibido como o número que está sendo calculado para inserir a pilha de números primeiro. operation é o método de operação. Como um operador foi clicado desta vez, na próxima vez que você clicar nele, você deve ignorar esse operador e definir a ISOPT como falsa.
O código de operação é o seguinte
// Compare a prioridade do operador de entrada atualmente e do operador da pilha do operador // Se a prioridade do operador superior for pequena, o operador atual será colocado na pilha e não a calcula. // Caso contrário, o operador superior é colocado na pilha e a pilha de números é colocada na pilha para dois elementos em sucessão e calcule // o operador atual é colocado na pilha. $ scope.operation = function (atual) {// Se a pilha do operador estiver vazia, coloque diretamente o operador atual na pilha if (! $ scope.opt.length) {$ scope.opt.push (corrente); retornar; } VAR Operador, direita, esquerda; var lastOpt = $ scope.opt [$ scope.opt.Length-1]; // Se a prioridade do operador atual for maior que o último operador, apenas a pilha será inserida se ($ scope.isPri (atual, lastOpt)) {$ scope.opt.push (corrente); } else {operator = $ scope.opt.pop (); direita = $ scope.num.pop (); esquerda = $ scope.num.pop (); $ scope.calculate (esquerda, operador, direita); $ scope.operation (atual); }};Este método aceita o operador de entrada atualmente como um parâmetro. A idéia principal é que um operador seja recebido atualmente. Se a pilha do operador estiver vazia, o operador atual será colocado na pilha e, em seguida, não há necessidade de fazer mais nada neste caso. Se a pilha atual do operador não estiver vazia, o elemento superior da pilha atual do operador será exibido, de modo que o operador atualmente recebido e o operador superior recebam prioridade (a prioridade da multiplicação e divisão é maior que a adição e a subtração, e o operador superior recebe prioridade da mesma prioridade porque é inserida pela primeira vez). O método ISPRI é usado para determinar a prioridade e receber dois parâmetros. O primeiro é o operador atualmente recebido e o segundo é o operador de primeira linha na pilha. Se o operador atual tiver uma prioridade mais alta de acordo com as regras mencionadas acima, o operador será colocado diretamente na pilha. Se a prioridade do operador atual for menor que a parte superior do operador da pilha, você precisará executar cálculos e alterar a exibição da calculadora. Os dois elementos na parte superior da pilha do número de operação são aparecidos por sua vez, pois os dois números operacionais para uma operação e, em seguida, a parte superior da pilha da pilha do operador é exibida como operador para esta operação, e o método de cálculo é chamado para o método de cálculo para operação.
O código do método é o seguinte
// Responsável pelo cálculo da função de resultado $ scope.CalCulate = function (esquerda, operador, direita) {switch (operador) {case " +": $ scope.result = $ scope.format (número (esquerda) + número (direita)); $ scope.num.push ($ scope.result); quebrar; case " -": $ scope.result = $ scope.format (número (esquerda) - número (direita)); $ scope.num.push ($ scope.result); quebrar; case "×": $ scope.result = $ scope.format (número (esquerda) * número (direita)); $ scope.num.push ($ scope.result); quebrar; case "÷": if (direita == 0) {$ scope.result = "error"; $ scope.init (); } else {$ scope.result = $ scope.format (número (esquerda) / número (direita)); $ scope.num.push ($ scope.result); } quebrar; Padrão: quebra; }};Este método aceita três parâmetros, o número da operação esquerda, o operador do meio e o número da operação correta e altera o resultado para exibir o resultado após a adição, subtração, multiplicação e operação de divisão, e coloca o resultado do cálculo na pilha do número de cálculo. Aqui é necessário observar que, se o cálculo for divisória e o divisor for 0, ocorre um erro, erros de exibição e todos os estados serão limpos, caso contrário, o cálculo é normal.
Após a conclusão de uma operação, os estados na pilha do operador e a pilha de números serão alterados e o valor atual atual não foi colocado na pilha. Portanto, o processo acima deve ser repetido para comparação prioritária e, em seguida, a operação é realizada. De fato, é um processo recursivo até que a pilha do operador esteja vazia ou a prioridade do operador atual seja maior que a parte superior do operador da pilha do operador. O método ISPRI é usado para determinar a prioridade do operador.
O código é o seguinte:
// julga se o operador atual tem maior prioridade que o último, se for retornado true //, caso contrário, retorne False $ scope.isPri = function (atual, último) {if (current == last) {return false; } else {if (current == "×" || current == "÷") {if (last == "×" || last == "÷") {return false; } else {return true; }} else {return false; }}};As regras de julgamento foram descritas anteriormente.
Além disso, existe um método checkOperator , que é para determinar se o símbolo de entrada são os quatro símbolos do operador de adição, subtração, multiplicação e divisão.
O código é o seguinte:
// julgue se o símbolo atual é um símbolo operável $ scope.cheCkoperator = function (opt) {if (opt == "+" || opt == "-" || opt == "×" || opt == "÷") {return true; } retornar false; }Nesse caso, retorne verdadeiro, retorne False.
Até agora, ainda há um ramo com entrada igual ao número que não tem
O código é o seguinte (conectado ao método ShowResult)
// se o clicado for o sinal igual mais se (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 à direita = $ scope.num.pop (); var esquerdo = $ scope.num.pop (); $ scope.calculate (esquerda, operador, direita); }}};Se a entrada for um sinal igual, primeiro o sinalizador definido como false, permitindo que a interface redisplay na próxima vez que você insira o número e o número atualmente exibido deverá ser colocado na pilha como um número de cálculo. Em seguida, você precisa executar operações de empilhamento contínuo até que a pilha do operador esteja vazia antes que ela possa parar.
Resumir
O exposto acima é o código principal e o processo da implementação. Como existem muitos códigos de ramificação, todas as ramificações são fornecidas de uma só vez e não podem ser descritas em detalhes. Portanto, o método ShowResult é separado, o que pode não ser adaptável. Como a escrita foi correr e não demorou muito tempo para testar, pode haver alguns bugs, aponte -os. Ao mesmo tempo, devido a níveis limitados, esse método pode não ser o melhor. Bem -vindo a dar um plano melhor para se comunicar e aprender juntos ~~ O acima é o conteúdo inteiro deste artigo. Espero que isso traga alguma ajuda para todos os estudos ou trabalho de todos.