“Pensando em AngularJS” se eu tiver um fundo jQuery?

Suponha que eu esteja familiarizado com o desenvolvimento de aplicativos do lado do cliente no jQuery , mas agora gostaria de começar a usar o AngularJS . Você pode descrever a mudança de paradigma que é necessária? Aqui estão algumas perguntas que podem ajudá-lo a formular uma resposta:

  • Como faço para arquitetar e projetar aplicativos da Web do lado do cliente de maneira diferente? Qual é a maior diferença?
  • O que devo parar de fazer / usar; O que devo começar a fazer / usar em vez disso?
  • Há alguma consideração / restrição do lado do servidor?

Eu não estou procurando uma comparação detalhada entre jQuery e AngularJS .

1. Não crie sua página e altere-a com manipulações DOM

No jQuery, você cria uma página e, em seguida, a torna dinâmica. Isso ocorre porque o jQuery foi projetado para aumento e cresceu incrivelmente a partir dessa premissa simples.

Mas no AngularJS, você deve começar do zero com sua arquitetura em mente. Em vez de começar pensando “Eu tenho essa parte do DOM e quero fazer X”, você precisa começar com o que deseja realizar, depois projetar seu aplicativo e, finalmente, projetar sua visualização.

2. Não aumente o jQuery com o AngularJS

Da mesma forma, não comece com a idéia de que o jQuery faz X, Y e Z, então adicionarei o AngularJS em cima disso para modelos e controladores. Isso é realmente tentador quando você está apenas começando, e é por isso que eu sempre recomendo que os novos desenvolvedores do AngularJS não usem o jQuery, pelo menos até que eles se acostumem a fazer as coisas como o “Angular Way”.

Eu vi muitos desenvolvedores aqui e na lista de discussão criarem essas soluções elaboradas com plugins jQuery de 150 ou 200 linhas de código que eles então colam no AngularJS com uma coleção de callbacks e $apply s que são confusos e complicados; mas eles eventualmente conseguem trabalhar! O problema é que na maioria dos casos o plugin jQuery pode ser reescrito em AngularJS em uma fração do código, onde de repente tudo se torna compreensível e direto.

A linha inferior é esta: ao resolver, primeiro “pense em AngularJS”; se você não consegue pensar em uma solução, pergunte à comunidade; se depois de tudo isso não houver uma solução fácil, sinta-se à vontade para encontrar o jQuery. Mas não deixe o jQuery se tornar uma muleta ou você nunca vai dominar o AngularJS.

3. Sempre pense em termos de arquitetura

Primeiro, saiba que aplicativos de uma única página são aplicativos . Eles não são páginas da web. Portanto, precisamos pensar como um desenvolvedor do lado do servidor, além de pensar como um desenvolvedor do lado do cliente. Temos que pensar em como dividir nosso aplicativo em componentes individuais, extensíveis e testáveis.

Então, como você faz isso? Como você “pensa em AngularJS”? Aqui estão alguns princípios gerais, contrastados com jQuery.

A visão é o “registro oficial”

No jQuery, nós programaticamente alteramos a exibição. Poderíamos ter um menu suspenso definido como ul assim:

  

Em jQuery, em nossa lógica de aplicativo, nós o ativamos com algo como:

 $('.main-menu').dropdownMenu(); 

Quando olhamos apenas para a visão, não é imediatamente óbvio que haja alguma funcionalidade aqui. Para pequenas aplicações, tudo bem. Mas, para aplicativos não triviais, as coisas ficam confusas e difíceis de manter.

No AngularJS, no entanto, a visão é o registro oficial da funcionalidade baseada em visão. Nossa declaração ul seria assim:

  

Esses dois fazem a mesma coisa, mas na versão do AngularJS qualquer um que olhar o modelo sabe o que deve acontecer. Sempre que um novo membro da equipe de desenvolvimento entra em cena, ela pode ver isso e saber que existe uma diretiva chamada dropdownMenu operando nele; ela não precisa intuir a resposta certa ou filtrar qualquer código. A visão nos dizia o que deveria acontecer. Muito mais limpo.

Desenvolvedores novatos no AngularJS muitas vezes fazem uma pergunta como: como eu encontro todos os links de um tipo específico e adiciono uma diretiva a eles. O desenvolvedor está sempre espantado quando respondemos: você não. Mas a razão pela qual você não faz isso é que isso é meio jQuery, meio AngularJS e não é bom. O problema aqui é que o desenvolvedor está tentando “fazer jQuery” no contexto do AngularJS. Isso nunca vai funcionar bem. A visão é o registro oficial. Fora de uma diretiva (mais sobre isso abaixo), você nunca, nunca, nunca muda o DOM. E diretivas são aplicadas na visão , então a intenção é clara.

Lembre-se: não projete e marque. Você deve arquitetar e depois projetar.

Ligação de dados

Esta é de longe uma das características mais impressionantes do AngularJS e elimina a necessidade de fazer os tipos de manipulações de DOM que mencionei na seção anterior. O AngularJS atualizará automaticamente sua visualização para que você não precise! No jQuery, respondemos a events e, em seguida, atualizamos o conteúdo. Algo como:

 $.ajax({ url: '/myEndpoint.json', success: function ( data, status ) { $('ul#log').append('
  • Data Received!
  • '); } });

    Para uma visão assim:

     

    Além de misturar preocupações, também temos os mesmos problemas de intenção significativa que mencionei antes. Mas, mais importante, tivemos que fazer referência e atualizar manualmente um nó DOM. E se quisermos excluir uma input de log, temos que codificar o DOM para isso também. Como podemos testar a lógica para além do DOM? E se quisermos mudar a apresentação?

    Isso é um pouco confuso e um pouco frágil. Mas no AngularJS, podemos fazer isso:

     $http( '/myEndpoint.json' ).then( function ( response ) { $scope.log.push( { msg: 'Data Received!' } ); }); 

    E nossa visão pode ser assim:

     
    • {{ entry.msg }}

    Mas, para essa questão, nossa visão poderia ser assim:

     
    {{ entry.msg }}

    E agora, em vez de usar uma lista não ordenada, estamos usando checkboxs de alerta do Bootstrap. E nós nunca tivemos que mudar o código do controlador! Mas o mais importante, não importa onde ou como o log é atualizado, a exibição também será alterada. Automaticamente. Arrumado!

    Embora eu não tenha mostrado aqui, a vinculação de dados é bidirecional. Então, essas mensagens de log também podem ser editadas na visualização apenas fazendo isso: . E havia muita alegria.

    Camada de modelo distinta

    No jQuery, o DOM é como o modelo. Mas no AngularJS, temos uma camada de modelo separada que podemos gerenciar da maneira que quisermos, de forma totalmente independente da exibição. Isso ajuda na vinculação de dados acima, mantém a separação de interesses e introduz testabilidade muito maior. Outras respostas mencionaram este ponto, por isso vou deixar por isso mesmo.

    Separação de preocupações

    E todos os itens acima se encheckboxm neste tema abrangente: mantenha suas preocupações separadas. Sua opinião age como o registro oficial do que é suposto acontecer (na maioria das vezes); seu modelo representa seus dados; você tem uma camada de serviço para executar tarefas reutilizáveis; você faz manipulação de DOM e aumenta sua visão com diretivas; e você cola tudo junto com os controladores. Isso também foi mencionado em outras respostas, e a única coisa que gostaria de acrescentar diz respeito à testabilidade, que discuto em outra seção abaixo.

    dependency injection

    Para nos ajudar com a separação das preocupações, está a injeção de dependência (DI). Se você vem de uma linguagem do lado do servidor (do Java para o PHP ) provavelmente já está familiarizado com esse conceito, mas se você é um cara do lado do cliente vindo da jQuery, esse conceito pode parecer de bobo a supérfluo a moderno . Mas isso não. 🙂

    De uma perspectiva ampla, DI significa que você pode declarar componentes muito livremente e, em seguida, a partir de qualquer outro componente, basta solicitar uma instância e será concedido. Você não precisa saber sobre a ordem de carregamento, localização de arquivos ou qualquer coisa assim. O poder pode não ser imediatamente visível, mas vou fornecer apenas um exemplo (comum): teste.

    Digamos que em nosso aplicativo, exigimos um serviço que implemente o armazenamento no servidor por meio de uma API REST e, dependendo do estado do aplicativo, também do armazenamento local. Ao executar testes em nossos controladores, não queremos ter que nos comunicar com o servidor – afinal, estamos testando o controlador . Podemos apenas adicionar um serviço falso com o mesmo nome do nosso componente original, e o injetor irá garantir que nosso controlador receba o falso automaticamente – nosso controlador não precisa e não precisa saber a diferença.

    Falando em testes …

    4. Desenvolvimento orientado a testes – sempre

    Isso é realmente parte da seção 3 da arquitetura, mas é tão importante que eu a coloque como sua própria seção de nível superior.

    De todos os muitos plugins do jQuery que você viu, usou ou escreveu, quantos deles tinham um conjunto de testes? Não são muitos, porque o jQuery não é muito receptivo a isso. Mas o AngularJS é.

    No jQuery, a única maneira de testar é criar o componente independentemente com uma página de amostra / demonstração na qual nossos testes podem executar a manipulação DOM. Então temos que desenvolver um componente separadamente e depois integrá-lo em nossa aplicação. Quão inconveniente! Na maioria das vezes, quando desenvolvemos com jQuery, optamos pelo desenvolvimento iterativo em vez de orientado a testes. E quem poderia nos culpar?

    Mas como temos separação de interesses, podemos fazer um desenvolvimento orientado a testes de forma iterativa no AngularJS! Por exemplo, digamos que queremos que uma diretiva super-simples indique em nosso menu qual é a rota atual. Podemos declarar o que queremos na visão de nossa aplicação:

     Hello 

    Ok, agora podemos escrever um teste para a diretiva inexistente when-active :

     it( 'should add "active" when the route changes', inject(function() { var elm = $compile( 'Hello' )( $scope ); $location.path('/not-matching'); expect( elm.hasClass('active') ).toBeFalsey(); $location.path( 'https://stackoverflow.com/hello' ); expect( elm.hasClass('active') ).toBeTruthy(); })); 

    E quando executamos nosso teste, podemos confirmar que ele falha. Só agora devemos criar nossa diretiva:

     .directive( 'whenActive', function ( $location ) { return { scope: true, link: function ( scope, element, attrs ) { scope.$on( '$routeChangeSuccess', function () { if ( $location.path() == element.attr( 'href' ) ) { element.addClass( 'active' ); } else { element.removeClass( 'active' ); } }); } }; }); 

    Nosso teste agora é aprovado e nosso menu é executado conforme solicitado. Nosso desenvolvimento é interativo e orientado a testes. Mau-legal.

    5. Conceitualmente, diretivas não são empacotadas jQuery

    Você frequentemente ouvirá “somente manipulação DOM em uma diretiva”. Isso é uma necessidade. Trate-o com a devida deferência!

    Mas vamos mergulhar um pouco mais fundo …

    Algumas diretivas apenas decoram o que já está na view (pense ngClass ) e, portanto, às vezes, manipulam o DOM imediatamente e depois são feitas basicamente. Mas se uma diretiva é como um “widget” e tem um modelo, também deve respeitar a separação de interesses. Ou seja, o modelo também deve permanecer amplamente independente de sua implementação nas funções de link e controlador.

    O AngularJS vem com um conjunto completo de ferramentas para tornar isso muito fácil; com ngClass podemos atualizar dinamicamente a class; ngModel permite vinculação de dados bidirecional; ngShow e ngHide programaticamente mostram ou ocultam um elemento; e muito mais – incluindo os que nós mesmos escrevemos. Em outras palavras, podemos fazer todos os tipos de grandeza sem manipulação de DOM. Quanto menos manipulação de DOM, mais fáceis são as diretivas para testar, mais fáceis são para estilizar, mais fáceis de alterar no futuro e mais reutilizáveis ​​e distribuíveis.

    Eu vejo muitos desenvolvedores novos no AngularJS usando diretivas como o lugar para jogar um monte de jQuery. Em outras palavras, eles pensam “desde que eu não posso fazer manipulação DOM no controlador, eu vou tomar esse código colocá-lo em uma diretiva”. Enquanto isso certamente é muito melhor, muitas vezes ainda está errado .

    Pense no logger que nós programamos na seção 3. Mesmo se colocarmos isso em uma diretiva, nós ainda queremos fazer o “Angular Way”. Ainda não há manipulação de DOM! Há muitas ocasiões em que a manipulação do DOM é necessária, mas é muito mais rara do que você pensa! Antes de manipular o DOM em qualquer lugar da sua aplicação, pergunte-se se realmente precisa. Pode haver um caminho melhor.

    Aqui está um exemplo rápido que mostra o padrão que vejo com mais frequência. Nós queremos um botão de toggle. (Nota: este exemplo é um pouco artificial e um texto detalhado para representar casos mais complicados que são resolvidos exatamente da mesma maneira.)

     .directive( 'myDirective', function () { return { template: 'Toggle me!', link: function ( scope, element, attrs ) { var on = false; $(element).click( function () { on = !on; $(element).toggleClass('active', on); }); } }; }); 

    Há algumas coisas erradas com isso:

    1. Primeiro, o jQuery nunca foi necessário. Não há nada que fizemos aqui que precisasse de jQuery!
    2. Segundo, mesmo que já tenhamos jQuery em nossa página, não há razão para usá-lo aqui; podemos simplesmente usar o angular.element e o nosso componente ainda funcionará quando inserido em um projeto que não tenha o jQuery.
    3. Em terceiro lugar, mesmo supondo que o jQuery foi necessário para esta diretiva funcionar, jqLite ( angular.element ) sempre usará o jQuery se ele foi carregado! Então, não precisamos usar o $ – podemos usar apenas angular.element .
    4. Quarto, intimamente relacionado ao terceiro, é que os elementos jqLite não precisam ser agrupados em $ – o element que é passado para a function link já seria um elemento jQuery!
    5. E quinto, que mencionamos nas seções anteriores, por que estamos misturando material de modelo em nossa lógica?

    Esta diretiva pode ser reescrita (mesmo para casos muito complicados!) Muito mais simplesmente assim:

     .directive( 'myDirective', function () { return { scope: true, template: 'Toggle me!', link: function ( scope, element, attrs ) { scope.on = false; scope.toggle = function () { scope.on = !scope.on; }; } }; }); 

    Novamente, o material do template está no template, então você (ou seus usuários) podem facilmente trocá-lo por um que atenda a qualquer estilo necessário, e a lógica nunca precisou ser tocada. Reutilização – boom!

    E ainda existem todos esses outros benefícios, como teste – é fácil! Não importa o que está no modelo, a API interna da diretiva nunca é tocada, portanto, a refatoração é fácil. Você pode alterar o modelo o quanto quiser sem tocar na diretiva. E não importa o que você mude, seus testes ainda passam.

    w00t!

    Portanto, se diretivas não são apenas collections de funções semelhantes à jQuery, o que são elas? Diretivas são, na verdade, extensões de HTML . Se o HTML não faz algo que você precisa fazer, você escreve uma diretiva para fazer isso para você, e então usa como se fosse parte do HTML.

    Dito de outra maneira, se o AngularJS não fizer algo ngClick , pense em como a equipe conseguiria se encheckboxr bem com ngClick , ngClass , et al.

    Resumo

    Nem use jQuery. Nem inclua isso. Ele vai te segurar de volta. E quando você chegar a um problema que você acha que já sabe como resolver em jQuery, antes de pegar o $ , tente pensar em como fazê-lo dentro dos limites do AngularJS. Se você não sabe, pergunte! 19 vezes em 20, a melhor maneira de fazer isso não precisa do jQuery e tentar resolvê-lo com o jQuery resulta em mais trabalho para você.

    Imperativo → declarativo

    No jQuery, os seletores são usados ​​para localizar elementos DOM e, em seguida, vincular / registrar manipuladores de events a eles. Quando um evento é acionado, esse código (imperativo) é executado para atualizar / alterar o DOM.

    No AngularJS, você quer pensar em views em vez de elementos DOM. As visualizações são HTML (declarativo) que contêm diretivas AngularJS. As diretivas definem os manipuladores de events nos bastidores para nós e nos dão uma binding de dados dinâmica. Os seletores raramente são usados, então a necessidade de IDs (e alguns tipos de classs) é muito reduzida. As visualizações estão vinculadas aos modelos (via escopos). Visualizações são uma projeção do modelo. Os modelos de mudança de events (isto é, dados, propriedades do escopo) e as exibições que projetam esses modelos são atualizados “automaticamente”.

    No AngularJS, pense em modelos, em vez de elementos DOM selecionados por jQuery que armazenam seus dados. Pense nas exibições como projeções desses modelos, em vez de registrar retornos de chamada para manipular o que o usuário vê.

    Separação de preocupações

    jQuery emprega JavaScript discreto – comportamento (JavaScript) é separado da estrutura (HTML).

    O AngularJS usa controladores e diretivas (cada qual pode ter seu próprio controlador, e / ou compilar e vincular funções) para remover o comportamento da view / structure (HTML). Angular também tem serviços e filtros para ajudar a separar / organizar seu aplicativo.

    Veja também https://stackoverflow.com/a/14346528/215945

    Design da aplicação

    Uma abordagem para projetar um aplicativo AngularJS:

    1. Pense nos seus modelos. Crie serviços ou seus próprios objects JavaScript para esses modelos.
    2. Pense em como você deseja apresentar seus modelos – seus pontos de vista. Crie modelos HTML para cada visualização, usando as diretivas necessárias para obter a binding de dados dinâmica.
    3. Anexe um controlador a cada visualização (usando ng-view e routing ou ng-controller). Peça ao controlador para localizar / obter apenas os dados do modelo que a visão precisa para fazer seu trabalho. Faça controladores o mais fino possível.

    Herança Prototypal

    Você pode fazer muito com o jQuery sem saber como funciona a inheritance prototípica do JavaScript. Ao desenvolver aplicativos AngularJS, você evitará algumas armadilhas comuns se tiver uma boa compreensão da inheritance do JavaScript. Leitura recomendada: Quais são as nuances do escopo protótipo / inheritance prototípica em AngularJS?

    AngularJS vs. jQuery

    AngularJS e jQuery adotam ideologias muito diferentes. Se você está vindo do jQuery, você pode achar algumas das diferenças surpreendentes. Angular pode te deixar com raiva.

    Isso é normal, você deve passar por isso. Angular vale a pena.

    A grande diferença (TLDR)

    O jQuery fornece um kit de ferramentas para selecionar bits arbitrários do DOM e fazer alterações ad-hoc neles. Você pode fazer praticamente qualquer coisa que quiser, peça por peça.

    Em vez disso, o AngularJS fornece um compilador .

    O que isto significa é que o AngularJS lê todo o seu DOM de cima para baixo e o trata como código, literalmente como instruções para o compilador. Ao percorrer o DOM, ele procura por diretivas específicas ( diretivas de compilador) que dizem ao compilador do AngularJS como se comportar e o que fazer. Diretivas são pequenos objects cheios de JavaScript que podem combinar contra atributos, tags, classs ou até mesmo comentários.

    Quando o compilador Angular determina que uma parte do DOM corresponde a uma diretiva específica, ele chama a function diretiva, passando o elemento DOM, quaisquer atributos, o escopo atual (que é um armazenamento de variável local) e alguns outros bits úteis. Estes atributos podem conter expressões que podem ser interpretadas pela Diretiva, e que dizem como renderizar, e quando devem ser redesenhadas.

    As diretivas podem, por sua vez, extrair componentes angulares adicionais, como controladores, serviços, etc. O que sai da parte inferior do compilador é um aplicativo da Web totalmente formado, com fio e pronto para uso.

    Isso significa que o Angular é dirigido por modelos . Seu modelo impulsiona o JavaScript, e não o contrário. Esta é uma inversão radical de papéis e o completo oposto do JavaScript discreto que escrevemos nos últimos 10 anos. Isso pode levar algum tempo para se acostumar.

    Se isso soa como se fosse excessivamente prescritivo e limitante, nada poderia estar mais longe da verdade. Como o AngularJS trata seu HTML como código, você obtém granularidade no nível HTML em seu aplicativo da web . Tudo é possível, e a maioria das coisas é surpreendentemente fácil quando você faz alguns saltos conceituais.

    Vamos descer ao âmago da questão.

    Primeiro, o Angular não substitui o jQuery

    Angular e jQuery fazem coisas diferentes. O AngularJS oferece um conjunto de ferramentas para produzir aplicativos da web. O jQuery fornece principalmente ferramentas para modificar o DOM. Se o jQuery estiver presente na sua página, o AngularJS irá utilizá-lo automaticamente. Se não for, o AngularJS vem com o jQuery Lite, que é uma versão reduzida, mas ainda perfeitamente utilizável do jQuery.

    Misko gosta de jQuery e não se opõe a você usá-lo. No entanto, você perceberá que pode realizar praticamente todo o seu trabalho usando uma combinação de escopo, modelos e diretivas, e deve preferir esse stream de trabalho sempre que possível, porque seu código será mais discreto, mais configurável e mais Angular.

    Se você usa o jQuery, não deveria estar espalhando por todo o lugar. O local correto para a manipulação do DOM no AngularJS está em uma diretiva. Mais sobre isso depois.

    JavaScript discreto com seletores versus modelos declarativos

    O jQuery é normalmente aplicado discretamente. Seu código JavaScript está vinculado no header (ou no rodapé) e esse é o único lugar mencionado. Usamos seletores para escolher pedaços da página e escrever plugins para modificar essas partes.

    O JavaScript está no controle. O HTML tem uma existência completamente independente. Seu HTML permanece semântico, mesmo sem JavaScript. Atributos Onclick são uma prática muito ruim.

    Uma das primeiras coisas que você notará sobre o AngularJS é que os atributos personalizados estão em todo lugar . Seu HTML será repleto de atributos ng, que são essencialmente atributos onClick em esteróides. Estas são diretivas (diretivas de compilador) e são uma das principais maneiras pelas quais o modelo é vinculado ao modelo.

    Quando você vê isso pela primeira vez, pode ser tentado a escrever AngularJS como JavaScript intrusivo da velha escola (como fiz no começo). Na verdade, o AngularJS não joga com essas regras. No AngularJS, seu HTML5 é um modelo. É compilado pelo AngularJS para produzir sua página web.

    Esta é a primeira grande diferença. Para jQuery, sua página da web é um DOM a ser manipulado. Para AngularJS, seu HTML é um código para ser compilado. AngularJS lê em toda a sua página web e, literalmente, compila em uma nova página usando seu compilador embutido.

    Seu modelo deve ser declarativo; seu significado deve ser claro simplesmente lendo-o. Usamos atributos personalizados com nomes significativos. Criamos novos elementos HTML, novamente com nomes significativos. Um designer com conhecimento mínimo de HTML e nenhuma habilidade de codificação pode ler seu modelo AngularJS e entender o que está fazendo. Ele ou ela pode fazer modificações. Este é o caminho angular.

    O modelo está no banco do motorista.

    Uma das primeiras perguntas que me fiz ao iniciar o AngularJS e percorrer os tutoriais é “Onde está meu código?” . Eu não escrevi JavaScript, e ainda assim tenho todo esse comportamento. A resposta é óbvia. Como o AngularJS compila o DOM, o AngularJS está tratando seu HTML como código. Para muitos casos simples, basta escrever um modelo e deixar o AngularJS compilá-lo em um aplicativo para você.

    Seu modelo impulsiona seu aplicativo. É tratado como uma DSL . Você escreve componentes do AngularJS, e o AngularJS cuidará de puxá-los e disponibilizá-los no momento certo com base na estrutura do seu modelo. Isso é muito diferente de um padrão MVC padrão, em que o modelo é apenas para saída.

    É mais semelhante ao XSLT do que ao Ruby on Rails, por exemplo.

    Esta é uma inversão radical de controle que leva algum tempo para se acostumar.

    Pare de tentar direcionar seu aplicativo a partir do seu JavaScript. Deixe o modelo orientar o aplicativo e deixe que o AngularJS cuide de conectar os componentes juntos. Este também é o caminho angular.

    HTML semântico vs. modelos semânticos

    Com o jQuery, sua página HTML deve conter conteúdo significativo semântico. Se o JavaScript estiver desativado (por um usuário ou mecanismo de pesquisa), seu conteúdo permanecerá acessível.

    Porque o AngularJS trata sua página HTML como um modelo. O modelo não deve ser semântico, pois seu conteúdo é normalmente armazenado em seu modelo, que, em última análise, vem da sua API. O AngularJS compila seu DOM com o modelo para produzir uma página da web semântica.

    Sua origem HTML não é mais semântica, em vez disso, sua API e o DOM compilado são semânticos.

    Em AngularJS, o que significa que vive no modelo, o HTML é apenas um modelo, apenas para exibição.

    Neste ponto, você provavelmente tem todos os tipos de perguntas sobre SEO e acessibilidade, e com razão. Existem questões em aberto aqui. A maioria dos leitores de canvas analisará o JavaScript. Os mecanismos de pesquisa também podem indexar o conteúdo do AJAX . No entanto, você vai querer certificar-se de que você está usando URLs pushstate e você tem um sitemap decente. Veja aqui uma discussão sobre o assunto: https://stackoverflow.com/a/23245379/687677

    Separação de preocupações (SOC) vs. MVC

    A separação de interesses (SOC) é um padrão que cresceu ao longo de muitos anos de desenvolvimento da Web por vários motivos, incluindo SEO, acessibilidade e incompatibilidade do navegador. Se parece com isso:

    1. HTML – significado semântico. O HTML deve ficar sozinho.
    2. CSS – Styling, sem o CSS, a página ainda é legível.
    3. JavaScript – Comportamento, sem o script, o conteúdo permanece.

    Mais uma vez, o AngularJS não joga de acordo com suas regras. Em um traçado, o AngularJS acaba com uma década de sabedoria recebida e, em vez disso, implementa um padrão MVC no qual o modelo não é mais semântico, nem mesmo um pouquinho.

    Se parece com isso:

    1. Modelo – seus modelos contêm seus dados semânticos. Modelos são geralmente objects JSON . Modelos existem como atributos de um object chamado $ scope. Você também pode armazenar funções utilitárias úteis no $ scope, que seus modelos podem acessar.
    2. Visualizar – suas visualizações são gravadas em HTML. A visão geralmente não é semântica porque seus dados residem no modelo.
    3. Controlador – Seu controlador é uma function JavaScript que conecta a exibição ao modelo. Sua function é inicializar $ escopo. Dependendo do seu aplicativo, você pode ou não precisar criar um controlador. Você pode ter muitos controladores em uma página.

    MVC e SOC não estão em extremidades opostas da mesma escala, eles estão em eixos completamente diferentes. O SOC não faz sentido em um contexto do AngularJS. Você tem que esquecer e seguir em frente.

    Se, como eu, você viveu as guerras do navegador, pode achar essa ideia bastante ofensiva. Supere isso, vai valer a pena, eu prometo.

    Plugins vs. diretivas

    Plugins estendem jQuery. As diretivas do AngularJS estendem as capacidades do seu navegador.

    No jQuery, definimos plugins adicionando funções ao jQuery.prototype. Em seguida, associamos esses itens ao DOM selecionando elementos e chamando o plug-in no resultado. A ideia é estender as capacidades do jQuery.

    Por exemplo, se você quiser um carrossel em sua página, poderá definir uma lista desordenada de figuras, talvez agrupada em um elemento de navegação. Você pode então escrever algum jQuery para selecionar a lista na página e reestilá-la como uma galeria com tempos limite para fazer a animação deslizante.

    No AngularJS, definimos diretivas. Uma diretiva é uma function que retorna um object JSON. Esse object informa ao AngularJS quais elementos DOM procurar e quais alterações fazer neles. As diretivas são conectadas ao modelo usando atributos ou elementos que você inventa. A ideia é estender os resources do HTML com novos atributos e elementos.

    A maneira AngularJS é estender os resources de HTML com aparência nativa. Você deve escrever HTML que se parece com HTML, estendido com atributos e elementos personalizados.

    Se você quer um carrossel, apenas use um elemento , então defina uma diretiva para puxar um modelo, e faça esse trabalho de sugador.

    Muitas pequenas diretivas vs. grandes plugins com switches de configuração

    A tendência do jQuery é escrever ótimos plugins como lightbox, os quais configuramos passando inúmeros valores e opções.

    Isso é um erro no AngularJS.

    Tomemos o exemplo de uma lista suspensa. When writing a dropdown plugin you might be tempted to code in click handlers, perhaps a function to add in a chevron which is either up or down, perhaps change the class of the unfolded element, show hide the menu, all helpful stuff.

    Until you want to make a small change.

    Say you have a menu that you want to unfold on hover. Well now we have a problem. Our plugin has wired in our click handler for us, we’re going to need to add a configuration option to make it behave differently in this specific case.

    In AngularJS we write smaller directives. Our dropdown directive would be ridiculously small. It might maintain the folded state, and provide methods to fold(), unfold() or toggle(). These methods would simply update $scope.menu.visible which is a boolean holding the state.

    Now in our template we can wire this up:

     Menu 
      ...

    Need to update on mouseover?

     Menu 
      ...

    The template drives the application so we get HTML level granularity. If we want to make case by case exceptions, the template makes this easy.

    Closure vs. $scope

    JQuery plugins are created in a closure. Privacy is maintained within that closure. It’s up to you to maintain your scope chain within that closure. You only really have access to the set of DOM nodes passed in to the plugin by jQuery, plus any local variables defined in the closure and any globals you have defined. This means that plugins are quite self contained. This is a good thing, but can get restrictive when creating a whole application. Trying to pass data between sections of a dynamic page becomes a chore.

    AngularJS has $scope objects. These are special objects created and maintained by AngularJS in which you store your model. Certain directives will spawn a new $scope, which by default inherits from its wrapping $scope using JavaScript prototypical inheritance. The $scope object is accessible in the controller and the view.

    This is the clever part. Because the structure of $scope inheritance roughly follows the structure of the DOM, elements have access to their own scope, and any containing scopes seamlessly, all the way up to the global $scope (which is not the same as the global scope).

    This makes it much easier to pass data around, and to store data at an appropriate level. If a dropdown is unfolded, only the dropdown $scope needs to know about it. If the user updates their preferences, you might want to update the global $scope, and any nested scopes listening to the user preferences would automatically be alerted.

    This might sound complicated, in fact, once you relax into it, it’s like flying. You don’t need to create the $scope object, AngularJS instantiates and configures it for you, correctly and appropriately based on your template hierarchy. AngularJS then makes it available to your component using the magic of dependency injection (more on this later).

    Manual DOM changes vs. Data Binding

    In jQuery you make all your DOM changes by hand. You construct new DOM elements programatically. If you have a JSON array and you want to put it to the DOM, you must write a function to generate the HTML and insert it.

    In AngularJS you can do this too, but you are encouraged to make use of data binding. Change your model, and because the DOM is bound to it via a template your DOM will automatically update, no intervention required.

    Because data binding is done from the template, using either an attribute or the curly brace syntax, it’s super easy to do. There’s little cognitive overhead associated with it so you’ll find yourself doing it all the time.

      

    Binds the input element to $scope.user.name . Updating the input will update the value in your current scope, and vice-versa.

    Da mesma forma:

     

    {{user.name}}

    will output the user name in a paragraph. It’s a live binding, so if the $scope.user.name value is updated, the template will update too.

    Ajax all of the time

    In jQuery making an Ajax call is fairly simple, but it’s still something you might think twice about. There’s the added complexity to think about, and a fair chunk of script to maintain.

    In AngularJS, Ajax is your default go-to solution and it happens all the time, almost without you noticing. You can include templates with ng-include. You can apply a template with the simplest custom directive. You can wrap an Ajax call in a service and create yourself a GitHub service, or a Flickr service, which you can access with astonishing ease.

    Service Objects vs Helper Functions

    In jQuery, if we want to accomplish a small non-dom related task such as pulling a feed from an API, we might write a little function to do that in our closure. That’s a valid solution, but what if we want to access that feed often? What if we want to reuse that code in another application?

    AngularJS gives us service objects.

    Services are simple objects that contain functions and data. They are always singletons, meaning there can never be more than one of them. Say we want to access the Stack Overflow API, we might write a StackOverflowService which defines methods for doing so.

    Let’s say we have a shopping cart. We might define a ShoppingCartService which maintains our cart and contains methods for adding and removing items. Because the service is a singleton, and is shared by all other components, any object that needs to can write to the shopping cart and pull data from it. It’s always the same cart.

    Service objects are self-contained AngularJS components which we can use and reuse as we see fit. They are simple JSON objects containing functions and Data. They are always singletons, so if you store data on a service in one place, you can get that data out somewhere else just by requesting the same service.

    Dependency injection (DI) vs. Instatiation – aka de-spaghettification

    AngularJS manages your dependencies for you. If you want an object, simply refer to it and AngularJS will get it for you.

    Until you start to use this, it’s hard to explain just what a massive time boon this is. Nothing like AngularJS DI exists inside jQuery.

    DI means that instead of writing your application and wiring it together, you instead define a library of components, each identified by a string.

    Say I have a component called ‘FlickrService’ which defines methods for pulling JSON feeds from Flickr. Now, if I want to write a controller that can access Flickr, I just need to refer to the ‘FlickrService’ by name when I declare the controller. AngularJS will take care of instantiating the component and making it available to my controller.

    For example, here I define a service:

     myApp.service('FlickrService', function() { return { getFeed: function() { // do something here } } }); 

    Now when I want to use that service I just refer to it by name like this:

     myApp.controller('myController', ['FlickrService', function(FlickrService) { FlickrService.getFeed() }]); 

    AngularJS will recognise that a FlickrService object is needed to instantiate the controller, and will provide one for us.

    This makes wiring things together very easy, and pretty much eliminates any tendency towards spagettification. We have a flat list of components, and AngularJS hands them to us one by one as and when we need them.

    Modular service architecture

    jQuery says very little about how you should organise your code. AngularJS has opinions.

    AngularJS gives you modules into which you can place your code. If you’re writing a script that talks to Flickr for example, you might want to create a Flickr module to wrap all your Flickr related functions in. Modules can include other modules (DI). Your main application is usually a module, and this should include all the other modules your application will depend on.

    You get simple code reuse, if you want to write another application based on Flickr, you can just include the Flickr module and voila, you have access to all your Flickr related functions in your new application.

    Modules contain AngularJS components. When we include a module, all the components in that module become available to us as a simple list identified by their unique strings . We can then inject those components into each other using AngularJS’s dependency injection mechanism.

    To sum up

    AngularJS and jQuery are not enemies. It’s possible to use jQuery within AngularJS very nicely. If you’re using AngularJS well (templates, data-binding, $scope, directives, etc.) you will find you need a lot less jQuery than you might otherwise require.

    The main thing to realise is that your template drives your application. Stop trying to write big plugins that do everything. Instead write little directives that do one thing, then write a simple template to wire them together.

    Think less about unobtrusive JavaScript, and instead think in terms of HTML extensions.

    My little book

    I got so excited about AngularJS, I wrote a short book on it which you’re very welcome to read online http://nicholasjohnson.com/angular-book/ . I hope it’s helpful.

    Can you describe the paradigm shift that is necessary?

    Imperative vs Declarative

    With jQuery you tell the DOM what needs to happen, step by step. With AngularJS you describe what results you want but not how to do it. Mais sobre isso aqui . Also, check out Mark Rajcok’s answer.

    How do I architect and design client-side web apps differently?

    AngularJS is an entire client-side framework that uses the MVC pattern (check out their graphical representation ). It greatly focuses on separation of concerns.

    What is the biggest difference? What should I stop doing/using; what should I start doing/using instead?

    jQuery is a library

    AngularJS is a beautiful client-side framework, highly testable, that combines tons of cool stuff such as MVC, dependency injection , data binding and much more.

    It focuses on separation of concerns and testing ( unit testing and end-to-end testing), which facilitates test-driven development.

    The best way to start is going through their awesome tutorial . You can go through the steps in a couple of hours; however, in case you want to master the concepts behind the scenes, they include a myriad of reference for further reading.

    Are there any server-side considerations/restrictions?

    You may use it on existing applications where you are already using pure jQuery. However, if you want to fully take advantage of the AngularJS features you may consider coding the server side using a RESTful approach.

    Doing so will allow you to leverage their resource factory , which creates an abstraction of your server side RESTful API and makes server-side calls (get, save, delete, etc.) incredibly easy.

    To describe the “paradigm shift”, I think a short answer can suffice.

    AngularJS changes the way you find elements

    In jQuery , you typically use selectors to find elements, and then wire them up:
    $('#id .class').click(doStuff);

    In AngularJS , you use directives to mark the elements directly, to wire them up:

    AngularJS doesn’t need (or want) you to find elements using selectors – the primary difference between AngularJS’s jqLite versus full-blown jQuery is that jqLite does not support selectors .

    So when people say “don’t include jQuery at all”, it’s mainly because they don’t want you to use selectors; they want you to learn to use directives instead. Direct, not select!

    jQuery

    jQuery makes ridiculously long JavaScript commands like getElementByHerpDerp shorter and cross-browser.

    AngularJS

    AngularJS allows you to make your own HTML tags/attributes that do things which work well with dynamic web applications (since HTML was designed for static pages).

    Editar:

    Saying “I have a jQuery background how do I think in AngularJS?” is like saying “I have an HTML background how do I think in JavaScript?” The fact that you’re asking the question shows you most likely don’t understand the fundamental purposes of these two resources. This is why I chose to answer the question by simply pointing out the fundamental difference rather than going through the list saying “AngularJS makes use of directives whereas jQuery uses CSS selectors to make a jQuery object which does this and that etc….”. This question does not require a lengthy answer.

    jQuery is a way to make programming JavaScript in the browser easier. Shorter, cross-browser commands, etc.

    AngularJS extends HTML, so you don’t have to put

    all over the place just to make an application. It makes HTML actually work for applications rather than what it was designed for, which is static, educational web pages. It accomplishes this in a roundabout way using JavaScript, but fundamentally it is an extension of HTML, not JavaScript.

    jQuery: you think a lot about ‘QUERYing the DOM ‘ for DOM elements and doing something.

    AngularJS: THE model is the truth, and you always think from that ANGLE.

    For example, when you get data from THE server which you intend to display in some format in the DOM, in jQuery, you need to ‘1. FIND’ where in the DOM you want to place this data, the ‘2. UPDATE/APPEND’ it there by creating a new node or just setting its innerHTML . Then when you want to update this view, you then ‘3. FIND’ the location and ‘4. UPDATE’. This cycle of find and update all done within the same context of getting and formatting data from server is gone in AngularJS.

    With AngularJS you have your model (JavaScript objects you are already used to) and the value of the model tells you about the model (obviously) and about the view, and an operation on the model automatically propagates to the view, so you don’t have to think about it. You will find yourself in AngularJS no longer finding things in the DOM.

    To put in another way, in jQuery, you need to think about CSS selectors, that is, where is the div or td that has a class or attribute, etc., so that I can get their HTML or color or value, but in AngularJS, you will find yourself thinking like this: what model am I dealing with, I will set the model’s value to true. You are not bothering yourself of whether the view reflecting this value is a checked box or resides in a td element (details you would have often needed to think about in jQuery).

    And with DOM manipulation in AngularJS, you find yourself adding directives and filters, which you can think of as valid HTML extensions.

    One more thing you will experience in AngularJS: in jQuery you call the jQuery functions a lot, in AngularJS, AngularJS will call your functions, so AngularJS will ‘tell you how to do things’, but the benefits are worth it, so learning AngularJS usually means learning what AngularJS wants or the way AngularJS requires that you present your functions and it will call it accordingly. This is one of the things that makes AngularJS a framework rather than a library.

    Those are some very nice, but lengthy answers.

    To sum up my experiences:

    1. Controllers and providers (services, factories, etc.) are for modifying the data model, NOT HTML.
    2. HTML and directives define the layout and binding to the model.
    3. If you need to share data between controllers, create a service or factory – they are singletons that are shared across the application.
    4. If you need an HTML widget, create a directive.
    5. If you have some data and are now trying to update HTML… STOP! update the model, and make sure your HTML is bound to the model.

    jQuery is a DOM manipulation library.

    AngularJS is an MV* framework.

    In fact, AngularJS is one of the few JavaScript MV* frameworks (many JavaScript MVC tools still fall under the category library).

    Being a framework, it hosts your code and takes ownership of decisions about what to call and when!

    AngularJS itself includes a jQuery-lite edition within it. So for some basic DOM selection/manipulation, you really don’t have to include the jQuery library (it saves many bytes to run on the network.)

    AngularJS has the concept of “Directives” for DOM manipulation and designing reusable UI components, so you should use it whenever you feel the need of doing DOM manipulation related stuff (directives are only place where you should write jQuery code while using AngularJS).

    AngularJS involves some learning curve (more than jQuery :-).

    –>For any developer coming from jQuery background, my first advice would be to “learn JavaScript as a first class language before jumping onto a rich framework like AngularJS!” I learned the above fact the hard way.

    Boa sorte.

    They’re apples and oranges. You don’t want to compare them. They’re two different things. AngularJs has already jQuery lite built in which allows you to perform basic DOM manipulation without even including the full blown jQuery version.

    jQuery is all about DOM manipulation. It solves all the cross browser pain otherwise you will have to deal with but it’s not a framework that allows you to divide your app into components like AngularJS.

    A nice thing about AngularJs is that it allows you to separate/isolate the DOM manipulation in the directives. There are built-in directives ready for you to use such as ng-click. You can create your own custom directives that will contain all your view logic or DOM manipulation so you don’t end up mingle DOM manipulation code in the controllers or services that should take care of the business logic.

    Angular breaks down your app into – Controllers – Services – Views – etc.

    and there is one more thing, that’s the directive. It’s an attribute you can attach to any DOM element and you can go nuts with jQuery within it without worrying about your jQuery ever conflicts with AngularJs components or messes up with its architecture.

    I heard from a meetup I attended, one of the founders of Angular said they worked really hard to separate out the DOM manipulation so do not try to include them back in.

    Listen to the podcast JavaScript Jabber: Episode #32 that features the original creators of AngularJS: Misko Hevery & Igor Minar. They talk a lot about what it’s like to come to AngularJS from other JavaScript backgrounds, especially jQuery.

    One of the points made in the podcast made a lot of things click for me with respects to your question:

    MISKO : […] one of the things we thought about very hardly in Angular is, how do we provide lots of escape hatches so that you can get out and basically figure out a way out of this. So to us, the answer is this thing called “Directives”. And with directives, you essentially become a regular little jQuery JavaScript, you can do whatever you want.

    IGOR : So think of directive as the instruction to the compiler that tells it whenever you come across this certain element or this CSS in the template, and you keep this kind of code and that code is in charge of the element and everything below that element in the DOM tree.

    A transcript of the entire episode is available at the link provided above.

    So, to directly answer your question: AngularJS is -very- opinionated and is a true MV* framework. However, you can still do all of the really cool stuff you know and love with jQuery inside of directives. It’s not a matter of “How do I do what I used to in jQuery?” as much as it’s a matter of “How do I supplement AngularJS with all of the stuff I used to do in jQuery?”

    It’s really two very different states of mind.

    I find this question interesting, because my first serious exposure to JavaScript programming was Node.js and AngularJS. I never learned jQuery, and I guess that’s a good thing, because I don’t have to unlearn anything. In fact, I actively avoid jQuery solutions to my problems, and instead, solely look for an “AngularJS way” to solve them. So, I guess my answer to this question would essentially boil down to, “think like someone who never learned jQuery” and avoid any temptation to incorporate jQuery directly (obviously AngularJS uses it to some extent behind the scenes).

    AngularJS and jQuery:

    AngularJs and JQuery are completely different at every level except the JQLite functionality and you will see it once you start learning the AngularJs core features (I explained it below).

    AngularJs is a client side framework that offers to build the independent client side application. JQuery is a client side library that play around the DOM.

    AngularJs Cool Principle – If you want some changes on your UI think from model data change perspective. Change your data and UI will re-render itself. You need not to play around DOM each time unless and until it is hardly required and that should also be handled through Angular Directives.

    To answer this question, I want to share my experience on the first enterprise application with AngularJS. These are the most awesome features that Angular provide where we start changing our jQuery mindset and we get the Angular like a framework and not the library.

    Two-way data binding is amazing: I had a grid with all functionality UPDATE, DELTE, INSERT. I have a data object that binds the grid’s model using ng-repeat. You only need to write a single line of simple JavaScript code for delete and insert and that’s it. grid automatically updates as the grid model changes instantly. Update functionality is real time, no code for it. You feel amazing!!!

    Reusable directives are super: Write directives in one place and use it throughout the application. OMG!!! I used these directive for paging, regex, validations, etc. It is really cool!

    Routing is strong: It’s up to your implementation how you want to use it, but it requires very few lines of code to route the request to specify HTML and controller (JavaScript)

    Controllers are great: Controllers take care of their own HTML, but this separation works well for common functionality well as. If you want to call the same function on the click of a button on master HTML, just write the same function name in each controller and write individual code.

    Plugins: There are many other similar features like showing an overlay in your app. You don’t need to write code for it, just use an overlay plugin available as wc-overlay, and this will automatically take care of all XMLHttpRequest (XHR) requests.

    Ideal for RESTful architecture: Being a complete frameworks makes AngularJS great to work with a RESTful architecture. To call REST CRUD APIs is very easier and

    Services : Write common codes using services and less code in controllers. Sevices can be used to share common functionalities among the controllers.

    Extensibility : Angular has extended the HTML directives using angular directives. Write expressions inside html and evaluate them on runtime. Create your own directives and services and use them in another project without any extra effort.

    As a JavaScript MV* beginner and purely focusing on the application architecture (not the server/client-side matters), I would certainly recommend the following resource (which I am surprised wasn’t mentioned yet): JavaScript Design Patterns , by Addy Osmani, as an introduction to different JavaScript Design Patterns . The terms used in this answer are taken from the linked document above. I’m not going to repeat what was worded really well in the accepted answer. Instead, this answer links back to the theoretical backgrounds which power AngularJS (and other libraries).

    Like me, you will quickly realize that AngularJS (or Ember.js , Durandal, & other MV* frameworks for that matter) is one complex framework assembling many of the different JavaScript design patterns.

    I found it easier also, to test (1) native JavaScript code and (2) smaller libraries for each one of these patterns separately before diving into one global framework. This allowed me to better understand which crucial issues a framework adresses (because you are personally faced with the problem).

    Por exemplo:

    • JavaScript Object-oriented Programming (this is a Google search link). It is not a library, but certainly a prerequisite to any application programming. It taught me the native implementations of the prototype, constructor, singleton & decorator patterns
    • jQuery / Underscore for the facade pattern (like WYSIWYG’s for manipulating the DOM)
    • Prototype.js for the prototype/ constructor/ mixin pattern
    • RequireJS / Curl.js for the module pattern/ AMD
    • KnockoutJS for the observable, publish/subscribe pattern

    NB: This list is not complete, nor ‘the best libraries’; they just happen to be the libraries I used. These libraries also include more patterns, the ones mentioned are just their main focuses or original intents. If you feel something is missing from this list, please do mention it in the comments, and I will be glad to add it.

    Actually, if you’re using AngularJS, you don’t need jQuery anymore. AngularJS itself has the binding and directive, which is a very good “replacement” for most things you can do with jQuery.

    I usually develop mobile applications using AngularJS and Cordova . The ONLY thing from jQuery I needed is the Selector.

    By googling, I see that there is a standalone jQuery selector module out there. It’s Sizzle.

    And I decided to make a tiny code snippet that help me quickly start a website using AngularJS with the power of jQuery Selector (using Sizzle).

    I shared my code here: https://github.com/huytd/Sizzular