diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:52 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:52 -0500 |
commit | 074785cea106179cb3305637055ab0a009ca74f2 (patch) | |
tree | e6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/pt-br/learn | |
parent | da78a9e329e272dedb2400b79a3bdeebff387d47 (diff) | |
download | translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.gz translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.bz2 translated-content-074785cea106179cb3305637055ab0a009ca74f2.zip |
initial commit
Diffstat (limited to 'files/pt-br/learn')
86 files changed, 25292 insertions, 0 deletions
diff --git a/files/pt-br/learn/accessibility/acessibilidade_problemas/index.html b/files/pt-br/learn/accessibility/acessibilidade_problemas/index.html new file mode 100644 index 0000000000..727433531a --- /dev/null +++ b/files/pt-br/learn/accessibility/acessibilidade_problemas/index.html @@ -0,0 +1,111 @@ +--- +title: 'Avaliação: solucionando problemas de acessibilidade' +slug: Learn/Accessibility/Acessibilidade_problemas +tags: + - Acessibilidade + - Avaliação + - CSS + - Codificação + - CodingScripting + - Iniciante + - JavaScript + - WAI-ARIA + - aprendizado +translation_of: Learn/Accessibility/Accessibility_troubleshooting +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/Accessibility/Mobile", "Learn/Accessibility")}}</div> + +<p class="summary">Na avaliação deste módulo, apresentamos a você um site simples com vários problemas de acessibilidade que você precisa diagnosticar e corrigir.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimento básico de informática, entendimento básico de HTML, CSS e Javascript, uma compreesão dos <a href="/en-US/docs/Learn/Accessibility">artigos anteriores deste curso</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Testar conhecimentos básicos e fundamentais para a acessibilidade.</td> + </tr> + </tbody> +</table> + +<h2 id="Ponto_de_partida">Ponto de partida</h2> + +<p>Para começar esta avaliação, você deve pegar <a href="https://github.com/mdn/learning-area/blob/master/accessibility/assessment-start/assessment-files.zip?raw=true" rel="noopener">o arquivo ZIP que contém os arquivos que compõem o exemplo</a>. Descompacte o conteúdo em um novo diretório em algum lugar de seu computador.</p> + +<p>O site de avaliação final, deve ser parecido com esse:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14555/assessment-site-finished.png" style="border-style: solid; border-width: 1px; display: block; height: 457px; margin: 0px auto; width: 800px;"></p> + +<p>Você verá algumas diferenças e/ou problemas com a exibição do estado inicial do site da avaliação - isso se deve principalmente as diferenças na marcação de código, o que, por sua vez, causa alguns problemas de estilo, pois o CSS não está aplicado corretamente. Não se preocupe - você irá corrigir esses problemas nas próximas seções!</p> + +<h2 id="Resumo_do_projeto">Resumo do projeto</h2> + +<p>Para este projeto, você é apresentado a um site fictício exibindo um artigo sobre ursos. Da forma como ele está, possui vários problemas de acessibilidade - a sua tarefa é explorar o site existente e corrigí-los da melhor forma possível, respondendo as seguintes perguntas.</p> + +<h3 id="Cor">Cor</h3> + +<p>O texto é difícil de ler devido ao esquema de cores atual. Você pode fazer um teste do contraste de cor atual (texto/plano de fundo), relatar os resultados do teste e corrigí-lo alterando as cores atribuídas?</p> + +<h3 id="HTML_semântico">HTML semântico</h3> + +<ol> + <li>O conteúdo ainda não é muito acessível - relate o que acontece quando você tenta navegar utilizando um leitor de telas.</li> + <li>Você consegue atualizar o texto do artigo para facilitar a navegação de usuários de leitores de telas?</li> + <li>A parte do menu de navegação do site (agrupada em <code><div class="nav"></div></code>) poderia estar mais acessível se estivesse dentro de um elemento semântico de HTML5 mais adequado. Qual elemento deve ser utilizado? Atualize-o.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Você precisará atualizar os seletores de CSS que estilizam as respectivas <font>tags para seus equivalentes aos cabeçalhos semânticos. </font><font>Depois de adicionar elementos de parágrafo, você perceberá que a estilização parecerá bem melhor.</font></p> +</div> + +<h3 id="As_imagens"><font>As imagens</font></h3> + +<p><font>As imagens estão atualmente inacessíveis para os usuários do leitor de tela.</font> <font>Você pode consertar isso?</font></p> + +<h3 id="O_player_de_áudio"><font>O "player" de áudio</font></h3> + +<ol> + <li><font>Foi utilizada o elemento <code><audio></code> para exibir o "player", porém ele não é acessível para pessoas com deficiência auditiva (surdos) - você consegue adicionar algum tipo de alternativa acessível para esses usuários?</font></li> + <li><font>O elemento <code><audio></code> para utilizar o "player" não é acessível para aqueles que usam navegadores mais antigos que não suportam HTML5.</font> <font>Como você pode fazer com que esses usuários consigam ter acesso ao áudio?</font></li> +</ol> + +<h3 id="Os_formulários"><font>Os formulários</font></h3> + +<ol> + <li><font>O elemento <code><input></code> no formulário de pesquisa no topo poderia ter um rótulo, mas não queremos adicionar um rótulo de texto visível que possa prejudicar o design e não seja realmente necessário para os usuários com visão.</font> <font>Como você pode adicionar um rótulo acessível apenas aos leitores de tela?</font></li> + <li><font>Os dois elementos <code><input></code> no formulário de comentários possui rótulos de texto visíveis, mas não estão associados corretamente entre eles. Como você poderia fazer isso?</font> <font>Note que você precisará atualizar algumas regras de CSS também.</font></li> +</ol> + +<h3 id="Os_controles_de_comentários_exibirocultar"><font>Os controles de comentários "exibir/ocultar"</font></h3> + +<p><font>O botão de controle "exibir/ocultar" não está acessível por teclado.</font> <font>Você pode torná-lo acessível, tanto em termos de deixá-lo "focável" através da utilização da tecla tab, como ativá-lo usando a tecla enter?</font></p> + +<h3 id="A_tabela"><font>A tabela</font></h3> + +<p><font>A tabela de dados não está muito acessível no momento - é difícil para os usuários de leitores de tela associarem linhas e colunas de dados juntas, e a tabela também não possui nenhum tipo de resumo para deixar claro o que mostra.</font> <font>Você pode adicionar alguns recursos ao seu HTML para corrigir esse problema?</font></p> + +<h3 id="Outras_considerações"><font>Outras considerações?</font></h3> + +<p>Você pode citar mais duas ideias de melhorias que poderiam tornar o site mais acessível?</p> + +<h2 id="Avaliação"><font>Avaliação</font></h2> + +<p><font>Se você está fazendo esta avaliação como parte de um curso, você deverá entregar o seu trabalho para um professor para que possa corrigí-lo. Se você é auto-didata, então você pode obter o guia com a marcação correta </font><font>perguntando no</font> <a href="https://discourse.mozilla.org/t/accessibility-troubleshooting-assessment/24691&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhh-F4r0i3lAG4IX8kI3Nk9lrJQa0A" rel="noopener">tópico de discussão para este exercício</a><font>, ou no canal de IRC <a href="irc://irc.mozilla.org/mdn">#mdn</a> no <a href="https://wiki.mozilla.org/IRC&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhgC5oFTH3iLqIFiwi9njruuEgsWHA" rel="noopener">IRC do Mozilla</a>.</font> Experimente tentar fazer<font> o exercício primeiro - você não ganhará nada trapaceando!</font></p> + +<p><font>{{PreviousMenu("Learn/Accessibility/Mobile", "Learn/Accessibility")}}</font></p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/What_is_accessibility&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhjKbO6WIg9b4xWjdZSQcnXxP1foyg">O que é acessibilidade?</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhg8RYEjwUHElGCpA1Q_60OiOtXeLg">HTML: uma boa base para acessibilidade</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/CSS_and_JavaScript&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhjUFLV1YWbEtSBOMPU_Bt7V-OmzDw">Práticas recomendadas de acessibilidade de CSS e JavaScript</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/WAI-ARIA_basics&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhj5LnkD6EVmrTiupwf932KoV4VCTw">Noções básicas de WAI-ARIA</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/Multimedia&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhgWAjBOw_jwWHOvK_zBEob2xQdEmA">Multimídia acessível</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/Mobile&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhgnwNfnWbOmqpMWRI1c1zBqGFfU1Q">Acessibilidade móvel</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/Accessibility_troubleshooting&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhjy6mgQ3Y6D6sT4QvsOicr2-Fmt9Q">Solução de problemas de acessibilidade</a></li> +</ul> diff --git a/files/pt-br/learn/accessibility/css_e_javascript/index.html b/files/pt-br/learn/accessibility/css_e_javascript/index.html new file mode 100644 index 0000000000..f0d8a728c5 --- /dev/null +++ b/files/pt-br/learn/accessibility/css_e_javascript/index.html @@ -0,0 +1,361 @@ +--- +title: CSS e JavaScript - melhores práticas de acessibilidade +slug: Learn/Accessibility/CSS_e_JavaScript +tags: + - Acessibilidade + - Artigo + - CSS + - JavaScript + - color + - contraste +translation_of: Learn/Accessibility/CSS_and_JavaScript +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Accessibility/HTML","Learn/Accessibility/WAI-ARIA_basics", "Learn/Accessibility")}}</div> + +<p class="summary">CSS e JavaScript, quando usados de maneira correta, têm também potencial para permitir experiências web acessíveis... ou podem causar danos significativos se usados de forma indevida. Este artigo descreve algumas das melhores práticas em CSS e JavaScript a serem consideradas para garantir que até mesmo conteúdos complexos estejam tão acessíveis quanto possível.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimento básico de computação, Conhecimento básico de HTML, CSS, e JavaScript, e entendimento sobre <a href="/en-US/docs/Learn/Accessibility/What_is_accessibility">o que é acessibilidade</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Tornar-se familiarizado com o uso de CSS e JavaScript apropriadamente em seus documentos web para maximizar a acessibilidade e não diminuir sua importância.</td> + </tr> + </tbody> +</table> + +<h2 id="CSS_e_JavaScript_são_acessíveis">CSS e JavaScript são acessíveis?</h2> + +<p>CSS e JavaScript não têm a mesma importância imediata que o HTML, mas eles continuam sendo capazes de ajudar ou causar danos à acessibilidade, dependendo de como são usados. Ou seja, é importante que você considere algumas das melhores práticas para assegurar que o seu uso de CSS e JavaScript não danifiquem a acessibilidade de seus documentos.</p> + +<h2 id="CSS">CSS</h2> + +<p>Vamos começar dando uma olhada no CSS.</p> + +<h3 id="Semântica_correta_e_expectativas_do_usuário">Semântica correta e expectativas do usuário</h3> + +<p>É possível usar CSS para fazer qualquer elemento HTML se parecer com qualquer coisa, mas isso não quer dizer que você deve. Como frequentemente mencionado no nosso artigo <a href="/en-US/docs/Learn/Accessibility/HTML">HTML: Uma boa base para acessibilidade</a>, você deve utilizar a semântica apropriada do elemento para determinada tarefa, sempre que possível. Se não o fizer, isso poderá acarretar confusão e problemas de usabilidade para todos, particularmente para usuários portadores de deficiência. Utilizar uma semântica correta tem muito a ver com as expectativas do usuário — elementos se parecem e se comportam de certas maneiras, de acordo com suas funcionalidades, e essas convenções são esperadas pelos usuários.</p> + +<p>Por exemplo, um usuário utilizando um leitor de tela não consegue navegar por uma página através de elementos de heading se o desenvolvedor não tiver usado apropriadamente estes elementos para marcação do conteúdo. Da mesma forma, um heading perde o seu propósito visual se você estilizá-lo de maneira que ele não se pareça com um heading.</p> + +<p>A regra de ouro é que você pode atualizar o estilo de recurso de página para se adequar ao seu design, mas não o altere tanto ao ponto de não mais se parecer ou se comportar como o esperado. As sessões que se seguem resumem os principais recursos HTML a serem considerados.</p> + +<h4 id="Estrututa_standard_de_conteúdo_textual">Estrututa "standard" de conteúdo textual</h4> + +<p>Headings, parágrafos, listss — o núcleo do conteúdo textual da sua página:</p> + +<pre class="brush: html"><h1>Heading</h1> + +<p>Parágrafo</p> + +<ul> + <li>Minha lista</li> + <li>tem dois itens.</li> +</ul></pre> + +<p>Um código CSS típico pode se parecer com isso:</p> + +<pre class="brush: css">h1 { + font-size: 5rem; +} + +p, li { + line-height: 1.5; + font-size: 1.6rem; +}</pre> + +<p>Você tem de:</p> + +<ul> + <li>Selecionar tamanhos de fonte sensíveis, altura de linhas, espaçamento entre letras, etc. para fazer com que o seu texto seja lógico, legível e de leitura confortável.</li> + <li>Tenha certeza que os seus headings se destaquem do corpo do seu texto, geralmente grande e em negrito conforme o estilo padrão.</li> + <li>A cor do seu texto deve ter um bom contraste com a cor de fundo.</li> +</ul> + +<p>Veja <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML fundamentos de texto</a> e <a href="/en-US/docs/Learn/CSS/Styling_text">Estilizando texto</a> para maiores informações.</p> + +<h4 id="Texto_em_negrito">Texto em negrito</h4> + +<p>Elemento de marcação que confere ênfase específica ao texto envolvido por ele:</p> + +<pre class="brush: html"><p>A água está <em>muito quente</em>.</p> + +<p>Gotículas de água em superfícies são chamadas de <strong>condensação</strong>.</p></pre> + +<p>Você pode querer adicionar alguma cor no seu texto em negrito:</p> + +<pre class="brush: css">strong, em { + color: #a60000; +}</pre> + +<p>De qualquer forma, você raramente irá precisar de estilizar um elemento de ênfase. As convenções para texto em negrito e itálico são bastante reconhecidas e alterar seu estilo pode causar confusão. Para saber mais sobre elemento ênfase (negrito), veja <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#Emphasis_and_importance">Emphasis and importance</a>.</p> + +<h4 id="Abreviações">Abreviações</h4> + +<p>É um elemento que permite abraviação, acrônimo ou inicialização que esteja associada com sua expansão:</p> + +<pre class="brush: html"><p>Web content is marked up using <abbr title="Hypertext Markup Language">HTML</abbr>.</p></pre> + +<p>Novamente, você pode querer estilizá-lo de alguma forma:</p> + +<pre class="brush: css">abbr { + color: #a60000; +}</pre> + +<p>A convenção de estilo que é reconhecida para abreviações é uma linha pontilhada, e não é recomendado estilizá-la. Para saber mais sobre abreviações, veja <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting#Abbreviations">Abbreviations</a>.</p> + +<h4 id="Links">Links</h4> + +<p>Hyperlinks — the way you get to new places on the web:</p> + +<pre class="brush: html"><p>Visit the <a href="https://www.mozilla.org">Mozilla homepage</a>.</p></pre> + +<p>Some very simple link styling is shown below:</p> + +<pre class="brush: css">a { + color: #ff0000; +} + +a:hover, a:visited, a:focus { + color: #a60000; + text-decoration: none; +} + +a:active { + color: #000000; + background-color: #a60000; +}</pre> + +<p>The standard link conventions are underlined and a different color (default: blue) in their standard state, another color variation when the link has previously been visited (default: purple), and yet another color when the link is activated (default: red). In addition, the mouse pointer changes to a pointer icon when links are moused over, and the link receives a highlight when focused (e.g. via tabbing) or activated. The following image shows the highlight in both Firefox (a dotted outline) and Chrome (a blue outline):</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14371/focus-highlight-firefox.png" style="display: block; height: 173px; margin: 0px auto; width: 319px;"></p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14369/focus-highlight-chrome.png" style="display: block; height: 169px; margin: 0px auto; width: 309px;"></p> + +<p>You can be creative with link styles, as long as you keep giving users feedback when they interact with the links. Something should definitely happen when states change, and you shouldn't get rid of the pointer cursor or the outline — both are very important accessibility aids for those using keyboard controls.</p> + +<h4 id="Form_elements">Form elements</h4> + +<p>Elements to allow users to input data into websites:</p> + +<pre class="brush: html"><div> + <label for="name">Enter your name</label> + <input type="text" id="name" name="name"> +</div></pre> + +<p>You can see some good example CSS in our <a href="https://github.com/mdn/learning-area/blob/master/accessibility/css/form-css.html">form-css.html</a> example (<a href="http://mdn.github.io/learning-area/accessibility/css/form-css.html">see it live</a> also).</p> + +<p>Most of the CSS you'll write for forms will be for sizing the elements, lining up labels and inputs, and getting them looking neat and tidy.</p> + +<p>You shouldn't however deviate too much from the expected visual feedback form elements receive when they are focused, which is basically the same as links (see above). You could style form focus/hover states to make this behaviour more consistent across browsers or fit in better with your page design, but don't get rid of it altogether — again, people rely on these clues to help them know what is going on.</p> + +<h4 id="Tables">Tables</h4> + +<p>Tables for presenting tabular data.</p> + +<p>You can see a good, simple example of table HTML and CSS in our <a href="https://github.com/mdn/learning-area/blob/master/accessibility/css/table-css.html">table-css.html</a> example (<a href="http://mdn.github.io/learning-area/accessibility/css/table-css.html">see it live also</a>).</p> + +<p>Table CSS generally serves to make the table fit better into your design and look less ugly. It is a good idea to make sure the table headers stand out (normally using bold), and use zebra striping to make different rows easier to parse.</p> + +<h3 id="Color_and_color_contrast">Color and color contrast</h3> + +<p>When choosing a color scheme for your website, make sure that the text (foreground) color contrasts well with the background color. Your design might look cool, but it is no good if people with visual impairments like color blindness can't read your content.</p> + +<p>There is an easy way to check whether your contrast is large enough to not cause problems. There are a number of contrast checking tools online that you can enter your foreground and background colors into, to check them. For example WebAIM's <a href="http://webaim.org/resources/contrastchecker/">Color Contrast Checker</a> is simple to use, and provides an explanation of what you need to conform to the WCAG criteria around color contrast.</p> + +<div class="note"> +<p><strong>Note</strong>: A high contrast ratio will also allow anyone using a smartphone or tablet with a glossy screen to better read pages when in a bright environment, such as sunlight.</p> +</div> + +<p>Another tip is to not rely on color alone for signposts/information, as this will be no good for those who can't see the color. Instead of marking required form fields in red, for example, mark them with an asterisk and in red.</p> + +<h3 id="Hiding_things">Hiding things</h3> + +<p>There are many instances where a visual design will require that not all content is shown at once. For example, in our <a href="http://mdn.github.io/learning-area/css/css-layout/practical-positioning-examples/info-box.html">Tabbed info box example</a> (see <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/practical-positioning-examples/info-box.html">source code</a>) we have three panels of information, but we are <a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">positioning</a> them on top of one another and providing tabs that can be clicked to show each one (it is also keyboard accessible — you can alternatively use Tab and Enter/Return to select them).</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13368/tabbed-info-box.png" style="display: block; height: 400px; margin: 0px auto; width: 450px;"></p> + +<p>Screen reader users don't care about any of this — they are happy with the content as long as the source order makes sense, and they can get to it all. Absolute positioning (as used in this example) is generally seen as one of the best mechanisms of hiding content for visual effect, because it doesn't stop screen readers from getting to it.</p> + +<p>On the other hand, you shouldn't use {{cssxref("visibility")}}<code>:hidden</code> or {{cssxref("display")}}<code>:none</code>, because they do hide content from screen readers. Unless of course, there is a good reason why you want this content to be hidden from screen readers.</p> + +<div class="note"> +<p><strong>Note</strong>: <span class="subtitle"><a href="http://webaim.org/techniques/css/invisiblecontent/">Invisible Content Just for Screen Reader Users</a> has a lot more useful detail surrounding this topic.</span></p> +</div> + +<h3 id="Accept_that_users_can_override_styles">Accept that users can override styles</h3> + +<h4 id="Accept_that_users_can_override_your_styles">Accept that users can override your styles</h4> + +<p>It is possible for users to override your styles with their own custom styles, for example:</p> + +<ul> + <li>See Sarah Maddox's <a class="external external-icon" href="https://www.itsupportguides.com/knowledge-base/computer-accessibility/how-to-use-a-custom-style-sheet-css-with-firefox/" rel="noopener">How to use a custom style sheet (CSS) with Firefox</a> for a useful guide covering how to do this manually in Firefox, and <a href="https://www.itsupportguides.com/knowledge-base/computer-accessibility/how-to-use-a-custom-style-sheet-css-with-internet-explorer/">How to use a custom style sheet (CSS) with Internet Explorer</a> by Adrian Gordon for the equivalent <abbr>IE</abbr> instructions.</li> + <li>It is probably easier to do it using an extension, for example the Stylish extension is available for <a href="https://addons.mozilla.org/en-US/firefox/addon/stylish/">Firefox</a>, <a href="https://safari-extensions.apple.com/details/?id=com.sobolev.stylish-5555L95H45">Safari</a>, <a href="https://addons.opera.com/en/extensions/details/stylish/">Opera</a>, and <a href="https://chrome.google.com/webstore/detail/stylish/fjnbnpbmkenffdnngjfgmeleoegfcffe">Chrome</a>.</li> +</ul> + +<p>Users might do this for a variety of reasons. A visually impaired user might want to make the text bigger on all websites they visit, or a user with severe color deficiency might want to put all websites in high contrast colors that are easy for them to see. Whatever the need, you should be comfortable with this, and make your designs flexible enough so that such changes will work in your design. As an example, you might want to make sure your main content area can handle bigger text (maybe it will start to scroll to allow it all to be seen), and won't just hide it, or break completely.</p> + +<h2 id="JavaScript">JavaScript</h2> + +<p>JavaScript can also break accessibility, depending on how it is used.</p> + +<p>Modern JavaScript is a powerful language, and we can do so much with it these days, from simple content and UI updates to fully-fledged 2D and 3D games. There is no rule that says all content has to be 100% accessible to all people — you just need to do what you can, and make your apps as accessible as possible.</p> + +<p>Simple content and functionality is arguably easy to make accessible — for example text, images, tables, forms and push button that activate functions. As we looked at in our <a href="/en-US/docs/Learn/Accessibility/HTML">HTML: A good basis for accessibility</a> article, the key considerations are:</p> + +<ul> + <li>Good semantics: Using the right element for the right job. For example, making sure you use headings and paragraphs, and {{htmlelement("button")}} and {{htmlelement("a")}} elements</li> + <li>Making sure content is available as text, either directly as text content, good text labels for form elements, or <a href="/en-US/docs/Learn/Accessibility/HTML#Text_alternatives">text alternatives</a>, e.g. alt text for images.</li> +</ul> + +<p>We also looked at an example of how to use JavaScript to build in functionality where it is missing — see <a href="/en-US/docs/Learn/Accessibility/HTML#Building_keyboard_accessibility_back_in">Building keyboard accessibility back in</a>. This is not ideal — really you should just use the right element for the right job — but it shows that it is possible in situations where for some reason you can't control the markup that is used. Another way to improve accessibility for non-semantic JavaScript-powered widgets is to use WAI-ARIA to provide extra semantics for screen reader users. The next article will also cover this in detail.</p> + +<p>Complex functionality like 3D games are not so easy to make accessible — a complex 3D game created using <a href="/en-US/docs/Web/API/WebGL_API">WebGL</a> will be rendered on a {{htmlelement("canvas")}} element, which has no facility at this time to provide text alternatives or other information for severely visually impaired users to make use of. It is arguable that such a game doesn't really have this group of people as a part of its main target audience, and it would be unreasonable to expect you to make it 100% accessible to blind people, however you could implement <a href="/en-US/docs/Games/Techniques/Control_mechanisms/Desktop_with_mouse_and_keyboard">keyboard controls</a> so it is usable by non-mouse users, and make the color scheme contrasting enough to be usable by those with color deficiencies.</p> + +<h3 id="The_problem_with_too_much_JavaScript">The problem with too much JavaScript</h3> + +<p>The problem often comes when people rely on JavaScript too much. Sometimes you'll see a website where everything has been done with JavaScript — the HTML has been generated by JavaScript, the CSS has been generated by JavaScript, etc. This has all kinds of accessibility and other issues associated with it, so it is not advised.</p> + +<p>As well as using the right element for the right job, you should also make sure you are using the right technology for the right job! Think carefully about whether you need that shiny JavaScript-powered 3D information box, or whether plain old text would do. Think carefully about whether you need a complex non-standard form widget, or whether a text input would do. And don't generate all your HTML content using JavaScript if at all possible.</p> + +<h3 id="Keeping_it_unobtrusive">Keeping it unobtrusive</h3> + +<p>You should keep <strong>unobtrusive JavaScript</strong> in mind when creating your content. The idea of unobtrusive JavaScript is that it should be used wherever possible to enhance functionality, not build it in entirely — basic functions should ideally work without JavaScript, although it is appreciated that this is not always an option. But again, a large part of it is using built-in browser functionality where possible.</p> + +<p>Good example uses of unobtrusive JavaScript include:</p> + +<ul> + <li>Providing client-side form validation, which alerts users to problems with their form entries quickly, without having to wait for the server to check the data. If it isn't available, the form will still work, but validation might be slower.</li> + <li>Providing custom controls for HTML5 <code><video></code>s that are accessible to keyboard-only users, along with a direct link to the video that can be used to access it if JavaScript is not available (the default <code><video></code> browser controls aren't keyboard accessible in most browsers).</li> +</ul> + +<p id="Client-side_form_validation">As an example, we've written a quick and dirty client-side form validation example — see <a href="https://github.com/mdn/learning-area/blob/master/accessibility/css/form-validation.html">form-validation.html</a> (also <a href="http://mdn.github.io/learning-area/accessibility/css/form-validation.html">see the demo live</a>). Here you'll see a simple form; when you try to submit the form with one or both fields left empty, the submit fails, and an error message box appears to tell you what is wrong.</p> + +<p>This kind of form validation is unobtrusive — you can still use the form absolutely fine without the JavaScript being available, and any sensible form implementation will have server-side validation active as well, because it is too easy for malicious users to bypass client-side validation (for example, by turning JavaScript off in the browser). The client-side validation is still really useful for reporting errors — users can know about mistakes they make instantly, rather than having to wait for a round trip to the server and a page reload. This is a definite usability advantage.</p> + +<div class="note"> +<p><strong>Note</strong>: Server-side validation has not been implemented in this simple demo.</p> +</div> + +<p>We've made this form validation pretty accessible too. We've used {{htmlelement("label")}} elements to make sure the form labels are unambiguously linked to their inputs, so screen readers can read them out alongside:</p> + +<pre class="brush: html"><label for="name">Enter your name:</label> +<input type="text" name="name" id="name"></pre> + +<p>We only do the validation when the form is submitted — this is so that we don't update the UI too often and potentially confuse screen reader (and possibly other) users:</p> + +<pre class="brush: js">form.onsubmit = validate; + +function validate(e) { + errorList.innerHTML = ''; + for(var i = 0; i < formItems.length; i++) { + var testItem = formItems[i]; + if(testItem.input.value === '') { + errorField.style.left = '360px'; + createLink(testItem); + } + } + + if(errorList.innerHTML !== '') { + e.preventDefault(); + } +}</pre> + +<div class="note"> +<p><strong>Note</strong>: In this example, we are hiding and showing the error message box using absolute positioning rather than another method such as visibility or display, because it doesn't interfere with the screen reader being able to read content from it.</p> +</div> + +<p>Real form validation would be much more complex than this — you'd want to check that the entered name actually looks like a name, the entered age is actually a number and is realistic (e.g. not a minus number, or four digits). Here we've just implemented a simple check that a value has been filled in to each input field (<code>if(testItem.input.value === '')</code>).</p> + +<p>When the validation has been performed, if the tests pass then the form is submitted. If there are errors (<code>if(errorList.innerHTML !== '')</code>) then we stop the form submitting (using <code><a href="/en-US/docs/Web/API/Event/preventDefault">preventDefault()</a></code>), and display any error messages that have been created (see below). This mechanism means that the errors will only be shown if there are errors, which is better for usability.</p> + +<p>For each input that doesn't have a value filled in when the form is submitted, we create a list item with a link and insert it in the <code>errorList</code>.</p> + +<pre class="brush: js">function createLink(testItem) { + var listItem = document.createElement('li'); + var anchor = document.createElement('a'); + anchor.textContent = testItem.input.name + ' field is empty: fill in your ' + testItem.input.name + '.'; + anchor.href = '#' + testItem.input.name; + anchor.onclick = function() { + testItem.input.focus(); + }; + listItem.appendChild(anchor); + errorList.appendChild(listItem); +}</pre> + +<p>Each link serves a dual purpose — it tells you what the error is, plus you can click on it/activate it to jump straight to the input element in question and correct your entry.</p> + +<div class="note"> +<p><strong>Note</strong>: The <code>focus()</code> part of this example is a bit tricky. Chrome and Edge (and newer versions of IE) will focus the element when the link is clicked, without needing the <code>onclick</code>/<code>focus()</code> block. Safari will only highlight the form element with the link on its own, so needs the <code>onclick</code>/<code>focus()</code> block to actually focus it. Firefox doesn't focus the inputs properly at all in this context, so Firefox users can't take advantage of this at present (although everything else works fine). The Firefox issue should be fixed soon — work is being done to give Firefox behaviour parity with other browsers (see {{bug(277178)}}).</p> +</div> + +<p>In addition, the <code>errorField</code> is placed at the top of the source order (although it is positioned differently in the UI using CSS), meaning that users can find out exactly what's wrong with their form submissions and get to the input elements in question by going back up to the start of the page.</p> + +<p>As a final note, we have used some WAI-ARIA attributes in our demo to help solve accessibility problems caused by areas of content constantly updating without a page reload (screen readers won't pick this up or alert users to it by default):</p> + +<pre><div class="errors" role="alert" aria-relevant="all"> + <ul> + </ul> +</div></pre> + +<p>We will explain these attributes in our next article, which covers <a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">WAI-ARIA</a> in much more detail.</p> + +<div class="note"> +<p><strong>Note</strong>: Some of you will probably be thinking about that fact that HTML5 forms have built-in validation mechanisms like the <code>required</code>, <code>min</code>/<code>minlength</code>, and <code>max</code>/<code>maxlength</code> attributes (see the {{htmlelement("input")}} element reference for more information). We didn't end up using these in the demo because cross-browser support for them is patchy (for example IE10 and above only).</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: WebAIM's <a href="http://webaim.org/techniques/formvalidation/">Usable and Accessible Form Validation and Error Recovery</a> provides some further useful information about accessible form validation.</p> +</div> + +<h3 id="Other_JavaScript_accessibility_concerns">Other JavaScript accessibility concerns</h3> + +<p>There are other things to be aware of when implementing JavaScript and thinking about accessibility. We will add more as we find them.</p> + +<h4 id="mouse-specific_events">mouse-specific events</h4> + +<p>As you will be aware, most user interactions are implemented in client-side JavaScript using event handlers, which allow us to run functions in response to certain events happening. Some events can have accessibility issues. The main example you'll come across is mouse-specific events like <a href="/en-US/docs/Web/Events/mouseover">mouseover</a>, <a href="/en-US/docs/Web/Events/mouseout">mouseout</a>, <a href="/en-US/docs/Web/Events/dblclick">dblclick</a>, etc. Functionality that runs in response to these events will not be accessible using other mechanisms, like keyboard controls.</p> + +<p>To mitigate such problems, you should double up these events with similar events that can be activated by other means (so-called device-independent event handlers) — <a href="/en-US/docs/Web/Events/focus">focus</a> and <a href="/en-US/docs/Web/Events/blur">blur</a> would provide accessibility for keyboard users.</p> + +<p>Let's look at an example that highlights when this could be useful. Maybe we want to provide a thumbnail image that shows a larger version of the image when it is moused over or focused (like you'd see on an e-commerce product catalog.)</p> + +<p>We've made a very simple example, which you can find at <a href="http://mdn.github.io/learning-area/accessibility/css/mouse-and-keyboard-events.html">mouse-and-keyboard-events.html</a> (see also the <a href="https://github.com/mdn/learning-area/blob/master/accessibility/css/mouse-and-keyboard-events.html">source code</a>). The code features two functions that show and hide the zoomed-in image; these are run by the following lines that set them as event handlers:</p> + +<pre class="brush: js">imgThumb.onmouseover = showImg; +imgThumb.onmouseout = hideImg; + +imgThumb.onfocus = showImg; +imgThumb.onblur = hideImg;</pre> + +<p>The first two lines run the functions when the mouse pointer hovers over and stops hovering over the thumbnail, respectively. This won't allow us to access the zoomed view by keyboard though — to allow that, we've included the last two lines, which run the functions when the image is focused and blurred (when focus stops). This can be done by tabbing over the image, because we've included <code>tabindex="0"</code> on it.</p> + +<p>The <a href="/en-US/docs/Web/Events/click">click</a> event is interesting — it sounds mouse-dependent, but most browsers will activate <a href="/en-US/docs/Web/API/GlobalEventHandlers/onclick">onclick</a> event handlers after Enter/Return is pressed on a link or form element that has focus, or when such an element is tapped on a touchscreen device. This doesn't work by default however when you allow a non-default-focusable event to have focus using tabindex — in such cases you need to detect specifically when that exact key is pressed (see <a href="/en-US/docs/Learn/Accessibility/HTML#Building_keyboard_accessibility_back_in">Building keyboard accessibility back in</a>).</p> + +<h2 id="Summary">Summary</h2> + +<p>We hope this article has given you a good amount of detail and understanding about the accessibility issues surrounding CSS and JavaScript use on web pages.</p> + +<p>Next up, WAI-ARIA!</p> + +<div>{{PreviousMenuNext("Learn/Accessibility/HTML","Learn/Accessibility/WAI-ARIA_basics", "Learn/Accessibility")}}</div> + +<div> +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Accessibility/What_is_accessibility">What is accessibility?</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/HTML">HTML: A good basis for accessibility</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/CSS_and_JavaScript">CSS and JavaScript accessibility best practices</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">WAI-ARIA basics</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Multimedia">Accessible multimedia</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Mobile">Mobile accessibility</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Accessibility_troubleshooting">Accessibility troubleshooting</a></li> +</ul> +</div> diff --git a/files/pt-br/learn/accessibility/html/index.html b/files/pt-br/learn/accessibility/html/index.html new file mode 100644 index 0000000000..0580751c5f --- /dev/null +++ b/files/pt-br/learn/accessibility/html/index.html @@ -0,0 +1,540 @@ +--- +title: 'HTML: Boas práticas em acessibilidade' +slug: Learn/Accessibility/HTML +tags: + - Acessibilidade + - Artigo + - Código + - Iniciante + - aprendizado + - botões + - formulários + - leitor de telas + - semántica + - teclado + - tecnologia assistiva +translation_of: Learn/Accessibility/HTML +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Accessibility/What_is_Accessibility","Learn/Accessibility/CSS_and_JavaScript", "Learn/Accessibility")}}</div> + +<p class="summary">Uma grande parte do conteúdo presente na internet pode se tornar acessível apenas com a utilização correta dos elementos HTML. Esse artigo mostra em detalhes como o HTML pode ser utilizado para garantir o máximo de acessibilidade.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requsitos:</th> + <td> + <p>Conceitos básicos de computadores, entendimento básico de HTML (veja <a href="/pt-BR/docs/Aprender/HTML/Introducao_ao_HTML">Introdução ao HTML</a>), e entendimento do <a href="/en-US/docs/Learn/Accessibility/What_is_accessibility">que é acessibilidade</a>.</p> + </td> + </tr> + <tr> + <th scope="row">Objetivos:</th> + <td> + <p>Ganhar familiaridade com os elementos do HTML que trabalham a favor da acessibilidade e utilizá-los de forma apropriada nos seus documentos da web.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="HTML_e_acessibilidade">HTML e acessibilidade</h2> + +<p>Na medida que se aprende mais sobre HTML — lendo sobre recursos, observando exemplos, etc. — é normal se deparar com um assunto: a importância de se utilizar a semântica HTML (as vezes chamada de POSH, ou <em>Plain Old Semantic HTML</em>). Esse assunto significa utilizar corretamente os elementos HTML, cada qual com seu propósito, o máximo que for possível.</p> + +<p>Você deve estar se perguntando porque isso é tão importante. Afinal, é possível usar uma combinação de CSS e JavaScript que faz com que qualquer elemento HTML se comporte da forma que você quiser. Por exemplo, um botão para dar play em um vídeo no seu site pode ser criado dessa forma:</p> + +<pre class="brush: html"><div>Play vídeo</div></pre> + +<p>Mas como você com mais detalhes a seguir, faz muito mais sentido utilizar o elemento correto para essa finalidade:</p> + +<pre class="brush: html"><button>Play vídeo</button></pre> + +<p>O elemento <code><button></code> possui vários estilos já aplicados nele mesmo por padrão (o que você provavelmente vai querer sobrescrever), ele já é embutido com padrões de acessibilidade pelo teclado — botões podem ser navegados através da tecla tab do teclado, e ativados utilizando a tecla Enter / Return.</p> + +<p>A semântica do HTML não demora mais para escrever do que a versão não-semântica (ruim) se você escrevê-la consistentemente desde o começo do seu projeto. Existem também outros benefícios de utilizá-la, além da acessibilidade:</p> + +<ol> + <li><strong>Mais fácil de ser desenvolvida</strong> — como mencionado acima, você consegue algumas funcionalidades por padrão, também torna o código mais fácil de ser lido e entendido.</li> + <li><strong>Melhor nos dispositivos móveis</strong> — HTML semântico é mais leve que o código não-semântico (aquele código espaguete) em comparação de tamanho de arquivos, também é mais fácil de ser adaptado ao responsivo.</li> + <li><strong>Bom para o SEO</strong> — mecanismos de busca dão mais importância para palavras-chave que são incluidas em títulos, links, etc. do que para palavras-chave incluídas em <code><div></code>s não semânticas, etc. Então suas páginas serão mais fáceis de serem encontradas pelos seus clientes.</li> +</ol> + +<p>Então vamos dar uma olhada em como fazer o HTML mais acessível.</p> + +<div class="note"> +<p><strong>Nota</strong>: É uma boa ideia ter um leitor de tela instalado no seu computador, dessa forma é possível testar os exemplos que serão mostrados abaixo. Veja o nosso <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Screenreaders">Guia de Leitores de Tela</a> para mais detalhes.</p> +</div> + +<h2 id="Boa_semântica">Boa semântica</h2> + +<p>Nós já falamos sobre a importância da boa semântica e porque precisamos utilizar os elementos HTML adequados para cada finalidade. Isso não pode ser ignorado, e é uma das grandes áreas onde a acessibilidade pode ser completamente quebrada se não feito de forma correta.</p> + +<p>Em toda a web, é verdade que as pessoas fazem coisas bem estranhas utilizando o HTML. Alguns abusos do HTML são resultado de práticas antigas que ainda não foram completamente esquecidas, e outros são só simples ignorância das boas práticas. Em qualquer um desses casos, é necessário a substituição de códigos ruins por códigos bons, em qualquer local que forem encontrados, se possível.</p> + +<p>As vezes você não terá em mãos o poder de jogar fora o código ruim — suas páginas web podem ter sido geradas por algum framework que você não possui controle total, ou você pode ter algum conteúdo de terceiros na sua página (como banners de publicidade) que você não tem controle sobre.</p> + +<p>O objetivo aqui não é "tudo ou nada", contudo — qualquer melhoria que você for capaz de fazer irá ajudar a causa da acessibilidade.</p> + +<h3 id="Conteúdo_textual">Conteúdo textual</h3> + +<p>Uma das melhores formas de ajudar um leitor de tela a interpretar sua página é criar uma boa e consistente estrutura de títulos, parágrafos, listas, etc. Um exemplo de boa semântica vai ser parecido com o a seguir:</p> + +<pre class="brush: html example-good line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>h1</span><span class="punctuation token">></span></span>Meu título<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>h1</span><span class="punctuation token">></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span>Essa é a primeira sessão do meu documento.<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span>Eu vou adicionar outro parágrafo aqui também.<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">> + +<ol> + <li>Aqui é</li> + <li>uma lista para</li> + <li>você ler</li> +</ol></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>h2</span><span class="punctuation token">></span></span>Meu sub-título<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>h2</span><span class="punctuation token">></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span>Essa é a primeira sub sessão do meu documento. Eu adoro quando as pessoas conseguem encontrar meu conteúdo!<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>h2</span><span class="punctuation token">></span></span>Meu segundo sub-título<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>h2</span><span class="punctuation token">></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span>Essa é a primeira sub sessão do meu documento. Eu acho que essa é mais interessante que a última.<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span></code></pre> + +<p>Nós preparamos uma versão com o texto mais longo para que você tente utilizar um leitor de tela (veja <a href="http://mdn.github.io/learning-area/accessibility/html/good-semantics.html">good-semantics.html</a>). Se você tentar navegar dentro do documento, vai perceber que é bem fácil:</p> + +<ol> + <li>O leitor de tela lê cada título a medida que você progride pelo conteúdo, notificando ao usuário o que é um título, o que é um parágrafo, etc.</li> + <li>Ele para depois de cada elemento, deixando você ir na velocidade em que é mais confortável.</li> + <li>Você pode pular para o título mais próximo/anterior em muitos leitores de tela.</li> + <li>Você também pode fazer uma lista com todos os títulos em muitos leitores de tela, possibilitando a navegação em um sumário para encontrar conteúdos específicos.</li> +</ol> + +<p>As pessoas ás vezes escrevem títulos, parágrafos, etc. utilizando HTML para vizualização e quebras de linha, ás vezes como o seguinte:</p> + +<pre class="brush: html example-bad line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>font</span> <span class="attr-name token">size</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>7<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Meu título<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>font</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span> +Essa é a primeira sessão do meu documento. +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span> +Eu vou adicionar outro parágrafo aqui também. +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">> +1. Aqui é +</span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">> +2. uma lista para +</span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">> +3. você ler. +</span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>font</span> <span class="attr-name token">size</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>5<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Meu sub-título<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>font</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span> +Essa é a primeira sub sessão do meu documento. Eu adoro quando as pessoas conseguem encontrar meu conteúdo! +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>font</span> <span class="attr-name token">size</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>5<span class="punctuation token">"</span></span><span class="punctuation token">>Meu segundo sub-título</span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>font</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span> +Essa é a primeira sub sessão do meu documento. Eu acho que essa é mais interessante que a última.</code></pre> + +<p>Se você tentar utilizar um leitor de tela na nossa versão mais longa (ver <a href="http://mdn.github.io/learning-area/accessibility/html/bad-semantics.html">bad-semantics.html</a>), você não terá uma boa experiência — o leitor de tela não encontrará nenhuma sinalização, então você não terá acesso ao conteúdo. A página inteira vai parecer como um único bloco gigante, então será lida de uma vez só, ao mesmo tempo.</p> + +<p>Existem também outros problemas além da acessibilidade — é mais difícil estilizar o seu conteúdo com CSS, ou manipulá-lo com JavaScript porque não há elementos para serem utilizados como seletores.</p> + +<h4 id="Usando_linguagem_clara">Usando linguagem clara</h4> + +<p>A linguagem que você usa também pode afetar a acessibilidade. No geral, você deve utilizar uma linguagem clara, que não é exageradamente complexa, e que não use jargões ou gírias desnecessárias. Isso não traz somente benefícios para pessoas com deficiência cognitiva, mas também beneficia pessoas que não estão lendo em usa primeira língua, jovens leitores... todo mundo, de fato! Tirando isso, você deve tentar evitar uma linguagem ou caracteres que não podem ser lidos ou entendidos bem por um leitor de tela. Por exemplo:</p> + +<ul> + <li>Não utilize traços se você pode evitá-los. Ao invés de escrever 5-7, escreva 5 a 7.</li> + <li>Expanda as abreviações — ao invés de escrever Jan, escreva Janeiro.</li> + <li>Expanda os acrônimos, pelo menos uma ou duaz vezes. Ao invés de escrever direto HTML, escreva <em>Hypertext Markup Language</em>, ou HTML.</li> +</ul> + +<h3 id="Layouts_de_páginas">Layouts de páginas</h3> + +<p>Antigamente, nos dias velhos e ruins, as pessoas costumavam criar layouts para páginas utilizando tabelas HTML — usando as células da tabela para se comportarem como cabeçalho, rodapé, barra lateral, coluna de conteúdo, etc. Essa não é uma boa ideia porque um leitor de tela provavelmente irá retornar umas leituras um pouco confusas, especialmente se o layout é complexo e possui várias tabelas aninhadas dentro das células.</p> + +<p>Tente ler o nosso exemplo <a href="http://mdn.github.io/learning-area/accessibility/html/table-layout.html">table-layout.html</a>, que se parece com algo assim:</p> + +<pre class="brush: html"><table width="1200"> + <!-- linha do título principal --> + <tr id="titulo"> + <td colspan="6"> + + <h1 align="center">Cabeçalho</h1> + + </td> + </tr> + <!-- linha do menu de navegação --> + <tr id="nav" bgcolor="#ffffff"> + <td width="200"> + <a href="#" align="center">Home</a> + </td> + <td width="200"> + <a href="#" align="center">Nossa equipe</a> + </td> + <td width="200"> + <a href="#" align="center">Projetos</a> + </td> + <td width="200"> + <a href="#" align="center">Contato</a> + </td> + <td width="300"> + <form width="300"> + <input type="pesquisa" name="q" placeholder="Pesquisar..." width="300"> + </form> + </td> + <td width="100"> + <button width="100">Ir!</button> + </td> + </tr> + <!-- linha de espaçamento --> + <tr id="espacamento" height="10"> + <td> + + </td> + </tr> + <!-- linha do conteúdo principal --> + <tr id="main"> + <td id="content" colspan="4" bgcolor="#ffffff"> + + <!-- conteudo vem aqui --> + </td> + <td id="aside" colspan="2" bgcolor="#ff80ff" valign="top"> + <h2>Related</h2> + + <!-- Outro conteúdo vem aqui --> + + </td> + </tr> + <!-- linha de espaçamento --> + <tr id="spacer" height="10"> + <td> + + </td> + </tr> + <!-- linha do rodapé --> + <tr id="footer" bgcolor="#ffffff"> + <td colspan="6"> + <p>©Copyright 2050 por ninguém. Todos os direitos reservados.</p> + </td> + </tr> + </table></pre> + +<p>Se você tentar navegar poresse código utilizando um leitor de texto, provavelmente ele vai te dizer que existe uma tabela que pode ser reconhecida (mesmo que alguns leitores de tela consigam diferenciar entre layouts de tabelas e o conteúdos das tabelas). Você provavelmente (dependendo de qual leitor de tela que está utilizando) terá que entrar na tabela como um objeto e ler as suas características separadamente, para depois precisar sair da tabela novamente e continuar navegando pelo conteúdo.</p> + +<p>Layouts feitos com tabela são uma relíquia do passado — fazia sentido utilizá-las lá atrás quando o suporte do CSS não era difundido pelos navegadores, mas esses layouts de tabela criam confusão para os usuários de leitor de tela, além de serem ruins por outros motivos (abuso de tabelas <span class="short_text" id="result_box" lang="pt"><span>indiscutivelmente precisa de mais marcação e torna o design menos flexível). Não faça dessa forma!</span></span></p> + +<p>Você pode verificar essas <span class="short_text" id="result_box" lang="pt"><span>reivindicações ao comparar a última experiêncua com um <a href="http://mdn.github.io/learning-area/html/introduction-to-html/document_and_website_structure/">exemplo de estrutura de website mais moderna</a>, o que pode se parecer com algo assim:</span></span></p> + +<pre class="brush: html"><header> + <h1>Cabeçalho</h1> +</header> + +<nav> + <!-- Navegação principal aqui --> +</nav> + +<!-- Aqui é o conteúdo principal da página --> +<main> + + <!-- Que contém um artigo --> + <article> + <h2>Título do artigo</h2> + + <!-- Conteúdo do artigo aqui --> + </article> + + <aside> + <h2>Relacionados</h2> + + <!-- Conteúdo a parte aqui --> + </aside> + +</main> + +<!-- E aqui é um rodapé utilizado em todas as páginas do nosso site --> + +<footer> + <!-- Conteúdo do rodapé aqui --> +</footer></pre> + +<p>Se você experimentar ler esse exemplo de estrutura mais moderna com um leitor de tela, você vai perceber que o layout feito por marcação não atrapalha na hora de retornar o conteúdo do site. Também é muito mais limpo e pequeno em termos de tamanho de código, o que significa um código mais fácil de se dar manutenção e menos uso de banda para o usuário fazer o download (particularmente prevalente para as pessoas com conexão lenta).</p> + +<p>Outra consideração que pode ser feita é criar layouts utilizando a semântica HTML5 nos elementos, como visto no exemplo (veja <a href="/en-US/docs/Web/HTML/Element#Content_sectioning">content sectioning</a>) — você pode criar um layout utilizando apenas elementos aninhados {{htmlelement("div")}}, mas é melhor e mais apropriado seccionar elementos de uma forma que eles envelopem a navegação principal ({{htmlelement("nav")}}), rodapé({{htmlelement("footer")}}), unidades de conteúdo repetidas({{htmlelement("article")}}), etc. Eles trazem semânticas extras para os leitores de tela(e outras ferramentas) para dar aos usuários mais dicas sobre o conteúdo no qual eles estão navegando (veja <a href="http://www.weba11y.com/blog/2016/04/22/screen-reader-support-for-new-html5-section-elements/">Screen Reader Support for new HTML5 Section Elements</a> para uma ideia do que é suporte de leitor de tela).</p> + +<div class="note"> +<p><strong>Nota</strong>: Ao mesmo tempo que seu conteúdo deve ter boa semântica e um layout bonito, deve-se fazer sentido que em sua ordem de fonte — você poderá sempre movimentá-la utilizando CSS depois, mas você deve colocar a ordem de fonte de forma correta desde o começo, para que os usuários que utilizam de leitores de tela possam receber uma leitura que faz sentido.</p> +</div> + +<h3 id="Controles_de_UI">Controles de UI</h3> + +<p>Por controles de UI, o que nós queremos dizer é as partes dos documentos web que os usuários interagem com — mais comumente botões, links, e formulários. Nessa sessão nós daremos uma olhada em princípios da acessibilidade que deverão ser analisados com cuidado ao criar esses controles de UI. Os artigos mais recentes do WAI-ARIA e multimedia irão olhar para outros aspectos da acessibilidade de UIs.</p> + +<p>Um aspecto chave da acessibilidade de controles Ui é que, por padrão, os navegadores premitem que esses controles sejam acessados pelo teclado. Você pode experimentar isso utilizando o nosso exemplo <a href="http://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html">native-keyboard-accessibility.html</a> (ver o <a href="https://github.com/mdn/learning-area/blob/master/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html">código-fonte</a>) — abra em uma nova aba e experimente apertar a tecla tab; depois de algumas tecladas, você irá ver o foco da aba se mover entre diferentes elementos que podem ser focados; os elementos focados são dados um estilo de destaque em todos os navegadores (muda levemente entre diferentes navegadores) dessa forma você pode dizer qual elemento está em foco.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14215/button-focused-unfocused.png" style="border-style: solid; border-width: 1px; display: block; height: 39px; margin: 0px auto; width: 288px;"></p> + +<p>Você pode apertar Enter/Return para seguir um link que está focado ou apertar um botão (nós incluimos um pouco de JavaScript para fazer os botões chamarem uma mensagem), ou começar a escrever para inserir um texto em um formulário de texto (outros elementos possuem controles diferentes, por exemplo o elemento {{htmlelement("select")}} pode ter suas opções visíveis e selecionáveis utilizando as teclas de flecha para cima e para baixo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Navegadores diferentes podem ter mais opções de controle pelo teclado. Veja <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Using_native_keyboard_accessibility">Using native keyboard accessibility</a> para mais detalhes.</p> +</div> + +<p>Você essencialmente consegue esse comportamento de graça, só ao utilizar os elementos apropriados, ex.</p> + +<pre class="brush: html example-good"><h1>Links</h1> + +<p>Esse é um link para <a href="https://www.mozilla.org">Mozilla</a>.</p> + +<p>Outro link, para <a href="https://developer.mozilla.org">Mozilla Developer Network</a>.</p> + +<h2>Botões</h2> + +<p> + <button data-message="Esse é do primeiro botão">Clique em mim!</button> + <button data-message="Esse é do segundo botão">Clique em mim também!</button> + <button data-message="Esse é do terceiro botão">E em mim!</button> +</p> + +<h2>Formulário</h2> + +<form> + <div> + <label for="name">Preencha com seu nome:</label> + <input type="text" id="name" name="name"> + </div> + <div> + <label for="age">Preencha com a sua idade:</label> + <input type="text" id="age" name="age"> + </div> + <div> + <label for="mood">Escolha o seu humor:</label> + <select id="mood" name="mood"> + <option>Feliz</option> + <option>Triste</option> + <option>Bravo</option> + <option>Preocupado</option> + </select> + </div> +</form></pre> + +<p>Isso significa que utilizar links, botões, elementos de formulário e rótulos adequadamente (incluindo o elemento {{htmlelement("label")}} para controles de formulário).</p> + +<p>Contudo, novamente é o caso onde as pessoas ás vezes fazem coisas estranhas utilizando o HTML. Por exemplo, você pode se deparar com botões escritos utilizando o elemento {{htmlelement("div")}}, como a seguir:</p> + +<pre class="brush: html example-bad"><div data-message="Esse é do primeiro botão">Clique em mim!</div> +<div data-message="Esse é do segundo botão">Clique em mim também!</div> +<div data-message="Esse é do terceiro botão">E em mim!</div></pre> + +<p>Mas usar esse código não é recomendado - você perde imediatamente a acessibilidade do teclado que você teria se tivesse usado apenas elementos {{htmlelement ("button")}}, além de não obter nenhum estilo padrão de CSS.</p> + +<h4 id="Aplicando_de_volta_a_acessibilidade_do_teclado">Aplicando de volta a acessibilidade do teclado</h4> + +<p>Adicionar tais vantagens de volta leva um pouco de trabalho (você pode ver um exemplo de código no nosso exemplo <a class="external external-icon" href="http://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/fake-div-buttons.html">fake-div-buttons.html</a> - e também pode ver o <a class="external external-icon" href="https://github.com/mdn/learning-area/blob/master/tools-testing/cross-browser-testing/accessibility/fake-div-buttons.html">source code</a>). Aqui nós acrescentamos aos nossos falsos botões <code><div></code> a capacidade de serem focados (inclusive via tab) dando a cada um o atributo <code>tabindex="0"</code>:</p> + +<pre class="brush: html"><div data-message="Esse é do primeiro botão" tabindex="0">Clique em mim!</div> +<div data-message="Esse é do segundo botão" tabindex="0">Clique em mim também!</div> +<div data-message="Esse é do terceiro botão" tabindex="0">E em mim!</div></pre> + +<p>Basicamente, o atributo {{htmlattrxref ("tabindex")}} destina-se principalmente a permitir que elementos tabulares tenham uma ordem de tabulação personalizada (especificada em ordem numérica positiva), em vez de apenas serem tabulados em sua ordem de origem padrão. Isso é quase sempre uma má ideia, pois pode causar grandes confusões. Use-o somente se você realmente precisar, por exemplo, se o layout mostrar coisas em uma ordem visual muito diferente do código-fonte, e você quiser fazer as coisas funcionarem mais logicamente. Existem duas outras opções para <code>tabindex</code>:</p> + +<ul> + <li><code>tabindex="0"</code> — conforme indicado acima, esse valor permite que elementos que normalmente não podem ser tabulados se tornem tabeláveis. Este é o valor mais útil do <code>tabindex</code>.</li> + <li><code>tabindex="-1"</code> — isso permite que elementos normalmente não tabuláveis recebam foco de maneira programática, por exemplo, via JavaScript, ou como alvo de links. </li> +</ul> + +<p>Embora a adição acima nos permita acessar os botões, ela não nos permite ativá-los através da tecla Enter/Return. Para fazer isso, temos que adicionar o seguinte truque de JavaScript:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js">document<span class="punctuation token">.</span>onkeydown <span class="operator token">=</span> <span class="keyword token">function</span><span class="punctuation token">(</span>e<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="keyword token">if</span><span class="punctuation token">(</span>e<span class="punctuation token">.</span>keyCode <span class="operator token">===</span> <span class="number token">13</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> <span class="comment token">// The Enter/Return key</span> + document<span class="punctuation token">.</span>activeElement<span class="punctuation token">.</span><span class="function token">click</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span> +<span class="punctuation token">}</span><span class="punctuation token">;</span></code></pre> + +<p> </p> + +<p>Aqui nós adicionamos um "ouvinte" (listener) ao objeto de documento (<code>document</code>) para detectar quando um botão foi pressionado no teclado. Verificamos qual botão foi pressionado por meio da propriedade <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode">keyCode</a></code> do objeto de evento; se for o código que corresponde a Enter/Return, executamos a função armazenada no manipulador <code>onclick</code> do botão usando <code>document.activeElement.click()</code>. <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement">activeElement</a></code> nos dá o elemento que está atualmente focado na página.</p> + +<p>Isso acrescenta um monte de problemas extras para construir a funcionalidade de volta. E não deveríamos ter outros problemas com isso. <strong>É sempre melhor apenas usar o elemento certo.</strong></p> + +<h4 id="Rótulos_de_texto_significativos">Rótulos de texto significativos</h4> + +<p>Os rótulos de texto de controle da interface do usuário são muito úteis para todos os usuários, mas deixá-los claros e simples é particularmente importante para usuários com deficiências.</p> + +<p>Você deve certificar-se de que seus rótulos de texto de botão e link sejam compreensíveis e distintos. Não use apenas "Clique aqui" para seus rótulos, pois os usuários de leitores de tela podem utilizar atalhos para exibir/ouvir listas de botões e controles de formulários e não identificá-los adequadamente. A captura de tela a seguir mostra nossos controles sendo listados pelo VoiceOver no Mac.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14335/voiceover-formcontrols.png" style="display: block; height: 604px; margin: 0px auto; width: 802px;"></p> + +<p>Certifique-se de que seus rótulos fazem sentido fora de contexto, lidos individualmente e no contexto do parágrafo em que estão. Por exemplo, este seria um bom exemplo para link:</p> + +<pre class="brush: html example-good"><p>As baleias são criaturas realmente incríveis. <a href="whales.html">Saiba mais sobre baleias</a>.</p></pre> + +<p>Porém este, é um exemplo ruim para link:</p> + +<pre class="brush: html example-bad"><p>As baleias são criaturas realmente incríveis. Para saber mais sobre baleias, <a href="whales.html">clique aqui</a>.</p></pre> + +<div class="note"> +<p><strong>Nota</strong>: Você pode encontrar muito mais sobre implementação de link e melhores práticas no artigo <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">Criando hyperlinks</a>. Você também pode ver alguns bons e maus exemplos em <a href="http://mdn.github.io/learning-area/accessibility/html/good-links.html">good-links.html</a> e <a href="http://mdn.github.io/learning-area/accessibility/html/bad-links.html">bad-links.html</a>.</p> +</div> + +<p>Os rótulos de formulário (labels) também são importantes para dar a você uma ideia sobre o que precisa ser preenchido em cada entrada de formulário. O seguinte exemplo aparentemente é bem razoável:</p> + +<pre class="brush: html example-bad">Preencha seu nome: <input type="text" id="nome" name="nome"></pre> + +<p>Entretanto, esse exemplo não é tão útil para usuários com deficiência. Não há nada para associar o rótulo de forma não ambígua à entrada do formulário e deixar claro como preenchê-lo, se você não puder vê-lo. Se você acessar esse item usando um leitor de tela, só irá ouvir uma descrição genérica "editar texto" sem associar corretamente qual o tipo de texto a ser editado.</p> + +<p>Já o exemplo a seguir, é bem melhor:</p> + +<pre class="brush: html example-good"><div> + <label for="nome">Preench seu nome:</label> + <input type="text" id="nome" name="nome"> +</div></pre> + +<p>Com o código assim, o rótulo será claramente associado à entrada; a descrição será algo como "Preencha seu nome: editar texto".</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14337/voiceover-good-form-label.png" style="display: block; margin: 0 auto;"></p> + +<p>Como um bônus adicional, na maioria dos navegadores a associação de um rótulo a uma entrada de formulário significa que você pode clicar no rótulo para selecionar/ativar o elemento de formulário. Isso consequentemente aumenta o tamanho da área clicável dos elementos, facilitando assim a seleção.</p> + +<div class="note"> +<p><strong>Nota</strong>: Você pode ver alguns bons e maus exemplos de formulários em <a href="http://mdn.github.io/learning-area/accessibility/html/good-form.html">good-form.html</a> e <a href="http://mdn.github.io/learning-area/accessibility/html/bad-form.html">bad-form.html</a>.</p> +</div> + +<h2 id="Tabelas_de_dados_acessíveis">Tabelas de dados acessíveis</h2> + +<p>Uma tabela básica de dados pode ser escrita com uma marcação muito simples, como neste exemplo:</p> + +<pre class="brush: html"><table> + <tr> + <td>Name</td> + <td>Age</td> + <td>Gender</td> + </tr> + <tr> + <td>Gabriel</td> + <td>13</td> + <td>Male</td> + </tr> + <tr> + <td>Elva</td> + <td>8</td> + <td>Female</td> + </tr> + <tr> + <td>Freida</td> + <td>5</td> + <td>Female</td> + </tr> +</table></pre> + +<p>Mas essa tabela possui alguns problemas - não há como um usuário de leitor de telas associar linhas ou colunas como agrupamentos de dados. Para fazer isso, você precisa saber quais são as linhas de cabeçalho e se elas estão direcionando linhas, colunas etc. Isso só pode ser feito visualmente para a tabela acima (veja o exemplo <a href="http://mdn.github.io/learning-area/accessibility/html/bad-table.html">bad-table.html</a> e tente navegar pela tabela você mesmo).</p> + +<p>Agora dê uma olhada no exemplo da nossa <a href="https://github.com/mdn/learning-area/blob/master/css/styling-boxes/styling-tables/punk-bands-complete.html">tabela de bandas punk</a> - você pode ver alguns recursos de acessibilidade aqui:</p> + +<ul> + <li>Os cabeçalhos de tabela são definidos usando elementos {{htmlelement ("th")}} - você também pode especificar se eles são cabeçalhos de linhas ou colunas usando o atributo <code>scope</code>. Isso fornece grupos completos de dados que podem ser consumidos pelos leitores de tela como unidades únicas.</li> + <li>O elemento {{htmlelement ("caption")}} e o atributo de resumo (<code><table></code> <code>summary</code>) executam tarefas semelhantes - eles funcionam como texto alternativo para uma tabela, fornecendo ao usuário de leitor de telas um resumo rápido e útil do conteúdo da tabela. <code><caption></code> é geralmente mais adequado, pois torna o seu conteúdo acessível para os usuários com visão também, que também poderão achar isso útil. Você não precisa ter os dois.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Consulte nossos artigos sobre <a href="/en-US/docs/Learn/HTML/Tables/Advanced">Recursos avançados de acessibilidade para tabelas em HTML</a> para obter mais detalhes sobre tabelas de dados acessíveis.</p> +</div> + +<h2 id="Alternativas_em_textos">Alternativas em textos</h2> + +<p>Considerando que o conteúdo textual é inerentemente acessível, o mesmo não pode necessariamente ser dito para conteúdo multimídia - conteúdo de imagem / vídeo não pode ser visto por pessoas com deficiência visual, e conteúdo de áudio não pode ser ouvido por pessoas com deficiência auditiva. Abordaremos o conteúdo de vídeo e áudio em detalhes no artigo sobre multimídia acessível mais adiante, mas para este artigo veremos a acessibilidade para o elemento {{htmlelement("img")}}.</p> + +<p>Temos um exemplo simples escrito, <a href="http://mdn.github.io/learning-area/accessibility/html/accessible-image.html">accessible-image.html</a>, que apresenta quatro cópias da mesma imagem:</p> + +<pre><img src="dinosaur.png"> + +<img src="dinosaur.png" + alt="Um tiranossauro Rex vermelho: Um dinossauro de duas patas em pé como um humano, com braços pequenos e uma cabeça grande com muitos dentes afiados."> + +<img src="dinosaur.png" + alt="Um tiranossauro Rex vermelho: Um dinossauro de duas patas em pé como um humano, com braços pequenos e uma cabeça grande com muitos dentes afiados." + title="O dinossauro vermelho da Mozilla."> + + +<img src="dinosaur.png" aria-labelledby="dino-label"> + +<p id="dino-label">O Tiranossauro Rex: um dinossauro de duas patas de pé como um humano, com braços pequenos e uma cabeça grande com muitos dentes afiados.</p> +</pre> + +<p>A primeira imagem, quando visualizada por um leitor de tela, não oferece muita ajuda ao usuário - o VoiceOver, por exemplo, lê "/dinosaur.png, image". Ele lê o nome do arquivo para tentar fornecer alguma ajuda. Neste exemplo, o usuário pelo menos saberá que é um tipo de dinossauro, mas muitas vezes os arquivos podem ser carregados com nomes de arquivos gerados por máquina (por exemplo, de uma câmera digital) e esses nomes provavelmente não fornecem nenhum contexto ao conteúdo da imagem.</p> + +<div class="note"> +<p><strong>Nota</strong>: É por isso que você nunca deve incluir conteúdo de texto dentro de uma imagem - os leitores de tela simplesmente não podem acessá-lo. Existem outras desvantagens também - você não pode selecioná-lo e copiá-lo/colá-lo. Apenas não faça isso!</p> +</div> + +<p>Quando um leitor de tela encontra a segunda imagem, ele lê todo o atributo <code>alt</code> - "Um tiranossauro Rex vermelho: Um dinossauro de duas patas em pé como um humano, com braços pequenos e uma cabeça grande com muitos dentes afiados".</p> + +<p>Isso destaca a importância de não apenas usar nomes de arquivos significativos, caso o <strong>texto alternativo</strong> não esteja disponível, mas também garantir que o texto alternativo seja fornecido em atributos <code>alt</code> sempre que possível. Observe que o conteúdo do atributo <code>alt</code> sempre deve fornecer uma representação direta da imagem e o que ela transmite visualmente. Qualquer conhecimento pessoal ou descrição extra não deve ser incluído aqui, já que não é útil para pessoas que não se depararam com a imagem antes.</p> + +<p>Uma coisa a considerar é se as imagens possuem algum significado dentro de seu conteúdo ou se elas são puramente decorativas. Se eles são decorativas, é melhor apenas incluí-las na página como imagens de fundo através de CSS.</p> + +<div class="note"> +<p><strong>Nota</strong>: Leia <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Imagens em HTML</a> e <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">Imagens Responsivas</a> para obter mais informações sobre a implementação de imagens e melhores práticas.</p> +</div> + +<p>Se você quiser fornecer informações contextuais extras, deverá colocá-las no texto ao redor da imagem ou dentro de um atributo de título (<code>title</code>), como mostrado acima. Nesse caso, a maioria dos leitores de tela lerá o texto alternativo, o atributo de título e o nome do arquivo. Além disso, os navegadores exibem o texto do título como dicas de ferramentas quando estão sobre o mouse.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14333/title-attribute.png" style="display: block; margin: 0 auto;"></p> + +<p>Vamos dar uma olhada rápida no quarto método:</p> + +<pre class="brush: html"><img src="dinosaur.png" aria-labelledby="dino-label"> + +<p id="dino-label">O dinossauro vermelho da Mozilla.</p></pre> + +<p>Nesse caso, não estamos usando o atributo <code>alt</code> - em vez disso, apresentamos nossa descrição da imagem como um parágrafo de texto regular, atribuímos um <code>id</code> e, em seguida, usamos o atributo <code>aria-labelledby</code> para nos referirmos a esse <code>id</code>, que faz com que os leitores de tela usem esse parágrafo como o texto/rótulo alternativo para essa imagem. Isso é especialmente útil se você quiser usar o mesmo texto como um rótulo para várias imagens - algo que não é possível com <code>alt</code>.</p> + +<div class="note"> +<p><strong>Nota</strong>: <code>aria-labelledby</code> é parte da especificação <a href="https://www.w3.org/TR/wai-aria-1.1/">WAI-ARIA</a>, que permite aos desenvolvedores adicionar uma semântica extra à sua marcação para melhorar a acessibilidade do leitor de tela quando necessário. Para saber mais sobre como funciona, leia nosso <a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">artigo básico sobre WAI-ARIA</a>.</p> +</div> + +<h3 id="Outros_mecanismos_alternativos_de_textos">Outros mecanismos alternativos de textos</h3> + +<p>Imagens também têm outros mecanismos disponíveis para fornecer texto descritivo. Por exemplo, há um atributo <code>longdesc</code> que serve para apontar para um documento da Web separado contendo uma descrição estendida da imagem:</p> + +<pre class="brush: html"><img src="dinosaur.png" longdesc="dino-info.html"></pre> + +<p>Isso aparentemente é uma boa ideia, especialmente para infográficos ou gráficos com muitas informações, que talvez possam ser representados como uma tabela de dados acessível (consulte a seção anterior). No entanto, o <code>longdesc</code> não é suportado de forma consistente pelos leitores de tela e o conteúdo é completamente inacessível para usuários que não usam leitores de tela. É sem dúvida muito melhor incluir a descrição longa na mesma página que a imagem ou vinculá-la a um link comum.</p> + +<p>O HTML5 inclui dois novos elementos - {{htmlelement ("figure")}} e {{htmlelement ("figcaption")}} - que devem associar uma figura de algum tipo (pode ser qualquer coisa, não necessariamente uma imagem) com uma legenda de figura:</p> + +<pre class="brush: html"><figure> + <img src="dinosaur.png" alt="O dinossauro da Mozilla."> + <figcaption>Um tiranossauro Rex vermelho: Um dinossauro de duas patas em pé como um humano, com braços pequenos e uma cabeça grande com muitos dentes afiados.</figcaption> +</figure></pre> + +<p>Infelizmente, a maioria dos leitores de tela parece não associar ainda as legendas utilizando o elemento "figure" às respectivas imagens, mas a estrutura do elemento é útil para o estilo CSS, além de fornecer uma maneira de inserir uma descrição da imagem.</p> + +<h3 id="Atributos_alt_vazios">Atributos "alt" vazios</h3> + +<pre class="brush: html"><h3> + <img src="article-icon.png" alt=""> + Tiranossauro Rex: O Rei dos dinossauros. +</h3></pre> + +<p>Pode haver momentos em que uma imagem é incluída no design de uma página, mas seu objetivo principal é a decoração visual. Você notará no exemplo de código acima que o atributo <code>alt</code> da imagem está vazio - isso é para fazer com que os leitores de tela reconheçam a imagem, mas não tentem descrever a imagem (em vez disso, dizem apenas "imagem" ou similar).</p> + +<p>A razão para usar um <code>alt</code> vazio ao invés de não incluí-lo é porque muitos leitores de tela anunciam o URL da imagem inteira se nenhum <code>alt</code> for fornecido. No exemplo acima, a imagem está agindo como uma decoração visual para o título ao qual está associada. Em casos como esse, e nos casos em que uma imagem é apenas decoração e não tem valor de conteúdo, você deve colocar um <code>alt</code> vazio em suas imagens. Outra alternativa é usar o atributo ARIA role (role="presentation") - isso também impede que os leitores de telas leiam textos alternativos.</p> + +<div class="note"> +<p><strong>Nota</strong>: se possível, você deve usar CSS para exibir imagens que são apenas decorativas.</p> +</div> + +<h2 id="Resumo">Resumo</h2> + +<p>Agora você deve estar familiarizado com a escrita de HTML acessível para a maioria das ocasiões. Nosso artigo básico do WAI-ARIA também preencherá algumas lacunas nesse conhecimento, mas este artigo cuidou do básico. Em seguida, exploraremos CSS e JavaScript e como a acessibilidade é afetada por seu uso bom ou ruim.</p> + +<p>{{PreviousMenuNext("Learn/Accessibility/What_is_Accessibility","Learn/Accessibility/CSS_and_JavaScript", "Learn/Accessibility")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/What_is_accessibility&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhjKbO6WIg9b4xWjdZSQcnXxP1foyg">O que é acessibilidade?</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhg8RYEjwUHElGCpA1Q_60OiOtXeLg">HTML: uma boa base para acessibilidade</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/CSS_and_JavaScript&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhjUFLV1YWbEtSBOMPU_Bt7V-OmzDw">Práticas recomendadas de acessibilidade de CSS e JavaScript</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/WAI-ARIA_basics&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhj5LnkD6EVmrTiupwf932KoV4VCTw">Noções básicas de WAI-ARIA</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/Multimedia&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhgWAjBOw_jwWHOvK_zBEob2xQdEmA">Multimídia acessível</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/Mobile&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhgnwNfnWbOmqpMWRI1c1zBqGFfU1Q">Acessibilidade móvel</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/Accessibility_troubleshooting&xid=17259,15700021,15700124,15700149,15700186,15700190,15700201,15700214&usg=ALkJrhjy6mgQ3Y6D6sT4QvsOicr2-Fmt9Q">Solução de problemas de acessibilidade</a></li> +</ul> diff --git a/files/pt-br/learn/accessibility/index.html b/files/pt-br/learn/accessibility/index.html new file mode 100644 index 0000000000..0c34fc5f4c --- /dev/null +++ b/files/pt-br/learn/accessibility/index.html @@ -0,0 +1,78 @@ +--- +title: Accessibility +slug: Learn/Accessibility +tags: + - ARIA + - Accessibility + - Articles + - Beginner + - CSS + - CodingScripting + - HTML + - JavaScript + - Landing + - Learn + - Module + - NeedsTranslation + - TopicStub +translation_of: Learn/Accessibility +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Aprender HTML, CSS e Javascript é útil se você quer se tornar um desenvolvedor web, mas seu conhecimento precisa ir além. Você deve usá-las de forma a maximizar a audiencia dos seus sites, e permitir que todos possam acessar o conteúdo. Para conseguir isso, será necessário seguir boas práticas, realizar testes em vários navegadores (<a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing">cross browser testing</a>) e pensar em acessibilidade desde o início do desenvolvimento. Este módulo abordará a acessibilidade em detalhes.</p> + +<h2 id="Visão_geral">Visão geral</h2> + +<p>Quando alguem descreve um site como 'acessível', entende-se que qualquer usuário pode acessar o conteúdo, independente de como o conteúdo foi acessado - mesmo, e especialmente portadores de limitações físicas ou mentais.</p> + +<ul> + <li>Os sites devem ser acessíveis por teclado, mouse ou telas sensíveis, e qualquer outra forma, incluindo leitores de tela, ou assistentes de voz, como Alexa, ou Google home.</li> + <li>As aplicações devem ser compreensíveis e usáveis pelos usuários independentemente de suas habilidades auditivas, visuais, físicas ou cognitivas.</li> + <li>Os sites também não podem oferecer perigo: alguns movimentos podem causar enxaquecas ou ataques epiléticos.</li> +</ul> + +<p><strong>Por padrão, o HTML é acessível, se utilizado corretamente.</strong> A acessibilidade web presume que o conteúdo continuará acessível, independente de como o conteúdo será acessado.</p> + +<p>O recurso <u>Inspecionar propriedades de acessibilidade</u> é uma ótima ferramenta para verificar problemas de acessibilidade nos sites. O vídeo a seguir fornece uma boa introdução sobre a ferramenta.</p> + +<p>{{EmbedYouTube("7mqqgIxX_NU")}}</p> + +<h2 id="Prerequisitos">Prerequisitos</h2> + +<p>Para ter o máximo proveito deste módulo, recomendamos que esteja familiarizados com pelos os dois primeiros módulos de <a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/HTML">HTML</a>, <a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/CSS">CSS</a>, e <a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/JavaScript">JavaScript</a>, ou melhor ainda, com as partes principais do módulo de acessibilidade de cada capítulo, à medida em que vai estudando.</p> + +<div class="note"> +<p><strong>Nota</strong>: Se você está estudando em um dispositivo que não pode criar novos arquivos, voce pode testar os exemplos em alguma aplicação de codificação online, como <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guias">Guias</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/Accessibility/What_is_accessibility">O que é acessibilidade?</a></dt> + <dd>Este artigo fornece uma visão geral do que é a acessibilidade - isso inclui quais grupos de pessoas devemos considerar e o motivo, quais ferramentas de acessibilidade são utilizadas para interagir com a web e como podemos fazer da acessibilidade web parte do nosso fluxo de desenvolvimento.</dd> + <dt><a href="/en-US/docs/Learn/Accessibility/HTML">HTML: A base para a acessibilidade</a></dt> + <dd>Boa parte do conteúdo da Web pode ser 'acessível' apenas garantindo que as tags HTML sejam sempre usadas para a finalidade correta. Este artigo analisa detalhadamente como utilizar o HTML garantindo a máxima acessibilidade.</dd> + <dt><a href="/en-US/docs/Learn/Accessibility/CSS_and_JavaScript">CSS e JavaScript: accessibilidade e boas práticas</a></dt> + <dd>CSS e JavaScript, usados corretamente, também podem proporcionar experiências acessíveis na web, mas se mal utilizadas, podem prejudicar a navegação. Este artigo descreve como utilizar o CSS e JS de forma a garantir que mesmo conteúdos complexos sejam acessíveis.</dd> + <dt><a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">Básico de WAI-ARIA</a></dt> + <dd>Continuando to tópico anterior, não é facil fazer interfaces web com HTML e conteúdo dinâmico atualizado por JavaScript. O WAI-ARIA é uma tecnologia que pode ajudar com esses problemas, adicionando mais propriedades semanticas que navegadores e tecnologias assistivas podem reconhecer e usar para permitir que os usuários saibam o que está acontecendo na tela. Aqui mostraremos o básico destas técnicas para melhorar a acessibilidade.</dd> + <dt><a href="/en-US/docs/Learn/Accessibility/Multimedia">Multimedia acessível</a></dt> + <dd>Outra categoria de conteúdo que pode criar problemas de acessibilidade é a multimédia - Audio, vídeo e imagens precisam de alternativas textuais, assim poderão ser compreendidas por tecnologias assistivas de seus usuários. Este artigo detalha como.</dd> + <dt><a href="/en-US/docs/Learn/Accessibility/Mobile">Accessibilidade Mobile</a></dt> + <dd>O acesso por dispositivos móveis e smartphones é muito popular, e plataformas como iOS e Android já possuem ferramentas bastante consolidadas, assim é importante considerar a acessibilidade do seu conteúdo também nestas plataformas. Este artigo faz considerações sobre acessibilidade mobile.</dd> +</dl> + +<h2 id="Avaliações">Avaliações</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/Accessibility/Accessibility_troubleshooting">Solução de problemas</a></dt> + <dd>Na avaliação deste módulo, disponibilizaremos um site com vários problemas de acessibilidade que você deve encontrar e corrigir. </dd> +</dl> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://egghead.io/courses/start-building-accessible-web-applications-today">Comece a desenvolver aplicações web hoje</a> — Marcy Sutton apresenta uma excelente série de video tutorials.</li> + <li><a href="https://dequeuniversity.com/resources/">Recursos Universidade Deque</a> — inclui codigos de exemplo, leitores de tela, e outros recursos interessantes.</li> + <li><a href="http://webaim.org/resources/">Recursos webAIM</a> — inlui guias, checklists, ferramentas e outras coisas.</li> +</ul> diff --git a/files/pt-br/learn/common_questions/como_a_internet_funciona/index.html b/files/pt-br/learn/common_questions/como_a_internet_funciona/index.html new file mode 100644 index 0000000000..6bc88ac21f --- /dev/null +++ b/files/pt-br/learn/common_questions/como_a_internet_funciona/index.html @@ -0,0 +1,102 @@ +--- +title: Como a Internet funciona? +slug: Learn/Common_questions/Como_a_internet_funciona +tags: + - Iniciante + - Mecanismos Web + - Tutorial + - Web +translation_of: Learn/Common_questions/How_does_the_Internet_work +--- +<div class="summary"> +<p>Este artigo discute sobre o que é e como funciona a internet.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Nenhum, mas encorajamos a ler primeiro <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Common_questions/Pensando_antes_de_codificar">Pensando antes de codificar</a></td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Você irá aprender o básico da infraestrutura técnica da Web e a diferença entre Internet e Web.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumo">Resumo</h2> + +<p>A <strong>Internet</strong> é a espinha dorsal da Web, a infraestrutura técnica que faz a Web possível. Mas basicamente, a Internet é uma gigantesca rede de computadores que se comunicam juntos.</p> + +<p><a href="https://pt.wikipedia.org/wiki/Internet#Hist.C3.B3ria" rel="external">A história da internet é um pouco obscura</a>. Ela começou nos anos 60 como um projeto de pesquisa consolidado pelo exército norte americano, e tornou-se uma infraestrutura pública nos anos 80 com o suporte dado por diversas universidades públicas e companias privadas. As várias tecnologias que suportam a internet se acoplaram através do tempo, mas a forma de funcionamento não mudou muito: Internet é uma forma de conectar computadores e garantir, em qualquer situação, que eles encontrem uma forma de se manter conectados.</p> + +<h2 id="Aprendizado_ativo">Aprendizado ativo</h2> + +<ul> + <li><a href="https://www.youtube.com/watch?v=7_LPdttKXPc" rel="external">Como a Internet funciona em 5 minutos</a> (em inglês): Um vídeo de 5 minutos para entender os conceitos básicos da Internet feito por Aaron Titus.</li> +</ul> + +<h2 id="Mergulho_profundo">Mergulho profundo</h2> + +<h3 id="Uma_rede_simples">Uma rede simples</h3> + +<p>Quando dois computadores precisam se comunicar, você precisa conectá-los, seja fisicamente (normalmente com um <a href="https://pt.wikipedia.org/wiki/Cabo_de_par_tran%C3%A7ado">Cabo de rede</a>) ou de uma forma sem fio (por exemplo com sistemas <a href="https://pt.wikipedia.org/wiki/Wi-Fi">WiFi</a> ou <a href="https://pt.wikipedia.org/wiki/Bluetooth">Bluetooth</a>). Todos os computadores modernos suportam alguma(s) dessas conexões.</p> + +<div class="note"> +<p><strong>Nota:</strong> Até o final deste artigo nós estaremos falando apenas a respeito de cabos físicos, mas redes sem fio funcionam da mesma forma</p> +</div> + +<p><img alt="Two computers linked together" src="https://mdn.mozillademos.org/files/8441/internet-schema-1.png" style="height: 152px; width: 600px;"></p> + +<p>Uma rede não é limitada a dois computadores. Você pode conectar quantos computadores desejar. Mas isto se torna complicado. Se você está tentando conectar, digamos, dez computadores você irá precisar de 45 cabos, com 9 conexões por computador.</p> + + + +<p><img alt="Ten computers all together" src="https://mdn.mozillademos.org/files/8443/internet-schema-2.png" style="height: 576px; width: 600px;"></p> + +<p>Para resolver este problema, cada computador na rede está conectado à um pequeno computador especial chamado de <em>roteador</em>. Este <em>roteador </em>tem um único trabalho: como um sinalizador em uma estação de trem, ter certeza de que a mensagem enviada por um determinado computador chege ao computador destinatário corretamente. Para enviar uma mensagem para o computador B, o computador A deve enviar a mensagem para o roteador, que por sua vez encaminha a mensagem para o computador B e tem a certeza de que a mensagem não foi entregue ao computador C.</p> + +<p>Uma vez que nós adicionamos um roteador no sistema, nossa rede de 10 computadores apenas necessitará de 10 cabos: uma unica conexão para cada computador e um roteador com 10 conexões.</p> + +<p><img alt="Ten computers with a router" src="https://mdn.mozillademos.org/files/8445/internet-schema-3.png" style="height: 576px; width: 600px;"></p> + +<h3 id="Uma_rede_de_redes">Uma rede de redes</h3> + +<p>Por enquanto, tudo bem. Mas como conectar centenas, milhares, bilhões de computadores? Claro que um unico roteador não pode se adaptar para tanto, mas, se você ler com cuidado, nós dissemos que um roteador é um computador como qualquer outro, então o que nos impede de conectar dois roteadores juntos? Nada, então façamos isto.</p> + +<p><img alt="Two routers linked together" src="https://mdn.mozillademos.org/files/8447/internet-schema-4.png"></p> + +<p>Conectando computadores a roteadores, e então roteadores a roteadores, nós podemos escalar nossa rede infinitamente.</p> + +<p><img alt="Routers linked to routers" src="https://mdn.mozillademos.org/files/8449/internet-schema-5.png" style="height: 563px; width: 600px;"></p> + +<p>Esta rede é muito parecida com o que chamamos de Internet, mas alguma coisa está faltando. Nós contruímos tais redes para nossos próprios fins. Existem outras redes além das nossas ligadas em outros lugares: nossos amigos, vizinhos, qualquer pessoa que tenha uma rede de computadores. Mas é inviável ligarmos cabos entre nossas casas e o resto do mundo, então como nos podemos lidar com isso? Muito bem, já existem cabos ligados a sua casa, como por exemplo, cabos de eletricidade e telefone. A estrutura do telefone já conecta nossa casa com o resto do mundo. Para conectar nossa rede a rede telefonica, precisamos de um equipamento especial chamado <em>modem.</em> Este <em>modem </em>transforma a informação da nossa rede em uma informação gerenciavel pela rede telefonica e vice-versa.</p> + +<p><img alt="A router linked to a modem" src="https://mdn.mozillademos.org/files/8451/internet-schema-6.png" style="height: 340px; width: 600px;"></p> + +<p>Então nós estamos conectados à infraestrutuca telefônica. O próximo passo é enviar mensagens da nossa rede para a rede que nós desejamos alcançar. Para fazer isto, vamos precisar conectar nossa rede a um Provedor de Serviço de Internet (ISP, em inglês). Um ISP é uma compania que gerencia alguns roteadores especiais que são conectados e pode também acessar roteadores de outros ISPs. Então a mensagem da nossa rede é transportada para a rede de redes do ISP e então para a rede de destino. A Internet é composta por toda esta infraestrutura de redes.</p> + +<p><img alt="Full Internet stack" src="https://mdn.mozillademos.org/files/8453/internet-schema-7.png" style="height: 1293px; width: 340px;"></p> + +<h3 id="Encontrando_computadores">Encontrando computadores</h3> + +<p>Se você quer enviar uma mensagem para um computador, você precisa especificar qual é este computador. Por isso, qualquer computador conectado à uma rede possui um único endereço de identificação, chamado de "Endereço IP" (onde IP, do inglês <em>Internet Protocol</em>, significa Protocolo de Internet). Este é um endereço composto por uma série de 4 números separados por pontos, por exemplo: 192.168.2.10.</p> + +<p>Isto é perfeito para computadores, mas nós seres humanos temos dificuldades para lembrar estes endereços. Para tornar as coisas mais fáceis, nós podemos dar apelidos aos endereços IP que nós humanos podemos compreender, chamados <em>nome de domínio</em>. Por exemplo, google.com é um nome de domínio usado para "apelidar" o endereço 173.194.121.32. Então, usando o nome de domínio é uma forma mais simples de encontrar um computador na Internet.</p> + +<p><img alt="Show how a domain name can alias an IP address" src="https://mdn.mozillademos.org/files/8405/dns-ip.png" style="height: 160px; width: 330px;"></p> + +<h3 id="A_Internet_e_a_Web">A Internet e a Web</h3> + +<p>Como você deve ter notado, quando navegamos na Web com nossos navegadores, normalmente utilizamos os nomes de domínios para chegar a um website. Isto significa que a Internet e a Web são a mesma coisa? Não tão simples assim. Como vimos, a Internet é uma infraestrutura técnica que permite conectar bilhões de computadores. Entre estes computadores, alguns computadores (chamados de servidores Web) podem enviar mensagens intelegíveis para navegadores Web. A Internet é a infraestrutura, enquanto a Web é um serviço construído sob esta infraestrutura. Vale a pena notar que existem diversos outros serviços que funcionam na Internet, tais como email e {{Glossary("IRC")}}.</p> + +<p>Noções básicas sobre nomes de domínio</p> + +<h2 id="Próximos_passos">Próximos passos</h2> + +<ul> + <li><a href="/pt-BR/docs/Aprender/Getting_started_with_the_web/Como_a_Web_funciona">Como a Web funciona</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Common_questions/Pages_sites_servers_and_search_engines">Entendendo a diferença entre uma página web, um website, um servidor web e um mecânismo de pesquisa</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Common_questions/What_is_a_domain_name">Entendendo nomes de domínio</a></li> +</ul> diff --git a/files/pt-br/learn/common_questions/como_configurar_um_servidor_de_testes_local/index.html b/files/pt-br/learn/common_questions/como_configurar_um_servidor_de_testes_local/index.html new file mode 100644 index 0000000000..83b4f50a41 --- /dev/null +++ b/files/pt-br/learn/common_questions/como_configurar_um_servidor_de_testes_local/index.html @@ -0,0 +1,112 @@ +--- +title: Como configurar um servidor de testes local +slug: Learn/Common_questions/Como_configurar_um_servidor_de_testes_local +tags: + - Aprender + - Express + - Flask + - Iniciante + - Node + - PHP + - Python + - django + - lamp + - servidores +translation_of: Learn/Common_questions/set_up_a_local_testing_server +--- +<div class="summary"> +<p>Este artigo explica como configurar um simples servidor de testes local em seu computador e o básico para utiliza-lo.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td> + <p>Primeiro você precisa saber <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Common_questions/Como_a_internet_funciona">como a internet funciona</a> e <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Common_questions/o_que_e_um_web_server">o que é um servidor Web</a>.</p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Você vai aprender como configurar um servidor de testes local.</td> + </tr> + </tbody> +</table> + +<h2 id="Arquivos_locais_vs._arquivos_remotos">Arquivos locais vs. arquivos remotos</h2> + +<p>Ao longo da maior parte da área de aprendizagem, nós lhe dissemos apenas para abrir seus exemplos diretamente no navegador — Isto pode ser feito atráves de um duplo clique no arquivo HTML, arrastando e soltando o arquivo na janela do navegador ou escolhendo Arquivo > Abrir<em>...</em> e navegando para o arquivo HTML. Existem muitas maneiras de realizar isso.</p> + +<p>Se o caminho do endereço web começa com <code>file://</code> seguido pelo caminho para o arquivo no seu disco rígido local, um arquivo local está sendo utilizado. No entanto, se você ver um dos nossos exemplos hospedado no GitHub (ou um exemplo em algum outro servidor remoto), o enderço web começará com <code>http://</code> ou <code>https://</code>, para mostrar que o arquivo foi recebido via HTTP.</p> + +<h2 id="O_problema_com_o_teste_de_arquivos_locais">O problema com o teste de arquivos locais</h2> + +<p>Alguns exemplos não serão executados se você os abrir como arquivos locais. Isto pode ser devido a uma série de razões, sendo o mais provável:</p> + +<ul> + <li><strong>Eles apresentam requisições assíncronas</strong>. Alguns navegadores (incluindo o Chrome) não executarão requisições assíncronas (consulte <a href="https://developer.mozilla.org/pt-BR/docs/Aprender/JavaScript/Client-side_web_APIs/Buscando_dados">Buscando dados no servidor</a>) se você simplesmente executar o exemplo de um arquivo local. Isso ocorre devido a restrições de segurança (para mais informações sobre segurança na web, leia <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/First_steps/Seguranca_site">Segurança do site</a>).</li> + <li><strong>Eles apresentam uma linguagem do site do servidor</strong>. Linguagens do lado do servidor (como PHP ou Python) requerem um servidor especial para interpretar o código e entregar os resultados.</li> +</ul> + +<h2 id="Executando_um_servidor_HTTP_local_simples">Executando um servidor HTTP local simples</h2> + +<p>Para contornar o problema de requisições assíncronas, precisamos testar esses exemplos executando-os através de um servidor web local. Uma das maneiras mais fáceis de fazer isso para nossos propósitos é usar o módulo <code>SimpleHTTPServer</code> do Python.</p> + +<p>Para fazer isso:</p> + +<ol> + <li> + <p>Instale o Python. Se você estiver usando Linux ou macOS, ele já deverá estár disponível em seu sistema. Se você é um usuário do Windows, pode obter um instalador na página inicial do Python e seguir as instruções para instalá-lo:</p> + + <ul> + <li>Vá para <a href="https://www.python.org/">python.org</a> (em inglês)</li> + <li>Na seção Download, clique no link para Python "3.xxx".</li> + <li>Na parte inferior da página, escolha o instalador executável do <em>Windows x86 </em>e baixe-o.</li> + <li>Quando tiver baixado, execute-o.</li> + <li>Na primeira página do instalador, certifique-se de marcar a caixa de seleção "Adicionar Python 3.xxx ao PATH".</li> + <li>Clique em <em>Instalar</em> e então, clique em <em>Fechar</em> quando a instalação terminar.</li> + </ul> + </li> + <li> + <p>Abra seu prompt de comando (Windows)/ terminal (macOS/ Linux). Para verificar se o Python está instalado, digite o seguinte comando:</p> + + <pre class="brush: bash">python -V</pre> + </li> + <li> + <p>Isso deve retornar um número de versão. Se estiver tudo OK, navegue até o diretório em que seu exemplo está dentro, usando o comando <code>cd</code>.</p> + + <pre class="brush: bash"># incluir o nome do diretório para entrar, por exemplo +cd Desktop +# use dois pontos para voltar um nível de diretório se você precisar +cd ..</pre> + </li> + <li> + <p>Digite o comando para inicializar o servidor nesse diretório:</p> + + <pre class="brush: bash"># Se a versão do Python retornada acima for 3.X +python3 -m http.server +# No windows, tente "python" em vez de "python3" +# Se a versão do Python retornada acima for 2.X +python -m <code>SimpleHTTPServer</code></pre> + </li> + <li> + <p>Por padrão, isso executará o conteúdo do diretório em um servidor web local, na porta 8000. Você pode ir para esse servidor acessando a URL <code>localhost:8000</code> no seu navegador web. Aqui você verá o conteúdo do diretório listado — clique no arquivo HTML que você deseja executar.</p> + </li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Se você já tiver algo em execução na porta 8000, você poderá escolher outra porta executando o comando do servidor seguido por um número de porta alternativo, por exemplo <code>python3 -m http.server 7800</code> (Python 3.x) ou <code>python -m SimpleHTTPServer 7800</code> (Python 2.x). Você pode acessar seu conteúdo em <code>localhost:7800</code>.</p> +</div> + +<h2 id="Executando_linguagens_do_lado_do_servidor_localmente">Executando linguagens do lado do servidor localmente</h2> + +<p>Os módulos <code>SimpleHTTPServer (python 2.0)</code> e <code>http.server (python 3.0)</code> do Python são úteis, mas não sabem como executar código escrito em linguagens como Python, PHP ou JavaScript. Para lidar com isso, você precisará de algo mais — exatamente o que você precisa depende da linguagem do lado do servidor que você está tentando executar. Aqui estão alguns exemplos:</p> + +<ul> + <li>Para executar o código Python no lado do servidor, você precisará usar um framework web em Python. Você pode descobrir como usar o framework Django lendo <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django">Django Web Framework (Python)</a>. O <a href="http://flask.pocoo.org/">Flask</a> (em inglês) também é uma boa alternativa ao Django (um pouco menos pesada). Para executar isso, você precisará <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/development_environment#Installing_Python_3">instalar o Python/PIP</a> e em seguida, instalar o Flask usando <code>pip3 install flask</code>. Neste ponto, você deve ser capaz de executar os exemplos em Python com Flask usando, por exemplo <code>python3 python-example.py</code> e em seguida acessar <code>localhost:5000</code> no seu navegador.</li> + <li>Para executar o código Node.js (JavaScript) no lado do servidor, você precisará usar o nó bruto ou uma estrutura construída sobre ele. Express é uma boa escolha — veja <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Express_Nodejs">Express Web Framework (Node.js/JavaScript)</a>.</li> + <li>Para executar o código PHP no lado do servidor, inicie o <a href="https://www.php.net/manual/pt_BR/features.commandline.webserver.php">servidor de desenvolvimento interno do PHP</a>:</li> +</ul> + +<pre class="shellcode">$ cd path/to/your/php/code +$ php -S localhost:8000</pre> diff --git a/files/pt-br/learn/common_questions/como_voce_hospeda_seu_site_google_app_engine/index.html b/files/pt-br/learn/common_questions/como_voce_hospeda_seu_site_google_app_engine/index.html new file mode 100644 index 0000000000..762169926c --- /dev/null +++ b/files/pt-br/learn/common_questions/como_voce_hospeda_seu_site_google_app_engine/index.html @@ -0,0 +1,61 @@ +--- +title: Como você hospeda seu site no Google App Engine? +slug: Learn/Common_questions/Como_voce_hospeda_seu_site_Google_App_Engine +translation_of: Learn/Common_questions/How_do_you_host_your_website_on_Google_App_Engine +--- +<p class="summary"><a href="https://cloud.google.com/appengine/" title="App Engine - Build Scalable Web & Mobile Backends in Any Language | Google Cloud">Google App Engine</a> é uma plataforma poderosa que lhe permite construir e rodar aplicações na infraestrutura do Google — se você precisa criar um aplicativo da web de várias camadas do zero ou hospedar um site estático. Aqui está um guia passo a passo para hospedar seu site no Google App Engine.</p> + +<h2 id="Criando_um_projeto_na_plataforma_do_Google_Cloud">Criando um projeto na plataforma do Google Cloud</h2> + +<p>Para usar as ferramentas do Google em seu próprio site ou aplicativo, você precisa criar um novo projeto no Google Cloud Platform. Isso requer ter uma conta do Google.</p> + +<ol> + <li>Vá para o <a href="https://console.cloud.google.com/projectselector/appengine">App Engine dashboard</a> no Google Cloud Platform e apert o botão <em>Create</em> (Criar).</li> + <li>Se você não criou um projeto antes, precisará selecionar se deseja receber atualizações por email ou não, concordar com os Termos de Serviço e, em seguida, poderá continuar.</li> + <li>Digite um nome para o projeto, edite a ID do seu projeto e anote-a. Para este tutorial, os seguintes valores são usados + <ul> + <li>Nome do projeto: <em>GAE Sample Site</em></li> + <li>ID do Projeto: <em>gaesamplesite</em></li> + </ul> + </li> + <li>Clique no botão <em>Create</em> para criar o seu projeto.</li> +</ol> + +<h2 id="Criando_uma_aplicação">Criando uma aplicação</h2> + +<p>Cada projeto do Cloud Platform pode conter um aplicativo do App Engine. Vamos preparar um aplicativo para o nosso projeto.</p> + +<ol> + <li>Precisamos de um aplicativo de amostra para publicar. Se você não tiver um para usar, faça o download e descompacte este <a href="http://gaesamplesite.appspot.com/downloads.html">aplicativo de exemplo</a>.</li> + <li> Dê uma olhada na estrutura da aplicação padrão — A pasta <code>website</code> contem o conteúdo do seu website e <code>app.yaml</code> é o seu arquivo de configuração da aplicação. + <ul> + <li>O conteúdo do seu website deve ser posto dentro da pasta <code>website</code>, e sua página de destino deve ser denominada <code>index.html</code>, mas fora isso ela pode conter qualquer coisa que você desejar.</li> + <li>O arquivo <code>app.yaml</code> é um arquivo de configuração que fala ao App Engine como mapear URLs para os seus arquivos estáticos. Você não precisa editá-lo.</li> + </ul> + </li> +</ol> + +<h2 id="Puplicando_sua_aplicação">Puplicando sua aplicação</h2> + +<p>Agora que nós temos o nosso projeto pronto e arquivos padrões de aplicativo colocados juntos, vamos publicar nosso app.</p> + +<ol> + <li>Abra o <a href="https://console.cloud.google.com/cloudshell/editor">Google Cloud Shell</a>.</li> + <li>Arraste e solte a pasta <code>sample-app</code> dentro do painel esquerdo do editor de código.</li> + <li>Rode a seguinte linha de comando dentro para selecionar seu projeto: + <pre class="brush:bash no-line-numbers" style="margin: 1em 0;">gcloud config set project <em>gaesamplesite</em></pre> + </li> + <li>Logo após rode o seguinte comando para ir ao diretório do seu app: + <pre class="brush:bash no-line-numbers" style="margin: 1em 0;">cd <em>sample-app</em></pre> + </li> + <li>Você agora está pronto para armazenar sua aplicação, i.e. fazer o upload para o App Engine: + <pre class="brush:bash no-line-numbers" style="margin: 1em 0;">gcloud app deploy</pre> + </li> + <li>Digite um número para escolher a região onde você quer que sua aplicação se localize.</li> + <li>Digite <code>Y</code> para confirmar.</li> + <li>Agora navegue no seu navegador para <em>your-project-id</em>.appspot.com to para ver seu website online. Por exemplo, para a ID do projeto <em>gaesamplesite</em>, vá para <a href="http://gaesamplesite.appspot.com/"><em>gaesamplesite</em>.appspot.com</a>.</li> +</ol> + +<h2 id="Veja_também">Veja também</h2> + +<p>Para aprender mais, veja <a href="https://cloud.google.com/appengine/docs/">Google App Engine Documentation</a>.</p> diff --git a/files/pt-br/learn/common_questions/ferramentas_de_desenvolvimento_do_navegador/index.html b/files/pt-br/learn/common_questions/ferramentas_de_desenvolvimento_do_navegador/index.html new file mode 100644 index 0000000000..80df8f9ddf --- /dev/null +++ b/files/pt-br/learn/common_questions/ferramentas_de_desenvolvimento_do_navegador/index.html @@ -0,0 +1,221 @@ +--- +title: O que são as ferramentas de desenvolvimento do navegador +slug: Learn/Common_questions/ferramentas_de_desenvolvimento_do_navegador +translation_of: Learn/Common_questions/What_are_browser_developer_tools +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<div class="summary"> +<p>Todo navegador web moderno inclui um poderoso conjunto de ferramentas para desenvolvedores. Essas ferramentas fazem muitas coisas, desde inspecionar o HTML, CSS e JavaScript recém carregado e quais recursos foram requeridos até mostrar quanto tempo a página precisou para carregar. Este artigo explica como usar as funções básicas das ferramentas para desenvolvedores do seu navegador.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Antes de você executar os exemplos abaixo, abra o <a href="http://mdn.github.io/beginner-html-site-scripted/">Beginner's example site</a> (site de exemplos do iniciante) que nós criamos durante o início da série de artigos da Web ( <a href="/en-US/Learn/Getting_started_with_the_web">Getting started with the Web</a> ). Você poderá abrir isso enquanto segue os passos abaixo.</p> +</div> + +<h2 id="Como_abrir_o_devtools_no_seu_navegador">Como abrir o devtools no seu navegador</h2> + +<p>O devtools está inserido no navegador em uma janela semelhante a esta:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9561/Screenshot%20from%202014-11-25%2012:32:57.png" style="display: block; height: 625px; margin: 0px auto; width: 775px;"></p> + +<p>Como você acessa? Três modos:</p> + +<ul> + <li><em><strong>Teclado.</strong></em> <em><kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>I</kbd></em>, exceto: + + <ul> + <li><strong>Internet Explorer.<kbd> </kbd></strong><em><kbd>F12</kbd> </em></li> + <li><strong>Mac OS X. </strong><em><span class="Unicode"><kbd>⌘</kbd> + <kbd>⌥</kbd> +<kbd> I</kbd> </span></em></li> + </ul> + </li> + <li><span class="Unicode"><em><strong>Menu bar. </strong></em></span> + <ul> + <li><strong>Firefox. </strong>Menu <img alt="" src="https://mdn.mozillademos.org/files/9637/2014-01-10-13-08-08-f52b8c.png" style="height: 16px; width: 16px;"> <span class="Unicode"><em><span class="Unicode">➤ <img alt="" src="https://mdn.mozillademos.org/files/9639/Screenshot%20from%202014-11-26%2014:24:56.png" style="height: 40px; width: 45px;"></span></em><em><span class="Unicode">➤ Toggle Tools, </span></em><span class="Unicode">or </span><em>Tools ➤</em></span><em> Web Developer ➤ Toggle Tools</em></li> + <li><strong>Chrome.</strong> <em><span class="Unicode">View ➤</span> Developer ➤ Developer Tools</em></li> + <li><strong>Safari.</strong> <em><span class="Unicode">Develop ➤</span> Show Web Inspector.</em> Se você não consegue ver o <em>menu Desenvolvedor</em> , vá para <em>Safari<span class="Unicode"> ➤</span> Preferências ➤ Avançado</em> e confira o <em>Show Develop menu no menu bar</em> checkbox. </li> + <li><strong>Opera</strong>. <em><span class="Unicode">Developer ➤</span> Web Inspector</em></li> + </ul> + </li> + <li><strong><em>Context menu.</em></strong> Pressione-e-segure/botão-direito no item da webpage (Ctrl-click on the Mac), e escolha <em>Inspect Element no</em> menu de contexto que aparece. (<em>An added bonus: </em>this method straight-away highlights the code of the element you right-clicked.)</li> +</ul> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9605/inspect-element-option.png" style="display: block; height: 264px; margin: 0px auto; width: 350px;"></p> + +<h2 id="O_Inspetor_DOM_explorer_e_editor_CSS">O Inspetor: DOM explorer e editor CSS</h2> + +<p>O devtools usualmente abre por padrão o inspetor, que se parece com a imagem abaixo. Esta ferramenta permite que você veja o resultado do HTML num site em execução, bem como o CSS aplicado en cada elemento na página. Ele também lhe mostra as mudanças efetuadas no HTML e CSS e os resultados são produzidos imediatamente, ao vivo, na janela do navegador.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9607/inspector.png" style="display: block; height: 727px; margin: 0px auto; width: 800px;"></p> + +<p>Se você não vê o inspector,</p> + +<ul> + <li>Clique a aba <em>Inspetor.</em></li> + <li>No Internet Explorer, Clique a aba <em>DOM Explorer, </em>ou pressione <kbd>Ctrl</kbd> +<kbd> 1</kbd>.</li> + <li>No Safari, os controles não são apresentados claramente, mas você poderia ver se não tiver selecionado algo para aparecerna janela. Pressione o botão <em>Style para ver o</em> CSS.</li> +</ul> + +<h3 id="Explore_o_inspector_DOM">Explore o inspector DOM</h3> + +<p>Para começar tente pressionar o botão direito do mouse sobre um elemento HTML no inspetor do DOM e olhe para o menu de contexto. As opções do menu variam nos navegadores, mas os mais importantes são os mesmos.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9609/dev-tool-context-menu.png" style="display: block; height: 236px; margin: 0px auto; width: 200px;"></p> + +<ul> + <li><strong>Delete Node</strong> (às vezes Delete<em> Element</em>). Exclui o elemento atual.</li> + <li><strong>Edit as HTML</strong> (às vezes <em>Add attribute</em>/<em>Edit text</em>). Permite alterar o HTML e ver os resultados na hora. Muito útil para depuração e teste.</li> + <li><strong>:hover/:active/:focus</strong>. Força os estados dos elementos a serem alternados, para que você possa ver como seria seu estilo.</li> + <li><strong>Copy/Copy as HTML</strong>. Copia o HTML atualmente selecionado.</li> + <li>Alguns navegadores também têm Copy CSS Path e Copy XPath available, para permitir que você copie o seletor CSS ou a expressão XPath que selecionaria o elemento HTML atual.</li> +</ul> + +<p>Tente editar alguns dos seus DOM agora. Clique duas vezes em um elemento ou clique com o botão direito do mouse e escolha Editar como HTML no menu de contexto. Você pode fazer alterações que quiser, mas não pode salvar suas alterações.</p> + +<h3 id="Explorando_o_editor_de_CSS">Explorando o editor de CSS</h3> + +<p>Por padrão, o editor CSS exibe as regras CSS aplicadas ao elemento atualmente selecionado:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9631/css-viewer-2.png" style="border: 1px solid black; display: block; height: 218px; margin: 0px auto; width: 326px;"></p> + +<p>Esses recursos são especialmente úteis:</p> + +<ul> + <li>As regras aplicadas ao elemento atual são mostradas em ordem de mais específicas.</li> + <li>Clique nas caixas de seleção ao lado de cada declaração para ver o que aconteceria se você removesse a declaração.</li> + <li>Clique na pequena seta ao lado de cada propriedade abreviada para mostrar os equivalentes de longhand da propriedade.</li> + <li>Clique no nome ou no valor de uma propriedade para exibir uma caixa de texto, na qual você pode digitar um novo valor para obter uma visualização ao vivo de uma alteração de estilo.</li> + <li>Ao lado de cada regra está o nome do arquivo e o número da linha em que a regra está definida. Clicar nessa regra faz com que as ferramentas dev pularem para mostrá-la em sua própria visão, onde geralmente podem ser editadas e salvas.</li> + <li>Você também pode clicar na chave de fechamento de qualquer regra para abrir uma caixa de texto em uma nova linha, onde você pode escrever uma declaração completamente nova para a sua página.</li> +</ul> + +<p>Você notará várias guias clicáveis na parte superior do Visualizador de CSS:</p> + +<ul> + <li><em>Computed</em>: Isso mostra os estilos calculados para o elemento atualmente selecionado (os valores finais normalizados que o navegador aplica).</li> + <li><em>Box model</em>: Isso representa visualmente o modelo de caixa do elemento atual, para que você possa ver rapidamente o preenchimento, a borda e a margem aplicados a ele e o tamanho do conteúdo.</li> + <li><em>Fonts</em>: No Firefox, a guia Fontes mostra as fontes aplicadas ao elemento atual.</li> +</ul> + +<h3 id="Descubra_mais">Descubra mais</h3> + +<p>Descubra mais sobre o Inspetor em diferentes navegadores:</p> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector">Inspetor de páginas do Firefox</a></li> + <li><a href="http://msdn.microsoft.com/en-us/library/ie/dn255008%28v=vs.85%29.aspx">IE DOM Explorer</a></li> + <li><a href="https://developer.chrome.com/devtools/docs/dom-and-styles">Chrome DOM inspector</a> (Inspetor da Opera funciona da mesma forma)</li> + <li><a href="https://developer.apple.com/library/safari/documentation/AppleApplications/Conceptual/Safari_Developer_Guide/ResourcesandtheDOM/ResourcesandtheDOM.html#//apple_ref/doc/uid/TP40007874-CH3-SW1">Inspetor do Safari DOM e explorador de estilo</a></li> +</ul> + +<h2 id="O_depurador_JavaScript">O depurador JavaScript</h2> + +<p>O depurador Javascript permite a visualização dos conteúdos das variáveis e a configuração dos pontos de paradas(breakpoints) no código. Breakpoints são marcadores de linha para analisar a execução do código. A identificação previne problemas.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/16239/firefox_debugger.png" style="border: 1px solid black; display: block; height: 556px; margin: 0 auto; width: 672px;"></p> + +<p>Para acessar o (debugger)depurador:</p> + +<p><strong>Firefox</strong>: Clique<img alt="" src="https://mdn.mozillademos.org/files/9637/2014-01-10-13-08-08-f52b8c.png" style="height: 16px; width: 16px;"> ➤ <em>Web Developer</em> ➤ <em>Debugger</em> ou pelo atalho <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd> para abrir o Debugger Javascript. Se a ferramenta já estiver vísivel, clique na aba <strong>Debugger</strong>.</p> + +<p><strong>Chrome</strong>: Abra as ferramentas de desenvolvimento e selecione a aba Fontes(<strong>Sources)</strong>. (Opera funciona igualmente).</p> + +<p><strong>Edge e Internet Explorer 11</strong>: Aperte <kbd>F12</kbd> então, <kbd>Ctrl</kbd> + <kbd>3</kbd>, ou se a ferramenta já estiver visível, clique na aba Debugger(depurador).</p> + +<p><strong>Safari</strong>: Abra as ferramentas de desenvolvedor e então selecione a aba Debugger(depurador).</p> + +<h3 id="Explorando_o_depurador">Explorando o depurador</h3> + +<p>Há três painéis no Depurador(debugger) no Firefox</p> + +<h4 id="Lista_de_Arquivos">Lista de Arquivos</h4> + +<p>O primeiro painel na parte esquerda contém uma lista de arquivos associado com a página que está sendo depurada(debugging). Selecione o arquivo da seleção. Clique no arquivo para selecionar e visualizar os conteúdos no painel central do Debugger.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/16240/File_List.png" style="border: 1px solid black; display: block; height: 326px; margin: 0 auto; width: 350px;"></p> + +<h4 id="Código_fonte">Código fonte</h4> + +<p>Insira os pontos de parada (breakpoints) onde deseja que a execução pare. Na imagem abaixo, a linha selecionada é a 18 na qual tem um ponto de parada (breakpoint).</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/16241/Source_code.png" style="border: 1px solid black; display: block; height: 251px; margin: 0 auto; width: 400px;"></p> + +<h4 id="Veja_as_expressões_e_pontos_de_paradas">Veja as expressões e pontos de paradas</h4> + +<p>À direita do painel é exibida uma lista de expressões e pontos de paradas adicionadas.</p> + +<p>Na imagem, na primeira seção, <strong>Watch expressions</strong>, mostra a lista de itens e variáveis que foram adicionadas. Expanda a lista para visualizar os valores no vetor. </p> + +<p>Na próxima seção, <strong>Pontos de paradas</strong>, lista os pontos de paradas na página. No arquivo example.js, um breakpoint foi adicionado <code>listItems.push(inputNewItem.value);</code></p> + +<p>As duas seções finais aparecem somente quando o código está executando.</p> + +<p>A seção <strong>Call stack</strong> (chamada na pilha) mostra que o código foi executado para a linha atual. A função manuseia o clique do mouse e o código está pausado no ponto de parada (breakpoint).</p> + +<p>A seção final, <strong>Scopes(escopos)</strong>, mostra os valores visíveis em vários pontos no código. Por exemplo, na imagem abaixo, os objetos disponíveis estão na função addItemClick.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/16242/watch_items.png" style="border: 1px solid black; display: block; height: 743px; width: 350px;"></p> + +<h2 id="O_console_JavaScript">O console JavaScript</h2> + +<p>O console JavaScript é uma ferramenta incrivelmente útil para depurar códigos em JavaScript que não está funcionando como o esperado. Ele permite que você execute linhas de JavaScript enquanto a página é carregada no navegador e relata os erros encontrados enquanto o navegador tenta executar o código.</p> + +<p>Para acessar o console basta abrir ferramentas de desenvolvimentos e escolher a aba Console.</p> + +<p>No Firefox o atalho é <kbd>ctrl</kbd> + <kbd>shift</kbd>+ <kbd>k</kbd> ou no menu comando: <img alt="" src="https://mdn.mozillademos.org/files/9637/2014-01-10-13-08-08-f52b8c.png" style="height: 16px; width: 16px;"> <span class="Unicode"><em><span class="Unicode">➤ Web Developer </span></em><em><span class="Unicode">➤ Web Console, </span></em><span class="Unicode">or </span><em>Tools ➤</em></span><em> Web Developer ➤ Web Console.</em></p> + +<p>Aparecerá uma janela como a seguinte:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9541/console.png" style="border: 1px solid black; display: block; height: 249px; margin: 0px auto; width: 821px;"></p> + +<p>Para ver o que acontece, tente inserir os seguintes trechos de código no console, um por um (e, em seguida, pressione Enter):</p> + +<ol> + <li> + <pre class="brush: js">alert('hello!');</pre> + </li> + <li> + <pre class="brush: js">document.querySelector('html').style.backgroundColor = 'purple';</pre> + </li> + <li> + <pre class="brush: js">var myImage = document.createElement('img'); +myImage.setAttribute('src','https://blog.mozilla.org/press/wp-content/themes/OneMozilla/img/mozilla-wordmark.png'); +document.querySelector('h1').appendChild(myImage);</pre> + </li> +</ol> + +<p>Agora, tente inserir as seguintes versões incorretas do código e veja o que você obtém.</p> + +<ol> + <li> + <pre class="brush: js">alert('hello!);</pre> + </li> + <li> + <pre class="brush: js">document.cheeseSelector('html').style.backgroundColor = 'purple';</pre> + </li> + <li> + <pre class="brush: js">var myImage = document.createElement('img'); +myBanana.setAttribute('src','https://blog.mozilla.org/press/wp-content/themes/OneMozilla/img/mozilla-wordmark.png'); +document.querySelector('h1').appendChild(myImage);</pre> + </li> +</ol> + +<p>Você começará a ver o tipo de erro que o navegador retorna. Muitas vezes, esses erros são bastante críticos, mas deve ser bem simples descobrir esses problemas!</p> + +<h3 id="Descubra_mais_2">Descubra mais</h3> + +<p>Descubra mais sobre o console JavaScript em diferentes navegadores:</p> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Tools/Web_Console">Firefox Web Console</a></li> + <li><a href="http://msdn.microsoft.com/en-us/library/ie/dn255006%28v=vs.85%29.aspx">IE JavaScript console</a></li> + <li><a href="https://developer.chrome.com/devtools/docs/console">Chrome JavaScript Console</a> (O inspetor do Ópera funciona da mesma forma)</li> + <li><a href="https://developer.apple.com/library/safari/documentation/AppleApplications/Conceptual/Safari_Developer_Guide/Console/Console.html#//apple_ref/doc/uid/TP40007874-CH6-SW1">Safari Console</a></li> +</ul> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">Debugging HTML</a></li> + <li><a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Debugging_CSS">Debugging CSS</a></li> +</ul> diff --git a/files/pt-br/learn/common_questions/index.html b/files/pt-br/learn/common_questions/index.html new file mode 100644 index 0000000000..87a576aa29 --- /dev/null +++ b/files/pt-br/learn/common_questions/index.html @@ -0,0 +1,125 @@ +--- +title: Questões comuns +slug: Learn/Common_questions +tags: + - Aprendendo + - Infraestrutura + - Internet + - NeedsTranslation + - TopicStub + - Web + - WebMechanics +translation_of: Learn/Common_questions +--- +<p class="summary">Esta sessão de Área de Aprendizado é voltada para dar respostas à questões comuns que possam surgir, que não necessariamente sejam parte do núcleo dos meios de aprendizado (ex. artigos sobre <a href="/en-US/docs/Learn/HTML">HTML</a> ou <a href="/en-US/docs/Learn/CSS">CSS</a>.) Estes artigos foram feitos para funcionar de forma independente.</p> + +<div> +<h2 id="Questões_sobre_HTML_e_CSS">Questões sobre HTML e CSS</h2> + +<p>Leia <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto">Use HTML to solve common problems</a> (em inglês) e <a href="/en-US/docs/Learn/CSS/Howto">Use CSS to solve common problems</a> (em inglês) para solução de problemas comuns com HTML/CSS.</p> +</div> + +<h2 id="Como_a_Web_funciona">Como a Web funciona?</h2> + +<p>Esta seção cobre a mecânica da Web —questões relacionadas a conhecimentos gerais sobre o ecossistema da Web e como ele funciona.</p> + +<dl> + <dt> + <h3 id="Como_a_Internet_funciona"><a href="/pt-BR/docs/Learn/Common_questions/Como_a_internet_funciona">Como a Internet funciona?</a></h3> + </dt> + <dd>A <strong>Internet</strong> é a espinha dorsal da Web, a infraestrutura técnica que faz a Web possível. Mais basicamente, a Internet é uma gigantesca rede de computadores que se comunicam juntos. Este artigo discute o básico sobre o funcionamento da Internet.</dd> + <dt> + <h3 id="Qual_a_diferença_entre_webpage_website_web_server_and_search_engine"><a href="/en-US/docs/Learn/Common_questions/Pages_sites_servers_and_search_engines">Qual a diferença entre webpage, website, web server, and search engine?</a></h3> + </dt> + <dd>Nesse artigo nós descrevemos vários conceitos relaciona a Web: webpages, websites, Web servers, and search engines. Esses termos são frequentemente confundidos por iniciantes na web, ou são utizados de maneira incorreta. Vamos entender o que eles realmente significam!</dd> + <dt> + <h3 id="O_que_é_uma_URL"><a href="/en-US/docs/Learn/Common_questions/What_is_a_URL">O que é uma URL?</a></h3> + </dt> + <dd>Com {{Glossary("Hypertext")}} e {{Glossary("HTTP")}}, URL é um conceito-chave quando se trata da Internet. Ele é um mecanimos utilizado pelos {{Glossary("Navegador","navegadores")}} para recuperar qualquer recurso publicado na Web</dd> + <dt> + <h3 id="O_que_é_um_domain_name"><a href="/en-US/docs/Learn/Common_questions/What_is_a_domain_name">O que é um domain name?</a></h3> + </dt> + <dd>Domain names eles são uma parte essencial para a infraestrutura da internet. Eles deixam o endereço legivel por humanos para qualquer Web server disponivel na internet.</dd> + <dt> + <h3 id="O_que_é_um_web_server"><a href="/en-US/docs/Learn/Common_questions/What_is_a_web_server">O que é um web server?</a></h3> + </dt> + <dd>O termo "Web server" pode se referir ao hardware ou ao software que serve sites para clientes na Web — ou ambos deles trabalhando juntos. Nesse artigo nós veremos como Web servers funcionam, e porque eles são importantes.</dd> + <dt> + <h3 id="O_que_são_hyperlinks"><a href="/en-US/docs/Learn/Common_questions/What_are_hyperlinks">O que são hyperlinks?</a></h3> + </dt> + <dd>Nesse artigo, nós veremos do que são hypelinks e porque eles importam.</dd> +</dl> + +<h2 id="Tools_and_setup">Tools and setup</h2> + +<p>Questions related to the tools/software you can use to build websites.</p> + +<dl> + <dt> + <h3 id="How_much_does_it_cost_to_do_something_on_the_Web"><a href="/en-US/docs/Learn/Common_questions/How_much_does_it_cost">How much does it cost to do something on the Web?</a></h3> + </dt> + <dd>When you're launching a website, you may spend nothing or your costs may go through the roof. In this article we discuss how much everything costs and what you get for what you pay (or don't pay).</dd> + <dt> + <h3 id="What_software_do_I_need_to_build_a_website"><a href="/en-US/docs/Learn/Common_questions/What_software_do_I_need">What software do I need to build a website?</a></h3> + </dt> + <dd>In this article we explain which software components you need when you're editing, uploading, or viewing a website.</dd> + <dt> + <h3 id="What_text_editors_are_available"><a href="/en-US/docs/Learn/Common_questions/Available_text_editors">What text editors are available?</a></h3> + </dt> + <dd>In this article we highlight some things to think about when choosing and installing a text editor for web development.</dd> + <dt> + <h3 id="How_do_I_set_up_a_basic_working_environment"><a href="/en-US/docs/Learn/Common_questions/Set_up_a_basic_working_environment">How do I set up a basic working environment?</a></h3> + </dt> + <dd>When working on a web project, you'll want to test it locally before you show it to the world. Some types of code require a server to test, and in this article we'll show you how to set one up. We'll also cover how to put a scalable structure in place so that your files stay organized even when your project gets big.</dd> + <dt> + <h3 id="What_are_browser_developer_tools"><a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">What are browser developer tools?</a></h3> + </dt> + <dd>Every browser features a set of devtools for debugging HTML, CSS, and other web code. This article explains how to use the basic functions of your browser's devtools.</dd> + <dt> + <h3 id="How_do_you_make_sure_your_website_works_properly"><a href="/en-US/docs/Learn/Common_questions/Checking_that_your_web_site_is_working_properly">How do you make sure your website works properly?</a></h3> + </dt> + <dd>So you've published your website online — very good! But are you sure it works properly? This article provides some basic troubleshooting steps.</dd> + <dt> + <h3 id="How_do_you_upload_files_to_a_web_server"><a href="/en-US/docs/Learn/Common_questions/Upload_files_to_a_web_server">How do you upload files to a web server?</a></h3> + </dt> + <dd>This article shows how to publish your site online with <a class="glossaryLink" href="https://developer.mozilla.org/en-US/docs/Glossary/FTP" title="FTP: FTP (File Transfer Protocol) is the standard network protocol for transferring files from one host to another over the Internet through TCP.">FTP</a> tools — one fo the most common ways to get a website online so others can access it from their computers.</dd> + <dt> + <h3 id="How_do_I_use_GitHub_Pages"><a href="/en-US/docs/Learn/Common_questions/Using_GitHub_Pages">How do I use GitHub Pages?</a></h3> + </dt> + <dd>This article provides a basic guide to publishing content using GitHub's gh-pages feature.</dd> + <dt> + <h3 id="How_do_you_host_your_website_on_Google_App_Engine"><a href="/en-US/Learn/Common_questions/How_do_you_host_your_website_on_Google_App_Engine">How do you host your website on Google App Engine?</a></h3> + </dt> + <dd>Looking for a place to host your website? Here's a step-by-step guide to hosting your website on Google App Engine.</dd> + <dt> + <h3 id="What_tools_are_available_to_debug_and_improve_website_performance"><a href="/en-US/docs/Tools/Performance">What tools are available to debug and improve website performance?</a></h3> + </dt> + <dd>This set of articles shows you how to use the Developer Tools in Firefox to debug and improve performance of your website, using the tools to check the memory usage, the JavaScript call tree, the amount of DOM nodes being rendered, and more.</dd> +</dl> + +<h2 id="Design_and_accessibility">Design and accessibility</h2> + +<p>This section lists questions related to aesthetics, page structure, accessibility techniques, etc.</p> + +<dl> + <dt> + <h3 id="How_do_I_start_to_design_my_website"><a href="/en-US/docs/Learn/Common_questions/Thinking_before_coding">How do I start to design my website?</a></h3> + </dt> + <dd>This article covers the all-important first step of every project: define what you want to accomplish with it.</dd> + <dt> + <h3 id="What_do_common_web_layouts_contain"><a href="/en-US/docs/Learn/Common_questions/Common_web_layouts">What do common web layouts contain?</a></h3> + </dt> + <dd>When designing pages for your website, it's good to have an idea of the most common layouts. This article runs thorugh some typical web layouts, looking at the parts that make up each one.</dd> + <dt> + <h3 id="What_is_accessibility"><a href="/en-US/docs/Learn/Common_questions/What_is_accessibility">What is accessibility?</a></h3> + </dt> + <dd>This article introduces the basic concepts behind web accessibility.</dd> + <dt> + <h3 id="How_can_we_design_for_all_types_of_users"><a href="/en-US/docs/Learn/Common_questions/Design_for_all_types_of_users">How can we design for all types of users?</a></h3> + </dt> + <dd>This article provides basic techniques to help you design websites for any kind of user — quick accessibility wins, and other such things.</dd> + <dt> + <h3 id="What_HTML_features_promote_accessibility"><a href="/en-US/docs/Learn/Common_questions/HTML_features_for_accessibility">What HTML features promote accessibility?</a></h3> + </dt> + <dd>This article describes specific features of HTML that can be used to make a web page more accessible to people with different disabilities.</dd> +</dl> diff --git a/files/pt-br/learn/common_questions/o_que_e_um_web_server/index.html b/files/pt-br/learn/common_questions/o_que_e_um_web_server/index.html new file mode 100644 index 0000000000..f963103480 --- /dev/null +++ b/files/pt-br/learn/common_questions/o_que_e_um_web_server/index.html @@ -0,0 +1,121 @@ +--- +title: O que é um servidor web (web server)? +slug: Learn/Common_questions/o_que_e_um_web_server +tags: + - HTTP + - Infraestrutura + - Iniciante + - servidor web +translation_of: Learn/Common_questions/What_is_a_web_server +--- +<div class="summary"> +<p>Neste artigo vamos revisar o que são web servers, como eles funcionam, e por que eles são importantes.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Você deve saber <a href="/pt-BR/docs/Learn/Common_questions/Como_a_internet_funciona">como a Internet funciona</a> e <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Common_questions/Pages_sites_servers_and_search_engines">entender a diferença entre uma página web, um site, um servidor web e um mecanismo de busca</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Você irá aprender o que é um servidor web e compreender de modo geral como ele funciona.</td> + </tr> + </tbody> +</table> + +<h2 id="Sumário">Sumário</h2> + +<p>"Servidor web (<em>web server</em>)" pode referir ao hardware ou ao software, ou ambos trabalhando juntos.</p> + +<ol> + <li>Referente ao hardware, um servidor web é um computador que armazena arquivos que compõem os sites (por exemplo, documentos HTML, imagens, folhas de estilo, e arquivos JavaScript) e os entrega para o dispositivo do usuário final. Está conectado a Internet e pode ser acessado através do seu nome de domínio (DNS), como por exemplo <code>mozilla.org</code>.</li> + <li>Referente ao software, um servidor web inclui diversos componentes que controlam como os usuários acessam os arquivos hospedados (armazenados para disponibilização), no mínimo um <em>servidor HTTP. </em>Um servidor HTTP é um software que compreende {{Glossary("URL","URLs")}} (endereços web) e {{Glossary("HTTP")}} (o protocolo que seu navegador utiliza para visualizar páginas web.</li> +</ol> + +<p>Em um nível mais básico, o navegador fará uma requisição utilizando o protocolo HTTP sempre que necessitar de um um arquivo hospedado em um servidor web. Quando a requisição alcançar o servidor web correto (hardware), o <em>servidor HTTP </em>(software) enviará o documento requerido, também via HTTP.</p> + +<p><img alt="Basic representation of a client/server connection through HTTP" src="https://mdn.mozillademos.org/files/8659/web-server.svg" style="height: 200px; width: 600px;"></p> + +<p>Para publicar um website, é necessário ou um servidor web estático ou um dinâmico.</p> + +<p>Um <strong>servidor web estático</strong> consiste em um computador (hardware) com um servidor HTTP (software). É chamado "estático" porque o servidor envia seus arquivos tal como foram criados e armazenados (hospedados) ao navegador.</p> + +<p>Um <strong>servidor web dinâmico</strong> consiste em um servidor web estático com software adicional, mais comumente um servidor de aplicações (<em>application server) </em>e um banco de dados (<em>database). </em>É chamado "dinâmico" porque o servidor de aplicações atualiza os arquivos hospedados antes de enviá-los ao navegador através do servidor HTTP.</p> + +<p>Por exemplo, para produzir as páginas finalizadas que você vê em seu navegador, o servidor de aplicações pode completar um modelo de página HTML (<em>HTML template</em>) com o conteúdo obtido de um banco de dados. Sites como o MDN ou a Wikipédia possuem vários milhares de páginas web, mas elas não são realmente documentos HTML, mas apenas alguns poucos <em>templates</em> HTML e uma gigantesca base de dados. Essa configuração agiliza e facilita o gerenciamento e a entrega do conteúdo.</p> + +<h2 id="Aprendizado_ativo">Aprendizado ativo</h2> + +<p><em>Ainda não há aprendizado ativo disponível. <a href="https://developer.mozilla.org/en-US/docs/MDN/Getting_started">Por favor, considere contribuir</a>.</em></p> + +<h2 id="Entrando_a_fundo">Entrando a fundo</h2> + +<p>Para carregar uma página <em>web</em>, como já foi dito, seu <em>browser</em> envia uma requisição ao servidor <em>web</em>, que busca pelo arquivo requisitado no seu próprio espaço de armazenamento. Ao encontrar o arquivo, o servidor <em>web</em> realiza a leitura, faz os processamentos necessários e o envia ao <em>browser</em>. Vamos olhar mais detalhamente para essas etapas.</p> + +<h3 id="Servindo_arquivos">Servindo arquivos</h3> + +<p>Um servidor <em>web</em> precisa primeiro armazenar os arquivos dos <em>websites</em>, como todos os documentos HTML e seus <em>assets</em>, que incluem imagens, páginas de estilo CSS, arquivos JavaScript, fontes e vídeos.</p> + +<p>Técnicamente, você pode servir todos esses arquivos em seu próprio computador. Mas, é muito mais conveniente armazená-los em um servidor web dedicado que</p> + +<ul> + <li>está sempre "vivo" e rodando</li> + <li>está sempre conectado à Internet</li> + <li>tem o mesmo endereço IP sempre (nem todos {{Glossary("ISP", "ISPs")}} fornecem um endereço IP fixo para linhas domésticas)</li> + <li>é mantido por um provedor de terceiros</li> +</ul> + +<p>Por todas essas razões, encontrar um bom provedor de servidores é a chave para criar seu próprio <em>website</em>. Pesquise pelos vários serviços oferecidos e escolha aquele que melhor se alinha às suas necessidades e ao bolso (os serviçoes variam em uma faixa desde zero até milhares de dólares por mês). Você pode encontrar mais detalhes <a href="https://developer.mozilla.org/en-US/Learn/How_much_does_it_cost#Hosting">nesse artigo</a>.</p> + +<p>Uma vez que você escolheu uma solução de servidores web, você só precisa <a href="/en-US/docs/Learn/Upload_files_to_a_web_server">fazer o <em>upload</em> dos seus arquivos para o servidor <em>web</em></a>.</p> + +<h3 id="Comunicando_através_do_HTTP">Comunicando através do HTTP</h3> + +<p>Segundo, um servidor web fornece suporte para {{Glossary("HTTP")}} (protocolo de transferência de hipertexto). Como o próprio nome indica, o HTTP especifica como transferir arquivos de hipertexto (ou seja, documentos vinculados da web) entre dois computadores.</p> + +<p>Um <em>protocolo </em>é um conjunto de regras para comunicação entre dois computadores. HTTP é um protocolo textual sem estado.</p> + +<dl> + <dt>Textual</dt> + <dd>Todos os comandos são de texto simples e legíveis por humanos.</dd> + <dt>Sem estado</dt> + <dd>Nem o servidor nem o cliente lembram de comunicações anteriores. Por exemplo, confiando apenas no HTTP, um servidor não consegue se lembrar de uma senha digitada ou da etapa em que você está em uma transação. Você precisa de um servidor de aplicativos para tarefas como essa. (Nós vamos cobrir esse tipo de tecnologia em mais artigos.)</dd> +</dl> + +<p>O HTTP fornece regras claras sobre como um cliente e um servidor se comunicam. Abordaremos o próprio HTTP em um artigo técnico mais adiante. Por enquanto, apenas fique atento a estas coisas:</p> + +<ul> + <li>Somente <em>clientes </em>podem fazer requisições HTTP, e somente para <em>servidores. </em>Servidores podem apenas<em> responder</em> a uma requisição HTTP dos <em>clientes</em>.</li> + <li>Quando fizer a requisição de um arquivo via HTTP, os clientes devem fornecer a {{Glossary("URL")}} do arquivo.</li> + <li>O servidor web <em>deve responder </em>todas as requisições HTTP, mesmo que seja com uma mensagem de erro.</li> +</ul> + +<p><a href="https://developer.mozilla.org/en-US/404"><img alt="The MDN 404 page as an example of such error page" src="https://mdn.mozillademos.org/files/8661/mdn-404.jpg" style="float: right; height: 300px; width: 300px;"></a>Em um servidor web, o servidor HTTP é responsável por processar e responder as requisições recebidas.</p> + +<ol> + <li>Ao receber uma requisição, um servidor HTTP primeiramente confirma se a URL requisitada corresponde ao arquivo existente.</li> + <li>Se confirmar, o servidor web envia o conteúdo do arquivo de volta ao navegador. Senão, o servidor de aplicações cria o arquivo necessário.</li> + <li>Se nenhum dos processos for possível, o servidor web retorna uma mensagem de erro ao navegador, mais conhecido como "404 Not Found". (Esse erro é tão comum que muitos desevolvedores web passam um bom tempo criando <a href="http://www.404notfound.fr/" rel="external">páginas de erro do 404</a>.)</li> +</ol> + +<h3 id="Conteúdo_estático_vs._dinâmico">Conteúdo estático vs. dinâmico</h3> + +<p>A grosso modo, um servidor pode fornecer tanto um conteúdo estático quanto dinâmico. "Estático" significa "da forma que está". Websites estáticos são os mais fáceis de configurar, então sugerimos que faça seu primeiro site estático.</p> + +<p>"Dinâmico" significa que o servidor processa o conteúdo ou o gera a partir de um banco de dados. Essa solução fornece mais flexibilidade, mas a arquitetura fica mais difícil de lidar, fazendo com que seja dramaticamente mais complexo desenvolver o website.</p> + +<p>Veja por exemplo a página na qual está lendo agora. No servidor web que a hospeda, há um servidor de aplicações que pega o conteúdo do artigo de um banco de dados, o formata, coloca dentro de um template HTML e lhe envia o resultado. Nesse caso, o servidor de aplicações é chamado de <a href="/en-US/docs/MDN/Kuma">Kuma</a> e é desevolvido em <a href="https://www.python.org/">Python</a> (usando o framework <a href="https://www.djangoproject.com/">Django</a> ). A equipe da Mozilla desenvolveu o Kuma devido a necessidades específicas do MDN, mas há muitas aplicações similares em muitas outras tecnologias..</p> + +<p>Existem tantos servidores de aplicações que é muito difícil sugerir algum em particular. Alguns servidores de aplicações atendem à categorias específicas de websites como blogs, wikis ou lojas virtuais. Outros, os chamados {{Glossary("CMS", "CMSs")}} (sistemas de gerenciamento de conteúdo), são mais genéricos. Se estiver desenvolvendo um website dinâmico, reserve um tempo para escolher uma ferramenta que atenda às suas necessidades. A menos que queria aprender sobre o desenvolvimento de um servidor web (que é uma área interessante por si só!), não há necessidade de criar seu próprio servidor de aplicação. Estará apenas reinventando a roda.</p> + +<h2 id="Próximos_passos">Próximos passos</h2> + +<p>Agora que está familiarizado com os servidores web, você pode:</p> + +<ul> + <li>ler sobre <a href="/en-US/docs/Learn/How_much_does_it_cost">quanto custa desenvolver para a web</a> (em inglês)</li> + <li>aprender mais sobre os <a href="/en-US/docs/Learn/What_software_do_I_need">vários softwares necessários para criar um site</a> (em inglês)</li> + <li>partir para a prática de <a href="/en-US/docs/Learn/Upload_files_to_a_web_server">como fazer o upload de arquivos em um servidor web</a> (em inglês).</li> +</ul> diff --git a/files/pt-br/learn/common_questions/o_que_são_hyperlinks/index.html b/files/pt-br/learn/common_questions/o_que_são_hyperlinks/index.html new file mode 100644 index 0000000000..5cfb905389 --- /dev/null +++ b/files/pt-br/learn/common_questions/o_que_são_hyperlinks/index.html @@ -0,0 +1,91 @@ +--- +title: O que são hyperlinks? +slug: Learn/Common_questions/O_que_são_hyperlinks +translation_of: Learn/Common_questions/What_are_hyperlinks +--- +<div class="summary"> +<p>Neste artigo, veremos o que são hiperlinks e por que eles são importantes.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré requisitos:</th> + <td>Você deve saber <a href="/en-US/Learn/How_the_Internet_works">como a Internet funciona </a>e estar familiarizado com<a href="/en-US/docs/Learn/page_vs_site_vs_server_vs_search_engine"> a diferença entre uma página da web, um site, um servidor da web e um mecanismo de pesquisa</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprenda sobre links na Web e por que eles são importantes.</td> + </tr> + </tbody> +</table> + +<h2 id="Sumário">Sumário</h2> + +<p>Hyperlinks, geralmente chamados de links, são um conceito fundamental da Web. Para explicar o que são links, precisamos voltar ao básico da arquitetura da Web.</p> + +<p>Em 1989, Tim Berners-Lee, o inventor da Web, falou sobre os três pilares sobre os quais a Web se sustenta:</p> + +<ol> + <li>"URL", um sistema de endereços que mantém o controle de documentos da Web;</li> + <li>"HTTP", um protocolo de transferência para encontrar documentos ao receber seus URLs;</li> + <li>"HTML", um formato de documento que permite incorporar <em>hyperlinks;</em></li> +</ol> + +<p>Como você pode ver nos três pilares, tudo na Web gira em torno de documentos e como acessá-los. O propósito original da Web era fornecer uma maneira fácil de acessar, ler e navegar por documentos de texto. Desde então, a Web evoluiu para fornecer acesso a imagens, vídeos e dados binários, mas essas melhorias dificilmente mudaram os três pilares.</p> + +<p>Antes da Web, era muito difícil acessar documentos e passar de um para outro. Por serem legíveis por humanos, os URLs já tornaram as coisas mais fáceis, mas é difícil digitar um URL longo sempre que você deseja acessar um documento. Foi aqui que os hiperlinks revolucionaram tudo. Os links podem correlacionar qualquer string de texto com um URL, de forma que o usuário possa acessar instantaneamente o documento de destino ativando o link.</p> + +<p>Os links se destacam do texto ao redor por serem sublinhados e em azul. Toque ou clique em um link para ativá-lo ou, se usar um teclado, pressione Tab até que o link esteja em foco e pressione Enter ou a barra de espaço.</p> + +<p><img alt="Example of a basic display and effect of a link in a web page" src="https://mdn.mozillademos.org/files/8625/link-1.png" style="height: 492px; width: 477px;"></p> + +<p>Os links são o avanço que tornou a Web tão útil e bem-sucedida. No restante deste artigo, discutiremos os vários tipos de links e sua importância para o design moderno da Web.</p> + +<h2 id="Mergulho_Profundo">Mergulho Profundo</h2> + +<p>Como dissemos, um link é uma string de texto ligada a uma URL e usamos links para permitir um salto fácil de um documento para outro. Dito isso, existem algumas nuances que vale a pena considerar:</p> + +<h3 id="Tipos_de_links">Tipos de links</h3> + +<dl> + <dt>Link interno</dt> + <dd>Um link entre duas páginas da web, em que ambas as páginas pertencem ao mesmo site, é chamado de link interno. Sem links internos, não existe site (a menos, é claro, que seja um site de uma página).</dd> + <dt>Link externo</dt> + <dd>Um link de sua página da web para a página de outra pessoa. Sem links externos, não há Web, pois a Web é uma rede de páginas da web. Use links externos para fornecer informações além do conteúdo disponível em sua página da web.</dd> + <dt>Links de entrada</dt> + <dd>Um link da página de outra pessoa para o seu site. É o oposto de um link externo. Observe que você não precisa vincular de volta quando alguém se vincula ao seu site.</dd> +</dl> + +<p>Ao construir um site, concentre-se nos links internos, pois eles tornam seu site utilizável. Encontre um bom equilíbrio entre ter muitos links e poucos. Falaremos sobre como projetar a navegação do site em outro artigo, mas como regra, sempre que você adicionar uma nova página da web, certifique-se de que pelo menos uma das outras páginas tenha um link para essa nova página. Por outro lado, se seu site tiver mais de dez páginas, é contraproducente vincular a todas as páginas a partir de todas as outras.</p> + +<p>Quando você está começando, não precisa se preocupar tanto com links externos e recebidos, mas eles são muito importantes se você deseja que os mecanismos de pesquisa encontrem seu site (veja abaixo para mais detalhes).</p> + +<h3 id="Âncoras">Âncoras</h3> + +<p>Muitos links unem duas páginas da web. <strong>Âncoras </strong>amarrar duas seções de um documento. Quando você segue um link que aponta para uma âncora, seu navegador salta para outra parte do documento atual em vez de carregar um novo documento. No entanto, você cria e usa âncoras da mesma forma que outros links.</p> + +<p><img alt="Example of a basic display and effect of an anchor in a web page" src="https://mdn.mozillademos.org/files/8627/link-2.png" style="height: 492px; width: 477px;"></p> + +<h3 id="Links_e_Mecanismos_de_pesquisa">Links e Mecanismos de pesquisa</h3> + +<p>Os links são importantes tanto para os usuários quanto para os mecanismos de pesquisa. Sempre que os mecanismos de pesquisa rastreiam uma página da web, eles indexam o site seguindo os links disponíveis na página. Os mecanismos de pesquisa não apenas seguem os links para descobrir as várias páginas do site, mas também usam o texto visível do link para determinar quais consultas de pesquisa são apropriadas para chegar à página da web de destino.</p> + +<p>Os links influenciam a rapidez com que um mecanismo de pesquisa se vincula ao seu site. O problema é que é difícil medir as atividades dos mecanismos de pesquisa. As empresas desejam naturalmente que seus sites tenham uma classificação elevada nos resultados de pesquisa. Sabemos o seguinte sobre como os mecanismos de pesquisa determinam a classificação de um site:</p> + +<ul> + <li>O <em> texto visível </em> de um link influencia quais consultas de pesquisa encontrarão um determinado URL.</li> + <li>Quanto mais <em> links de entrada </em> uma página da web pode mostrar, melhor ela se classifica nos resultados de pesquisa.</li> + <li><em>Links externos </em> influenciam a classificação de pesquisa das páginas da web de origem e de destino, mas não está claro quanto.</li> +</ul> + +<p><a href="http://en.wikipedia.org/wiki/Search_engine_optimization">SEO</a> (search engine optimization) é o estudo de como fazer com que os sites tenham uma classificação elevada nos resultados de pesquisa. Melhorar o uso de links em um site é uma técnica de SEO útil.</p> + +<h2 id="Próximos_Passos">Próximos Passos</h2> + +<p>Agora você vai querer configurar algumas páginas da web com links.</p> + +<ul> + <li>Para obter mais informações teóricas, aprenda sobre <a href="/en-US/docs/Learn/Common_questions/What_is_a_URL">URLs e sua estrutura</a>, já que cada link aponta para um URL.</li> + <li>Quer algo um pouco mais prático? O <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">Criando hyperlinks</a> <em>(em inglês)</em>, artigo da nossa <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introdução ao HTML </a><em>(em inglês)</em>, explica como implementar links em detalhes.</li> +</ul> diff --git a/files/pt-br/learn/common_questions/pages_sites_servers_and_search_engines/index.html b/files/pt-br/learn/common_questions/pages_sites_servers_and_search_engines/index.html new file mode 100644 index 0000000000..1e92399a64 --- /dev/null +++ b/files/pt-br/learn/common_questions/pages_sites_servers_and_search_engines/index.html @@ -0,0 +1,123 @@ +--- +title: 'Qual a diferença entre página web, site, servidor web e mecanismo de busca?' +slug: Learn/Common_questions/Pages_sites_servers_and_search_engines +tags: + - Iniciante + - Mecânica da Web + - Precisa de Aprendizagem Ativa +translation_of: Learn/Common_questions/Pages_sites_servers_and_search_engines +--- +<div class="summary"> +<p><span class="seoSummary">Neste artigo, iremos apresentar diversos conceitos relacionados à Web: páginas web, sites, servidores web e mecanismos de busca. Estes termos são confundidos frequentemente por iniciantes na web, ou são empregados de forma incorreta. Vamos aprender o que cada um significa! </span></p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Você deverá conhecer <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Common_questions/Como_a_internet_funciona">como a Internet funciona</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Tornar o leitor apto a descrever as diferenças entre uma página web, um site, um servidor web e um mecanismo de busca.</td> + </tr> + </tbody> +</table> + +<h2 id="Sumário">Sumário</h2> + +<p>Como qualquer outra área do conhecimento, a web possui um grande número de jargões. Não se preocupe, nós não iremos te sobrecarregar com todos eles (temos um <a href="https://developer.mozilla.org/pt-BR/docs/Glossario">glossário</a> se você estiver curioso). Todavia, existem alguns termos básicos que você precisa conhecer inicialmente, já que você sempre ouvirá estas expressões enquanto estiver lendo sobre o assunto. É muito fácil confundir tais termos ocasionalmente, uma vez que eles se referem a funcionalidades relacionadas porém diferentes. Na verdade, às vezes você verá esses termos mal utilizados nos noticiários e em outros lugares, portanto, misturá-los é compreensível.</p> + +<p>Cobriremos esses termos e tecnologias com mais detalhes à medida que exploramos mais, mas essas definições rápidas serão um ótimos começo para você:</p> + +<dl> + <dt>página web</dt> + <dd>Um documento que pode ser mostrado em um navegador web como Firefox, Google Chrome, Opera, Microsoft Internet Explorer ou Edge, ou Safari da Apple. Tais documentos também podem ser referenciados apenas por "páginas".</dd> + <dt>site</dt> + <dd>Um conjunto de páginas web agrupadas juntas e geralmente conectadas juntas de diversas formas. Também conhecido como "web site" ou simplesmente "site".</dd> + <dt>servidor web</dt> + <dd>Um computador que hospeda um site na Internet.</dd> + <dt>mecanismo de busca</dt> + <dd>Um serviço da web que te auxilia a encontrar outras páginas da web, como o Google, o Bing, o Yahoo ou o DuckDuckGo. Os motores de busca são normalmente acessados através de um navegador da web (por exemplo, você pode realizar pesquisas em mecanismos de busca diretamente na barra de endereços do Firefox, Chrome, etc.) ou através de uma página da web (por exemplo, <a href="https://www.bing.com/">bing.com</a> ou <a href="https://duckduckgo.com/">duckduckgo.com</a>).</dd> +</dl> + +<p>Vamos ver uma analogia simples - uma biblioteca pública. Isto é o que você geralmente faria ao visitar uma biblioteca:</p> + +<ol> + <li>Procura no índice de buscas e verifica o título do livro que você deseja.</li> + <li>Anota o número de catálogo do livro desejado.</li> + <li>Se dirige à seção particular que contém o livro, encontra o número catalográfico correto, e então apanha o livro.</li> +</ol> + +<p>Comparemos a biblioteca com um servidor web:</p> + +<ul> + <li>A biblioteca é como um servidor web. Ela possui muitas seções, tal qual um servidor hospedando múltiplos websites.</li> + <li>As diferentes seções (Ciências, Matemática, História, etc.) na biblioteca são como os sites. Cada seção é como um único site (duas seções não conterão os mesmos livros).</li> + <li>Os livros em cada seção correspondem às páginas web. Um website pode conter diversas páginas, por exemplo, na seção de Ciências (o site) terá livros sobre calor, som, termodinâmica, estática, etc. (as páginas web). As páginas da web podem ser encontradas em um local exclusivo (URL).</li> + <li>O índice de buscas é como o mecanismo de busca. Cada livro possui sua própria localização exclusiva na biblioteca (dois livros não podem ser armazenados no mesmo local), o que é especificado pelo código catalográfico.</li> +</ul> + +<dl> +</dl> + +<h2 id="Aprendizado_ativo">Aprendizado ativo</h2> + +<p><em>Ainda não há nenhum aprendizado ativo. <a href="https://developer.mozilla.org/pt-BR/docs/MDN/Primeiros_Passos">Por favor, considere fazer uma contribuição</a>.</em></p> + +<h2 id="Imersão_a_Fundo">Imersão a Fundo</h2> + +<p>Bem, então vamos escavar um pouco mais a fundo sobre estes quatro termos, em como se inter-relacionam e por qual motivo são, ocasionalmente, confundidos entre si.</p> + +<h3 id="Página_web">Página web</h3> + +<p>Uma <strong>página web </strong>é simplesmente um documento que é renderizado ("mostrado") por um <a href="https://developer.mozilla.org/pt-BR/docs/Glossario/Navegador">navegador</a>. Tais documentos são escritos com uso da linguagem {{Glossary("HTML")}} (a qual iremos ver em maiores detalhes em <a href="https://developer.mozilla.org/pt-BR/docs/Web/HTML">outros artigos</a>). Uma página web pode possuir uma variedade de diferentes tipos de recursos incorporados a ela, como:</p> + +<ul> + <li><em>informação de estilo </em>— controlando como a página se apresenta e se comporta (<em>look-and-feel</em>)</li> + <li><em>scripts</em> — os quais são responsáveis por adicionar interatividade à página</li> + <li><em>mídia</em> — imagens, sons e vídeos.</li> +</ul> + +<div class="note"> +<p><strong>Nota: </strong>Navegadores também são capazes de renderizar outros documentos, como arquivos {{Glossary("PDF")}} ou imagens, porém o termo <strong>página web </strong>se refere especificamente a documentos HTML. Todavia, usaremos apenas o termo <strong>documento</strong>.</p> +</div> + +<p>Todas as páginas web disponíveis na web são alcançáveis através de um único endereço. Para acessar uma página, basta digitar seu endereço na barra de endereços do seu navegador:</p> + +<p style="text-align: center;"><img alt="Example of a web page address in the browser address bar" src="https://mdn.mozillademos.org/files/8529/web-page.jpg" style="height: 239px; width: 650px;"></p> + +<h3 id="Site">Site</h3> + +<p>Um <em>site</em> é um conjunto de páginas web vinculadas (mais os recursos associados a elas) que compartilham um único nome de domínio. Cada página web de um dado website provê links explícitos - na maior parte do tempo na forma de texto clicável - que possibilitam a um usuário mover-se de uma página do website à outra.</p> + +<p>Para acessar um website, digite o nome de domínio na barra de endereço do seu navegador, e então o navegador irá mostrar a página web principal daquele website, ou a <em>homepage</em> (casualmente referenciada como "a <em>home</em>").</p> + +<p><img alt="Example of a web site domain name in the browser address bar" src="https://mdn.mozillademos.org/files/8531/web-site.jpg" style="display: block; height: 365px; margin: 0px auto; width: 650px;"></p> + +<p>Os conceitos de página web e de website são especialmente fáceis de se confundir quando um <em>website </em>possui apenas uma <em>página web</em>. Websites com esta característica são ocasionalmente chamados de <em>websites de página única </em>(<em>single-page website</em>).</p> + +<h3 id="Servidor_web">Servidor web</h3> + +<p>Um <em>servidor </em><em>web </em>nada mais é que um computador hospedando um ou mais <em>websites</em>. "Hospedar" significa que todas as <em>páginas web </em>e seus arquivos auxiliares estão disponíveis a partir daquele computador. O <em>servidor web </em>enviará qualquer <em>página web </em>a partir do <em>website </em>que está hospedado nele para o navegador de qualquer usuário que o tenha requisitado (feito uma <em>requisição</em>).</p> + +<p>Não confunda <em>websites </em>e <em>servidores</em>. Por exemplo, caso você ouça alguém dizer: "Meu website não está respondendo", isto atualmente significa que o <em>servidor web </em>não está respondendo, logo o <em>website </em>encontra-se indisponível. Mais importante, uma vez que um único servidor web é capaz de hospedar múltiplos <em>websites</em>, o termo <em>servidor web </em>nunca deve ser empregado para se referir a um website, uma vez que isso pode provocar uma grande confusão. Em nosso exemplo anterior, caso disséssemos: "Meu servidor web não está respondendo", significaria que todos os websites hospedados naquele servidor específico encontrariam-se indisponíveis.</p> + +<h3 id="Mecanismos_de_Pesquisa">Mecanismos de Pesquisa</h3> + +<p>Mecanismos de pesquisa são uma fonte comum de confusão na web. Um mecanismo de pesquisa é um tipo especial de website que auxilia usuários a encontrar páginas web de <em>outros </em>websites.</p> + +<p>Há um número abundante destas ferramentas: <a href="https://www.google.com/">Google</a>, <a href="https://www.bing.com/">Bing</a>, <a href="https://www.yandex.com/">Yandex</a>, <a href="https://duckduckgo.com/">DuckDuckGo</a> e diversos outros. Alguns são genéricos, outros especializam-se em tópicos específicos. Utilize qualquer um de sua preferência.</p> + +<p>Muitos iniciantes na web confundem mecanismos de pesquisa e navegadores. Tornemos tudo mais claro: um <strong>navegador</strong> é uma aplicação de software que recupera e renderiza páginas web; um <strong>mecanismo de pesquisa</strong> é um website que ajuda pessoas a encontrarem páginas web de outros websites. A confusão ocorre porque, da primeira vez que alguém executa um navegador, este mostra uma página inicial de um mecanismo de pesquisa. Este comportamento faz sentido, pois, evidentemente, a primeira coisa que você deseja fazer com um navegador é encontrar uma página web para renderizar. Não confunda a infraestrutura (neste caso, o navegador) com o serviço (aqui representado pelo mecanismo de pesquisa). A distinção irá ajudá-lo muito, mas mesmo alguns profissionais tendem a falar de forma mais informal, portanto não se preocupe com isso.</p> + +<p>Aqui há uma instância do Firefox mostrando uma caixa de pesquisa do Google como sua página inicial padrão:</p> + +<p><img alt="Example of Firefox nightly displaying a custom Google page as default" src="https://mdn.mozillademos.org/files/8533/search-engine.jpg" style="display: block; height: 399px; margin: 0px auto; width: 650px;"></p> + +<h2 id="Próximos_passos">Próximos passos</h2> + +<ul> + <li>Escavando a fundo: <a href="/en-US/docs/Learn/What_is_a_web_server">O que é um servidor web</a></li> + <li>Veja como páginas web são vinculadas dentro de um website: <a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_hyperlinks">Entendendo links na web</a></li> +</ul> diff --git a/files/pt-br/learn/common_questions/pensando_antes_de_codificar/index.html b/files/pt-br/learn/common_questions/pensando_antes_de_codificar/index.html new file mode 100644 index 0000000000..342692db46 --- /dev/null +++ b/files/pt-br/learn/common_questions/pensando_antes_de_codificar/index.html @@ -0,0 +1,178 @@ +--- +title: Como eu começo a criar meu site? +slug: Learn/Common_questions/Pensando_antes_de_codificar +tags: + - Composição + - Iniciante +translation_of: Learn/Common_questions/Thinking_before_coding +--- +<p class="summary">Este artigo abrange o primeiro passo, muito importante, de cada projeto: definir o que você deseja realizar com ele.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Nenhum</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Aprenda a definir metas para direcionar seu projeto da web.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Sumário">Sumário</h2> + +<p><span class="seoSummary">Ao começar um projeto web, muitas pessoas se concentram no lado técnico. É claro que você deve estar familiarizado com a técnica do seu ofício, mas o que realmente importa é o que você quer realizar. Sim, parece óbvio, mas muitos projetos falham não por falta de conhecimento técnico, mas por falta de objetivos e visão.</span></p> + +<p>Então, quando você tem uma ideia e quer transformá-la em um site, há algumas perguntas que você deve responder antes de qualquer outra coisa:</p> + +<ul> + <li>O que exatamente eu quero realizar?</li> + <li>Como um site me ajudará a atingir meus objetivos?</li> + <li>O que precisa ser feito, e em que ordem, para alcançar meus objetivos?</li> +</ul> + +<p>Tudo isso é chamado de ideação do projeto e é um primeiro passo necessário para atingir seu objetivo, seja você um iniciante ou um desenvolvedor experiente.</p> + +<h2 id="Aprendizado_Ativo">Aprendizado Ativo</h2> + +<p><em>Ainda não há aprendizado ativo disponível. <a href="https://developer.mozilla.org/en-US/docs/MDN/Getting_started">Por favor, considere contribuir</a>.</em></p> + +<h2 id="Mergulho_mais_profundo">Mergulho mais profundo</h2> + +<p>Um projeto nunca começa com o lado técnico. Os músicos, nunca farão uma música, a menos que tenham uma ideia do que querem tocar e o mesmo vale para pintores, escritores e desenvolvedores da web. Técnica vem em segundo lugar.</p> + +<p>A técnica é obviamente crítica. Músicos devem dominar seu instrumento. Mas bons músicos nunca podem produzir boa música sem uma ideia. Portanto, antes de pular para o lado técnico (por exemplo, código e ferramentas) você deve primeiro recuar e decidir detalhadamente o que deseja fazer.</p> + +<p>Uma hora de discussão com amigos é um bom começo, mas inadequado. Você precisa se sentar e estruturar suas ideias para ter uma visão clara do caminho que deve seguir para tornar suas ideias realidade. Para fazer isso, você precisa apenas de caneta e papel e de algum tempo para responder pelo menos as seguintes perguntas.</p> + +<div class="note"> +<p><strong>Nota:</strong> Existem inúmeras maneiras de realizar a ideação do projeto. Não podemos colocá-las todas aqui (um livro inteiro não seria suficiente). O que vamos apresentar aqui é um método simples para lidar com o que os profissionais chamam de <a href="http://en.wikipedia.org/wiki/Ideation_(idea_generation)">Ideação do Projeto</a>, <a href="http://en.wikipedia.org/wiki/Project_planning">Planejamento do Projeto</a>, e <a href="http://en.wikipedia.org/wiki/Project_management">Gerenciamento do Projeto</a>.</p> +</div> + +<h3 id="O_que_exatamente_eu_quero_realizar">O que exatamente eu quero realizar?</h3> + +<p>Esta é a pergunta mais importante a responder, já que direciona todo o resto. Relacione todos os objetivos que você deseja alcançar. Pode ser qualquer coisa: vender mercadorias para ganhar dinheiro, expressar opiniões políticas, conhecer novos amigos, apresentar-se com músicos, colecionar fotos de gatos ou o que você quiser.</p> + +<p>Suponha que você seja um músico. Você poderia desejar:</p> + +<ul> + <li>Deixar as pessoas ouvirem sua música.</li> + <li>Vender guloseimas.</li> + <li>Conhecer outros músicos.</li> + <li>Falar sobre sua música.</li> + <li>Ensinar música através de vídeos.</li> + <li>Publicar fotos de seus gatos.</li> + <li>Encontrar um(a) novo(a) namorado(a).</li> +</ul> + +<p>Depois de ter essa lista, você precisa priorizar. Ordene os objetivos do mais importante para o menos importante:</p> + +<ol> + <li>Encontrar um(a) novo(a) namorado(a).</li> + <li>Deixar as pessoas ouvirem sua música.</li> + <li>Falar sobre sua música.</li> + <li>Conhecer outros músicos.</li> + <li>Vender guloseimas.</li> + <li>Ensinar música através de vídeos.</li> + <li>Publicar fotos de seus gatos.</li> +</ol> + +<p>Fazer esse exercício simples (escrever objetivos e classificá-los), ajudará você quando tiver decisões a tomar. (Devo implementar esses recursos, usar esses serviços, criar esses designs?)</p> + +<p>Então, agora que você tem uma lista de prioridades, vamos para a próxima pergunta.</p> + +<h3 id="Como_um_site_poderia_me_levar_aos_meus_objetivos">Como um site poderia me levar aos meus objetivos?</h3> + +<p>Então você tem uma lista de objetivos e acha que precisa de um site para alcançar esses objetivos. Você tem certeza?</p> + +<p>Vamos olhar denovo para o nosso exemplo. Temos cinco objetivos ligados à música, um objetivo relacionado à vida pessoal (encontrar sua cara metade) e as fotos de gatos completamente independentes. É razoável construir um site único para cobrir todos esses objetivos? É mesmo necessário? Afinal, dezenas de serviços existentes na Web, podem levar você aos seus objetivos sem criar um novo site.</p> + +<p>Encontrar um(a) namorado(a) é um bom caso em que faz mais sentido usar recursos existentes do que contruir um site totalmente novo. Por que? Porque passaremos mais tempo construindo e mantendo o site em vez de realmente procurar um(a) namorado(a). Como nosso objetivo é o mais importante, devemos gastar nossa energia em alavancar as ferramentas existentes, em vez de começar do zero. Mais uma vez, existem tantos serviços web já disponíveis para mostrar fotos que não vale a pena o esforço para construir um novo site apenas para divulgar o quanto nossos gatos são fofos.</p> + +<p>Os outros cinco objetivos estão todos ligados à música. Existem, é claro, muitos serviços da web que poderiam lidar com esses objetivos, mas faz sentido, nesse caso, construir um site próprio. Esse site é a melhor maneira de agregar todas as coisas que queremos publicar em um único lugar (bom para os objetivos 3, 5 e 6) e promover a interação entre nós e o público (bom para os objetivos 2 e 4). Em suma, como todas essas metas giram em torno do mesmo tópico, ter tudo em um só lugar nos ajudará a atingir nossos objetivos e a ajudar nossos seguidores a se conectarem conosco.</p> + +<p>Como um site pode me ajudar a atingir minhas metas? Ao responder isso, você encontrará a melhor maneira de atingir seus objetivos e evitar o desperdício de esforços.</p> + +<h3 id="O_que_precisa_ser_feito_e_em_que_ordem_para_alcançar_meus_objetivos">O que precisa ser feito, e em que ordem, para alcançar meus objetivos?</h3> + +<p>O que precisa ser feito, e em que ordem, para alcançar meus objetivos?</p> + +<p>Agora que você sabe o que quer realizar, é hora de decompor os objetivos em etapas. Como uma anotação auxiliar, seus objetivos não são necessariamente definidos em pedra. Eles evoluem ao longo do tempo, mesmo no decorrer do projeto, especialmente se você se deparar com obstáculos inesperados ou simplemente mudar de idéia.</p> + +<p>Em vez de passar por uma longa explicação, voltemos ao nosso exemplo com esta tabela:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Objetivos</th> + <th scope="col">Coisas a fazer</th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Deixar as pessoas ouvirem sua música</td> + <td> + <ol> + <li>Gravar música</li> + <li>Preparar alguns arquivos de áudio utilizáveis on-line (você poderia fazer isso com os serviços da Web existentes?)</li> + <li>Dar às pessoas acesso à sua música em alguma parte do seu site</li> + </ol> + </td> + </tr> + <tr> + <td style="vertical-align: top;">Falar sobre sua música</td> + <td> + <ol> + <li>Escrever alguns artigos para iniciar a discussão</li> + <li>Definir como os artigos devem parecer</li> + <li>Publicar esses artigos no site (Como fazer isso?)</li> + </ol> + </td> + </tr> + <tr> + <td style="vertical-align: top;">Conhecer outros músicos</td> + <td> + <ol> + <li>Fornecer maneiras para as pessoas entrarem em contato com você (E-mail? Facebook? Telefone? Correio?)</li> + <li>Definir como as pessoas encontrarão esses canais de contato em seu site</li> + </ol> + </td> + </tr> + <tr> + <td style="vertical-align: top;">Vender guloseimas</td> + <td> + <ol> + <li>Criar as guloseimas</li> + <li>Armazenar as guloseimas</li> + <li>Encontrar uma maneira de lidar com o envio</li> + <li>Encontrar uma maneira de lidar com o pagamento</li> + <li>Criar um mecanismo no seu site para que as pessoas façam pedidos</li> + </ol> + </td> + </tr> + <tr> + <td style="vertical-align: top;">Ensinar música através de vídeos</td> + <td> + <ol> + <li>Gravar videoaulas</li> + <li>Preparar arquivos de vídeo online (Novamente, você poderia fazer isso com os serviços existentes na Web?)</li> + <li>Dar às pessoas acesso aos seus vídeos em alguma parte do seu site</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<p>Duas coisas para tomar nota. Primeiro, alguns desses itens não são relacionados à web (por exemplo, gravar música, escrever artigos). Muitas vezes essas atividades off-line são mais importantes do que o lado da web do projeto. Nas vendas, por exemplo, é muito mais importante e demorado lidar com suprimentos, pagamento e remessa do que construir um site onde as pessoas possam fazer pedidos.</p> + +<p>Em segundo lugar, a definição das etapas leva a novas perguntas que você precisará responder. Geralmente, há mais perguntas do que pensávamos inicialmente. (Por exemplo, devo aprender como fazer tudo isso sozinho, pedir a alguém para fazer isso por mim ou usar serviços de terceiros?)</p> + +<h2 id="Conclusão">Conclusão</h2> + +<p>Como você pode ver, a simples idéia "Eu quero fazer um site" gera uma longa lista de tarefas, que só cresce, quanto mais você pensa sobre isso. Logo pode parecer impressionante, mas não entre em pânico. Você não precisa responder todas as perguntas e não precisa fazer tudo na sua lista. O que importa é ter uma visão do que você quer e como chegar lá. Depois de ter essa visão clara, você precisa decidir como e quando fazê-lo. Divida as grandes tarefas em etapas pequenas e realizáveis. E essas pequenas tarefas resultarão em grandes conquistas.</p> + +<p>A partir deste artigo, você deve ser capaz de elaborar um plano básico para criar um site. Um próximo passo pode ser ler <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Common_questions/Como_a_internet_funciona">como a Internet funciona</a>.</p> diff --git a/files/pt-br/learn/common_questions/quanto_custa_fazer_algo_web/index.html b/files/pt-br/learn/common_questions/quanto_custa_fazer_algo_web/index.html new file mode 100644 index 0000000000..7c92c2fb03 --- /dev/null +++ b/files/pt-br/learn/common_questions/quanto_custa_fazer_algo_web/index.html @@ -0,0 +1,155 @@ +--- +title: Quanto custa fazer algo na Web? +slug: Learn/Common_questions/Quanto_custa_fazer_algo_web +translation_of: Learn/Common_questions/How_much_does_it_cost +--- +<div class="summary"> +<p>Getting involved on the Web isn't as cheap as it looks. In this article we discuss how much you may have to spend, and why.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>You should already understand <a href="/en-US/Learn/What_software_do_I_need">what software you need</a>, the difference between <a href="/en-US/Learn/page_vs_site_vs_server_vs_search_engine">a webpage, a website, etc</a>., and what <a href="/en-US/Learn/Understanding_domain_names">a domain name is</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Review the complete process for creating a website and find out how much each step can cost.</td> + </tr> + </tbody> +</table> + +<h2 id="Sumário">Sumário</h2> + +<p><span class="seoSummary">When launching a website, you may spend nothing, or your costs may go through the roof. In this article we discuss how much everything costs, and how you get what you pay (or don't pay).</span></p> + +<h2 id="Software">Software</h2> + +<h3 id="Editores_de_texto">Editores de texto</h3> + +<p>You likely have a text editor: such as, Notepad on Windows, Gedit on Linux, TextEdit on Mac. You'll have an easier time writing code if you choose an editor that color-codes, checks your syntax, and assists you with code structure.</p> + +<p>Many editors are free, for example <a href="https://atom.io/">Atom</a>, <a href="http://brackets.io/">Brackets</a>, <a href="http://bluefish.openoffice.nl/">Bluefish</a>, <a href="http://www.barebones.com/products/textwrangler/">TextWrangler</a>, <a href="http://eclipse.org/">Eclipse</a>, <a href="https://netbeans.org/">Netbeans</a>, and <a href="https://code.visualstudio.com/">Visual Studio Code</a>. Some, like <a href="http://www.sublimetext.com/">Sublime Text</a>, you can test as long as you like, but you're encouraged to pay. Some, like <a href="https://www.jetbrains.com/phpstorm/">PhpStorm</a>, can cost between a few dozen and 200 dollars, depending on the plan you purchase. Some of them, like <a href="http://www.visualstudio.com/">Microsoft Visual Studio</a>, can cost hundreds, or thousands of dollars; though Visual Studio Express is free for individual developers or open source projects. Often, for-pay editors will have a trial version.</p> + +<p>To start, we suggest trying out several editors, to get a sense of which works best for you. If you're only writing simple {{Glossary("HTML")}}, {{Glossary("CSS")}}, and {{Glossary("Javascript")}}, go with a simple editor.</p> + +<p>Price does not reliably reflect a text editor's quality or usefulness. You have to try it for yourself and decide if it meets your needs. For example, Sublime Text is cheap, but comes with many free plugins that can greatly extend its functionality.</p> + +<h3 id="Image_editors">Image editors</h3> + +<p>Your system likely includes a simple image editor, or viewer: Paint on Windows, Eye of Gnome on Ubuntu, Preview on Mac. Those programs are relatively limited, you'll soon want a more robust editor to add layers, effects, and grouping.</p> + +<p>Editors can be free (<a href="http://www.gimp.org/">GIMP</a>, <a href="https://www.getpaint.net/">Paint.NET</a>), moderately expensive (<a href="http://www.paintshoppro.com/">PaintShop Pro</a>, less than $100), or several hundred dollars (<a href="https://www.adobe.com/products/photoshop.html">Adobe Photoshop</a>).</p> + +<p>You can use any of them, as they will have similar functionality, though some are so comprehensive you'll never use every feature. If at some point you need to exchange projects with other designers, you should find out what tools they're using. Editors can all export finished projects to standard file formats, but each editor saves ongoing projects in its own specialized format. Most of the images on the internet are copyrighted, so it is better to check the license of the file before you use it. Sites like <a href="https://pixabay.com/">Pixabay</a> provide images under CC0 license, so you can use, edit and publish them even with modification for commercial use.</p> + +<h3 id="Media_editors">Media editors</h3> + +<p>If you want to include video or audio into your website, you can either embed online services (for example YouTube, Vimeo, or Dailymotion), or include your own videos (see below for bandwidth costs).</p> + +<p>For audio files, you can find free software (<a href="http://audacity.sourceforge.net/?lang=en">Audacity</a>, <a href="http://www.wavosaur.com/">Wavosaur</a>), or paying up to a few hundred dollars (<a href="http://www.sonycreativesoftware.com/soundforge">Sony Sound Forge</a>, <a href="http://www.adobe.com/products/audition.html">Adobe Audition</a>). Likewise, video-editing software can be free (<a href="http://www.pitivi.org/">PiTiVi</a>, <a href="http://www.openshot.org/">OpenShot</a> for Linux, <a href="https://www.apple.com/mac/imovie/">iMovie</a> for Mac), less than $100 (<a href="https://www.adobe.com/us/products/premiere-elements.html">Adobe Premiere Elements</a>), or several hundred dollars (<a href="https://www.adobe.com/products/premiere.html">Adobe Premiere Pro</a>, <a href="http://www.avid.com/US/products/family/Media-Composer">Avid Media Composer</a>, <a href="https://www.apple.com/final-cut-pro/">Final Cut Pro</a>). The software you received with your digital camera may cover all your needs.</p> + +<h3 id="Publishing_tools">Publishing tools</h3> + +<p>You also need a way to upload files: from your hard drive to a distant web server. To do that you should use a publishing tool such as an (S)<a href="/en-US/docs/Glossary/FTP">FTP client</a>, <a href="https://en.wikipedia.org/wiki/Rsync">RSync</a>, or <a href="https://help.github.com/articles/using-a-custom-domain-with-github-pages/">Git/GitHub</a>.</p> + +<p>Each operating system includes an (S)FTP client, as part of its file manager. Windows Explorer, Nautilus (a common Linux file manager), and the Mac Finder all include this functionality. However, people often choose dedicated (S)FTP clients to display local or remote directories side-by-side and store server passwords.</p> + +<p>If you want to install an (S)FTP client, there are several reliable and free options: for example, <a href="https://filezilla-project.org/">FileZilla</a> for all platforms, <a href="http://winscp.net/">WinSCP</a> for Windows, <a href="https://cyberduck.io/">Cyberduck</a> for Mac or Windows, <a href="https://en.wikipedia.org/wiki/List_of_FTP_server_software">and more</a>.</p> + +<p>Because FTP is inherently insecure, you should make sure to use SFTP — the secure, encrypted version of FTP that most hosting sites you'll deal with these days will offer by default — or another secure solution like Rsync over SSH.</p> + +<h2 id="Browsers">Browsers</h2> + +<p>You either already have a browser or can get one for free. If necessary, download Firefox <a href="https://www.mozilla.org/en-US/firefox/all/">here</a> or Google Chrome <a href="https://www.google.com/chrome/browser/">here</a>.</p> + +<h2 id="Web_access">Web access</h2> + +<h3 id="Computer_modem">Computer / modem</h3> + +<p>You need a computer. Costs can vary tremendously, depending on your budget, and where you live. To publish a barebones website, you only need a basic computer capable of launching an editor, and a Web browser, so the entry level can be quite low.</p> + +<p>Of course, you'll need a more serious computer if you want to produce complicated designs, touch up photos, or produce audio and video files.</p> + +<p>You need to upload content to a remote server (see <em>Hosting</em> below), so you need a modem. Your {{Glossary("ISP")}} can rent Internet connectivity to you for a few dollars per month, though your budget might vary, depending on your location.</p> + +<h3 id="ISP_access">ISP access</h3> + +<p>Make sure that you have sufficient {{Glossary("Bandwidth", "bandwidth")}}:</p> + +<ul> + <li>Low-bandwidth access may be adequate to support a 'simple' website: reasonably-sized images, texts, some CSS and JavaScript. That will likely cost you a few dozen dollars, including the rent for the modem.</li> + <li>On the other hand, you'll need a high-bandwidth connections, such as DSL, cable, or fiber access, if you want a more advanced website with hundreds of files, or if you want to deliver heavy video/audio files directly from your web server. It could cost the same as low-bandwidth access, upwards to several hundred dollars per month for more professional needs.</li> +</ul> + +<h2 id="Hosting">Hosting</h2> + +<h3 id="Understanding_bandwidth">Understanding bandwidth</h3> + +<p>Hosting providers charge you according to how much {{Glossary("Bandwidth", "bandwidth")}} your website consumes. This depends on how many people, and Web crawling robots, access your content during a given time, and how much server space your content takes up. This is why people usually store their videos on dedicated services such as Youtube, Dailymotion, and Vimeo. For example, your provider may have a plan that includes up to several thousand visitors per day, for “reasonable” bandwidth usage. Be careful, however as this is defined differently from one hosting provider to another. As a rule of thumb, recognize that reliable, paid, personal hosting can cost around ten to fifteen dollars per month.</p> + +<div class="note"> +<p>Note that there is no such thing as “unlimited” bandwidth. If you consume a huge amount of bandwidth, expect to pay a huge amount of money.</p> +</div> + +<h3 id="Domain_names">Domain names</h3> + +<p>Your domain name has to be purchased through a domain name provider (a registrar). Your hosting provider may also be a registrar (<a href="https://www.1and1.com/">1&1</a>, <a href="https://www.gandi.net/?lang=en">Gandi</a> for instance are at the same time registrars and hosting providers). The domain name usually costs $5-15 per year. This cost varies depending on:</p> + +<ul> + <li>Local obligations: some country top-level domain names are more costly, as different countries set different prices.</li> + <li>Services associated with the domain name: some registrars provide spam protection by hiding your postal address and email address behind their own addresses: the postal address can be provided in care of the registrar, and your email address can be obscured via your registrar's alias.</li> +</ul> + +<h3 id="Do-it-yourself_hosting_vs._“packaged”_hosting">Do-it-yourself hosting vs. “packaged” hosting</h3> + +<p>When you want to publish a website, you could do everything by yourself: set up a database (if needed), Content Management System, or {{Glossary("CMS")}} (like <a href="http://wordpress.org/">Wordpress</a>, <a href="http://dotclear.org/">Dotclear</a>, <a href="http://www.spip.net/en_rubrique25.html">spip</a>, etc.), upload pre-made or your own templates.</p> + +<p>You could use your hosting provider's environment, for roughly ten to fifteen dollars per month, or subscribe directly to a dedicated hosting service with pre-packaged CMSs (e.g., <a href="http://wordpress.com/">Wordpress</a>, <a href="https://www.tumblr.com/">Tumblr</a>, <a href="https://www.blogger.com/">Blogger</a>). For the latter, you won't have to pay anything, but you may have less control over templating and other options.</p> + +<h3 id="Free_hosting_vs._paid_hosting">Free hosting vs. paid hosting</h3> + +<p>You might ask, why should I pay for my hosting when there are so many free services?</p> + +<ul> + <li>You have more freedom when you pay. Your website is yours, and you can migrate seamlessly from one hosting provider to the next.</li> + <li>Free hosting providers may add advertising to your content, beyond your control.</li> +</ul> + +<p>It is better to go for paid hosting rather than relying on free hosting, as it is possible to move your files easily and uptime is <span>guaranteed </span>by most paid sites. Most hosting providers give you a huge discount to start with.</p> + +<p>Some people opt for a mixed approach. For example, their main blog on a paid host with a full domain name, and spontaneous, less strategic, content on a free host service.</p> + +<h2 id="Professional_website_agencies_and_hosting">Professional website agencies and hosting</h2> + +<p>If you desire a professional website, you will likely ask a web agency to do it for you.<br> + <br> + Here, costs depend on multiple factors, such as:</p> + +<ul> + <li>Is this a simple website with a few pages of text? Or a more complex, thousand-pages-long website?</li> + <li>Will you want to update it regularly? Or will it be a static website?</li> + <li>Must the website connect to your company’s IT structure to gather content (say, internal data)?</li> + <li>Do you want some shiny new feature that is the rage of the moment? At the time of writing, clients are seeking single pages with complex parallax</li> + <li>Will you need the agency to think up user stories or solve complex {{Glossary("UX")}} problems? For example, creating a strategy to engage users, or A/B testing to choose a solution among several ideas</li> +</ul> + +<p>...and for hosting:</p> + +<ul> + <li>Do you want redundant servers, in case your server goes down?</li> + <li>Is 95% percent reliability adequate, or do you need professional, around-the-clock service?</li> + <li>Do you want high-profile, ultra-responsive dedicated servers, or can you cope with a slower, shared machine?</li> +</ul> + +<p>Depending on how you answer these questions, your site could cost thousands to hundreds of thousands of dollars.</p> + +<h2 id="Next_steps">Next steps</h2> + +<p>Now that you understand what kind of money your website may cost you, it's time to start designing that website and <a href="/en-US/docs/Learn/Set_up_a_basic_working_environment">setting up your work environment</a>.</p> + +<ul> + <li>Read on about <a href="/en-US/docs/Learn/Choose,_Install_and_set_up_a_text_editor">how to choose and install a text editor</a>.</li> + <li>If you're more focused on design, take a look at the <a href="/en-US/Learn/Anatomy_of_a_web_page">anatomy of a web page</a>.</li> +</ul> diff --git a/files/pt-br/learn/common_questions/que_software_eu_preciso/index.html b/files/pt-br/learn/common_questions/que_software_eu_preciso/index.html new file mode 100644 index 0000000000..392b7fd03a --- /dev/null +++ b/files/pt-br/learn/common_questions/que_software_eu_preciso/index.html @@ -0,0 +1,222 @@ +--- +title: Que software eu preciso para construir um site? +slug: Learn/Common_questions/Que_software_eu_preciso +tags: + - Iniciante +translation_of: Learn/Common_questions/What_software_do_I_need +--- +<div class="summary"> + + +<p>Neste artigo nós destacamos quais <em>softwares</em> você precisa para editar, fazer <em>upload</em> ou visualizar um <em>site</em>.</p> +</div> + +<table class="learn-box nostripe standard-table"> + <tbody> + <tr> + <th scope="row">Pré requisitos:</th> + <td>Você deve saber <a href="/en-US/docs/Learn/page_vs_site_vs_server_vs_search_engine">a diferença entre páginas <em>web</em>, <em>sites web</em>, servidores<em>web</em>, e mecanismos de busca.</a></td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender quais <em>softwares</em> você precisa se quiser editar, fazer <em>upload</em>, ou visualizar um <em>site</em>.</td> + </tr> + </tbody> +</table> + +<h2 id="Sumário">Sumário</h2> + +<p>Você pode baixar a maioria dos programas que precisa para desenvolvimento <em>web</em> gratuitamente. Nós disponibilizamos alguns links neste artigo.</p> + +<p>Você precisa de ferramentas para:</p> + +<ul> + <li>Criar e editar páginas <em>web</em></li> + <li>Fazer <em>upload</em> de arquivos para o seu servidor web</li> + <li>Visualizar seu <em>site</em></li> +</ul> + +<p>Quase todos os sistemas operacionais incluem por padrão um editor de texto e um navegador de internet que você pode usar para visualizar sites. Como resultado, normalmente você só precisa obter um <em>software</em> para transferir arquivos para o seu servidor <em>web</em>.</p> + +<h2 id="Práticas">Práticas</h2> + +<p>Ainda não existem práticas disponíveis. <a href="/en-US/docs/MDN/Getting_started">Por favor, considere contribuir</a>.</p> + +<h2 id="Aprofundando">Aprofundando</h2> + +<h3 id="Criando_e_editando_páginas_web">Criando e editando páginas <em>web</em></h3> + +<p>Para criar e editar um <em>site</em>, você precisa de um editor de texto. Editores de texto criam e modificam arquivos de texto não formatados. Outros formatos, como <strong>{{Glossary("RTF")}}</strong>, permitem que você adicione formatação, como negrito ou sublinhado. Esses formatos não são adequados para escrever em páginas <em>web.</em> Você deve pensar bem em qual editor de texto vai usar, considerando que você trabalhará por bastante tempo nele enquanto estiver construíndo seu <em>site</em>.</p> + +<p>Todos os sistemas operacionais <em>desktop</em> possuem um editor de texto básico. Todos esses editores são diretos em sua função, mas não possuem os recursos especiais para codificar uma página <em>web</em>. Se você quiser algo um pouco mais sofisticado, existem muitas ferramentas de terceiros disponíveis. Editores de terceiros possuem funções extras, como coloração de sintaxe, autocompletação, separadores de seção, e busca de código. Aqui está uma pequena lista de editores:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Sistema Operacional</th> + <th scope="col">Editores Padrão</th> + <th scope="col">Editores de Terceiros</th> + </tr> + </thead> + <tbody> + <tr> + <td>Windows</td> + <td> + <ul> + <li><a href="http://en.wikipedia.org/wiki/Notepad_%28software%29" rel="external">Notepad</a></li> + </ul> + </td> + <td> + <ul> + <li><a href="http://notepad-plus-plus.org/">Notepad++</a></li> + <li><a href="https://www.visualstudio.com/">Visual Studio Code</a></li> + <li><a href="https://www.jetbrains.com/webstorm/">Web Storm</a></li> + <li><a href="http://brackets.io/">Brackets</a></li> + <li><a href="https://shiftedit.net/">ShiftEdit</a></li> + <li><a href="https://www.sublimetext.com/">Sublime Text</a></li> + </ul> + </td> + </tr> + <tr> + <td>Mac OS</td> + <td> + <ul> + <li><a href="http://en.wikipedia.org/wiki/TextEdit" rel="external">TextEdit</a></li> + </ul> + </td> + <td> + <ul> + <li><a href="http://www.barebones.com/products/textwrangler/">TextWrangler</a></li> + <li><a href="https://www.visualstudio.com/">Visual Studio Code</a></li> + <li><a href="http://brackets.io/">Brackets</a></li> + <li><a href="https://shiftedit.net/">ShiftEdit</a></li> + <li><a href="https://www.sublimetext.com/">Sublime Text</a></li> + </ul> + </td> + </tr> + <tr> + <td>Linux</td> + <td> + <ul> + <li><a href="http://en.wikipedia.org/wiki/Vi" rel="external">Vi</a> (All UNIX)</li> + <li><a href="http://en.wikipedia.org/wiki/Gedit" rel="external">GEdit</a> (Gnome)</li> + <li><a href="http://en.wikipedia.org/wiki/Kate_%28text_editor%29" rel="external">Kate</a> (KDE)</li> + <li><a href="http://en.wikipedia.org/wiki/Leafpad" rel="external">LeafPad</a> (Xfce)</li> + </ul> + </td> + <td> + <ul> + <li><a href="http://www.gnu.org/software/emacs/">Emacs</a></li> + <li><a href="http://www.vim.org/" rel="external">Vim</a></li> + <li><a href="https://www.visualstudio.com/">Visual Studio Code</a></li> + <li><a href="http://brackets.io/">Brackets</a></li> + <li><a href="https://shiftedit.net/">ShiftEdit</a></li> + <li><a href="https://www.sublimetext.com/">Sublime Text</a></li> + </ul> + </td> + </tr> + <tr> + <td>Chrome OS</td> + <td></td> + <td> + <ul> + <li><a href="https://shiftedit.net/">ShiftEdit</a></li> + </ul> + </td> + </tr> + </tbody> +</table> + +<p>Aqui está uma captura de tela de um editor de texto avançado:</p> + +<p><img alt="Screenshot of Notepad++." src="https://mdn.mozillademos.org/files/8221/NotepadPlusPlus.png" style="display: block; height: 311px; margin: 0 auto; width: 450px;"> </p> + +<p>Aqui está uma captura de tela de um editor de texto online:</p> + +<p><img alt="Screenshot of ShiftEdit" src="https://mdn.mozillademos.org/files/15837/shiftedit.png" style="display: block; height: 311px; margin: 0 auto; width: 475px;"></p> + +<h3 id="Fazendo_upload_de_arquivos_na_web">Fazendo <em>upload</em> de arquivos na <em>web</em></h3> + +<p>Quando seu <em>site</em> está pronto para visualização pública, você precisa fazer <em>upload</em> de suas páginas <em>web</em> para o seu servidor<em>web. </em>Você precisa comprar espaço em um servidor, entre vários provedores (veja <a class="new" href="/en-US/docs/Learn/Common_questions/How_much_does_it_cost">Quanto custa fazer algo na <em>web</em></a>). Após você decidir qual provedor usar, o provador te enviará um <em>e-mail</em> com suas informações de acesso, normalmente em forma de uma SFTP URL, nome de usuário, senha, e outra informação necessária para conectar no servidor. Tenha em mente que (S)FTP está um tanto quanto antiquado, e outros sistemas de <em>upload</em> de arquivos estão se tornando populares, como <a href="https://en.wikipedia.org/wiki/Rsync">RSync</a> e <a href="https://help.github.com/articles/using-a-custom-domain-with-github-pages/">Git/GitHub</a>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota: </strong>FTP é inerentemente inseguro. Você precisa se certificar que seu provedor permite o uso de uma conexão segura, por exemplo o SFTP ou RSync com SSH.</p> +</div> + +<p>Fazer <em>upload</em> de arquivos para um servidor <em>web</em> é um importante passo durante a criação de um <em>site</em>, por isso cobrimos isso detalhadamente em um <a href="/en-US/docs/Learn/Upload_files_to_a_web_server">artigo separado</a>. Agora, aqui está uma pequena lista de clientes (S)FTP básicos e gratuítos:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Sistema Operacional</th> + <th colspan="2" rowspan="1" scope="col" style="text-align: center;"> Cliente FTP</th> + </tr> + </thead> + <tbody> + <tr> + <td>Windows</td> + <td> + <ul> + <li><a href="http://winscp.net" rel="external">WinSCP</a></li> + <li><a href="http://mobaxterm.mobatek.net/">Moba Xterm</a></li> + </ul> + </td> + <td colspan="1" rowspan="3"> + <ul> + <li><a href="https://filezilla-project.org/">FileZilla</a> (Qualquer Sistema Operacional)</li> + </ul> + </td> + </tr> + <tr> + <td>Linux</td> + <td> + <ul> + <li><a href="https://wiki.gnome.org/action/show/Apps/Files?action=show&redirect=Apps%2FNautilus" rel="external">Nautilus/Files</a> (Gnome)</li> + <li><a href="http://dolphin.com/" rel="external">Dolphin</a> (KDE)</li> + </ul> + </td> + </tr> + <tr> + <td>Mac OS</td> + <td> + <ul> + <li><a href="http://cyberduck.de/">Cyberduck</a></li> + </ul> + </td> + </tr> + <tr> + <td>Chrome OS</td> + <td> + <ul> + <li><a href="https://shiftedit.net/">ShiftEdit</a> (Qualquer Sistema Operacional)</li> + </ul> + </td> + <td colspan="1"></td> + </tr> + </tbody> +</table> + +<h3 id="Navegando_em_sites">Navegando em <em>sites</em></h3> + +<p>Como você já sabe, é necessário um navegador <em>web</em> para visualizar <em>sites</em>. Existem dezenas de opções de navegadores <em>web </em>para seu uso pessoal, mas quando você está desenvolvendo um <em>site</em>, deve testá-lo ao menos nestes navegadores principais, para garantir que seu <em>site </em>funcionará para a maior parte das pessoas:</p> + +<ul> + <li><a href="https://www.mozilla.org/en-US/firefox/new/" rel="external">Mozilla Firefox</a></li> + <li><a href="https://www.google.com/chrome/" rel="external">Google Chrome</a></li> + <li><a href="http://windows.microsoft.com/en-US/internet-explorer/download-ie" rel="external">Microsoft Internet Explorer</a></li> + <li><a href="http://www.apple.com/safari/" rel="external">Apple Safari</a></li> +</ul> + +<p>Se você estiver buscando um grupo espécífico (como usuários de uma plataforma ou de algum país), deve testar seu <em>site</em> em navegadores adicionais, como <a href="http://www.opera.com/" rel="external">Opera</a>, <a href="http://www.konqueror.org/">Konqueror</a>, ou<a href="http://www.ucweb.com/ucbrowser/" rel="external"> UC Browser</a>.</p> + +<p>Mas testar é complicado, pois alguns navegadores apenas funcionam em determinados sistemas operacionais. O <em>Apple Safari</em> funciona no <em>iOS</em> e no <em>Mac OS</em>, enquanto o <em>Internet Explorer</em> funciona apenas no <em>Windows</em>. É melhor se valer dos benefícios de serviços como o<span style=""> </span><a href="http://browsershots.org/" rel="external" style="">Browsershots</a><span style=""> ou </span><a href="http://www.browserstack.com/" rel="external" style="">Browserstack</a><span style="">. O <em>Browsershots</em> fornece capturas de tela de como seu <em>site</em> é visto por vários navegadores. O <em>Browserstack</em> atualmente concede a você total acesso remoto à máquinas virtuais de forma que você pode testar seu site nos ambientes mais comuns. Alternativamente você pode configurar sua própria máquina virtual, mas isso demanda certos conhecimentos específicos. (Se você quiser seguir esse caminho, a <em>Microsoft</em> possui algumas ferramentas para desenvoledores, incluíndo uma máquina virtual pronta para o uso, chamada </span><a href="https://modern.ie" rel="external" style="">modern.ie</a><span style="">.).</span></p> + +<p>Por todos os meios possíveis, execute testes em dispositivos reais, especialmente em dispositivos móveis reais. Simulação de dispositivos móveis é uma nova tecnologia, está em evolução e é menos confiável que a simulação de computadores. Dispositivos móveis custam dinheiro, é claro, portanto sugerimos que se veja a <a href="http://opendevicelab.com/" rel="external">Open Device Lab initiative</a>. Você também pode compartilhar dispositivos se quiser testar em várias plataformas sem gastar muito.</p> + +<h2 id="Próximos_passos">Próximos passos</h2> + +<ul> + <li>Alguns desses <em>software</em> são gratis, mas não todos eles. <a href="/en-US/docs/Learn/Common_questions/How_much_does_it_cost">Descubra quanto custa fazer algo na <em>web</em></a><a class="new" href="/en-US/docs/Learn/How_much_does_it_cost">.</a></li> + <li>Se você deseja aprender mais sobre editores de texto, leia nosso artigo sobre <a href="/en-US/docs/Learn/Choose,_Install_and_set_up_a_text_editor">como escolher e instalar um editor de texto.</a></li> + <li>Se você está se perguntando como publicar seu<em>site</em> na<em>web</em>, veja <a href="/en-US/docs/Learn/Upload_files_to_a_web_server">"Como fazer <em>upload</em> para um servidor<em>web</em>"</a>.</li> +</ul> diff --git a/files/pt-br/learn/common_questions/upload_files_to_a_web_server/index.html b/files/pt-br/learn/common_questions/upload_files_to_a_web_server/index.html new file mode 100644 index 0000000000..a7d7fe509f --- /dev/null +++ b/files/pt-br/learn/common_questions/upload_files_to_a_web_server/index.html @@ -0,0 +1,172 @@ +--- +title: Como eu faço o upload de arquivos para um servidor web ? +slug: Learn/Common_questions/Upload_files_to_a_web_server +tags: + - FTP + - GitHub + - Iniciante + - MecanismosWeb + - hospedagem + - rsync + - sftp +translation_of: Learn/Common_questions/Upload_files_to_a_web_server +--- +<div class="summary"> +<p>Este artigo mostra como publicar seu site online usando ferramentas de transferência de arquivos.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos :</th> + <td>Você deve saber <a href="https://developer.mozilla.org/en-US/Learn/What_is_a_web_server">what a web server is</a> e <a href="https://developer.mozilla.org/en-US/Learn/Understanding_domain_names">how domain names work</a>. Você também deve saber como <a href="/en-US/Learn/Set_up_a_basic_working_environment">set up a basic environment</a> e como <a href="/en-US/Learn/HTML/Write_a_simple_page_in_HTML">write a simple webpage</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender como enviar arquivos para um servidor usando as várias ferramentas de transferências de arquivos disponíveis.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumo">Resumo</h2> + +<p>Se você construiu uma página web básica (veja <a href="/en-US/docs/Learn/Getting_started_with_the_web/HTML_basics">HTML basics</a>, por exemplo), provavelmente desejará colocá-la online, em um servidor da web. Neste artigo, discutiremos como fazer isso, usando várias opções disponíveis, como clientes SFTP, RSync e Github.</p> + +<h2 id="SFTP">SFTP</h2> + +<p>Existem vários clientes SFTP . Nossa demo cobre o FileZilla, já que é gratuito e está disponível para Windows, macOS e Linux. Para instalar o FileZilla, vá para a página de downloads do FileZilla, clique no botão Download grande e instale a partir do arquivo de instalação da maneira usual.</p> + +<div class="note"> +<p><strong>Nota</strong>: Claro que existem outras opções. Consulte <a href="/en-US/Learn/How_much_does_it_cost#Publishing_tools.3A_FTP_client">Publishing tools</a> para mais informações.</p> +</div> + +<p>Abra o FileZilla, você verá algo semelhante a isso: </p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15767/filezilla-ui.png" style="display: block; height: 451px; margin: 0px auto; width: 690px;"></p> + +<h3 id="Logging_in">Logging in</h3> + +<p>Para este exemplo, vamos supor que nosso provedor de hospedagem (o serviço que hospedará nosso servidor web HTTP) seja uma empresa fictícia ,"Example hosting provider" , cujos URLs são semelhantes a este: <code>mypersonalwebsite.examplehostingprovider.net</code>.</p> + +<p>Acabamos de abrir uma conta e receber estas informações : </p> + +<blockquote> +<p>Parabéns por abrir uma conta no Example Hosting Provider.</p> + +<p>Sua conta: <code>demozilla</code></p> + +<p>Seu site estará disponível em : <code>demozilla.examplehostingprovider.net</code></p> + +<p>Para publicar nessa conta, conecte-se por meio do SFTP com as seguintes credenciais :</p> + +<ul> + <li>Servidor SFTP: <code>sftp://demozilla.examplehostingprovider.net</code></li> + <li>Usuário: <code>demozilla</code></li> + <li>Senha: <code>quickbrownfox</code></li> + <li>Porta: <code>5548</code></li> + <li>Para publicar na web, coloque seus arquivos no diretório <code>Public/htdocs</code> .</li> +</ul> +</blockquote> + +<p>Primeiramente, olhe em <code>http://demozilla.examplehostingprovider.net/</code> — como você pode ver até o momento, não há nada lá :</p> + +<p><img alt="Our demozilla personal website, seen in a browser: it's empty" src="https://mdn.mozillademos.org/files/9615/demozilla-empty.png" style="border-style: solid; border-width: 1px; display: block; height: 233px; margin: 0 auto; width: 409px;"></p> + +<div class="note"> +<p><strong>Nota</strong>: Dependendo do seu provedor de hospedagem, na maioria das vezes você verá uma página dizendo algo como como "Este site é hospedado por [serviço de hospedagem]".Isso é claro, quando você acessa seu endereço da web pela primeira vez.</p> +</div> + +<p>Para conectar seu cliente SFTP ao servidor, siga estas etapas:</p> + +<ol> + <li>Escolha o arquivo<em> > Site Manager(Gerenciador de sites)...</em> no menu principal.</li> + <li>Na janela do gerenciador de site, vá em novo site e preencha o nome do site como <strong>demozilla</strong> no espaço fornecido.</li> + <li>Preencha o servidor SFTP que seu host forneceu no campo <em>Host:</em> field.</li> + <li>Em <em>Logon Type(tipo de LogOn):</em> Escolha normal e ,em seguida , preencha com o nome de usuário e a senha fornecida nos campos relevantes.</li> + <li>Preencha a porta correta e outras informações.</li> +</ol> + +<p>Sua janela estará semelhante a esta: </p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15769/site-manager.png" style="display: block; height: 561px; margin: 0px auto; width: 684px;"></p> + +<p>Agora pressione <em>Connect</em> para conectar ao servidor SFTP.</p> + +<p>Nota: Atenção, certifique-se de que seu provedor de hospedagem oferece conexão SFTP (FTP seguro) ao seu espaço de hospedagem. O FTP é inerentemente inseguro e você não deve usá-lo.</p> + +<h3 id="Visão_local_e_remota">Visão local e remota</h3> + +<p>Depois de conectada, sua tela deve ser semelhante a esta (conectamos a um exemplo nosso para lhe dar uma ideia):</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15768/connected.png" style="border-style: solid; border-width: 1px; display: block; height: 199px; margin: 0px auto; width: 700px;"></p> + +<p>Vamos analisar o que você está vendo:</p> + +<ul> + <li>No painel esquerdo central, você vê seus arquivos locais. Navegue até o diretório onde você armazena seu site (e.g. <code>mdn</code>).</li> + <li>No painel direito central, você vê arquivos remotos.Estamos conectados em nossa raiz FTP distante(Nesse caso, <code>users/demozilla</code>)</li> + <li>No momento, você pode ignorar os painéis inferiores e superiores.Respectivamente, trata-se de um log de mensagens que mostra o status de conexão entre seu computador e o servidor SFTP e um log em tempo real de cada interação entre seu cliente SFTP e o servidor.</li> +</ul> + +<h3 id="Enviando_para_o_servidor">Enviando para o servidor </h3> + +<p>Nossas instruções de host de exemplo nos disseram "Para publicar na web, coloque seus arquivos no diretório <code>Public/htdocs</code> " Você precisa navegar até o diretório especificado no painel direito. Este diretório é efetivamente a raiz do seu site — onde seu arquivo <code>index.html</code> e outros irão.</p> + +<p>Depois de encontrar o diretório remoto correto para colocar seus arquivos, para carregá-los no servidor, você precisa arrastá-los e soltá-los do painel esquerdo para o painel direito.</p> + +<h3 id="Eles_estão_realmente_online">Eles estão realmente online ?</h3> + +<p>Até agora, tudo bem , mas os arquivos estão realmente online ? Você pode verificar novamente voltando ao seu site (e.g. <code>http://demozilla.examplehostingprovider.net/</code>) no seu navegador:</p> + +<p><img alt="Here we go: our website is live!" src="https://mdn.mozillademos.org/files/9627/here-we-go.png" style="border-style: solid; border-width: 1px; display: block; height: 442px; margin: 0 auto; width: 400px;"></p> + +<p><span lang="fr">E </span><em lang="fr">voilà</em>! Nosso website está vivo!</p> + +<h2 id="Rsync">Rsync</h2> + +<p>{{Glossary("Rsync")}} é uma ferramenta de sincronização de arquivos local para remoto, que geralmente está disponível na maioria dos sistemas baseados em Unix (como macOS e Linux), mas também existem versões do Windows.</p> + +<p>É visto como uma ferramenta mais avançada do que o SFTP, porque por padrão é usado na linha de comando. Um comando básico se parece com isto:</p> + +<pre class="brush: bash notranslate">rsync [-options] SOURCE user@x.x.x.x:DESTINATION</pre> + +<ul> + <li><code>-options</code> é um travessão seguido por uma ou mais letras, por exemplo -v para mensagens de erros detalhadas e -b para fazer backups. Você pode ver a lista completa em <a href="https://linux.die.net/man/1/rsync">rsync man page</a> (Pesquise por "Options summary").</li> + <li><code>SOURCE</code> é o caminho para o arquivo ou diretório local do qual você deseja copiar os arquivos.</li> + <li><code>user@</code> são as credenciais de usuário no servidor remoto para o qual você deseja copiar os arquivos.</li> + <li><code>x.x.x.x</code> é o endereço de IP do servidor remoto.</li> + <li><code>DESTINATION</code> é o caminho para o local que você deseja copiar seu diretório ou arquivos no servidor remoto.</li> +</ul> + +<p>Você precisa obter esses detalhes do seu provedor de hospedagem.</p> + +<p>Para mais informações, veja <a href="https://www.atlantic.net/hipaa-compliant-cloud-hosting-services/how-to-use-rsync-copy-sync-files-servers/">How to Use Rsync to Copy/Sync Files Between Servers</a>.</p> + +<p>Obviamente, é uma boa ideia usar uma conexão segura, como no FTP. No caso do Rsync, você especifica os detalhes do SSH para fazer a conexão por SSH, usando a opção -e. Por exemplo:</p> + +<pre class="brush: bash notranslate">rsync [-options] -e "ssh [SSH DETAILS GO HERE]" SOURCE user@x.x.x.x:DESTINATION</pre> + +<p>Você pode encontrar mais detalhes sobre o assunto em <a href="https://www.digitalocean.com/community/tutorials/how-to-copy-files-with-rsync-over-ssh">How To Copy Files With Rsync Over SSH</a>.</p> + +<h3 id="Ferramentas_Rsync_GUI">Ferramentas Rsync GUI</h3> + +<p>Ferramentas GUI estão disponíveis para Rsync (para aqueles que não se sentem tão confortáveis com o uso da linha de comando). <a href="https://acrosync.com/mac.html">Acrosync</a> é uma dessas ferramentas e está disponível para Windows e macOS</p> + +<p>Novamente, você teria que obter as credenciais de conexão do seu provedor de hospedagem, mas desta forma você teria uma GUI para inseri-lás.</p> + +<h2 id="GitHub">GitHub</h2> + +<p>Github permite você publicar páginas por meio do <a href="https://pages.github.com/">GitHub pages</a> (gh-pages).</p> + +<p>Cobrimos o básico de como usar isso no <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Publishing_your_website">Publishing your website</a> artigo do guia <a href="/en-US/Learn/Getting_started_with_the_web">Getting started with the Web</a> , então não vamos repetir tudo aqui.</p> + +<p>No entanto, é importante saber que você também pode hospedar um site no GitHub, mas usar um domínio personalizado com ele. Para obter um guia detalhado, consulte <a href="https://help.github.com/articles/using-a-custom-domain-with-github-pages/">Using a custom domain with GitHub Pages</a> .</p> + +<h2 id="Outros_métodos_para_enviar_arquivos">Outros métodos para enviar arquivos</h2> + +<p>O protocolo FTP é um método conhecido de publicação de um site, mas não o único. Aqui estão algumas outras possibilidades:</p> + +<ul> + <li><strong>Web interfaces(Interfaces Web)</strong>. Uma interface HTML que atua como front-end para um serviço de envio de arquivo remoto. Fornecido pelo seu serviço de hospedagem.</li> + <li><strong>{{Glossary("WebDAV")}}</strong>. Uma extensão do protocolo {{Glossary("HTTP")}} para permitir um gerenciamento de arquivos mais avançado.</li> +</ul> diff --git a/files/pt-br/learn/common_questions/using_github_pages/index.html b/files/pt-br/learn/common_questions/using_github_pages/index.html new file mode 100644 index 0000000000..35c7636ef2 --- /dev/null +++ b/files/pt-br/learn/common_questions/using_github_pages/index.html @@ -0,0 +1,101 @@ +--- +title: How do I use GitHub Pages? +slug: Learn/Common_questions/Using_Github_pages +translation_of: Learn/Common_questions/Using_Github_pages +--- +<p class="summcary"><a href="https://github.com/">GitHub</a> is a "social coding" site. It allows you to upload code repositories for + storage in thecelio <a href="http://git-scm.com/">Git</a> <strong>version control system. </strong>You can then collaborate on code projects, and the system is open-source by default, meaning that anyone in the world can find your GitHub code, use it, learn from it, and improve on it. You can do that with other people's code too! This article provides a basic guide to publishing content using Github's gh-pages feature.</p> + +<h2 id="Publishing_content">Publishing content</h2> + +<p>GitHub is a very important and useful community to get involved in, and Git/GitHub is a very popular <a href="http://git-scm.com/book/en/v2/Getting-Started-About-Version-Control">version control system</a> — most tech companies now use it in their workflow. GitHub has a very useful feature called <a href="https://pages.github.com/">GitHub Pages</a>, which allows you to publish website code live on the Web.</p> + +<h3 id="Basic_Github_setup">Basic Github setup</h3> + +<ol> + <li>First of all, <a href="http://git-scm.com/downloads">install Git</a> on your machine. This is the underlying version control system software that GitHub works on top of.</li> + <li>Next, <a href="https://github.com/join">sign up for a GitHub account</a>. It's simple and easy.</li> + <li>Once you've signed up, log in to <a href="https://github.com">github.com</a> with your username and password.</li> +</ol> + +<h3 id="Preparing_your_code_for_upload">Preparing your code for upload</h3> + +<p>You can store any code you like in a Github repository, but to use the GitHub Pages feature to full effect, your code should be structured as a typical website, e.g. with the primary entry point being an HTML file called <code>index.html</code>.</p> + +<p>The other thing you need to do before moving on is to initialise your code directory as a Git repository. To do this:</p> + +<ol> + <li>Point the command line to your <code>test-site</code> directory (or whatever you called the directory containing your website). For this, use the <code>cd</code> command (i.e. "<em>c</em>hange <em>d</em>irectory"). Here's what you'd type if you've put your website in a directory called <code>test-site</code> on your desktop: + + <pre class="brush: bash">cd Desktop/test-site</pre> + </li> + <li>When the command line is pointing inside your website directory, type the following command, which tells the <code>git</code> tool to turn the directory into a git repository: + <pre class="brush: bash">git init</pre> + </li> +</ol> + +<h4 id="An_aside_on_command_line_interfaces">An aside on command line interfaces</h4> + +<p>The best way to upload your code to Github is via the command line — this is a window where you type in commands to do things like create files and run programs, rather than clicking inside a user interface. It will look something like this:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9483/command-line.png" style="display: block; height: 478px; margin: 0px auto; width: 697px;"></p> + +<div class="note"> +<p><strong>Note</strong>: You could also consider using a <a href="http://git-scm.com/downloads/guis">Git graphical user interface</a> to do the same work, if you feel uncomfortable with the command line.</p> +</div> + +<p><span id="command-line">Every operating system comes with a command line tool:</span></p> + +<ul> + <li><strong>Windows</strong>: <strong>Command Prompt</strong> can be accessed by pressing the Windows key, typing <em>Command Prompt</em>, and choosing it from the list that appears. Note that Windows has its own command conventions differing from Linux and OS X, so the commands below may vary on your machine.</li> + <li><strong>OS X</strong>: <strong>Terminal</strong> can be found in <em>Applications > Utilities</em>.</li> + <li><strong>Linux</strong>: Usually you can pull up a terminal with <em>Ctrl + Alt + T</em>. If that doesn't work, look for <strong>Terminal </strong>in an app bar or menu.</li> +</ul> + +<p>This may seem a bit scary at first, but don't worry — you'll soon get the hang of the basics. You tell the computer to do something in the terminal by typing in a command and hitting Enter, as seen above.</p> + +<h3 id="Creating_a_repo_for_your_code">Creating a repo for your code</h3> + +<ol> + <li>Next, you need to create a new repo for your files to go in. Click Plus (+) in the top right of the GitHub homepage, then choose <em>New Repository</em>.</li> + <li>On this page, in the <em>Repository name</em> box, enter a name for your code repository, for example <em>my-repository</em>.</li> + <li>Also fill in a description to say what your repository is going to contain. Your screen should look like this:<br> + <img alt="" src="https://mdn.mozillademos.org/files/12143/create-new-repo.png" style="display: block; height: 548px; margin: 0px auto; width: 800px;"></li> + <li>Click <em>Create repository</em>; this should bring you to the following page: <br> + <img alt="" src="https://mdn.mozillademos.org/files/12141/github-repo.png" style="display: block; height: 520px; margin: 0px auto; width: 800px;"></li> +</ol> + +<h3 id="Uploading_your_files_to_GitHub">Uploading your files to GitHub</h3> + +<ol> + <li>On the current page, you are interested in the section <em>…or push an existing repository from the command line</em>. You should see two lines of code listed in this section. Copy the whole of the first line, paste it into the command line, and press Enter. The command should look something like this: + + <pre class="copyable-terminal-content js-zeroclipboard-target"><span class="user-select-contain">git remote add origin <span class="js-live-clone-url">https://github.com/chrisdavidmills/my-repository.git</span></span></pre> + </li> + <li>Next, type the following two commands, pressing Enter after each one. These prepare the code for uploading to GitHub, and ask Git to manage these files. + <pre class="brush: bash">git add --all +git commit -m 'adding my files to my repository'</pre> + </li> + <li>Finally, push the code up to GitHub by going to the GitHub web page you're on and entering into the terminal the second of the two commands we saw the <em>…or push an existing repository from the command line</em> section: + <pre class="brush: bash">git push -u origin master</pre> + </li> + <li>Now you need to create a gh-pages branch of your repo; refresh the current page and you'll see a repository page something like the one below. You need to press the button that says <em>Branch: <strong>master</strong></em>, type <em>gh-pages</em> in the text input, then press the blue button that says <em>Create branch: gh-pages</em>. This creates a special code branch called gh-pages that is published at a special location. It's URL takes the form <em>username.github.io/my-repository-name</em>, so in my example's case, the URL would be <em>https://chrisdavidmills.github.io/my-repository</em>. The page shown is the index.html page.<br> + <img alt="" src="https://mdn.mozillademos.org/files/12145/repo-site.png" style="display: block; margin: 0 auto;"></li> + <li>Navigate to your GitHub Pages' web address in a new browser tab, and you should see your site online! Email it to your friends and show off your mastery.</li> +</ol> + +<div class="note"> +<p><strong>Note</strong>: If you get stuck, the <a href="https://pages.github.com/">GitHub Pages homepage</a> is also really helpful.</p> +</div> + +<h3 id="Further_GitHub_knowledge">Further GitHub knowledge</h3> + +<p>If you want to make more changes to your test site and upload those to GitHub, you simply need to make the change to your files just like you did before. Then, you need to enter the following commands (pressing Enter after each one) to push those changes to GitHub:</p> + +<pre>git add --all +git commit -m 'another commit' +git push</pre> + +<p>You can replace <em>another commit</em> with a more suitable message to describe what change you just made.</p> + +<p>We have barely scratched the surface of Git. To learn more, start off with the <a href="https://help.github.com/index.html">GitHub Help site</a>.</p> diff --git a/files/pt-br/learn/common_questions/what_is_a_domain_name/index.html b/files/pt-br/learn/common_questions/what_is_a_domain_name/index.html new file mode 100644 index 0000000000..998e1091d6 --- /dev/null +++ b/files/pt-br/learn/common_questions/what_is_a_domain_name/index.html @@ -0,0 +1,152 @@ +--- +title: O que é um nome de domínio? +slug: Learn/Common_questions/What_is_a_domain_name +translation_of: Learn/Common_questions/What_is_a_domain_name +--- +<div class="summary"> +<p>Nesse artigo examinaremos nomes de domínios: o que são, como são estruturados, e como conseguir um.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Primeiro você precisa conhecer <strong><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Common_questions/Como_a_internet_funciona">como a Internet funciona</a></strong> e entender <strong><a href="/en-US/Learn/Understanding_URLs">what URLs are</a>.</strong></td> + </tr> + <tr> + <th scope="row">Objetivos:</th> + <td>Aprender o que são <strong>"nomes de domínios"</strong>, como funcionam, e porquê são importantes.</td> + </tr> + </tbody> +</table> + +<h2 id="Sumário">Sumário</h2> + +<p><span class="seoSummary">"Nomes de Domínios" são uma parte fundamental da infraestrutura da Internet. Eles provêm um endereço legível para qualquer servidor web disponível na Internet.</span></p> + +<p>Qualquer computador conectado na Internet pode ser alcançado através de um endereço {{Glossary("IP")}} público, consistido de 32 bits para IPv4 (eles são, normalmente, escritos com quatro grupos de três números entre 0 e 255, separados por pontos (p.e., <code>173.194.121.32</code>) ou consistidos de 128 bits para IPv6 (eles são normalmente escritos com oito grupos de 4 números hexadecimais, separados por dois pontos (p.e., <code>2027:0da8:8b73:0000:0000:8a2e:0370:1337</code>). Computadores podem manipular esses endereços facilmente, mas as pessoas tem dificuldade em descobrir quem está executando o servidor ou que serviço o site oferece. Endereços de IP são difíceis de lembrar e podem mudar com o tempo. Para resolver todos esses problemas nós usamos endereços legíveis chamados domain names (nomes de domínio).</p> + +<h2 id="Active_Learning">Active Learning</h2> + +<p><em>There is no active learning available yet. <a href="/en-US/docs/MDN/Getting_started">Please, consider contributing</a>.</em></p> + +<h2 id="Deeper_dive">Deeper dive</h2> + +<h3 id="Estrutura_dos_domain_names">Estrutura dos domain names</h3> + +<p>Um "nome de domínio" tem uma estrutura simples feita de várias partes (pode ser apenas uma parte, duas, três...), separados por pontos e<strong> lidos da direita para a esquerda</strong>:</p> + +<p><img alt="Anatomy of the MDN domain name" src="https://mdn.mozillademos.org/files/11229/structure.png" style="height: 76px; width: 252px;"></p> + +<p>Cada uma dessas partes fornece informações específicas sobre todo o domain name.</p> + +<dl> + <dt>{{Glossary("TLD")}} (Top-Level Domain).</dt> + <dd>O TLD fornece as informações mais genéricas. TLDs informa aos usuários o propósito geral do serviço por trás do nome de domínio. Os TLDs mais genéricos (.com, .org, .net) não requer web services para atender a critérios rigorosos, mas alguns TLDs impõem políticas mais rigorosas. Por exemplo, TLDs locais tais como .us, .fr, or .sh podem exigir que o serviço seja fornecido em um determinado idioma ou hospedado em um determinado país.</dd> + <dt>Label (ou componente)</dt> + <dd>Os labels são os que seguem o TLD. Um label pode ser qualquer coisa, de uma letra a uma frase completa. O label localizado a direita antes do TLD pode também ser referido como um <em>Domínio de Nível Secundário</em> (SLD). Um <em>nome de domínio</em> pode ter muitos labels, não é obrigatório nem necessário ter 3 labels para formar um nome de domínio. Por exemplo, www.inf.ed.ac.uk é um nome de domínio correto. Ao controlar a parte "superior" de um nome de domínio (p.e. <a href="https://mozilla.org">mozilla.org</a>), pode-se criar outros nomes de domínios (às vezes chamados de "subdomínios") (p.e. <a href="https://developer.mozilla.org">developer.mozilla.org</a>).</dd> +</dl> + +<h3 id="Comprando_um_nome_de_domínio">Comprando um nome de domínio</h3> + +<h4 id="Quem_possui_um_nome_de_domínio">Quem possui um nome de domínio?</h4> + +<p>Você não pode “comprar um nome de domínio”. Você paga pelo direito de usar um nome de domínio por um ano ou mais. Você pode renovar seu direito, e sua renovação tem prioridade sobre as aplicações de outras pessoas. Mas você nunca possui o nome de domínio.</p> + +<p>As empresas chamadas registradoras usam registros de nome de domínio para acompanhar as informações técnicas e administrativas que conectam você a seu nome de domínio.</p> + +<div class="note"> +<p><strong>Nota : </strong>Alguns nomes de domínios podem não ter um registrador encarregado de acompanhar. Por exemplo, todo o nome sob o domínio .fire é gerenciado pela Amazon.</p> +</div> + +<h4 id="Encontrando_um_nome_de_domínio_disponível">Encontrando um nome de domínio disponível</h4> + +<p>Para descobrir se um determinado domain name está disponível,</p> + +<ul> + <li>Ir até um site registrador de nome de domínio. A maioria deles fornece um serviço “whois” que diz se seu nome de domínio está disponível.</li> + <li>Alternativamente, se você usa um sistema com shell embutido nele, digite um comnaod <code>whois</code> nele, como mostrado aqui para <code>mozilla.org</code>:</li> +</ul> + +<pre>$ whois mozilla.org +Domain Name:MOZILLA.ORG +Domain ID: D1409563-LROR +Creation Date: 1998-01-24T05:00:00Z +Updated Date: 2013-12-08T01:16:57Z +Registry Expiry Date: 2015-01-23T05:00:00Z +Sponsoring Registrar:MarkMonitor Inc. (R37-LROR) +Sponsoring Registrar IANA ID: 292 +WHOIS Server: +Referral URL: +Domain Status: clientDeleteProhibited +Domain Status: clientTransferProhibited +Domain Status: clientUpdateProhibited +Registrant ID:mmr-33684 +Registrant Name:DNS Admin +Registrant Organization:Mozilla Foundation +Registrant Street: 650 Castro St Ste 300 +Registrant City:Mountain View +Registrant State/Province:CA +Registrant Postal Code:94041 +Registrant Country:US +Registrant Phone:+1.6509030800 +</pre> + +<p>Como você pode ver, eu não posso registrar <code>mozilla.org</code> porque a Mozilla Foundation já registrou.</p> + +<p>Por outro lado, vamos ver se eu poderia registrar <code>afunkydomainname.org</code>:</p> + +<pre>$ whois afunkydomainname.org +NOT FOUND +</pre> + +<p>Como você pode ver, o domínio não existe no banco de dados <code>whois</code> (neste momento em que escrevo), então poderíamos pedir para registrá-lo. Bom saber!</p> + +<h4 id="Obtendo_um_nome_de_domínio">Obtendo um nome de domínio</h4> + +<p>O processo é bastante simples:</p> + +<ol> + <li>Ir para o site de um registrador.</li> + <li>Geralmente há um apelo chamativo “Obeter um domain name” call to action. Clique nele.</li> + <li>Preencher o formulário com todos os detalhes requeridos. Certifique-se especialmente de que você não digitou incorretamente o domain name desejado. Uma vez pago, é tarde demais!</li> + <li>O registrador informará quando o domain name estiver registrado corretamente. Dentro de algumas horas, todos os servidores de DNS receberão suas informações de DNS.</li> +</ol> + +<div class="note"> +<p><strong>Nota:</strong> Este tempo é frequentemente chamado de <strong>tempo de propagação.</strong> No entanto, este termo não é preciso, pois a atualização não está se propagando (top → down). Os servidores DNS consultados pelo seu computador (abaixo) são aqueles que buscam as informações do servidor autoritativo (superior) quando precisam.</p> +</div> + +<h4 id="Atualização_de_DNS">Atualização de DNS</h4> + +<p>Bancos de dados DNS são armazenados em todos os servidores DNS em todo o mundo, e todos esses servidores referem-se a alguns chamados "servidores de nome autoritativo" ou "servidores DNS de nível superior". Sempre que seu registrador cria ou atualiza qualquer informação para um determinado domínio, a informação deve ser atualizada em todo banco de dados DNS. Cada servidor DNS que conhece um determinado domínio armazena as informações por algum tempo antes de serem automaticamente invalidadas e atualizadas (o servidor DNS cosulta novamente um servidor autoritativo). Assim, leva algum tempo para que os servidores DNS que conhecem esse nome de domínio obtenham as informações atualizadas.</p> + +<div class="note"> +<p><strong>Note :</strong> This time is often called <strong>propagation time</strong>. However this term is not precise since the update is not propagating itself (top → down). DNS servers queried by your computer (down) are the ones that fetch the information from the authoritative server (top) when they need it.</p> +</div> + +<h3 id="Como_funciona_uma_solicitação_de_DNS">Como funciona uma solicitação de DNS?</h3> + +<p> </p> + +<p>Como já vimos, quando você deseja exibir uma página da Web em seu navegador, é mais fácil digitar um nome de domínio do que um endereço IP. Vamos dar uma olhada no processo:</p> + +<ol> + <li>Digite mozilla.org na barra de localização do seu navegador.</li> + <li>Seu navegador pergunta ao seu computador se ele já reconhece o endereço IP identificado por esse nome de domínio (usando um cache DNS local). Em caso afirmativo, o nome é traduzido para o endereço IP e o navegador negocia o conteúdo com o servidor da Web. Fim da história.</li> + <li>Se o seu computador não sabe qual IP está por trás do nome mozilla.org, ele vai perguntar a um servidor DNS, cujo trabalho é precisamente informar ao seu computador qual endereço IP corresponde a cada nome de domínio registrado.</li> + <li>Agora que o computador conhece o endereço IP solicitado, seu navegador pode negociar o conteúdo com o servidor da web.</li> +</ol> + +<p><img alt="Explanation of the steps needed to obtain the result to a DNS request" src="https://mdn.mozillademos.org/files/8961/2014-10-dns-request2.png" style="height: 702px; width: 544px;"></p> + +<h2 id="Próximos_passos">Próximos passos</h2> + +<p>Ok, conversamos muito sobre processos e arquitetura. Hora de seguir em frente.</p> + +<ul> + <li>Se você quer se envolver, é um bom momento para começar a investigar o design e explorar a <a href="/en-US/Learn/Anatomy_of_a_web_page">anatomia de uma página da web.</a></li> + <li>É importante notar também que alguns aspectos da construção de um site custam dinheiro. Por favor, <a href="/en-US/docs/Learn/How_much_does_it_cost">consulte quanto custa construir um site</a>.</li> + <li>Ou leia mais sobre o <a href="http://en.wikipedia.org/wiki/Domain_name">nome de domínio</a> na Wikipedia.</li> + <li>Você também pode encontrar <a href="https://howdns.works/">aqui </a>uma explicação divertida e colorida de como o DNS funciona.</li> +</ul> diff --git a/files/pt-br/learn/css/building_blocks/selectors/attribute_selectors/index.html b/files/pt-br/learn/css/building_blocks/selectors/attribute_selectors/index.html new file mode 100644 index 0000000000..98d26ea002 --- /dev/null +++ b/files/pt-br/learn/css/building_blocks/selectors/attribute_selectors/index.html @@ -0,0 +1,157 @@ +--- +title: Attribute selectors +slug: Learn/CSS/Building_blocks/Selectors/Attribute_selectors +translation_of: Learn/CSS/Building_blocks/Selectors/Attribute_selectors +--- +<p>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors", "Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements", "Learn/CSS/Building_blocks")}}</p> + +<p>Como você sabe de seu estudo de HTML, os elementos podem ter atributos que fornecem mais detalhes sobre o elemento que está sendo marcado. Em CSS, você pode usar seletores de atributo para direcionar elementos com determinados atributos. Esta lição mostrará como usar esses seletores que são muito úteis.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>Basic computer literacy, <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Installing_basic_software">basic software installed</a>, basic knowledge of <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Dealing_with_files">working with files</a>, HTML basics (study <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introduction to HTML</a>), and an idea of how CSS works (study <a href="/en-US/docs/Learn/CSS/First_steps">CSS first steps</a>.)</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>To learn what attribute selectors are and how to use them.</td> + </tr> + </tbody> +</table> + +<h2 id="Seletores_de_Presença_e_Valor">Seletores de Presença e Valor</h2> + +<p>Esses seletores permitem a seleção de um elemento com base na presença de um atributo sozinho (por exemplo, href) ou em várias correspondências diferentes com o valor do atributo.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Selector</th> + <th scope="col">Example</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>[<em>attr</em>]</code></td> + <td><code>a[title]</code></td> + <td>Corresponde a elementos com um atributo attr (cujo nome é o valor entre colchetes).</td> + </tr> + <tr> + <td><code>[<em>attr</em>=<em>value</em>]</code></td> + <td><code>a[href="https://example.com"]</code></td> + <td>Corresponde a elementos com um atributo attr cujo valor é exatamente value - a string entre aspas.</td> + </tr> + <tr> + <td><code>[<em>attr</em>~=<em>value</em>]</code></td> + <td><code>p[class~="special"]</code></td> + <td> + <p>Corresponde a elementos com um atributo attr cujo valor é exatamente value, ou contém valor em sua lista de valores (separados por espaço).</p> + </td> + </tr> + <tr> + <td><code>[<em>attr</em>|=<em>value</em>]</code></td> + <td><code>div[lang|="zh"]</code></td> + <td>Corresponde a elementos com um atributo attr cujo valor é exatamente value ou começa com value imediatamente seguido por um hífen.</td> + </tr> + </tbody> +</table> + +<p>No exemplo abaixo você pode ver esses seletores sendo usados.</p> + +<ul> + <li>usando <code>li[class]</code> podemos combinar qualquer seletor com um atributo de classe. Isso corresponde a todos os itens da lista, <u>exceto o primeiro.</u></li> + <li><code>li[class="a"]</code> corresponde a um seletor com uma classe de a, mas não a um seletor com uma classe de a com outra classe separada por espaço como parte do valor. Ele seleciona o segundo item da lista.</li> + <li><code>li[class~="a"]</code> corresponderá a uma classe de a, mas também a um valor que contém a classe de a como parte de uma lista separada por espaços em branco. Ele seleciona o segundo e o terceiro itens da lista.</li> +</ul> + +<ul> +</ul> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/attribute.html", '100%', 800)}}</p> + +<h2 id="Seletores_de_SubString">Seletores de SubString</h2> + +<p>Esses seletores permitem uma correspondência mais avançada de substrings dentro do valor do seu atributo. Por exemplo, se você tivesse classes de <code>box-warning</code> e <code>box-error</code> e quisesse combinar tudo que começou com a string "box-", você poderia usar <code>[class^="box-"]</code> para selecionar os dois (ou <code>[class|="box"]</code> como descrito abaixo).</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Selector</th> + <th scope="col">Example</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>[<em>attr</em>^=<em>value</em>]</code></td> + <td><code>li[class^="box-"]</code></td> + <td>Corresponde a elementos com um atributo attr (cujo nome é o valor entre colchetes), cujo valor começa com valor.</td> + </tr> + <tr> + <td><code>[<em>attr</em>$=<em>value</em>]</code></td> + <td><code>li[class$="-box"]</code></td> + <td>Corresponde a elementos com um atributo attr cujo valor termina com valor.</td> + </tr> + <tr> + <td><code>[<em>attr</em>*=<em>value</em>]</code></td> + <td><code>li[class*="box"]</code></td> + <td>Corresponde a elementos com um atributo attr cujo valor contém o valor em qualquer lugar dentro da string.</td> + </tr> + </tbody> +</table> + +<p>(À parte/lado: pode ser útil notar que <code>^</code> e <code>$</code> há muito são usados como âncoras nas chamadas expressões regulares para significar que começa com e termina com.)</p> + +<p>O próximo exemplo mostra o uso desses seletores:</p> + +<ul> + <li>li [class ^ = "a"] corresponde a qualquer valor de atributo que comece com a, portanto, corresponde aos dois primeiros itens da lista.</li> + <li>li [class $ = "a"] corresponde a qualquer valor de atributo que termina com a, portanto, corresponde ao primeiro e terceiro item da lista.</li> + <li>li [class * = "a"] corresponde a qualquer valor de atributo onde a apareça em qualquer lugar na string, portanto, corresponde a todos os itens da nossa lista</li> +</ul> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/attribute-substring.html", '100%', 800)}}</p> + +<h2 id="Case-sensitivity">Case-sensitivity</h2> + +<p>Se você deseja combinar valores de atributo sem distinção entre maiúsculas e minúsculas, você pode usar o valor i antes do colchete de fechamento. Este sinalizador informa ao navegador para corresponder caracteres ASCII sem distinção entre maiúsculas e minúsculas. Sem o sinalizador, os valores serão correspondidos de acordo com a distinção entre maiúsculas e minúsculas do idioma do documento - no caso do HTML, será sensível a maiúsculas e minúsculas.</p> + +<p>No exemplo abaixo, o primeiro seletor corresponderá a um valor que começa com um - ele corresponde apenas ao primeiro item da lista porque os outros dois itens da lista começam com um A maiúsculo. O segundo seletor usa o sinalizador que não diferencia maiúsculas de minúsculas e, portanto, corresponde a todos os itens da lista.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/attribute-case.html", '100%', 800)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Há tambem um valor mais novo <code>s</code>, que forçará a correspondência com distinção entre maiúsculas e minúsculas em contextos em que a correspondência normalmente não diferencia maiúsculas de minúsculas; no entanto, isso não é bem suportado em navegadores e não é muito útil em um contexto HTML.</p> +</div> + +<h2 id="Próximos_passos">Próximos passos</h2> + +<p>Agora que terminamos com os seletores de atributo, você pode continuar no próximo artigo e ler sobre <a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">pseudo-class and pseudo-element selectors</a>.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors", "Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">Cascade and inheritance</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">CSS selectors</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Type, class, and ID selectors</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Attribute selectors</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Pseudo-classes and pseudo-elements</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Combinators</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">The box model</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Backgrounds and borders</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">Handling different text directions</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">Overflowing content</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Values and units</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Sizing items in CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Images, media, and form elements</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Styling tables</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Debugging CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizing your CSS</a></li> +</ol> diff --git a/files/pt-br/learn/css/building_blocks/selectors/index.html b/files/pt-br/learn/css/building_blocks/selectors/index.html new file mode 100644 index 0000000000..34562ced95 --- /dev/null +++ b/files/pt-br/learn/css/building_blocks/selectors/index.html @@ -0,0 +1,234 @@ +--- +title: CSS selectors +slug: Learn/CSS/Building_blocks/Selectors +tags: + - Attribute + - Beginner + - CSS + - Class + - Learn + - NeedsTranslation + - Pseudo + - Selectors + - TopicStub + - id +translation_of: Learn/CSS/Building_blocks/Selectors +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Cascade_and_inheritance", "Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors", "Learn/CSS/Building_blocks")}}</div> + +<p class="summary">Em {{Glossary("CSS")}}, <font>os seletores são usados para direcionar os </font><font>elementos</font> {{glossary("HTML")}} <font>em nossas páginas da web que queremos estilizar. </font><font>Há uma grande variedade de seletores CSS disponíveis, permitindo uma precisão refinada ao selecionar os elementos a serem estilizados. </font><font>Neste artigo e seus sub-artigos, examinaremos os diferentes tipos em grande detalhe, vendo como eles funcionam.</font></p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td><font><font>Conhecimento </font><font>básico de informática, </font></font><a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Installing_basic_software"><font><font>software básico instalado</font></font></a><font><font> , conhecimento básico de como </font></font><a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Dealing_with_files"><font><font>trabalhar com arquivos</font></font></a><font><font> , conceitos básicos de HTML (estude </font></font><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML"><font><font>Introdução ao HTML</font></font></a><font><font> ) e uma ideia de como o CSS funciona (estude os </font></font><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps"><font><font>primeiros passos do CSS</font></font></a><font><font> ).</font></font></td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Para saber como os seletores CSS funcionam em detalhes.</td> + </tr> + </tbody> +</table> + +<h2 id="O_que_é_um_seletor"><font><font>O que é um seletor?</font></font></h2> + +<p><font><font>Você já conheceu os seletores. </font><font>Um seletor CSS é a primeira parte de uma regra CSS. </font><font>É um padrão de elementos e outros termos que informam ao navegador quais elementos HTML devem ser selecionados para que os valores de propriedade CSS dentro da regra sejam aplicados a eles. </font><font>O elemento ou elementos que são selecionados pelo seletor são referidos como o </font></font><em><font><font>assunto do seletor</font></font></em><font><font> .</font></font></p> + +<p><img alt="Some code with the h1 highlighted." src="https://mdn.mozillademos.org/files/16550/selector.png" style="border: 1px solid #cccccc; height: 218px; width: 471px;"></p> + +<p><font><font>Em artigos anteriores, você conheceu alguns seletores diferentes e aprendeu que existem seletores que direcionam o documento de maneiras diferentes - por exemplo, selecionando um elemento como </font></font><code>h1</code><font><font>, ou uma classe como </font></font><code>.special</code><font><font>.</font></font></p> + +<p><font><font>Em CSS, os seletores são definidos na especificação dos seletores CSS; </font><font>como qualquer outra parte do CSS, eles precisam ter suporte em navegadores para funcionarem. </font><font>A maioria dos seletores que você encontrará são definidos na </font></font><a href="https://www.w3.org/TR/selectors-3/" rel="noopener"><font><font>especificação de Seletores de nível 3</font></font></a><font><font> , que é uma especificação madura, portanto, você encontrará um excelente suporte de navegador para esses seletores.</font></font></p> + +<h2 id="Listas_de_seleção"><font><font>Listas de seleção</font></font></h2> + +<p><font><font>Se você tiver mais de um item que usa o mesmo CSS, os seletores individuais podem ser combinados em uma </font></font><em><font><font>lista de seletores</font></font></em><font><font> para que a regra seja aplicada a todos os seletores individuais. </font><font>Por exemplo, se eu tiver o mesmo CSS para um </font></font><code>h1</code><font><font>e também para uma classe de </font></font><code>.special</code><font><font>, poderia escrever isso como duas regras separadas.</font></font></p> + +<pre class="brush: css notranslate"><code>h1 { + color: blue; +} + +.special { + color: blue; +} </code></pre> + +<p><font><font>Eu também poderia combiná-los em uma lista de seletores, adicionando uma vírgula entre eles.</font></font></p> + +<pre class="brush: css notranslate"><code>h1, .special { + color: blue; +} </code></pre> + +<p><font><font>O espaço em branco é válido antes ou depois da vírgula. </font><font>Você também pode achar os seletores mais legíveis se cada um estiver em uma nova linha.</font></font></p> + +<pre class="brush: css notranslate"><code>h1, +.special { + color: blue; +} </code></pre> + +<p><font>No exemplo ao vivo abaixo, tente combinar os dois seletores que têm declarações idênticas. </font><font>A exibição visual deve ser a mesma após combiná-los.</font></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/selector-list.html", '100%', 1000)}} </p> + +<p><font><font>Ao agrupar seletores dessa forma, se algum seletor for inválido, a regra inteira será ignorada.</font></font></p> + +<p><font><font>No exemplo a seguir, a regra do seletor de classe inválida será ignorada, enquanto o </font></font><code>h1</code><font><font>ainda seria estilizado.</font></font></p> + +<pre class="brush: css notranslate"><code>h1 { + color: blue; +} + +..special { + color: blue; +} </code></pre> + +<p><font><font>Quando combinados, no entanto, nem o </font></font><code>h1</code><font><font>nem a classe terão o estilo, pois a regra inteira é considerada inválida.</font></font></p> + +<pre class="brush: css notranslate"><code>h1, ..special { + color: blue; +} </code></pre> + +<h2 id="Tipos_de_seletores"><font><font>Tipos de seletores</font></font></h2> + +<p><font><font>Existem alguns agrupamentos diferentes de seletores e saber qual tipo de seletor você pode precisar o ajudará a encontrar a ferramenta certa para o trabalho. </font><font>Nos subartículos deste artigo, examinaremos os diferentes grupos de seletores com mais detalhes.</font></font></p> + +<h3 id="Seletores_de_tipo_classe_e_ID"><font><font>Seletores de tipo, classe e ID</font></font></h3> + +<p><font><font>Este grupo inclui seletores que têm como alvo um elemento HTML, como um </font></font><code><h1></code><font><font>.</font></font></p> + +<pre class="brush: css notranslate">h1 { }</pre> + +<p><font><font>Também inclui seletores que direcionam uma classe:</font></font></p> + +<pre class="brush: css notranslate">.box { }</pre> + +<p><font><font>ou um ID:</font></font></p> + +<pre class="brush: css notranslate">#unique { }</pre> + +<h3 id="Seletores_de_atributos"><font><font>Seletores de atributos</font></font></h3> + +<p><font><font>Este grupo de seletores oferece diferentes maneiras de selecionar elementos com base na presença de um determinado atributo em um elemento:</font></font></p> + +<pre class="brush: css notranslate">a[title] { }</pre> + +<p><font><font>Ou até mesmo faça uma seleção com base na presença de um atributo com um valor específico:</font></font></p> + +<pre class="brush: css notranslate">a[href="https://example.com"] { }</pre> + +<h3 id="Pseudo_classes_e_pseudo-elementos"><font><font>Pseudo classes e pseudo-elementos</font></font></h3> + +<p><font><font>Este grupo de seletores inclui pseudo classes, que definem o estilo de certos estados de um elemento. </font><font>A </font></font><code>:hover</code><font><font>pseudoclasse, por exemplo, seleciona um elemento apenas quando ele está sendo passado pelo ponteiro do mouse:</font></font></p> + +<pre class="brush: css notranslate">a:hover { }</pre> + +<p><font><font>Também inclui pseudoelementos, que selecionam uma determinada parte de um elemento em vez do próprio elemento. </font><font>Por exemplo, </font></font><code>::first-line</code><font><font>sempre seleciona a primeira linha de texto dentro de um elemento (a </font></font><code><p></code><font><font>no caso abaixo), agindo como se a tivesse </font></font><code><span></code><font><font>sido colocado em volta da primeira linha formatada e então selecionado.</font></font></p> + +<pre class="brush: css notranslate">p::first-line { }</pre> + +<h3 id="Combinadores"><font><font>Combinadores</font></font></h3> + +<p><font><font>O grupo final de seletores combina outros seletores para direcionar os elementos em nossos documentos. </font><font>O seguinte, por exemplo, seleciona parágrafos que são filhos diretos de </font></font><code><article></code><font><font>elementos usando o combinador filho ( </font></font><code>></code><font><font>):</font></font></p> + +<pre class="brush: css notranslate">article > p { }</pre> + +<h2 id="Próximos_passos"><font><font>Próximos passos</font></font></h2> + +<p><font><font>Você pode dar uma olhada na tabela de referência de seletores abaixo para obter links diretos para os vários tipos de seletores nesta seção Aprender ou no MDN em geral, ou continuar para iniciar sua jornada descobrindo sobre </font></font><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors"><font><font>seletores de tipo, classe e ID</font></font></a><font><font> .</font></font></p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Cascade_and_inheritance", "Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="Tabela_de_referência_de_seletores"><font><font>Tabela de referência de seletores</font></font></h2> + +<p><font><font>A tabela a seguir fornece uma visão geral dos seletores disponíveis para uso, juntamente com links para as páginas deste guia que mostram como usar cada tipo de seletor. </font><font>Também incluí um link para a página MDN de cada seletor, onde você pode verificar as informações de suporte do navegador. </font><font>Você pode usar isso como uma referência para voltar quando precisar consultar os seletores mais tarde no material, ou quando você experimentar CSS em geral.</font></font></p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Selector</th> + <th scope="col">Example</th> + <th scope="col">Learn CSS tutorial</th> + </tr> + </thead> + <tbody> + <tr> + <td><a href="/en-US/docs/Web/CSS/Type_selectors">Type selector</a></td> + <td><code>h1 { }</code></td> + <td><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors#Type_selectors">Type selectors</a></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/CSS/Universal_selectors">Universal selector</a></td> + <td><code>* { }</code></td> + <td><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors#The_universal_selector">The universal selector</a></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/CSS/Class_selectors">Class selector</a></td> + <td><code>.box { }</code></td> + <td><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors#Class_selectors">Class selectors</a></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/CSS/ID_selectors">id selector</a></td> + <td><code>#unique { }</code></td> + <td><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors#ID_Selectors">ID selectors</a></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/CSS/Attribute_selectors">Attribute selector</a></td> + <td><code>a[title] { }</code></td> + <td><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Attribute selectors</a></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/CSS/Pseudo-classes">Pseudo-class selectors</a></td> + <td><code>p:first-child { }</code></td> + <td><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseuso-classes_and_Pseudo-elements#What_is_a_pseudo-class">Pseudo-classes</a></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/CSS/Pseudo-elements">Pseudo-element selectors</a></td> + <td><code>p::first-line { }</code></td> + <td><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseuso-classes_and_Pseudo-elements#What_is_a_pseudo-element">Pseudo-elements</a></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/CSS/Descendant_combinator">Descendant combinator</a></td> + <td><code>article p</code></td> + <td><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators#Descendant_Selector">Descendant combinator</a></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/CSS/Child_combinator">Child combinator</a></td> + <td><code>article > p</code></td> + <td><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators#Child_combinator">Child combinator</a></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/CSS/Adjacent_sibling_combinator">Adjacent sibling combinator</a></td> + <td><code>h1 + p</code></td> + <td><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators#Adjacent_sibling">Adjacent sibling</a></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/CSS/General_sibling_combinator">General sibling combinator</a></td> + <td><code>h1 ~ p</code></td> + <td><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators#General_sibling">General sibling</a></td> + </tr> + </tbody> +</table> + +<h2 id="In_this_module">In this module</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">Cascade and inheritance</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">CSS selectors</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Type, class, and ID selectors</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Attribute selectors</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Pseudo-classes and pseudo-elements</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Combinators</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">The box model</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Backgrounds and borders</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">Handling different text directions</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">Overflowing content</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Values and units</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Sizing items in CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Images, media, and form elements</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Styling tables</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Debugging CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizing your CSS</a></li> +</ol> diff --git a/files/pt-br/learn/css/css_layout/flexbox/index.html b/files/pt-br/learn/css/css_layout/flexbox/index.html new file mode 100644 index 0000000000..f6e68c94d7 --- /dev/null +++ b/files/pt-br/learn/css/css_layout/flexbox/index.html @@ -0,0 +1,342 @@ +--- +title: Flexbox +slug: Learn/CSS/CSS_layout/Flexbox +tags: + - Aprender + - Artigo + - CSS + - Caixas Flexíveis + - Flex + - Guía + - Iniciante + - Layout + - flexbox + - grid css + - laioutes css + - ordenação +translation_of: Learn/CSS/CSS_layout/Flexbox +--- +<div> +<p>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/CSS_layout/Practical_positioning_examples", "Learn/CSS/CSS_layout/Grids", "Learn/CSS/CSS_layout")}}</p> +</div> + +<p class="summary">Uma nova tecnologia, mas com suporte bastante difundido entre navegadores, o Flexbox está se tornando apto para uso geral. Flexbox provê ferramentas para criação rápida de layouts complexos e flexíveis, e características que se mostraram historicamente difíceis com CSS. Este artigo explica todos os seus fundamentos.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>HTML básico (estude <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introdução a HTML</a>), e uma ideia de como CSS funciona (estude <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">Introdução a CSS</a>.)</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender como usar o sistema de Flexbox layout para criar web layouts.</td> + </tr> + </tbody> +</table> + +<h2 id="Por_quê_Flexbox">Por quê <em>Flexbox</em>?</h2> + +<p>Por um longo tempo, as únicas ferramentas compatíveis entre browsers disponíveis para criação de layouts CSS eram coisas como <a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">floats</a> e <a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">posicionamento</a>. Estas são boas e funcionam, mas em alguns casos também são limitadas e frustrantes.</p> + +<p>Os requisitos de layouts a seguir são difíceis ou impossíveis de se conseguir com estas ferramentas, em qualquer tipo conveniente e flexível:</p> + +<ul> + <li>Centralizar um bloco de conteúdo verticalmente dentro de seu pai.</li> + <li>Fazer com que os filhos de um container ocupe uma quantidade igual de largura/altura disponível, independente da quantidade de largura/altura disponível.</li> + <li>Fazer todas as colunas de um layout com múltiplas colunas adotem a mesma altura, mesmo que contenham uma quantidade diferente de conteúdo.</li> +</ul> + +<p>Como você verá nas seções subsequentes, <em>flexbox</em> faz muitas tarefas de layouts de maneira mais fácil. Vamos nos aprofundar!</p> + +<h2 id="Introduzindo_um_exemplo_simples">Introduzindo um exemplo simples</h2> + +<p>Neste artigo nós vamos trabalhar uma série de exercícios para ajudá-lo a entender como o flexbox funciona. Para começar, você deve fazer uma cópia local do arquivo inicial — <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/flexbox/flexbox0.html">flexbox0.html</a> do nosso repositório no github — carregue-o em um navegador moderno (como Firefox ou Chrome), e abra o arquivo no seu editor de código. Você pode <a href="http://mdn.github.io/learning-area/css/css-layout/flexbox/flexbox0.html">ver a página aqui</a> também.</p> + +<p>Você verá que temos um elemento {{HTMLElement("header")}} com um cabeçalho no nível superior dentro dele, e um elemento {{HTMLElement("section")}} contendo três {{HTMLElement("article")}}s. Nós vamos usá-los para criar um layout padrão de três colunas.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13406/flexbox-example1.png" style="border-style: solid; border-width: 1px; display: block; height: 324px; margin: 0px auto; width: 800px;"></p> + +<h2 id="Especificando_os_elementos_a_serem_definidos_como_caixas_flex">Especificando os elementos a serem definidos como caixas <em>flex</em></h2> + +<p>Para iniciar, vamos definir quais elementos serão flexible boxes. Para isto, temos que definir um valor especial de {{cssxref("display")}} no elemento pai dos elementos que queremos afetar. neste caso são os elementos {{HTMLElement("article")}}, portanto vamos definir o valor no elemento {{HTMLElement("section")}} (que se torna um flex container):</p> + +<pre class="brush: css">section { + display: flex; +}</pre> + +<p>O resultado disso deve ser algo assim:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13408/flexbox-example2.png" style="border-style: solid; border-width: 1px; display: block; height: 348px; margin: 0px auto; width: 800px;"></p> + +<p>Então, esta única declaração nos dá tudo que precisamos — incrivel, certo? Nós temos um layout de múltiplas com tamanhos iguais, e todas as colunas tem a mesma altura. Isto porque o valor padrão dado aos flex items (os filhos do flex container) são configurados para resolver problemas comuns, como este. Voltaremos a este assunto depois.</p> + +<div class="note"> +<p><strong>Nota</strong>: Você pode definir também ao {{cssxref("display")}} o valor <code>inline-flex</code> se quiser colocar os items em linha como flexible boxes.</p> +</div> + +<h2 id="Um_aparte_no_modelo_flex">Um aparte no modelo <em>flex</em></h2> + +<p>Quando os elementos são definidos como flexibles boxes, eles são dispostos ao longo de dois eixos:</p> + +<p><img alt="flex_terms.png" class="default internal" src="/files/3739/flex_terms.png" style="display: block; margin: 0px auto;"></p> + +<ul> + <li>O <em><strong>main axis</strong></em> é o eixo que corre na direção em que os flex items estão dispostos (por exemplo, as linhas da página, ou colunas abaixo da página.) O início e o fim do eixo é chamado <em><strong>main start</strong></em> e <em><strong>main end</strong></em>.</li> + <li>O <em><strong>cross axis</strong></em> é o eixo perpendicular que corre na direção em que os flex items são dispostos. O início e o fim deste eixo são chamados de <em><strong>cross start</strong></em> e <em><strong>cross end</strong></em>.</li> + <li>O elemento pai que possui <code>display: flex</code> configurado ( {{HTMLElement("section")}} em nosso exemplo) é chamado de <em><strong>flex container</strong></em>.</li> + <li>Os itens iniciados como flexible boxes dentro do flex container são chamados <em><strong>flex items</strong></em> (o {{HTMLElement("article")}} em nosso caso).</li> +</ul> + +<p>Tenha esta terminologia em mente à medida que passar para as seções subsequentes. Você pode voltar a esta referência se ficar confuso quanto aos termos usados inicialmente.</p> + +<h2 id="Colunas_ou_linhas">Colunas ou linhas?</h2> + +<p>Flexbox possui uma propriedade chamada {{cssxref("flex-direction")}} que especifica a direção do eixo principal (em qual direção os filhos da <em>flexbox</em> estarão arranjados) — que por padrão seu valor é <code>row</code> (linha), que faz com que eles fiquem arranjados numa linha na direção que o seu navegador está configurado de acordo com a direção de leitura do seu idioma (da esquerda para a direita, no caso do inglês ou português).</p> + +<p>Experimente adicionar a seguinte declaração na seção de sua regra:</p> + +<pre class="brush: css">flex-direction: column;</pre> + +<p>Você verá que isso organiza os elementos no laioute de coluna, assim como eles estavam antes de adicionarmos qualquer regra CSS. Antes de você seguir, remova essa declaração do seu exemplo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Você também pode arranjar itens flexíveis em direção reversa usando os valores <code>row-reverse</code> e <code>column-reverse</code>. Experimente usar esses valores no seu exemplo também!</p> +</div> + +<h2 id="Embrulhamento">Embrulhamento</h2> + +<p>Um problema que aparece quando você tem uma quantidade fixa de elementos com a mesma largura e altura no seu esquema é que eventualmente seus elementos filhos <em>flexbox</em> irão sobrepor seu elemento pai (<em>container</em>), quebrando o laioute. Dê uma olhada no nosso exemplo <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/flexbox/flexbox-wrap0.html">flexbox-wrap0.html</a>, e experimente <a href="http://mdn.github.io/learning-area/css/css-layout/flexbox/flexbox-wrap0.html">visualizá-lo online</a> (tenha uma cópia local desse arquivo no seu computador se você quiser continuar acompanhando os exemplos):</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13410/flexbox-example3.png" style="display: block; height: 646px; margin: 0px auto; width: 800px;"></p> + +<p>Aqui vemos que os filhos estão de fato saindo fora do elemento recipiente (<em>container</em>). Uma maneira de consertar isso é adicionando a seguinte declaração na seção de sua regra CSS:</p> + +<pre class="brush: css">flex-wrap: wrap;</pre> + +<p>Experimente isso agora; você verá que o laioute parece muito melhor agora com essa regra:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13412/flexbox-example4.png" style="display: block; height: 646px; margin: 0px auto; width: 800px;">Agora temos várias linhas — tantos elementos filhos <em>flexbox</em> estão encaixados em cada linha quantos fazem sentido, e qualquer sobreposição é movida para a próxima linha. A declaração <code>flex: 200px</code> configurada nos elementos {{htmlelement("article")}} significa que cada um terá pelo menos 200 pixels de largura; discutiremos essa propriedade mais detalhadamente mais tarde. Você também deve notar que os últimos filhos na última linha estão mais largos para que a linha inteira possa ser preenchida.</p> + +<p>Mas ainda tem mais para fazermos com isso. Primeiro, experimente mudar sua propriedade {{cssxref("flex-direction")}} para o valor <code>row-reverse</code> — agora você verá que ainda tem um laioute com várias linhas, mas ele começa no canto oposto da janela do navegador e segue na direção reversa.</p> + +<h2 id="Forma_abreviada_flex-flow">Forma abreviada: <em>flex-flow</em></h2> + +<p>A esta altura vale ressaltar que existe uma abreviação para as regras {{cssxref("flex-direction")}} e {{cssxref("flex-wrap")}}: a {{cssxref("flex-flow")}}. Logo, você pode substituir as seguintes regras</p> + +<pre class="brush: css">flex-direction: row; +flex-wrap: wrap;</pre> + +<p>por</p> + +<pre class="brush: css">flex-flow: row wrap;</pre> + +<h2 id="Dimensionamento_flexível_de_elementos_flex">Dimensionamento flexível de elementos <em>flex</em></h2> + +<p>Vamos agora voltar ao nosso primeiro exemplo, e ver como podemos controlar qual a proporção de espaço os elementos <em>flex</em> pode tomar. Localize sua cópia local do arquivo <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/flexbox/flexbox0.html">flexbox0.html</a>, ou tenha uma cópia de <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/flexbox/flexbox1.html">flexbox1.html</a> como um novo ponto de partida (<a href="http://mdn.github.io/learning-area/css/css-layout/flexbox/flexbox1.html">veja online</a>).</p> + +<p>Primeiro adicione a seguinte regra no final do seu CSS:</p> + +<pre class="brush: css">article { + flex: 1; +}</pre> + +<p>Esse é um valor relativo sem unidade que define quanto de espaço disponível pelo eixo principal cada elemento <em>flex</em> pode ter. Neste caso, estamos dando para cada elemento {{HTMLElement("article")}} o valor de 1, que significa que eles terão uma quantidade igual de espaço restante depois de coisas como preenchimento ({{cssxref("padding")}}) e margem ({{cssxref("margin")}})<em> </em>forem definidos. É uma proporção, o que significa que dado que mesmo que você coloque o valor de "400000", para cada elemento <em>flex</em>, terá o mesmo efeito que o valor "1" previamente colocado.</p> + +<p>Agora, adicione a seguinte regra abaixo da última:</p> + +<pre class="brush: css">article:nth-of-type(3) { + flex: 2; +}</pre> + +<p>Assim que você atualizar a página, você verá que o terceiro elemento {{HTMLElement("article")}} ocupa duas vezes mais do espaço disponível que os outros dois — existe agora quatro unidades na proporção total disponível. Os dois primeiros elementos <em>flex</em> tem uma unidade cada, dessa proporção, logo cada um deles ocupam 1/4 do espaço disponível. O terceiro tem 2 unidades, logo ele ocupa 2/4 (ou metade, 1/2) do espaço disponível. </p> + +<p>Você também pode especificar um valor de tamanho mínimo para a regra <em>flex</em>. Experimente atualizar a regra para o {{HTMLElement("article")}} existente para que fique assim:</p> + +<pre class="brush: css">article { + flex: 1 200px; +} + +article:nth-of-type(3) { + flex: 2 200px; +}</pre> + +<p>Isso basicamente diz o seguinte: "Para cada elemento <em>flex</em> primeiro será dado 200px do espaço disponível. Depois, o restante do espaço disponível será distribuído entre os elementos, de acordo com a unidade de proporção definida.". Atualize a página e você verá a diferença de como o espaço é distribuído.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13406/flexbox-example1.png" style="border-style: solid; border-width: 1px; display: block; height: 324px; margin: 0px auto; width: 800px;"></p> + +<p>O valor real de cada caixa <em>flex</em> pode ser visto pela sua flexibilidade/responsividade — se você redimensionar a janela do navegador, ou adicionar outro elemento {{HTMLElement("article")}}, o laioute continua funcionando sem quebrar.</p> + +<h2 id="flex_Forma_abreviada_ou_forma_normal"><em>flex</em>: Forma abreviada ou forma normal?</h2> + +<p>{{cssxref("flex")}} é uma propriedade abreviada que pode especificar até três valores diferentes:</p> + +<ul> + <li>O valor de proporção sem unidade que falamos sobre ele acima. Ele também pode ser especificado individualmente usando a regra {{cssxref("flex-grow")}}.</li> + <li>Um segundo valor de proporção sem unidade — {{cssxref("flex-shrink")}} — que convém ser usado quando os elementos <em>flex</em> estão sobrepondo a elemento recipiente (<em>container</em>). Este especifica qual a quantidade será retirada do tamanho de cada elemento <em>flex</em>, para que ele não ultrapasse o valor do elemento recipiente (<em>container</em>). Esta é uma funcionalidade bem avançada do <em>flexbox</em>, e não será abordada neste artigo.</li> + <li>O valor mínimo para o tamanho que discutimos acima. Este pode ser especificado individualmente usando a regra {{cssxref("flex-basis")}}.</li> +</ul> + +<p>Aconselhamos usar sempre a forma abreviada a menos que você precise usar a regra normal (por exemplo para sobrescrever algum valor pré-definido). As regras normais, isto é não abreviadas, geram muito mais código e podem gerar confusão.</p> + +<h2 id="Alinhamento_Horizontal_e_Vertical">Alinhamento Horizontal e Vertical</h2> + +<p>Você também pode usar as funcionalidade do <em>flexbox</em> para alinhar elementos no eixo principal ou no eixo transversal (relembre esse assunto na seção <a href="/pt-BR/docs/Learn/CSS/CSS_layout/Flexbox#Um_aparte_no_modelo_flex">Um aparte no modelo flex</a>). Vamos explorar isso olhando para um outro exemplo — <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/flexbox/flex-align0.html">flex-align0.html</a> (<a href="http://mdn.github.io/learning-area/css/css-layout/flexbox/flex-align0.html">veja online</a>) — o qual vamos transformá-lo num botão/barra de ferramentas bem feito e flexível. Neste momento você verá uma barra de menu horizontal, com alguns botões expremidos no canto superior esquerdo:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13414/flexbox-example5.png" style="display: block; height: 77px; margin: 0px auto; width: 600px;"></p> + +<p>Primeiro, tenha uma cópia local desse exemplo.</p> + +<p>Agora, adicione o seguinte trecho ao final do CSS no arquivo do exemplo:</p> + +<pre class="brush: css">div { + display: flex; + align-items: center; + justify-content: space-around; +}</pre> + +<p>Atualize a página e você verá que os botões estão agora bem arranjados no centro, horizontalmente e verticalmente. Fizemos isso através de duas novas propriedades.</p> + +<div class="note"> +<p><strong>Nota</strong>: Nesse exemplo, o eixo principal é representado horizontalmente e o eixo transversal é o vertical.</p> +</div> + +<p>{{cssxref("align-items")}} controla onde os elementos <em>flex</em> ficam no eixo transversal:</p> + +<ul> + <li>Por padrão, seu valor é <code>stretch</code>, que estica todos os elementos <em>flex</em> para preencher o elemento pai na direção do eixo transversal. Se o elemento pai não tem largura fixa na direção do eixo transversal, então todos os elementos <em>flex</em> esticarão até o mais comprido dos elementos <em>flex</em>. Foi assim que o nosso primeiro exemplo ficou com colunas de mesma altura por padrão.</li> + <li>O valor <code>center</code> que usamos no exemplo acima, faz com que os elementos mantenham suas dimensões intrínsecas, mas que seja centralizados ao longo do eixo transversal. É por isso que os botões do nosso exemplo atual estão centralizados verticalmente.</li> + <li>Você também pode colocar valores como <code>flex-start</code> e <code>flex-end</code>, os quais alinharão todos os elementos no início ou fim do eixo transversal, respectivamente. Veja {{cssxref("align-items")}} para maiores detalhes.</li> +</ul> + +<p>Você pode sobrescrever o comportamento de {{cssxref("align-items")}} para elementos individuais, usando a regra {{cssxref("align-self")}} nesses elementos. Por exemplo, experimente adicionar o seguinte trecho no seu CSS:</p> + +<pre class="brush: css">button:first-child { + align-self: flex-end; +}</pre> + +<p>Veja qual efeito isso dá, e remova novamente quando terminar.</p> + +<p>{{cssxref("justify-content")}} controla onde os elementos <em>flex</em> ficam no eixo principal.</p> + +<ul> + <li>O valor padrão é <code>flex-start</code>, que faz com que todos os elementos estejam no início do eixo principal.</li> + <li>Você pode usar <code>flex-end</code> para que eles fiquem no final.</li> + <li><code>center</code> também é um valor para {{cssxref("justify-content")}}, e fará com que os elementos <em>flex</em> fiquem no centro do eixo principal.</li> + <li>O valor que usamos acima, <code>space-around</code>, é útil pois ele distribui todos os elementos igualmente pelo eixo principal, com um pouquinho de espaço no final.</li> + <li>Existe um outro valor, <code>space-between</code>, o qual é muito similar ao <code>space-around</code>, exceto que ele não deixa nenhum espaço no final.</li> +</ul> + +<p>Nós sugerimos que você brinque um pouco mais com essas regras e seus valores para ver como funcionam ainda mais, antes de seguir nos estudos.</p> + +<h2 id="Ordenação_de_elementos_flex">Ordenação de elementos <em>flex</em></h2> + +<p>O <em>flexbox</em> também tem uma funcionalidade para alteração da ordem dos elementos <em>flex</em> no laioute, sem afetar a ordem no código fonte HTML. Esta é mais uma coisa que é impossível fazer nos métodos tradicionais de esquema de laioutes.</p> + +<p>O código para fazer isso é bem simples: experimente adicionar o seguinte CSS ao final do código do exemplo da barra de botões:</p> + +<pre class="brush: css">button:first-child { + order: 1; +}</pre> + +<p>Atualize seu navegador, você verá que o botão "<em>Smile</em>" foi movido para o final do eixo principal. Vamos falar sobre como isso funciona com mais detalhes:</p> + +<ul> + <li>Por padrão, todos os elementos <em>flex</em> possuem uma propriedade {{cssxref("order")}} com valor 0 (zero).</li> + <li>Elementos <em>flex</em> com valores maiores de {{cssxref("order")}}, aparecerão depois na tela, do que elementos com valores menores, os quais aparecem antes.</li> + <li>Elementos <em>flex</em> com o mesmo valor aparecerão de acordo com a ordem que possuem no documento HTML. Logo, se você tiver quatro elementos com os seguintes valores para {{cssxref("order")}}: 2, 1, 1 e 0, eles aparecerão na tela na seguinte ordem: 4º, 2º, 3º e 1º elemento, respectivamente.</li> + <li>O 3º elemento aparece depois do 2º pois ele tem o mesmo valor para {{cssxref("order")}} mas está definido depois no documento fonte.</li> +</ul> + +<p>Você também pode usar valores negativos para fazer elementos aparecerem antes do(s) elemento(s) definidos com {{cssxref("order")}} 0 (zero). Por exemplo, Você poderia fazer com que o botão "<em>Blush</em>" aparecesse no começo do eixo principal (horizontal), usando a seguinte regra:</p> + +<pre class="brush: css">button:last-child { + order: -1; +}</pre> + +<h2 id="Elementos_flex_aninhados">Elementos <em>flex</em> aninhados</h2> + +<p>É possível criar laioutes bem complexos com <em>flexbox</em>. É perfeitamente aceitável configurar um elemento <em>flex</em> para também ser um <em>container</em>, para que seus filhos também se comportem como caixas <em>flex</em>. Dê uma olhada em <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/flexbox/complex-flexbox.html">complex-flexbox.html</a> (<a href="http://mdn.github.io/learning-area/css/css-layout/flexbox/complex-flexbox.html">veja também online</a>).</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13418/flexbox-example7.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>O HTML desse exemplo é relativamente simples. Temos um elemento {{HTMLElement("section")}} contendo três {{HTMLElement("article")}}. O terceiro desses {{HTMLElement("article")}} contém três elementos {{HTMLElement("div")}}:</p> + +<pre>section - article + article + article - div - button + div button + div button + button + button</pre> + +<p>Vamos dar uma olhada no código que usamos no laioute.</p> + +<p>Primeiro, configuramos para que os filhos da {{HTMLElement("section")}} se arranjem como elementos <em>flex</em>.</p> + +<pre class="brush: css">section { + display: flex; +}</pre> + +<p>Em seguida, configuramos alguns valores <em>flex</em> nos próprios elementos {{HTMLElement("article")}}. Veja especialmente a segunda regra aqui — estamos configurando para que o terceiro {{HTMLElement("article")}} tenha seus filhos arranjados como elementos <em>flex</em> também, mas desta vez eles estarão dispostos em coluna.</p> + +<pre class="brush: css">article { + flex: 1 200px; +} + +article:nth-of-type(3) { + flex: 3 200px; + display: flex; + flex-flow: column; +} +</pre> + +<p>Depois, selecionamos o primeiro elemento {{HTMLElement("div")}}. Primeiro usamos <code>flex:1 100px;</code> para efetivamente dar a ele a altura de 100px, depois configuramos para que seus filhos (os elementos {{HTMLElement("button")}}) se arranjem como elementos <em>flex</em>. Aqui, nós os arranjamos em uma linha que os envolvem, e os alinhamos no centro do espaço disponível, como fizemos no exemplo do botão individual que vimos anteriormente:</p> + +<pre class="brush: css">article:nth-of-type(3) div:first-child { + flex:1 100px; + display: flex; + flex-flow: row wrap; + align-items: center; + justify-content: space-around; +}</pre> + +<p>Finalmente, configuramos alguns tamanhos no botão, mas o mais interessante é que demos a ele o valor 1 para a propriedade <em>flex</em>. Isso dá um resultado interessante, que você verá se redimensionar a largura da janela do seu navegador. Esses botões tomarão o máximo de espaço que puderem e ficarão ao máximo na mesma linha, se puderem, mas quando não puderem mais caber na mesma linha, os que estão muito apertados irão para novas linhas de forma que o laioute não quebre e o conteúdo ainda esteja legível ao usuário.</p> + +<pre class="brush: css">button { + flex: 1; + margin: 5px; + font-size: 18px; + line-height: 1.5; +}</pre> + +<h2 id="Compatibilidade_entre_navegadores">Compatibilidade entre navegadores</h2> + +<p>O suporte a f<em>lexbox</em> está disponível nos navegadores mais novos — Firefox, Chrome, Opera, Microsoft Edge e IE 11, nas versões mais novas do Android e iOS, etc.<br> + Contudo você deve estar ciente que ainda existem navegadores antigos em uso que não suportam a regra <em>flexbox</em> (ou até suportam, mas numa versão desatualizada).</p> + +<p>Enquanto você está apenas aprendendo ou testando, a compatibilidade entre navegadores não importa muito; no entanto se você pretende usar o <em>flexbox</em> num site de verdade, você precisa fazer testes e certificar que a experiência do usuário é aceitável em qualquer navegador possível.</p> + +<p><em>Flexbox</em> é um pouco mais ardiloso que algumas propriedades CSS. Por exemplo, se o suporte a sombras de CSS falta num browser, é muito menos provável de comprometer a usabilidade, afinal apenas as sombras dos elementos que não estarão aparecendo. Contudo, a falta de suporte à propriedade <em>flexbox</em> pode quebrar o laioute do seu site, e comprometer a sua usabilidade.</p> + +<p>Iremos discutir estratégias para contornar problemas complicados de compatibilidade entre navegadores num módulo futuro.</p> + +<h2 id="Sumário">Sumário</h2> + +<p>Isso conclui nosso tour sobre o básico de <em>flexbox</em>. Esperamos que você tenha aproveitado, e que você continue aproveitando enquanto avança com seu aprendizado.<br> + No próximo tópico, veremos outro aspecto importante dos Esquemas em CSS: os sistemas de <em>grid, </em>como você pode ver nesse artigo sobre <a href="https://blog.alura.com.br/criando-layouts-com-css-grid-layout/">CSS grid layout</a>.</p> + +<div>{{PreviousMenuNext("Learn/CSS/CSS_layout/Practical_positioning_examples", "Learn/CSS/CSS_layout/Grids", "Learn/CSS/CSS_layout")}}</div> + +<div> +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introdução a Esquemas CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Flutuando Elementos com "float"</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Posicionamento de elementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Practical_positioning_examples">Exemplos práticos de posicionamento</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grids</a></li> +</ul> +</div> diff --git a/files/pt-br/learn/css/css_layout/fluxo_normal/index.html b/files/pt-br/learn/css/css_layout/fluxo_normal/index.html new file mode 100644 index 0000000000..c27a403fa7 --- /dev/null +++ b/files/pt-br/learn/css/css_layout/fluxo_normal/index.html @@ -0,0 +1,95 @@ +--- +title: Fluxo Normal +slug: Learn/CSS/CSS_layout/Fluxo_Normal +translation_of: Learn/CSS/CSS_layout/Normal_Flow +--- +<div>{{LearnSidebar}}</div> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Introduction", "Learn/CSS/CSS_layout/Flexbox", "Learn/CSS/CSS_layout")}}</p> + +<p class="summary">Este artigo aborda o <em>Fluxo Normal</em> de alinhamento e acomodação do conteúdo de uma página HTML, na qual o desenvolvedor não inseriu estilos pessoais. Este fluxo é um padrão usado pelos navegodares web. É uma solução preguiçosa ou rápida. Se o <em>Fluxo Normal</em> por ventura não desagradar o programador, poupado será o seu tempo e esforço. Com o ônus adiado para quando ele quiser algo diferente.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Introdução ao HTML (study <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introduction to HTML</a>), e uma noção de como o CSS funciona (study <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">Introduction to CSS</a>.)</td> + </tr> + <tr> + <th scope="row">Objectivo:</th> + <td>Explicar qual é o leiaute padrão aplicado pelos navegadores web - a um arquivo HTML - sempre que não houver estilo ou formatos definidos pelo desenvolvedor da referida página.</td> + </tr> + </tbody> +</table> + +<p>Conforme detalhado na última lição de introdução ao leiaute, os elementos em uma página da web acomodam-se em Fluxo Normal, quando não é aplicada qualquer regra CSS para alterar a maneira como estes se comportam. And, as we began to discover, you can change how elements behave either by adjusting their position in that normal flow, or removing them from it altogether. Starting with a solid, well-structured document that is readable in normal flow is the best way to begin any webpage. It ensures that your content is readable, even if the user is using a very limited browser or a device such as a screen reader that reads out the content of the page. In addition, as normal flow is designed to make a readable document, by starting in this way you are working with the document rather than fighting against it as you make changes to the layout.</p> + +<p>Before digging deeper into different layout methods, it is worth revisiting some of the things you will have studied in previous modules with regard to normal document flow.</p> + +<h2 id="How_are_elements_laid_out_by_default">How are elements laid out by default?</h2> + +<p>First of all, individual element boxes are laid out by taking the elements' content, then adding any padding, border and margin around them — it's that box model thing again, which we've looked at earlier.</p> + +<p>By default, a <a href="/en-US/docs/Web/HTML/Block-level_elements">block level element</a>'s content is 100% of the width of its parent element, and as tall as its content. <a href="/en-US/docs/Web/HTML/Inline_elements">Inline elements</a> are as tall as their content, and as wide as their content. You can't set width or height on inline elements — they just sit inside the content of block level elements. If you want to control the size of an inline element in this manner, you need to set it to behave like a block level element with <code>display: block;</code> (or even,<code>display: inline-block;</code> which mixes characteristics from both.)</p> + +<p>That explains individual elements, but what about how elements interact with one another? The normal layout flow (mentioned in the layout introduction article) is the system by which elements are placed inside the browser's viewport. By default, block-level elements are laid out in the <em>block flow direction</em>, based on the parent's <a href="/en-US/docs/Web/CSS/writing-mode">writing mode</a> (<em>initial</em>: horizontal-tb) — each one will appear on a new line below the last one, and they will be separated by any margin that is set on them. In English therefore, or any other horizontal, top to bottom writing mode, block-level elements are laid out vertically.</p> + +<p>Inline elements behave differently — they don't appear on new lines; instead, they sit on the same line as one another and any adjacent (or wrapped) text content, as long as there is space for them to do so inside the width of the parent block level element. If there isn't space, then the overflowing text or elements will move down to a new line.</p> + +<p>If two adjacent elements both have the margin set on them and the two margins touch, the larger of the two remains, and the smaller one disappears — this is called margin collapsing, and we have met this before too.</p> + +<p>Let's look at a simple example that explains all of this:</p> + +<div id="Normal_Flow"> +<pre class="brush: html"><h1>Basic document flow</h1> + +<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p> + +<p>By default we span 100% of the width of our parent element, and we are as tall as our child content. Our total width and height is our content + padding + border width/height.</p> + +<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p> + +<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements will <span>wrap onto a new line if possible (like this one containing text)</span>, or just go on to a new line if not, much like this image will do: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +p { + background: rgba(255,84,104,0.3); + border: 2px solid rgb(255,84,104); + padding: 10px; + margin: 10px; +} + +span { + background: white; + border: 1px solid black; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Normal_Flow', '100%', 500) }}</p> + +<h2 id="Summary">Summary</h2> + +<p>Now that you understand normal flow, and how the browser lays things out by default, move on to understand how to change this default display to create the layout needed by your design.</p> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Introduction", "Learn/CSS/CSS_layout/Flexbox", "Learn/CSS/CSS_layout")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introduction to CSS layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Normal flow</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grid</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Floats</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Positioning</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Multiple-column layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design">Responsive design</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Beginner's guide to media queries</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Legacy layout methods</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Supporting older browsers</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Fundamental layout comprehension assessment</a></li> +</ul> diff --git a/files/pt-br/learn/css/css_layout/index.html b/files/pt-br/learn/css/css_layout/index.html new file mode 100644 index 0000000000..18740f1b03 --- /dev/null +++ b/files/pt-br/learn/css/css_layout/index.html @@ -0,0 +1,69 @@ +--- +title: CSS layout +slug: Learn/CSS/CSS_layout +tags: + - Beginner + - CSS + - Floating + - Grids + - Guide + - Landing + - Layout + - Learn + - Module + - Multiple column + - NeedsTranslation + - Positioning + - TopicStub + - flexbox + - float +translation_of: Learn/CSS/CSS_layout +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Até esse ponto nós já vimos fundamentos do CSS, como estilizar textos, e como estilizar e manipular os blocos que envolvem o conteúdo. Chegou a hora de ver como posicionar seus blocos no lugar certo tendo como referência o viewport ou outro elemento. Cobrimos os pré-requisitos necessários para que possamos ir mais a fundo no layout CSS, veremos diferentes configurações de exibição, métodos tradicionais de layout envolvendo float e posicionamento, e ferramentas modernas de layout como flexbox.</p> + +<h2 id="Prerequisitos">Prerequisitos</h2> + +<p>Antes de iniciar esse modulo, você precisa:</p> + +<ol> + <li>Ter um conhecimento básico de HTML, como discutido no módulo <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introdução ao HTML</a>.</li> + <li>Estar confortável com os fundamentos do CSS, como discutido em <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">Introdução ao CSS</a>.</li> + <li>Entender como <a href="/en-US/docs/Learn/CSS/Styling_boxes">estilizar blocos</a>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Se você estiver trabalhando em um computador/tablete/outro dispositivo em que você não possa criar seus próprios arquivos, você pode testar (muitos dos) os códigos de exemplo em um programa de códigos online como o <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guias">Guias</h2> + +<p>Esse artigo ira introduzir as ferramentas fundamentais para o layout e as técnicas disponiveis no CSS.</p> + +<dl> + <dt><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introdução ao CSS</a></dt> + <dd>Este artigo recapitulará alguns dos recursos de layout CSS que já abordamos em módulos anteriores — como diferentes valores {{cssxref("display")}} — e apresentará alguns dos conceitos que abordaremos ao longo deste módulo.</dd> +</dl> + +<dl> + <dt><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Fluxo normal</a></dt> + <dd>Os elementos das páginas web apresentam-se de acordo com o fluxo normal (até que façamos algo para mudar isso). Este artigo explica os fundamentos do fluxo normal, bem como uma base para aprender como alterá-lo.</dd> + <dt><a href="https://developer.mozilla.org/pt-BR/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></dt> + <dd>É um método para criar layout unidimensional, renderizando itens em linhas ou colunas. Os itens flexíveis preenchem os espaços pondendo encolher para caberem em espaços menores. Este artigo explica todos os fundamentos.</dd> + <dt><a href="https://developer.mozilla.org/pt-BR/docs/Learn/CSS/CSS_layout/Flexbox">Grids</a></dt> + <dd>CSS Grid layout é um sistema de layout bidimensional para páginas web. Ele permite que você coloque conteúdo em linhas e colunas. Tem muitos recursos que facilitam a criação de layouts complexos. Este artigo fornecerá tudo o que você precisa saber para começar a usar Grid layout em suas páginas.</dd> +</dl> + +<dl> + <dt><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Floats</a></dt> + <dd>Originalmente para imagens flutuantes em blocos de texto, a propriedade {{cssxref("float")}} tornou-se uma das ferramentas mais usadas para criar layouts de várias colunas em páginas web. Com o advento do Flexbox e do Grid o Flot retorna ao seu propósto original. Este artigo explica tudo.</dd> + <dt><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Posicionamento</a></dt> + <dd>O posicionamento permite retirar elementos do fluxo normal do layout do documento fazendo com que se comportem de maneira diferente, por exemplo, posicionando-se um em cima do outro ou permanecendo numa posição fixa no navegador. Este artigo explica os diferentes valores de {{cssxref("position")}} e como usá-los.</dd> + <dt><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Layout de múltiplas colunas</a></dt> + <dd>A especificação de layout de várias colunas fornece um método para colocar conteúdo em colunas, como nos jornais. Este artigo explicará como usar este recurso.</dd> + <dt><a href="/en-US/docs/Learn/CSS/CSS_layout/Practical_positioning_examples">Exemplos práticos de posicionamento</a></dt> + <dd>Com as noções básicas de posicionamento abordadas no último artigo, veremos agora a construção de alguns exemplos do mundo real, para ilustrar que tipos de coisas você pode fazer com o posicionamento.</dd> + <dt><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grids</a></dt> + <dd>Os sistemas de Grid são outro recurso muito comum usado nos layouts de CSS, que tendem a ser implementados usando flutuadores ou outros recursos de layout. Você imagina seu layout como um número definido de colunas (por exemplo, 4, 6 ou 12) e ajusta suas colunas de conteúdo dentro dessas colunas imaginárias. Neste artigo, exploraremos a idéia básica por trás da criação de um sistema de grade, examinaremos o uso de um sistema de grade pronto fornecido por uma estrutura de grade e terminaremos com a experiência com CSS Grids - um novo recurso de navegador que torna a implementação do design de grade em a Web muito mais fácil.</dd> +</dl> diff --git a/files/pt-br/learn/css/css_layout/intro_leiaute_css/index.html b/files/pt-br/learn/css/css_layout/intro_leiaute_css/index.html new file mode 100644 index 0000000000..9314e8efd3 --- /dev/null +++ b/files/pt-br/learn/css/css_layout/intro_leiaute_css/index.html @@ -0,0 +1,707 @@ +--- +title: Introdução ao leiaute com CSS +slug: Learn/CSS/CSS_layout/Intro_leiaute_CSS +translation_of: Learn/CSS/CSS_layout/Introduction +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/CSS/CSS_layout/Normal_Flow", "Learn/CSS/CSS_layout")}}</div> + +<p class="summary">This article will recap some of the CSS layout features we've already touched upon in previous modules — such as different {{cssxref("display")}} values — and introduce some of the concepts we'll be covering throughout this module.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>The basics of HTML (study <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introduction to HTML</a>), and an idea of How CSS works (study <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">Introduction to CSS</a>.)</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>To give you an overview of CSS page layout techniques. Each technique can be learned in greater detail in subsequent tutorials.</td> + </tr> + </tbody> +</table> + +<p>CSS page layout techniques allow us to take elements contained in a web page and control where they are positioned relative to their default position in normal layout flow, the other elements around them, their parent container, or the main viewport/window. The page layout techniques we'll be covering in more detail in this module are</p> + +<ul> + <li>Normal flow</li> + <li>The {{cssxref("display")}} property</li> + <li>Flexbox</li> + <li>Grid</li> + <li>Floats</li> + <li>Positioning</li> + <li>Table layout</li> + <li>Multiple-column layout</li> +</ul> + +<p>Each technique has its uses, advantages, and disadvantages, and no technique is designed to be used in isolation. By understanding what each method is designed for you will be in a good place to understand which is the best layout tool for each task.</p> + +<h2 id="Normal_flow">Normal flow</h2> + +<p>Normal flow is how the browser lays out HTML pages by default when you do nothing to control page layout. Let's look at a quick HTML example:</p> + +<pre class="brush: html"><p>I love my cat.</p> + +<ul> + <li>Buy cat food</li> + <li>Exercise</li> + <li>Cheer up friend</li> +</ul> + +<p>The end!</p></pre> + +<p>By default, the browser will display this code as follows:</p> + +<p>{{ EmbedLiveSample('Normal_flow', '100%', 200) }}</p> + +<p>Note here how the HTML is displayed in the exact order in which it appears in the source code, with elements stacked up on top of one another — the first paragraph, followed by the unordered list, followed by the second paragraph.</p> + +<p>The elements that appear one below the other are described as <em>block</em> elements, in contrast to <em>inline</em> elements, which appear one beside the other, like the individual words in a paragraph.</p> + +<div class="note"> +<p><strong>Note</strong>: The direction in which block element contents are laid out is described as the Block Direction. The Block Direction runs vertically in a language such as English, which has a horizontal writing mode. It would run horizontally in any language with a Vertical Writing Mode, such as Japanese. The corresponding Inline Direction is the direction in which inline contents (such as a sentence) would run.</p> +</div> + +<p>When you use CSS to create a layout, you are moving the elements away from the normal flow, but for many of the elements on your page the normal flow will create exactly the layout you need. This is why starting with a well-structured HTML document is so important, as you can then work with the way things are laid out by default rather than fighting against it.</p> + +<p>The methods that can change how elements are laid out in CSS are as follows:</p> + +<ul> + <li><strong>The {{cssxref("display")}} property</strong> — Standard values such as <code>block</code>, <code>inline</code> or <code>inline-block</code> can change how elements behave in normal flow (see <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Box_model#Types_of_CSS_boxes">Types of CSS boxes</a> for more information). We then have entire layout methods that are switched on via a value of <code>display</code>, for example <a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">CSS Grid</a> and <a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a>.</li> + <li><strong>Floats</strong> — Applying a {{cssxref("float")}} value such as <code>left</code> can cause block level elements to wrap alongside one side of an element, like the way images sometimes have text floating around them in magazine layouts.</li> + <li><strong>The {{cssxref("position")}} property</strong> — Allows you to precisely control the placement of boxes inside other boxes. <code>static</code> positioning is the default in normal flow, but you can cause elements to be laid out differently using other values, for example always fixed to the top left of the browser viewport.</li> + <li><strong>Table layout</strong> — features designed for styling the parts of an HTML table can be used on non-table elements using <code>display: table</code> and associated properties.</li> + <li><strong>Multi-column layout</strong> — The <a href="/en-US/docs/Web/CSS/CSS_Columns">Multi-column layout</a> properties can cause the content of a block to layout in columns, as you might see in a newspaper.</li> +</ul> + +<h2 id="The_display_property">The display property</h2> + +<p>The main methods of achieving page layout in CSS are all values of the <code>display</code> property. This property allows us to change the default way something displays. Everything in normal flow has a value of <code>display</code>, used as the default way that elements they are set on behave. For example, the fact that paragraphs in English display one below the other is due to the fact that they are styled with <code>display: block</code>. If you create a link around some text inside a paragraph, that link remains inline with the rest of the text, and doesn’t break onto a new line. This is because the {{htmlelement("a")}} element is <code>display: inline</code> by default.</p> + +<p>You can change this default display behavior. For example, the {{htmlelement("li")}} element is <code>display: block</code> by default, meaning that list items display one below the other in our English document. If we change the display value to <code>inline</code> they now display next to each other, as words would do in a sentence. The fact that you can change the value of <code>display</code> for any element means that you can pick HTML elements for their semantic meaning, without being concerned about how they will look. The way they look is something that you can change.</p> + +<p>In addition to being able to change the default presentation by turning an item from <code>block</code> to <code>inline</code> and vice versa, there are some bigger layout methods that start out as a value of <code>display</code>. However, when using these, you will generally need to invoke additional properties. The two values most important for our purposes when discussing layout are <code>display: flex</code> and <code>display: grid</code>.</p> + +<h2 id="Flexbox">Flexbox</h2> + +<p>Flexbox is the short name for the <a href="/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout">Flexible Box Layout</a> Module, designed to make it easy for us to lay things out in one dimension — either as a row or as a column. To use flexbox, you apply <code>display: flex</code> to the parent element of the elements you want to lay out; all its direct children then become flex items. We can see this in a simple example.</p> + +<p>The HTML markup below gives us a containing element, with a class of <code>wrapper</code>, inside which are three {{htmlelement("div")}} elements. By default these would display as block elements, below one another, in our English language document.</p> + +<p>However, if we add <code>display: flex</code> to the parent, the three items now arrange themselves into columns. This is due to them becoming <em>flex items</em> and being affected by some initial values that flexbox sets on the flex container. They are displayed in a row, because the initial value of {{cssxref("flex-direction")}} set on their parent is <code>row</code>. They all appear to stretch to the height of the tallest item, because the initial value of the {{cssxref("align-items")}} property set on their parent is <code>stretch</code>. This means that the items stretch to the height of the flex container, which in this case is defined by the tallest item. The items all line up at the start of the container, leaving any extra space at the end of the row.</p> + +<div id="Flex_1"> +<div class="hidden"> +<h6 id="Flexbox_Example_1">Flexbox Example 1</h6> + +<pre class="brush: css">* {box-sizing: border-box;} + +.wrapper > div { + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; +} + </pre> +</div> + +<pre class="brush: css">.wrapper { + display: flex; +} +</pre> + +<pre class="brush: html"><div class="wrapper"> + <div class="box1">One</div> + <div class="box2">Two</div> + <div class="box3">Three</div> +</div> +</pre> +</div> + +<p>{{ EmbedLiveSample('Flex_1', '300', '200') }}</p> + +<p>In addition to the above properties that can be applied to the flex container, there are properties that can be applied to the flex items. These properties, among other things, can change the way that the items flex, enabling them to expand and contract to fit into the available space.</p> + +<p>As a simple example of this, we can add the {{cssxref("flex")}} property to all of our child items, with a value of <code>1</code>. This will cause all of the items to grow and fill the container, rather than leaving space at the end. If there is more space then the items will become wider; if there is less space they will become narrower. In addition, if you add another element to the markup the items will all become smaller to make space for it — they will adjust size to take up the same amount of space, whatever that is.</p> + +<div id="Flex_2"> +<div class="hidden"> +<h6 id="Flexbox_Example_2">Flexbox Example 2</h6> + +<pre class="brush: css"> * {box-sizing: border-box;} + + .wrapper > div { + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; + } + </pre> +</div> + +<pre class="brush: css">.wrapper { + display: flex; +} + +.wrapper > div { + flex: 1; +} +</pre> + +<pre class="brush: html"><div class="wrapper"> + <div class="box1">One</div> + <div class="box2">Two</div> + <div class="box3">Three</div> +</div> +</pre> +</div> + +<p>{{ EmbedLiveSample('Flex_2', '300', '200') }}</p> + +<div class="note"> +<p><strong>Note</strong>: This has been a very short introduction to what is possible in Flexbox, to find out more, see our <a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a> article.</p> +</div> + +<h2 id="Grid_Layout">Grid Layout</h2> + +<p>While flexbox is designed for one-dimensional layout, Grid Layout is designed for two dimensions — lining things up in rows and columns.</p> + +<p>Once again, you can switch on Grid Layout with a specific value of display — <code>display: grid</code>. The below example uses similar markup to the flex example, with a container and some child elements. In addition to using <code>display: grid</code>, we are also defining some row and column tracks on the parent using the {{cssxref("grid-template-rows")}} and {{cssxref("grid-template-columns")}} properties respectively. We've defined three columns each of <code>1fr</code> and two rows of <code>100px</code>. I don’t need to put any rules on the child elements; they are automatically placed into the cells our grid has created.</p> + +<div id="Grid_1"> +<div class="hidden"> +<h6 id="Grid_example_1">Grid example 1</h6> + +<pre class="brush: css"> * {box-sizing: border-box;} + + .wrapper > div { + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; + } + </pre> +</div> + +<pre class="brush: css">.wrapper { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: 100px 100px; + grid-gap: 10px; +} +</pre> + +<pre class="brush: html"><div class="wrapper"> + <div class="box1">One</div> + <div class="box2">Two</div> + <div class="box3">Three</div> + <div class="box4">Four</div> + <div class="box5">Five</div> + <div class="box6">Six</div> +</div> +</pre> +</div> + +<p>{{ EmbedLiveSample('Grid_1', '300', '330') }}</p> + +<p>Once you have a grid, you can explicitly place your items on it, rather than relying on the auto-placement behavior seen above. In the second example below we have defined the same grid, but this time with three child items. We've set the start and end line of each item using the {{cssxref("grid-column")}} and {{cssxref("grid-row")}} properties. This causes the items to span multiple tracks.</p> + +<div id="Grid_2"> +<div class="hidden"> +<h6 id="Grid_example_2">Grid example 2</h6> + +<pre class="brush: css"> * {box-sizing: border-box;} + + .wrapper > div { + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; + } + </pre> +</div> + +<pre class="brush: css">.wrapper { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: 100px 100px; + grid-gap: 10px; +} + +.box1 { + grid-column: 2 / 4; + grid-row: 1; +} + +.box2 { + grid-column: 1; + grid-row: 1 / 3; +} + +.box3 { + grid-row: 2; + grid-column: 3; +} +</pre> + +<pre class="brush: html"><div class="wrapper"> + <div class="box1">One</div> + <div class="box2">Two</div> + <div class="box3">Three</div> +</div> +</pre> +</div> + +<p>{{ EmbedLiveSample('Grid_2', '300', '330') }}</p> + +<div class="note"> +<p><strong>Note</strong>: These two examples are just a small part of the power of Grid layout; to find out more see our <a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grid Layout</a> article.</p> +</div> + +<p>The rest of this guide covers other layout methods, which are less important for the main layout structures of your page but can still help you achieve specific tasks. By understanding the nature of each layout task, you will soon find that when you look at a particular component of your design the type of layout best suited to it will often be clear.</p> + +<h2 id="Floats">Floats</h2> + +<p>Floating an element changes the behavior of that element and the block level elements that follow it in normal flow. The element is moved to the left or right and removed from normal flow, and the surrounding content floats around the floated item.</p> + +<p>The {{cssxref("float")}} property has four possible values:</p> + +<ul> + <li><code>left</code> — Floats the element to the left.</li> + <li><code>right</code> — Floats the element to the right.</li> + <li><code>none</code> — Specifies no floating at all. This is the default value.</li> + <li><code>inherit</code> — Specifies that the value of the <code>float</code> property should be inherited from the element's parent element.</li> +</ul> + +<p>In the example below we float a <code><div></code> left, and give it a {{cssxref("margin")}} on the right to push the text away from the element. This gives us the effect of text wrapped around that box, and is most of what you need to know about floats as used in modern web design.</p> + +<div id="Float_1"> +<div class="hidden"> +<h6 id="Floats_example">Floats example</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 0 auto; +} + +p { + line-height: 2; + word-spacing: 0.1rem; +} + +.box { + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); + padding: 10px; + border-radius: 5px; +} +</pre> +</div> + +<pre class="brush: html"><h1>Simple float example</h1> + +<div class="box">Float</div> + +<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +</pre> + +<pre class="brush: css"> +.box { + float: left; + width: 150px; + height: 150px; + margin-right: 30px; +} +</pre> +</div> + +<p>{{ EmbedLiveSample('Float_1', '100%', 600) }}</p> + +<div class="note"> +<p><strong>Note</strong>: Floats are fully explained in our lesson on the <a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">float and clear</a> properties. Prior to techniques such as Flexbox and Grid Layout floats were used as a method of creating column layouts. You may still come across these methods on the web; we will cover these in the lesson on <a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">legacy layout methods</a>.</p> +</div> + +<h2 id="Positioning_techniques">Positioning techniques</h2> + +<p>Positioning allows you to move an element from where it would be placed when in normal flow to another location. Positioning isn’t a method for creating your main page layouts, it is more about managing and fine-tuning the position of specific items on the page.</p> + +<p>There are however useful techniques for certain layout patterns that rely on the {{cssxref("position")}} property. Understanding positioning also helps in understanding normal flow, and what it is to move an item out of normal flow.</p> + +<p>There are five types of positioning you should know about:</p> + +<ul> + <li><strong>Static positioning</strong> is the default that every element gets — it just means "put the element into its normal position in the document layout flow — nothing special to see here".</li> + <li><strong>Relative positioning</strong> allows you to modify an element's position on the page, moving it relative to its position in normal flow — including making it overlap other elements on the page.</li> + <li><strong>Absolute positioning</strong> moves an element completely out of the page's normal layout flow, like it is sitting on its own separate layer. From there, you can fix it in a position relative to the edges of the page's <code><html></code> element (or its nearest positioned ancestor element). This is useful for creating complex layout effects such as tabbed boxes where different content panels sit on top of one another and are shown and hidden as desired, or information panels that sit off screen by default, but can be made to slide on screen using a control button.</li> + <li><strong>Fixed positioning</strong> is very similar to absolute positioning, except that it fixes an element relative to the browser viewport, not another element. This is useful for creating effects such as a persistent navigation menu that always stays in the same place on the screen as the rest of the content scrolls.</li> + <li><strong>Sticky positioning</strong> is a newer positioning method which makes an element act like <code>position: static</code> until it hits a defined offset from the viewport, at which point it acts like <code>position: fixed</code>.</li> +</ul> + +<h3 id="Simple_positioning_example">Simple positioning example</h3> + +<p>To provide familiarity with these page layout techniques, we'll show you a couple of quick examples. Our examples will all feature the same HTML, which is as follows:</p> + +<pre class="brush: html"><h1>Positioning</h1> + +<p>I am a basic block level element.</p> +<p class="positioned">I am a basic block level element.</p> +<p>I am a basic block level element.</p></pre> + +<p>This HTML will be styled by default using the following CSS:</p> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +p { + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); + padding: 10px; + margin: 10px; + border-radius: 5px; +} +</pre> + +<p>The rendered output is as follows:</p> + +<p>{{ EmbedLiveSample('Simple_positioning_example', '100%', 300) }}</p> + +<h3 id="Relative_positioning">Relative positioning</h3> + +<p>Relative positioning allows you to offset an item from the position in normal flow it would have by default. This means you could achieve a task such as moving an icon down a bit so it lines up with a text label. To do this, we could add the following rule to add relative positioning:</p> + +<pre class="brush: css">.positioned { + position: relative; + top: 30px; + left: 30px; +}</pre> + +<p>Here we give our middle paragraph a {{cssxref("position")}} value of <code>relative</code> — this doesn't do anything on its own, so we also add {{cssxref("top")}} and {{cssxref("left")}} properties. These serve to move the affected element down and to the right — this might seem like the opposite of what you were expecting, but you need to think of it as the element being pushed on its left and top sides, which result in it moving right and down.</p> + +<p>Adding this code will give the following result:</p> + +<div id="Relative_1"> +<div class="hidden"> +<h6 id="Relative_positioning_example">Relative positioning example</h6> + +<pre class="brush: html"><h1>Relative positioning</h1> + +<p>I am a basic block level element.</p> +<p class="positioned">This is my relatively positioned element.</p> +<p>I am a basic block level element.</p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +p { + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); + padding: 10px; + margin: 10px; + border-radius: 5px; +} +</pre> +</div> + +<pre class="brush: css">.positioned { + position: relative; + background: rgba(255,84,104,.3); + border: 2px solid rgb(255,84,104); + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Relative_1', '100%', 300) }}</p> + +<h3 id="Absolute_positioning">Absolute positioning</h3> + +<p>Absolute positioning is used to completely remove an element from normal flow, and place it using offsets from the edges of a containing block.</p> + +<p>Going back to our original non-positioned example, we could add the following CSS rule to implement absolute positioning:</p> + +<pre class="brush: css">.positioned { + position: absolute; + top: 30px; + left: 30px; +}</pre> + +<p>Here we give our middle paragraph a {{cssxref("position")}} value of <code>absolute</code>, and the same {{cssxref("top")}} and {{cssxref("left")}} properties as before. Adding this code, however, will give the following result:</p> + +<div id="Absolute_1"> +<div class="hidden"> +<h6 id="Absolute_positioning_example">Absolute positioning example</h6> + +<pre class="brush: html"><h1>Absolute positioning</h1> + +<p>I am a basic block level element.</p> +<p class="positioned">This is my absolutely positioned element.</p> +<p>I am a basic block level element.</p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +p { + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); + padding: 10px; + margin: 10px; + border-radius: 5px; +} +</pre> +</div> + +<pre class="brush: css">.positioned { + position: absolute; + background: rgba(255,84,104,.3); + border: 2px solid rgb(255,84,104); + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Absolute_1', '100%', 300) }}</p> + +<p>This is very different! The positioned element has now been completely separated from the rest of the page layout and sits over the top of it. The other two paragraphs now sit together as if their positioned sibling doesn't exist. The {{cssxref("top")}} and {{cssxref("left")}} properties have a different effect on absolutely positioned elements than they do on relatively positioned elements. In this case the offsets have been calculated from the top and left of the page. It is possible to change the parent element that becomes this container and we will take a look at that in the lesson on <a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">positioning</a>.</p> + +<h3 id="Fixed_positioning">Fixed positioning</h3> + +<p>Fixed positioning removes our element from document flow in the same way as absolute positioning. However, instead of the offsets being applied from the container, they are applied from the viewport. As the item remains fixed in relation to the viewport we can create effects such as a menu which remains fixed as the page scrolls beneath it.</p> + +<p>For this example our HTML is three paragraphs of text, in order that we can cause the page to scroll, and a box to which we will give <code>position: fixed</code>.</p> + +<pre class="brush: html"><h1>Fixed positioning</h1> + +<div class="positioned">Fixed</div> + +<p>Paragraph 1.</p> +<p>Paragraph 2.</p> +<p>Paragraph 3.</p> +</pre> + +<div id="Fixed_1"> +<div class="hidden"> +<h6 id="Fixed_positioning_example">Fixed positioning example</h6> + +<pre class="brush: html"><h1>Fixed positioning</h1> + +<div class="positioned">Fixed</div> + +<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> + +<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +</pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +.positioned { + background: rgba(255,84,104,.3); + border: 2px solid rgb(255,84,104); + padding: 10px; + margin: 10px; + border-radius: 5px; +}</pre> +</div> + +<pre class="brush: css">.positioned { + position: fixed; + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Fixed_1', '100%', 200) }}</p> + +<h3 id="Sticky_positioning">Sticky positioning</h3> + +<p>Sticky positioning is the final positioning method that we have at our disposal. It mixes the default static positioning with fixed positioning. When an item has <code>position: sticky</code> it will scroll in normal flow until it hits offsets from the viewport that we have defined. At that point it becomes "stuck" as if it had <code>position: fixed</code> applied.</p> + +<div id="Sticky_1"> +<div class="hidden"> +<h6 id="Sticky_positioning_example">Sticky positioning example</h6> + +<pre class="brush: html"><h1>Sticky positioning</h1> + +<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<div class="positioned">Sticky</div> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> + +<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> </pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +.positioned { + background: rgba(255,84,104,.3); + border: 2px solid rgb(255,84,104); + padding: 10px; + margin: 10px; + border-radius: 5px; +}</pre> +</div> + +<pre class="brush: css">.positioned { + position: sticky; + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Sticky_1', '100%', 200) }}</p> + +<div class="note"> +<p><strong>Note</strong>: to find more out about positioning, see our <a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Positioning</a> article.</p> +</div> + +<h2 id="Table_layout">Table layout</h2> + +<p>HTML tables are fine for displaying tabular data, but many years ago — before even basic CSS was supported reliably across browsers — web developers used to also use tables for entire web page layouts — putting their headers, footers, different columns, etc. in various table rows and columns. This worked at the time, but it has many problems — table layouts are inflexible, very heavy on markup, difficult to debug, and semantically wrong (e.g., screen reader users have problems navigating table layouts).</p> + +<p>The way that a table looks on a webpage when you use table markup is due to a set of CSS properties that define table layout. These properties can be used to lay out elements that are not tables, a use which is sometimes described as "using CSS tables".</p> + +<p>The example below shows one such use; using CSS tables for layout should be considered a legacy method at this point, for those situations where you have very old browsers without support for Flexbox or Grid.</p> + +<p>Let's look at an example. First, some simple markup that creates an HTML form. Each input element has a label, and we've also included a caption inside a paragraph. Each label/input pair is wrapped in a {{htmlelement("div")}}, for layout purposes.</p> + +<pre class="brush: html"><form> + <p>First of all, tell us your name and age.</p> + <div> + <label for="fname">First name:</label> + <input type="text" id="fname"> + </div> + <div> + <label for="lname">Last name:</label> + <input type="text" id="lname"> + </div> + <div> + <label for="age">Age:</label> + <input type="text" id="age"> + </div> +</form></pre> + +<p>Now, the CSS for our example. Most of the CSS is fairly ordinary, except for the uses of the {{cssxref("display")}} property. The {{htmlelement("form")}}, {{htmlelement("div")}}s, and {{htmlelement("label")}}s and {{htmlelement("input")}}s have been told to display like a table, table rows, and table cells respectively — basically, they'll act like HTML table markup, causing the labels and inputs to line up nicely by default. All we then have to do is add a bit of sizing, margin, etc. to make everything look a bit nicer and we're done.</p> + +<p>You'll notice that the caption paragraph has been given <code>display: table-caption;</code> — which makes it act like a table {{htmlelement("caption")}} — and <code>caption-side: bottom;</code> to tell the caption to sit on the bottom of the table for styling purposes, even though the markup is before the <code><input></code> elements in the source. This allows for a nice bit of flexibility.</p> + +<pre class="brush: css">html { + font-family: sans-serif; +} + +form { + display: table; + margin: 0 auto; +} + +form div { + display: table-row; +} + +form label, form input { + display: table-cell; + margin-bottom: 10px; +} + +form label { + width: 200px; + padding-right: 5%; + text-align: right; +} + +form input { + width: 300px; +} + +form p { + display: table-caption; + caption-side: bottom; + width: 300px; + color: #999; + font-style: italic; +}</pre> + +<p>This gives us the following result:</p> + +<p>{{ EmbedLiveSample('Table_layout', '100%', '170') }}</p> + +<p>You can also see this example live at <a href="https://mdn.github.io/learning-area/css/styling-boxes/box-model-recap/css-tables-example.html">css-tables-example.html</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/css/styling-boxes/box-model-recap/css-tables-example.html">source code</a> too.)</p> + +<h2 id="Multi-column_layout">Multi-column layout</h2> + +<p>The multi-column layout module gives us a way to lay out content in columns, similar to how text flows in a newspaper. While reading up and down columns is less useful in a web context as you don’t want to force users to scroll up and down, arranging content into columns can be a useful technique.</p> + +<p>To turn a block into a multicol container we use either the {{cssxref("column-count")}} property, which tells the browser how many columns we would like to have, or the {{cssxref("column-width")}} property, which tells the browser to fill the container with as many columns of at least that width.</p> + +<p>In the below example we start with a block of HTML inside a containing <code><div></code> element with a class of <code>container</code>.</p> + +<pre class="brush: html"><div class="container"> + <h1>Multi-column layout</h1> + + <p>Paragraph 1.</p> + <p>Paragraph 2.</p> + +</div> +</pre> + +<p>We are using a <code>column-width</code> of 200 pixels on that container, causing the browser to create as many 200-pixel columns as will fit in the container and then share the remaining space between the created columns.</p> + +<div id="Multicol_1"> +<div class="hidden"> +<h6 id="Multicol_example">Multicol example</h6> + +<pre class="brush: html"> <div class="container"> + <h1>Multi-column Layout</h1> + + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + + + <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> + + </div> + </pre> + +<pre class="brush: css">body { max-width: 800px; margin: 0 auto; } </pre> +</div> + +<pre class="brush: css"> .container { + column-width: 200px; + }</pre> +</div> + +<p>{{ EmbedLiveSample('Multicol_1', '100%', 200) }}</p> + +<h2 id="Summary">Summary</h2> + +<p>This article has provided a brief summary of all the layout technologies you should know about. Read on for more information on each individual technology!</p> + +<p>{{NextMenu("Learn/CSS/CSS_layout/Normal_Flow", "Learn/CSS/CSS_layout")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introduction to CSS layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Normal flow</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grid</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Floats</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Positioning</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Multiple-column layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design">Responsive design</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Beginner's guide to media queries</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Legacy layout methods</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Supporting older browsers</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Fundamental layout comprehension assessment</a></li> +</ul> diff --git a/files/pt-br/learn/css/css_layout/layout_de_varias_colunas/index.html b/files/pt-br/learn/css/css_layout/layout_de_varias_colunas/index.html new file mode 100644 index 0000000000..2605843ff4 --- /dev/null +++ b/files/pt-br/learn/css/css_layout/layout_de_varias_colunas/index.html @@ -0,0 +1,414 @@ +--- +title: Layout de varias colunas +slug: Learn/CSS/CSS_layout/Layout_de_varias_colunas +translation_of: Learn/CSS/CSS_layout/Multiple-column_Layout +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/CSS_layout/Positioning", "Learn/CSS/CSS_layout/Responsive_Design", "Learn/CSS/CSS_layout")}}</div> + +<p class="summary">A especificação de layout de várias colunas fornece um método de disposição do conteúdo em colunas, como você pode ver em um jornal. Este artigo explica como usar esse recurso.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré requisitos:</th> + <td>HTML basico (estude <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introduction to HTML</a>) e uma ideia de como CSS funciona (estude <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">Introduction to CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Aprender como criar layouts de várias colunas em paginas web, tal qual estão formatadas as paginas de um jornal.</p> + + + </td> + </tr> + </tbody> +</table> + +<h2 id="Um_exemplo_basico">Um exemplo basico</h2> + +<p>Agora nós vamos explorar como usar layouts de varias colunas, frequentemente referido como <em>multicol</em>. Você pode começar pelo <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/multicol/0-starting-point.html">download do arquivo multicol - ponto de partida</a>, e adicionar o CSS nos locais apropriados. Na parte inferior desta seção, você pode ver um exemplo real da aparência do código final.</p> + +<p>Nosso ponto de partida contem um HTML simples; um invólucro com uma classe de <code>container</code> dentro do qual há um cabeçalho e alguns parágrafos.</p> + +<p>O {{htmlelement("div")}} com a classe de container se tornará nosso <em>muticol</em> container. Nós ativamos o <em>multicol</em> usando uma de duas propriedades {{cssxref("column-count")}} ou {{cssxref("column-width")}}. A propriedade <code>column-count</code> criará tantas colunas quanto o valor que você atribuir; portanto, se voce adicionar o seguinte CSS à sua <em>stylesheet</em> e recarregar a pagina, você obterá três colunas:</p> + +<p> + </p><pre class="brush: css">.container { + column-count: 3; +} +</pre> + + +<p>As colunas que você criar têm larguras flexíveis - o navegador calcula quanto espaço será atribuido a cada coluna.</p> + +<div id="Multicol_1"> +<div class="hidden"> +<h6 id="column-count_example">column-count example</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; +} + </pre> +</div> + +<pre class="brush: html"><div class="container"> + <h1>Simple multicol example</h1> + + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. + Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. + Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse + ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit + quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + + <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique + elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit + cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis + dis parturient montes, nascetur ridiculus mus.</p> +</div> +</pre> + +<pre class="brush: css">.container { + column-count: 3; +} +</pre> +</div> + +<p>{{ EmbedLiveSample('Multicol_1', '100%', 400) }}</p> + +<p>Mude o seu CSS para usar <code>column-width</code>, como a seguir:</p> + +<pre class="brush: css">.container { + column-width: 200px; +} +</pre> + +<p>O navegador agora fornecerá o maior número possível de colunas, do tamanho que você especificar; qualquer espaço restante é compartilhado entre as colunas existentes. Isso significa que você não terá exatamente a largura que especificar, a menos que seu container seja exatamente divisível por essa largura.</p> + +<div id="Multicol_2"> +<div class="hidden"> +<h6 id="column-width_example">column-width example</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; +}</pre> + +<pre class="brush: html"><div class="container"> + <h1>Simple multicol example</h1> + + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. + Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. + Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse + ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit + quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + + <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique + elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit + cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis + dis parturient montes, nascetur ridiculus mus.</p> +</div></pre> +</div> + +<pre class="brush: css">.container { + column-width: 200px; +} +</pre> +</div> + +<p>{{ EmbedLiveSample('Multicol_2', '100%', 400) }}</p> + +<h2 id="Styling_the_columns">Styling the columns</h2> + +<p>The columns created by multicol cannot be styled individually. There is no way to make one column bigger than other columns, or to change the background or text color of a single column. You have two opportunities to change the way that columns display:</p> + +<ul> + <li>Changing the size of the gap between columns using the {{cssxref("column-gap")}}.</li> + <li>Adding a rule between columns with {{cssxref("column-rule")}}.</li> +</ul> + +<p>Using your example above, change the size of the gap by adding a <code>column-gap</code> property:</p> + +<pre class="brush: css">.container { + column-width: 200px; + column-gap: 20px; +}</pre> + +<p>You can play around with different values — the property accepts any length unit. Now add a rule between the columns, with <code>column-rule</code>. In a similar way to the {{cssxref("border")}} property that you encountered in previous lessons, <code>column-rule</code> is a shorthand for {{cssxref("column-rule-color")}}, {{cssxref("column-rule-style")}}, and {{cssxref("column-rule-width")}}, and accepts the same values as <code>border</code>.</p> + +<pre class="brush: css">.container { + column-count: 3; + column-gap: 20px; + column-rule: 4px dotted rgb(79, 185, 227); +}</pre> + +<p>Try adding rules of different styles and colors.</p> + +<div id="Multicol_3"> +<div class="hidden"> +<h6 id="Styling_the_columns_2">Styling the columns</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; +} +.container { + column-count: 3; + column-gap: 20px; + column-rule: 4px dotted rgb(79, 185, 227); +}</pre> + +<pre class="brush: html"><div class="container"> + <h1>Simple multicol example</h1> + + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. + Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. + Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse + ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit + quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + + <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique + elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit + cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis + dis parturient montes, nascetur ridiculus mus.</p> +</div></pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Multicol_3', '100%', 400) }}</p> + +<p>Something to take note of is that the rule does not take up any width of its own. It lies across the gap you created with <code>column-gap</code>. To make more space either side of the rule you will need to increase the <code>column-gap</code> size.</p> + +<h2 id="Columns_and_fragmentation">Columns and fragmentation</h2> + +<p>The content of a multi-column layout is fragmented. It essentially behaves the same way as content behaves in paged media — such as when you print a webpage. When you turn your content into a multicol container it is fragmented into columns, and the content breaks to allow this to happen.</p> + +<p>Sometimes, this breaking will happen in places that lead to a poor reading experience. In the live example below, I have used multicol to lay out a series of boxes, each of which have a heading and some text inside. The heading becomes separated from the text if the columns fragment between the two.</p> + +<div id="Multicol_4"> +<div class="hidden"> +<h6 id="Cards_example">Cards example</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; +} </pre> +</div> + +<pre class="brush: html"><div class="container"> + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + +</div> +</pre> + +<pre class="brush: css">.container { + column-width: 250px; + column-gap: 20px; +} + +.card { + background-color: rgb(207, 232, 220); + border: 2px solid rgb(79, 185, 227); + padding: 10px; + margin: 0 0 1em 0; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Multicol_4', '100%', 600) }}</p> + +<p>To control this behavior we can use properties from the <a href="/en-US/docs/Web/CSS/CSS_Fragmentation">CSS Fragmentation</a> specification. This specification gives us properties to control breaking of content in multicol and in paged media. For example, add the property {{cssxref("break-inside")}} with a value of <code>avoid</code> to the rules for <code>.card</code>. This is the container of the heading and text, and therefore we do not want to fragment this box.</p> + +<p>At the present time it is also worth adding the older property <code>page-break-inside: avoid</code> for best browser support.</p> + +<pre class="brush: css">.card { + break-inside: avoid; + page-break-inside: avoid; + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); + padding: 10px; + margin: 0 0 1em 0; +} +</pre> + +<p>Reload the page and your boxes should stay in one piece.</p> + +<div id="Multicol_5"> +<div class="hidden"> +<h6 id="Multicol_Fragmentation">Multicol Fragmentation</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; +} </pre> + +<pre class="brush: html"><div class="container"> + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + + <div class="card"> + <h2>I am the heading</h2> + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat + vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies + tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci + vel, viverra egestas ligula.</p> + </div> + +</div> +</pre> +</div> + +<pre class="brush: css">.container { + column-width: 250px; + column-gap: 20px; +} + +.card { + break-inside: avoid; + page-break-inside: avoid; + background-color: rgb(207, 232, 220); + border: 2px solid rgb(79, 185, 227); + padding: 10px; + margin: 0 0 1em 0; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Multicol_5', '100%', 600) }}</p> + +<h2 id="Summary">Summary</h2> + +<p>You now know how to use the basic features of multiple-column layout, another tool at your disposal when choosing a layout method for the designs you are building.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Web/CSS/CSS_Fragmentation">CSS Fragmentation</a></li> + <li><a href="/en-US/docs/Web/CSS/CSS_Columns/Using_multi-column_layouts">Using multi-column layouts</a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Positioning", "Learn/CSS/CSS_layout/Responsive_Design", "Learn/CSS/CSS_layout")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introduction to CSS layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Normal flow</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grid</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Floats</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Positioning</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Multiple-column layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design">Responsive design</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Beginner's guide to media queries</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Legacy layout methods</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Supporting older browsers</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Fundamental layout comprehension assessment</a></li> +</ul> diff --git a/files/pt-br/learn/css/css_layout/positioning/index.html b/files/pt-br/learn/css/css_layout/positioning/index.html new file mode 100644 index 0000000000..51a024e875 --- /dev/null +++ b/files/pt-br/learn/css/css_layout/positioning/index.html @@ -0,0 +1,574 @@ +--- +title: Positioning +slug: Learn/CSS/CSS_layout/Positioning +translation_of: Learn/CSS/CSS_layout/Positioning +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Aprenda/CSS/CSS_layout/Floats", "Aprenda/CSS/CSS_layout/Multiple-column_Layout", "Aprenda/CSS/CSS_layout")}}</div> + +<p class="summary">Positioning allows you to take elements out of the normal document layout flow, and make them behave differently; for example sitting on top of one another, or always remaining in the same place inside the browser viewport. This article explains the different {{cssxref("position")}} values, and how to use them.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>HTML basics (study <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introduction to HTML</a>), and an idea of How CSS works (study <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">Introduction to CSS</a>.)</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>To learn how CSS positioning works.</td> + </tr> + </tbody> +</table> + +<p>We'd like you to follow along with the exercises on your local computer, if possible — grab a copy of <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/0_basic-flow.html">0_basic-flow.html</a></code> from our GitHub repo (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/0_basic-flow.html">source code here</a>) and use that as a starting point.</p> + +<h2 id="Introducing_positioning">Introducing positioning</h2> + +<p>The whole idea of positioning is to allow us to override the basic document flow behavior described above, to produce interesting effects. What if you want to slightly alter the position of some boxes inside a layout from their default layout flow position, to give a slightly quirky, distressed feel? Positioning is your tool. Or if you want to create a UI element that floats over the top of other parts of the page, and/or always sits in the same place inside the browser window no matter how much the page is scrolled? Positioning makes such layout work possible.</p> + +<p>There are a number of different types of positioning that you can put into effect on HTML elements. To make a specific type of positioning active on an element, we use the {{cssxref("position")}} property.</p> + +<h3 id="Static_positioning">Static positioning</h3> + +<p>Static positioning is the default that every element gets — it just means "put the element into its normal position in the document layout flow — nothing special to see here."</p> + +<p>To demonstrate this, and get your example set up for future sections, first add a <code>class</code> of <code>positioned</code> to the second {{htmlelement("p")}} in the HTML:</p> + +<pre class="brush: html"><p class="positioned"> ... </p></pre> + +<p>Now add the following rule to the bottom of your CSS:</p> + +<pre class="brush: css">.positioned { + position: static; + background: yellow; +}</pre> + +<p>If you now save and refresh, you'll see no difference at all, except for the updated background color of the 2nd paragraph. This is fine — as we said before, static positioning is the default behavior!</p> + +<div class="note"> +<p><strong>Note</strong>: You can see the example at this point live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/1_static-positioning.html">1_static-positioning.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/1_static-positioning.html">see source code</a>).</p> +</div> + +<h3 id="Relative_positioning">Relative positioning</h3> + +<p>Relative positioning is the first position type we'll take a look at. This is very similar to static positioning, except that once the positioned element has taken its place in the normal layout flow, you can then modify its final position, including making it overlap other elements on the page. Go ahead and update the <code>position</code> declaration in your code:</p> + +<pre class="brush: css">position: relative;</pre> + +<p>If you save and refresh at this stage, you won't see a change in the result at all. So how do you modify the element's position? You need to use the {{cssxref("top")}}, {{cssxref("bottom")}}, {{cssxref("left")}}, and {{cssxref("right")}} properties, which we'll explain in the next section.</p> + +<h3 id="Introducing_top_bottom_left_and_right">Introducing top, bottom, left, and right</h3> + +<p>{{cssxref("top")}}, {{cssxref("bottom")}}, {{cssxref("left")}}, and {{cssxref("right")}} are used alongside {{cssxref("position")}} to specify exactly where to move the positioned element to. To try this out, add the following declarations to the <code>.positioned</code> rule in your CSS:</p> + +<pre class="brush: css">top: 30px; +left: 30px;</pre> + +<div class="note"> +<p><strong>Note</strong>: The values of these properties can take any <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Values_and_units">units</a> you'd logically expect — pixels, mm, rems, %, etc.</p> +</div> + +<p>If you now save and refresh, you'll get a result something like this:</p> + +<div class="hidden"> +<pre class="brush: html"><h1>Relative positioning</h1> + +<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p> + +<p class="positioned">By default we span 100% of the width of our parent element, and we are as tall as our child content. Our total width and height is our content + padding + border width/height.</p> + +<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p> + +<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements <span>wrap onto a new line if possible — like this one containing text</span>, or just go on to a new line if not, much like this image will do: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +p { + background: aqua; + border: 3px solid blue; + padding: 10px; + margin: 10px; +} + +span { + background: red; + border: 1px solid black; +} + +.positioned { + position: relative; + background: yellow; + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Introducing_top_bottom_left_and_right', '100%', 500) }}</p> + +<p>Cool, huh? Ok, so this probably wasn't what you were expecting — why has it moved to the bottom and right if we specified top and left? Illogical as it may initially sound, this is just the way that relative positioning works — you need to think of an invisible force that pushes the specified side of the positioned box, moving it in the opposite direction. So for example, if you specify <code>top: 30px;</code>, a force pushes the top of the box, causing it to move downwards by 30px.</p> + +<div class="note"> +<p><strong>Note</strong>: You can see the example at this point live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/2_relative-positioning.html">2_relative-positioning.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/2_relative-positioning.html">see source code</a>).</p> +</div> + +<h3 id="Absolute_positioning">Absolute positioning</h3> + +<p>Absolute positioning brings very different results. Let's try changing the position declaration in your code as follows:</p> + +<pre class="brush: css">position: absolute;</pre> + +<p>If you now save and refresh, you should see something like so:</p> + +<div class="hidden"> +<pre class="brush: html"><h1>Absolute positioning</h1> + +<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p> + +<p class="positioned">By default we span 100% of the width of our parent element, and we are as tall as our child content. Our total width and height is our content + padding + border width/height.</p> + +<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p> + +<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements <span>wrap onto a new line if possible — like this one containing text</span>, or just go on to a new line if not, much like this image will do: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +p { + background: aqua; + border: 3px solid blue; + padding: 10px; + margin: 10px; +} + +span { + background: red; + border: 1px solid black; +} + +.positioned { + position: absolute; + background: yellow; + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Absolute_positioning', '100%', 420) }}</p> + +<p>First of all, note that the gap where the positioned element should be in the document flow is no longer there — the first and third elements have closed together like it no longer exists! Well, in a way, this is true. An absolutely positioned element no longer exists in the normal document layout flow. Instead, it sits on its own layer separate from everything else. This is very useful: it means that we can create isolated UI features that don't interfere with the position of other elements on the page. For example, popup information boxes and control menus; rollover panels; UI features that can be dragged and dropped anywhere on the page; and so on...</p> + +<p>Second, notice that the position of the element has changed — this is because {{cssxref("top")}}, {{cssxref("bottom")}}, {{cssxref("left")}}, and {{cssxref("right")}} behave in a different way with absolute positioning. Instead of specifying the direction the element should move in, they specify the distance the element should be from each containing element's sides. So in this case, we are saying that the absolutely positioned element should sit 30px from the top of the "containing element", and 30px from the left.</p> + +<div class="note"> +<p><strong>Note</strong>: You can use {{cssxref("top")}}, {{cssxref("bottom")}}, {{cssxref("left")}}, and {{cssxref("right")}} to resize elements if you need to. Try setting <code>top: 0; bottom: 0; left: 0; right: 0;</code> and <code>margin: 0;</code> on your positioned elements and see what happens! Put it back again afterwards...</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: Yes, margins still affect positioned elements. Margin collapsing doesn't, however.</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: You can see the example at this point live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/3_absolute-positioning.html">3_absolute-positioning.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/3_absolute-positioning.html">see source code</a>).</p> +</div> + +<h3 id="Positioning_contexts">Positioning contexts</h3> + +<p>Which element is the "containing element" of an absolutely positioned element? This is very much dependent on the position property of the ancestors of the positioned element (See <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#Identifying_the_containing_block">Identifying the containing block</a>). </p> + +<p>If no ancestor elements have their position property explicitly defined, then by default all ancestor elements will have a static position. The result of this is, the absolutely positioned element will be contained in the <strong>initial containing block</strong>. The initial containing block has the dimensions of the viewport, and is also the block that contains the {{htmlelement("html")}} element. Simply put, the absolutely positioned element will be contained outside of the {{htmlelement("html")}} element, and be positioned relative to the initial viewport. </p> + +<p>The positioned element is nested inside the {{htmlelement("body")}} in the HTML source, but in the final layout, it is 30px away from the top and left of the edge of the page. We can change the <strong>positioning context</strong> — which element the absolutely positioned element is positioned relative to. This is done by setting positioning on one of the element's ancestors — to one of the elements it is nested inside (you can't position it relative to an element it is not nested inside). To demonstrate this, add the following declaration to your <code>body</code> rule:</p> + +<pre class="brush: css">position: relative;</pre> + +<p>This should give the following result:</p> + +<div class="hidden"> +<pre class="brush: html"><h1>Positioning context</h1> + +<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p> + +<p class="positioned">Now I'm absolutely positioned relative to the <code>&lt;body&gt;</code> element, not the <code>&lt;html&gt;</code> element!</p> + +<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p> + +<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements <span>wrap onto a new line if possible — like this one containing text</span>, or just go on to a new line if not, much like this image will do: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; + position: relative; +} + +p { + background: aqua; + border: 3px solid blue; + padding: 10px; + margin: 10px; +} + +span { + background: red; + border: 1px solid black; +} + +.positioned { + position: absolute; + background: yellow; + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Positioning_contexts', '100%', 420) }}</p> + +<p>The positioned element now sits relative to the {{htmlelement("body")}} element.</p> + +<div class="note"> +<p><strong>Note</strong>: You can see the example at this point live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/4_positioning-context.html">4_positioning-context.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/4_positioning-context.html">see source code</a>).</p> +</div> + +<h3 id="Introducing_z-index">Introducing z-index</h3> + +<p>All this absolute positioning is good fun, but there is another thing we haven't considered yet — when elements start to overlap, what determines which elements appear on top of which other elements? In the example we've seen so far, we only have one positioned element in the positioning context, and it appears on the top, since positioned elements win over non-positioned elements. What about when we have more than one?</p> + +<p>Try adding the following to your CSS, to make the first paragraph absolutely positioned too:</p> + +<pre class="brush: css">p:nth-of-type(1) { + position: absolute; + background: lime; + top: 10px; + right: 30px; +}</pre> + +<p>At this point you'll see the first paragraph colored lime, moved out of the document flow, and positioned a bit above from where it originally was. It is also stacked below the original <code>.positioned</code> paragraph, where the two overlap. This is because the <code>.positioned</code> paragraph is the second paragraph in the source order, and positioned elements later in the source order win over positioned elements earlier in the source order.</p> + +<p>Can you change the stacking order? Yes, you can, by using the {{cssxref("z-index")}} property. "z-index" is a reference to the z-axis. You may recall from previous points in the course where we discussed web pages using horizontal (x-axis) and vertical (y-axis) coordinates to work out positioning for things like background images and drop shadow offsets. (0,0) is at the top left of the page (or element), and the x- and y-axes run across to the right and down the page (for left to right languages, anyway.)</p> + +<p>Web pages also have a z-axis: an imaginary line that runs from the surface of your screen, towards your face (or whatever else you like to have in front of the screen). {{cssxref("z-index")}} values affect where positioned elements sit on that axis; positive values move them higher up the stack, and negative values move them lower down the stack. By default, positioned elements all have a <code>z-index</code> of <code>auto</code>, which is effectively 0.</p> + +<p>To change the stacking order, try adding the following declaration to your <code>p:nth-of-type(1)</code> rule:</p> + +<pre class="brush: css">z-index: 1;</pre> + +<p>You should now see the finished example, with the lime paragraph on top:</p> + +<div class="hidden"> +<pre class="brush: html"><h1>z-index</h1> + +<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p> + +<p class="positioned">Now I'm absolutely positioned relative to the <code>&lt;body&gt;</code> element, not the <code>&lt;html&gt;</code> element!</p> + +<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p> + +<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements <span>wrap onto a new line if possible — like this one containing text</span>, or just go on to a new line if not, much like this image will do: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; + position: relative; +} + +p { + background: aqua; + border: 3px solid blue; + padding: 10px; + margin: 10px; +} + +span { + background: red; + border: 1px solid black; +} + +.positioned { + position: absolute; + background: yellow; + top: 30px; + left: 30px; +} + +p:nth-of-type(1) { + position: absolute; + background: lime; + top: 10px; + right: 30px; + z-index: 1; +} +</pre> +</div> + +<p>{{ EmbedLiveSample('Introducing_z-index', '100%', 400) }}</p> + +<p>Note that <code>z-index</code> only accepts unitless index values; you can't specify that you want one element to be 23 pixels up the Z-axis — it doesn't work like that. Higher values will go above lower values, and it is up to you what values you use. Using 2 and 3 would give the same effect as 300 and 40000.</p> + +<div class="note"> +<p><strong>Note</strong>: You can see the example at this point live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/5_z-index.html">5_z-index.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/5_z-index.html">see source code</a>).</p> +</div> + +<h3 id="Fixed_positioning">Fixed positioning</h3> + +<p>Let's now look at fixed positioning. This works in exactly the same way as absolute positioning, with one key difference: whereas absolute positioning fixes an element in place relative to the {{htmlelement("html")}} element or its nearest positioned ancestor, fixed positioning fixes an element in place relative to the browser viewport itself. This means that you can create useful UI items that are fixed in place, like persisting navigation menus.</p> + +<p>Let's put together a simple example to show what we mean. First of all, delete the existing <code>p:nth-of-type(1)</code> and <code>.positioned</code> rules from your CSS.</p> + +<p>Now, update the <code>body</code> rule to remove the <code>position: relative;</code> declaration and add a fixed height, like so:</p> + +<pre class="brush: css">body { + width: 500px; + height: 1400px; + margin: 0 auto; +}</pre> + +<p>Now we're going to give the {{htmlelement("h1")}} element <code>position: fixed;</code>, and get it to sit at the top center of the viewport. Add the following rule to your CSS:</p> + +<pre class="brush: css">h1 { + position: fixed; + top: 0; + width: 500px; + margin: 0 auto; + background: white; + padding: 10px; +}</pre> + +<p>The <code>top: 0;</code> is required to make it stick to the top of the screen; we then give the heading the same width as the content column and use the faithful old <code>margin: 0 auto;</code> trick to center it. We then give it a white background and some padding, so the content won't be visible underneath it.</p> + +<p>If you save and refresh now, you'll see a fun little effect whereby the heading stays fixed, and the content appears to scroll up and disappear underneath it. But we could improve this more — at the moment some of the content starts off underneath the heading. This is because the positioned heading no longer appears in the document flow, so the rest of the content moves up to the top. We need to move it all down a bit; we can do this by setting some top margin on the first paragraph. Add this now:</p> + +<pre class="brush: css">p:nth-of-type(1) { + margin-top: 60px; +}</pre> + +<p>You should now see the finished example:</p> + +<div class="hidden"> +<pre class="brush: html"><h1>Fixed positioning</h1> + +<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p> + +<p class="positioned">I'm not positioned any more...</p> + +<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p> + +<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements <span>wrap onto a new line if possible — like this one containing text</span>, or just go on to a new line if not, much like this image will do: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + height: 1400px; + margin: 0 auto; +} + +p { + background: aqua; + border: 3px solid blue; + padding: 10px; + margin: 10px; +} + +span { + background: red; + border: 1px solid black; +} + +h1 { + position: fixed; + top: 0px; + width: 500px; + margin: 0 auto; + background: white; + padding: 10px; +} + +p:nth-of-type(1) { + margin-top: 60px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Fixed_positioning', '100%', 400) }}</p> + +<div class="note"> +<p><strong>Note</strong>: You can see the example at this point live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/6_fixed-positioning.html">6_fixed-positioning.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/6_fixed-positioning.html">see source code</a>).</p> +</div> + +<h3 id="position_sticky">position: sticky</h3> + +<p>There is another position value available called <code>position: sticky</code>, which is somewhat newer than the others. This is basically a hybrid between relative and fixed position, which allows a positioned element to act like it is relatively positioned until it is scrolled to a certain threshold point (e.g. 10px from the top of the viewport), after which it becomes fixed. This can be used to for example cause a navigation bar to scroll with the page until a certain point, and then stick to the top of the page. </p> + +<div id="Sticky_1"> +<div class="hidden"> +<h6 id="Sticky_positioning_example">Sticky positioning example</h6> + +<pre class="brush: html"><h1>Sticky positioning</h1> + +<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<div class="positioned">Sticky</div> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> + +<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> </pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +.positioned { + background: rgba(255,84,104,.3); + border: 2px solid rgb(255,84,104); + padding: 10px; + margin: 10px; + border-radius: 5px; +}</pre> +</div> + +<pre class="brush: css">.positioned { + position: sticky; + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Sticky_1', '100%', 200) }}</p> + +<p>An interesting and common use of <code>position: sticky</code> is to create a scrolling index page where different headings stick to the top of the page as they reach it. The markup for such an example might look like so:</p> + +<pre class="brush: html"><h1>Sticky positioning</h1> + +<dl> + <dt>A</dt> + <dd>Apple</dd> + <dd>Ant</dd> + <dd>Altimeter</dd> + <dd>Airplane</dd> + <dt>B</dt> + <dd>Bird</dd> + <dd>Buzzard</dd> + <dd>Bee</dd> + <dd>Banana</dd> + <dd>Beanstalk</dd> + <dt>C</dt> + <dd>Calculator</dd> + <dd>Cane</dd> + <dd>Camera</dd> + <dd>Camel</dd> + <dt>D</dt> + <dd>Duck</dd> + <dd>Dime</dd> + <dd>Dipstick</dd> + <dd>Drone</dd> + <dt>E</dt> + <dd>Egg</dd> + <dd>Elephant</dd> + <dd>Egret</dd> +</dl> +</pre> + +<p>The CSS might look as follows. In normal flow the {{htmlelement("dt")}} elements will scroll with the content. When we add <code>position: sticky</code> to the {{htmlelement("dt")}} element, along with a {{cssxref("top")}} value of 0, supporting browsers will stick the headings to the top of the viewport as they reach that position. Each subsequent header will then replace the previous one as it scrolls up to that position.</p> + +<pre class="brush: css">dt { + background-color: black; + color: white; + padding: 10px; + position: sticky; + top: 0; + left: 0; + margin: 1em 0; +} +</pre> + +<div id="Sticky_2"> +<div class="hidden"> +<pre class="brush: css">body { + width: 500px; + height: 1400px; + margin: 0 auto; +} + +dt { + background-color: black; + color: white; + padding: 10px; + position: sticky; + top: 0; + left: 0; + margin: 1em 0; +} +</pre> + +<pre class="brush: html"><h1>Sticky positioning</h1> + +<dl> + <dt>A</dt> + <dd>Apple</dd> + <dd>Ant</dd> + <dd>Altimeter</dd> + <dd>Airplane</dd> + <dt>B</dt> + <dd>Bird</dd> + <dd>Buzzard</dd> + <dd>Bee</dd> + <dd>Banana</dd> + <dd>Beanstalk</dd> + <dt>C</dt> + <dd>Calculator</dd> + <dd>Cane</dd> + <dd>Camera</dd> + <dd>Camel</dd> + <dt>D</dt> + <dd>Duck</dd> + <dd>Dime</dd> + <dd>Dipstick</dd> + <dd>Drone</dd> + <dt>E</dt> + <dd>Egg</dd> + <dd>Elephant</dd> + <dd>Egret</dd> +</dl> +</pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Sticky_2', '100%', 200) }}</p> + +<div class="note"> +<p><strong>Note</strong>: You can see this example live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/7_sticky-positioning.html">7_sticky-positioning.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/7_sticky-positioning.html">see source code</a>).</p> +</div> + +<h2 id="Summary">Summary</h2> + +<p>I'm sure you had fun playing with basic positioning; while it is not a method you would use for entire layouts, as you can see there are many tasks it is suited for.</p> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Floats", "Learn/CSS/CSS_layout/Multiple-column_Layout", "Learn/CSS/CSS_layout")}}</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li>The {{cssxref("position")}} property reference.</li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Practical_positioning_examples">Practical positioning examples</a>, for some more useful ideas.</li> +</ul> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introduction to CSS layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Normal flow</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grid</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Floats</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Positioning</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Multiple-column layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design">Responsive design</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Beginner's guide to media queries</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Legacy layout methods</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Supporting older browsers</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Fundamental layout comprehension assessment</a></li> +</ul> diff --git a/files/pt-br/learn/css/css_layout/responsive_design/index.html b/files/pt-br/learn/css/css_layout/responsive_design/index.html new file mode 100644 index 0000000000..bc554e4537 --- /dev/null +++ b/files/pt-br/learn/css/css_layout/responsive_design/index.html @@ -0,0 +1,324 @@ +--- +title: Design Responsivo +slug: Learn/CSS/CSS_layout/Responsive_Design +translation_of: Learn/CSS/CSS_layout/Responsive_Design +--- +<div>{{learnsidebar}}{{PreviousMenuNext("Learn/CSS/CSS_layout/Multiple-column_Layout", "Learn/CSS/CSS_layout/Media_queries", "Learn/CSS/CSS_layout")}}</div> + +<p>Nos primórdios do web design, páginas eram criadas para serem visualizadas em um tamanho de tela específico. Se o usuário tivesse uma tela maior ou menor do que o esperado, os resultados iam de barras de rolagem indesejadas, tamanhos de linha excessivamente longos e uso inadequado do espaço. À medida que diferentes tamanhos de tela foram aparecendo, surgiu o conceito de web design responsivo (RWD), um conjunto de práticas que permite que páginas da Web alterem seu layout e aparência para se adequarem a diferentes larguras, resoluções, etc. É uma ideia que mudou a forma de como projetamos para a Web com múltiplos dispositivos e, neste artigo, ajudaremos você a entender as principais técnicas que você precisa conhecer para dominá-la.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>HTML básico (estude <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introduction to HTML</a>), e uma idea de como o CSS funciona (estude <a href="/en-US/docs/Learn/CSS/First_steps">CSS first steps</a> e <a href="/en-US/docs/Learn/CSS/Building_blocks">CSS building blocks</a>.)</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender os conceitos fundamentais e a história do design responsivo.</td> + </tr> + </tbody> +</table> + +<h2 id="História_dos_layouts_de_sites">História dos layouts de sites</h2> + +<p>Em algum ponto da história, você tinha duas opções ao criar um site:</p> + +<ul> + <li>Você pode criar um site <em>líquido</em>, que se estenderia para preencher a janela do navegador</li> + <li>ou um site de <em>largura fixa</em>, que seria um tamanho fixo em pixels.</li> +</ul> + +<p>Essas duas abordagens, geralmente, resultavam em um site com a melhor aparência na tela da pessoa que o projetava! O site líquido resultou em um design esmagado para telas menores (como visto abaixo) e comprimentos de linha muito longos em telas maiores.</p> + +<figure><img alt="A layout with two columns squashed into a mobile size viewport." src="https://mdn.mozillademos.org/files/16834/mdn-rwd-liquid.png" style="display: block; height: 406px; width: 300px;"> +<figcaption></figcaption> +</figure> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Veja este layout líquido simples: <a href="https://mdn.github.io/css-examples/learn/rwd/liquid-width.html">exemplo</a>, <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/liquid-width.html">código-fonte</a>. Ao visualizar o exemplo, arraste a janela do navegador para dentro e para fora para ver como isso fica em tamanhos diferentes.</p> +</div> + +<p>O site de largura fixa criava uma barra de rolagem horizontal em telas menores que a largura do site (como mostrado abaixo) e muito espaço em branco nas bordas do design em telas maiores.</p> + +<figure><img alt="A layout with a horizontal scrollbar in a mobile viewport." src="https://mdn.mozillademos.org/files/16835/mdn-rwd-fixed.png" style="display: block; height: 411px; width: 300px;"> +<figcaption></figcaption> +</figure> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Veja este layout simples de largura fixa: <a href="https://mdn.github.io/css-examples/learn/rwd/fixed-width.html">exemplo</a>, <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/fixed-width.html">código-fonte</a>. Observe novamente o resultado ao alterar o tamanho da janela do navegador.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: As capturas de tela acima foram tiradas usando o <a href="/en-US/docs/Tools/Responsive_Design_Mode">Responsive Design Mode</a> no Firefox DevTools.</p> +</div> + +<p>À medida que a Web para dispositivos móveis começava a se tornar realidade com os primeiros telefones com essas características, empresas que desejavam adotar os dispositivos móveis geralmente criavam uma versão mobile do seu site, com uma URL diferente (geralmente algo como m.exemplo.com ou exemplo.mobi) Isso significava que duas versões separadas do site tinham que ser desenvolvidas e mantidas atualizadas.</p> + +<p>Além disso, esses sites para celular geralmente ofereciam uma experiência muito restrita. À medida que os dispositivos móveis se tornaram mais poderosos e capazes de exibir sites completos, os usuários de celular ficaram frustrados, pois, se viram presos na versão mobile do site e incapazes de acessar todas as informações que faziam parte da versão para desktop.</p> + +<h2 id="Layouts_flexiveis_antes_do_design_responsivo">Layouts flexiveis antes do design responsivo</h2> + +<p>Várias abordagens foram desenvolvidas para tentar resolver as desvantagens dos métodos de largura líquida ou largura fixa da construção de sites. Em 2004, Cameron Adams escreveu um artigo intitulado <a href="http://www.themaninblue.com/writing/perspective/2004/09/21/">Resolution dependent layout</a>, descrevendo um método para criar um design que pudesse se adaptar a diferentes resoluções de tela. Essa abordagem necessitava do JavaScript para detectar a resolução da tela e carregar o CSS correto.</p> + +<p>Zoe Mickley Gillenwater foi fundamental no <a href="http://zomigi.com/blog/voices-that-matter-slides-available/">seu trabalho</a> de descrever e formalizar as diferentes maneiras pelas quais sites flexíveis poderiam ser criados, tentando encontrar um meio termo entre preencher a tela ou ter tamanho completamente fixo.</p> + +<h2 id="Design_Responsivo">Design Responsivo</h2> + +<p>O termo design responsivo foi <a href="https://alistapart.com/article/responsive-web-design/">cunhado por Ethan Marcotte em 2010</a>, e descreveu o uso de três técnicas combinadas.</p> + +<ol> + <li>A primeira foi a ideia de grids fluidas, que já estava sendo explorada por Gillenwater, e pode ser encontrada no artigo de Marcotte, <a href="https://alistapart.com/article/fluidgrids/">Fluid Grids</a> (publicado em 2009 em A List Apart).</li> + <li>A segunda técnica foi a ideia de <a href="http://unstoppablerobotninja.com/entry/fluid-images">imagens fluidas</a>. Usando uma técnica muito simples que setava a propriedade <code>max-width</code> com <code>100%</code>, as imagens seriam reduzidas se a coluna que as continha se tornasse mais estreita que o tamanho intrínseco da imagem, mas nunca aumentariam. Isso permitiu que uma imagem fosse reduzida em tamanho para caber em uma coluna de tamanho flexível, em vez de transbordar, mas não aumentava e nem tornava-se pixelizada se a coluna fosse mais larga que a imagem.</li> + <li>O terceiro componente-chave foi a <a href="/en-US/docs/Web/CSS/Media_Queries">media query</a>. Media Queries habilitavam o tipo de opção de layout usando o JavaScript, que Cameron Adams havia explorado anteriormente, usando apenas CSS. Em vez de ter um layout para todos os tamanhos de tela, o layout podia ser alterado. As barras laterais podiam ser reposicionadas para a tela menor ou uma navegação alternativa podia ser exibida.</li> +</ol> + +<p>É importante entender que <strong>o design responsivo não é uma tecnologia separada</strong> — é um termo usado para descrever uma abordagem ao web design, ou um conjunto de melhores práticas, usado para criar um layout que possa <em>responder</em> ao dispositivo que está sendo usado para visualizar o conteúdo. Na exploração original de Marcotte, isso significava grades flexíveis (usando floats) e media queries, no entanto, nos últimos 10 anos, desde que o artigo foi escrito, trabalhar de forma responsiva se tornou um padrão. Os métodos de layout CSS modernos são inerentemente responsivos, e temos coisas novas incorporadas à plataforma web para facilitar o design de sites responsivos.</p> + +<p>O restante deste artigo indicará os vários recursos da plataforma web que você pode usar ao criar um site responsivo.</p> + +<h2 id="Media_Queries">Media Queries</h2> + +<p>O Design Responsivo apenas foi capaz de emergir devido o recurse de media query. A especificação Media Queries Level 3 se tornou uma Recomendação de Candidato em 2009, significando que estava pronto para ser implementado nos browsers. Media Queries nos permitem executar uma série de testes (e.g. se a tela do usuário é maior que uma certa largura, ou uma certa resolução) e aplicar um CSS seletivamente para estilizar a página de acordo com as necessidades do usuário.</p> + +<p>Por exemplo, a seguinte media querie testa se a página atual está sendo exibida como mídia de tela (portanto, não é um documento impresso) e o viewport tem pelo menos 800 pixels de largura. O CSS para o seletor <code>.container</code> será aplicado apenas se essas duas condições forem verdade.</p> + +<pre class="brush: css notranslate"><code>@media screen and (min-width: 800px) { + .container { + margin: 1em 2em; + } +} </code> +</pre> + +<p>Você pode adicionar múltiplos media queries dentro de uma folha de de estilo, ajustando inteiramente seu layout ou partes dele que melhor se adequem a vários tamanhos de tela. Os pontos em quem uma Media Query é introduzida e o layout alterado são conhecidos como <em>breakpoints</em>.</p> + +<p>Uma abordagem comum ao utilizar Media Queries é criar um layout de única coluna para dispositivos de telas pequenas (e.g smartphones), então fazer a checagem para telas maiores e implementar um layout de múltiplas colunas quando houver largura suficiente. Esse design é frequentemente descrito como <strong>mobile first</strong>.</p> + +<p>Encontre mais detalhes na documentação MDN para <a href="/en-US/docs/Web/CSS/Media_Queries">Media Queries</a>.</p> + +<h2 id="Grids_Flexíveis">Grids Flexíveis</h2> + +<p>Sites responsivos não apenas mudam seu layout entre <em>breakpoints</em>, eles são construídos em grids flexíveis. Um grid flexível significa que não há necessidade de marcar todos os tamanhos possíveis existentes, e sim, construir um layout perfeito baseado em pixels que se adequa automaticamente à tela. Essa abordagem seria impossível dado o vasto número de dispositivos com tamanhos diferentes que existem e o fato de que, mesmo nos desktops, as pessoas nem sempre utilizam a janela do navegador maximizada.</p> + +<p>Com o uso de um grid flexível, não há necessidade de adicionar um <em>breakpoint</em> e alterar o desing no ponto onde o conteúdo começa a parecer ruim em determinada tela. Por exemplo, se o comprimento da linha se torna ilegível à medida que o tamanho da tela aumenta, ou uma caixa se fica espremida com duas palavras em cada linha, conforme o tamanho diminui.</p> + +<p>Nos primórdios do design responsivo a única opção disponível para realizar layouts era utilizando <a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">floats</a>. Layouts flexíveis flutuantes eram alcançados dando a cada elemento uma largura percentual, garantindo que em todo layout os totais não fossem maior que 100%. In his original piece on fluid grids, Marcotte detailed a formula for taking a layout designed using pixels and converting it into percentages.</p> + +<pre class="notranslate"><code>target / context = result </code> +</pre> + +<p>For example if our target column size is 60 pixels, and the context (or container) it is in is 960 pixels, we divide 60 by 960 to get a value we can use in our CSS, after moving the decimal point two places to the right.</p> + +<pre class="brush: css notranslate"><code>.col { + width: 6.25%; /* 60 / 960 = 0.0625 */ +} </code> +</pre> + +<p>This approach will be found in many places across the web today, and it is documented here in the layout section of our <a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Legacy layout methods</a> article. It is likely that you will come across websites using this approach in your work, so it is worth understanding it, even though you would not build a modern site using a float-based flexible grid.</p> + +<p>The following example demonstrates a simple responsive design using Media Queries and a flexible grid. On narrow screens the layout displays the boxes stacked on top of one another:</p> + +<figure><img alt="A mobile view of the layout with boxes stacked on top of each other vertically." src="https://mdn.mozillademos.org/files/16836/mdn-rwd-mobile.png" style="display: block; height: 407px; width: 300px;"> +<p>On wider screens they move to two columns:</p> + +<figcaption></figcaption> +</figure> + +<figure><img alt="A desktop view of a layout with two columns." src="https://mdn.mozillademos.org/files/16837/mdn-rwd-desktop.png" style="display: block; height: 217px; width: 600px;"> +<figcaption></figcaption> +</figure> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You can find the <a href="https://mdn.github.io/css-examples/learn/rwd/float-based-rwd.html">live example</a> and <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/float-based-rwd.html">source code</a> for this example on GitHub.</p> +</div> + +<h2 id="Modern_layout_technologies">Modern layout technologies</h2> + +<p>Modern layout methods such as <a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Multiple-column layout</a>, <a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a>, and <a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grid</a> are responsive by default. They all assume that you are trying to create a flexible grid and give you easier ways to do so.</p> + +<h3 id="Multicol">Multicol</h3> + +<p>The oldest of these layout methods is multicol — when you specify a <code>column-count</code>, this indicates how many columns you want your content to be split into. The browser then works out the size of these, a size that will change according to the screen size.</p> + +<pre class="brush: css notranslate"><code>.container { + column-count: 3; +} </code> +</pre> + +<p>If you instead specify a <code>column-width</code>, you are specifying a <em>minimum</em> width. The browser will create as many columns of that width as will comfortably fit into the container, then share out the remaining space between all the columns. Therefore the number of columns will change according to how much space there is.</p> + +<pre class="brush: css notranslate"><code>.container { + column-width: 10em; +} </code> +</pre> + +<h3 id="Flexbox">Flexbox</h3> + +<p>In Flexbox, flex items will shrink and distribute space between the items according to the space in their container, as their initial behavior. By changing the values for <code>flex-grow</code> and <code>flex-shrink</code> you can indicate how you want the items to behave when they encounter more or less space around them.</p> + +<p>In the example below the flex items will each take an equal amount of space in the flex container, using the shorthand of <code>flex: 1</code> as described in the layout topic <a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox#Flexible_sizing_of_flex_items">Flexbox: Flexible sizing of flex items</a>.</p> + +<pre class="brush: css notranslate"><code>.container { + display: flex; +} + +.item { + flex: 1; +} </code> +</pre> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: As an example we have rebuilt the simple responsive layout above, this time using flexbox. You can see how we no longer need to use strange percentage values to calculate the size of the columns: <a href="https://mdn.github.io/css-examples/learn/rwd/flex-based-rwd.html">example</a>, <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/flex-based-rwd.html">source code</a>.</p> +</div> + +<h3 id="CSS_grid">CSS grid</h3> + +<p>In CSS Grid Layout the <code>fr</code> unit allows the distribution of available space across grid tracks. The next example creates a grid container with three tracks sized at <code>1fr</code>. This will create three column tracks, each taking one part of the available space in the container. You can find out more about this approach to create a grid in the Learn Layout Grids topic, under <a href="en-US/docs/Learn/CSS/CSS_layout/Grids#Flexible_grids_with_the_fr_unit">Flexible grids with the fr unit</a>.</p> + +<pre class="brush: css notranslate"><code>.container { + display: grid; + grid-template-columns: 1fr 1fr 1fr; +} </code> +</pre> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: The grid layout version is even simpler as we can define the columns on the .wrapper: <a href="https://mdn.github.io/css-examples/learn/rwd/grid-based-rwd.html">example</a>, <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/grid-based-rwd.html">source code</a>.</p> +</div> + +<h2 id="Responsive_images">Responsive images</h2> + +<p>The simplest approach to responsive images was as described in Marcotte's early articles on responsive design. Basically, you would take an image that was at the largest size that might be needed, and scale it down. This is still an approach used today, and in most stylesheets you will find the following CSS somewhere:</p> + +<pre class="brush: css notranslate"><code>img { + max-width: 100%: +} </code> +</pre> + +<p>There are obvious downsides to this approach. The image might be displayed a lot smaller than its intrinsic size, which is a waste of bandwidth — a mobile user may be downloading an image several times the size of what they actually see in the browser window. In addition, you may not want the same image aspect ratio on mobile as on desktop. For example, it might be nice to have a square image for mobile, but show the same scene as a landscape image on desktop. Or, acknowledging the smaller size of an image on mobile you might want to show a different image altogether, one which is more easily understood at a small screen size. These things can't be achieved by simply scaling down an image.</p> + +<p>Responsive Images, using the <code><a href="/en-US/docs/Web/HTML/Element/picture"><picture></a></code> element and the <code><a href="/en-US/docs/Web/HTML/Element/img"><img></a></code> <code>srcset</code> and <code>sizes</code> attributes solve both of these problems. You can provide multiple sizes along with "hints" (meta data that describes the screen size and resolution the image is best suited for), and the browser will choose the most appropriate image for each device, ensuring that a user will download an image size appropriate for the device they are using.</p> + +<p>You can also <em>art direct</em> images used at different sizes, thus providing a different crop or completely different image to different screen sizes.</p> + +<p>You can find a detailed <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">guide to Responsive Images in the Learn HTML section</a> here on MDN.</p> + +<h2 id="Responsive_typography">Responsive typography</h2> + +<p>An element of responsive design not covered in earlier work was the idea of responsive typography. Essentially, this describes changing font sizes within media queries to reflect lesser or greater amounts of screen real estate.</p> + +<p>In this example, we want to set our level 1 heading to be <code>4rem</code>, meaning it will be four times our base font size. That's a really large heading! We only want this jumbo heading on larger screen sizes, therefore we first create a smaller heading then use media queries to overwrite it with the larger size if we know that the user has a screen size of at least 1200px.</p> + +<pre class="brush: css notranslate"><code>html { + font-size: 1em; +} + +h1 { + font-size: 2rem; +} + +@media (min-width: 1200px) { + h1 { + font-size: 4rem; + } +} </code> +</pre> + +<p>We have edited our responsive grid example above to also include responsive type using the method outlined. You can see how the heading switches sizes as the layout goes to the two column version.</p> + +<p>On mobile the heading is smaller:</p> + +<figure><img alt="A stacked layout with a small heading size." src="https://mdn.mozillademos.org/files/16838/mdn-rwd-font-mobile.png" style="display: block; height: 407px; width: 300px;"> +<p>On desktop however we see the larger heading size:</p> + +<figcaption></figcaption> +</figure> + +<figure><img alt="A two column layout with a large heading." src="https://mdn.mozillademos.org/files/16839/mdn-rwd-font-desktop.png" style="display: block; height: 169px; width: 600px;"> +<figcaption></figcaption> +</figure> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: See this example in action: <a href="https://mdn.github.io/css-examples/learn/rwd/type-rwd.html">example</a>, <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/type-rwd.html">source code</a>.</p> +</div> + +<p>As this approach to typography shows, you do not need to restrict media queries to only changing the layout of the page. They can be used to tweak any element to make it more usable or attractive at alternate screen sizes.</p> + +<h3 id="Using_viewport_units_for_responsive_typography">Using viewport units for responsive typography</h3> + +<p>An interesting approach is to use the viewport unit <code>vw</code> to enable responsive typography. <code>1vw</code> is equal to one percent of the viewport width, meaning that if you set your font size using <code>vw</code>, it will always relate to the size of the viewport.</p> + +<pre class="brush: css notranslate">h1 { + font-size: 6vw; +}</pre> + +<p>The problem with doing the above is that the user loses the ability to zoom any text set using the vw unit, as that text is always related to the size of the viewport. <strong>Therefore you should never set text using viewport units alone</strong>.</p> + +<p>There is a solution, and it involves using <code><a href="/en-US/docs/Web/CSS/calc">calc()</a></code>. If you add the <code>vw</code> unit to a value set using a fixed size such as <code>em</code>s or <code>rem</code>s then the text will still be zoomable. Essentially, the <code>vw</code> unit adds on top of that zoomed value:</p> + +<pre class="brush: css notranslate">h1 { + font-size: calc(1.5rem + 3vw); +}</pre> + +<p>This means that we only need to specify the font size for the heading once, rather than set it up for mobile and redefine it in the media queries. The font then gradually increases as you increase the size of the viewport.</p> + +<div class="blockIndicator note"> +<p>See an example of this in action: <a href="https://mdn.github.io/css-examples/learn/rwd/type-vw.html">example</a>, <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/type-vw.html">source code</a>.</p> +</div> + +<h2 id="The_viewport_meta_tag">The viewport meta tag</h2> + +<p>If you look at the HTML source of a responsive page, you will usually see the following {{htmlelement("meta")}} tag in the <code><head></code> of the document.</p> + +<pre class="brush: html notranslate"><code><meta name="viewport" content="width=device-width,initial-scale=1"></code> +</pre> + +<p>This meta tag tells mobile browsers that they should set the width of the viewport to the device width, and scale the document to 100% of its intended size, which shows the document at the mobile-optimized size that you intended.</p> + +<p>Why is this needed? Because mobile browsers tend to lie about their viewport width.</p> + +<p>This meta tag exists because when the original iPhone launched and people started to view websites on a small phone screen, most sites were not mobile optimized. The mobile browser would therefore set the viewport width to 960 pixels, render the page at that width, and show the result as a zoomed-out version of the desktop layout. Other mobile browsers (e.g. on Google Android) did the same thing. Users could zoom in and pan around the website to view the bits they were interested in, but it looked bad. You will still see this today if you have the misfortune to come across a site that does not have a responsive design.</p> + +<p>The trouble is that your responsive design with breakpoints and media queries won't work as intended on mobile browsers. If you've got a narrow screen layout that kicks in at 480px viewport width or less, and the viewport is set at 960px, you'll never see your narrow screen layout on mobile. By setting <code>width=device-width</code> you are overriding Apple's default <code>width=960px</code> with the actual width of the device, so your media queries will work as intended.</p> + +<p><strong>So you should <em>always</em> include the above line of HTML in the head of your documents.</strong></p> + +<p>There are other settings you can use with the viewport meta tag, however in general the above line is what you will want to use.</p> + +<ul> + <li><code>initial-scale</code>: Sets the initial zoom of the page, which we set to 1.</li> + <li><code>height</code>: Sets a specific height for the viewport.</li> + <li><code>minimum-scale</code>: Sets the minimum zoom level.</li> + <li><code>maximum-scale</code>: Sets the maximum zoom level.</li> + <li><code>user-scalable</code>: Prevents zooming if set to <code>no</code>.</li> +</ul> + +<p>You should avoid using <code>minimum-scale</code>, <code>maximum-scale</code>, and in particular setting <code>user-scalable</code> to <code>no</code>. Users should be allowed to zoom as much or as little as they need to; preventing this causes accessibility problems.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: There is a CSS @ rule designed to replace the viewport meta tag — <a href="/en-US/docs/Web/CSS/@viewport">@viewport</a> — however it has poor browser support. It was implemented in Internet Explorer and Edge, however once the Chromium-based Edge ships it will no longer be part of the Edge browser.</p> +</div> + +<h2 id="Summary">Summary</h2> + +<p>Responsive design refers to a site or application design that responds to the environment in which it is viewed. It encompasses a number of CSS and HTML features and techniques, and is now essentially just how we build websites by default. Consider the sites that you visit on your phone — it is probably fairly unusual to come across a site that is the desktop version scaled down, or where you need to scroll sideways to find things. This is because the web has moved to this approach of designing responsively.</p> + +<p>It has also become much easier to achieve responsive designs with the help of the layout methods you have learned in these lessons. If you are new to web development today you have many more tools at your disposal than in the early days of responsive design. It is therefore worth checking the age of any materials you are referencing. While the historical articles are still useful, modern use of CSS and HTML makes it far easier to create elegant and useful designs, no matter what device your visitor views the site with.</p> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Multiple-column_Layout", "Learn/CSS/CSS_layout/Media_queries", "Learn/CSS/CSS_layout")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introduction to CSS layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Normal flow</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grid</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Floats</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Positioning</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Multiple-column layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design">Responsive design</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Beginner's guide to media queries</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Legacy layout methods</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Supporting older browsers</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Fundamental layout comprehension assessment</a></li> +</ul> diff --git a/files/pt-br/learn/css/first_steps/como_css_e_estruturado/index.html b/files/pt-br/learn/css/first_steps/como_css_e_estruturado/index.html new file mode 100644 index 0000000000..4084647920 --- /dev/null +++ b/files/pt-br/learn/css/first_steps/como_css_e_estruturado/index.html @@ -0,0 +1,502 @@ +--- +title: Como CSS é estruturado +slug: Learn/CSS/First_steps/Como_CSS_e_estruturado +translation_of: Learn/CSS/First_steps/How_CSS_is_structured +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/First_steps/Getting_started", "Learn/CSS/First_steps/How_CSS_works", "Learn/CSS/First_steps")}}</div> + +<p class="summary">Agora que você tem uma ideia sobre o que é o CSS e seu uso basico, é hora de olhar um pouco mais a fundo das estruturas da linguagem em si. Nós ja conhecemos muitos conceitos discutidos aqui, entretanto, você pode voltar para qualquer um em específico, se achar algum dos proximos conceitos um tanto confuso</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conceitos básicos de computação, <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Installing_basic_software">softwares básicos instalados</a>, conhecimentos básicos de <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Dealing_with_files">operação com arquivos</a>, básico de HTML (veja <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introdução ao HTML</a>), e uma ideia de <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/How_CSS_works">Como funciona o CSS</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender as estruturas da sintaxe básica do CSS em detalhes.</td> + </tr> + </tbody> +</table> + +<h2 id="Aplicando_CSS_no_seu_HTML">Aplicando CSS no seu HTML</h2> + +<p>A primeira coisa que você vai olhar é, os três métodos de aplicação do CSS em um documento.</p> + +<h3 id="Folha_de_Estilos_Externa">Folha de Estilos Externa</h3> + +<p>Em <a href="https://developer.mozilla.org/pt-BR/docs/Aprender/Getting_started_with_the_web/CSS_basico">Começando com o CSS</a> nós linkamos uma folha de estilos externas em nossa página. Isso é o metodo mias comum utilizado para juntar CSS em um documento, podendo utilizar tal método em multiplas páginas, permitindo você estillizar todas as páginas como as mesmas folha de estilos. Na maioria dos casos, as diferentes páginas do site vão parecer bem iguais entre si e por isso você pode usar as mesmas regras para o estilo padrão da página.</p> + +<p><code><font face="Arial, x-locale-body, sans-serif"><span style="background-color: #ffffff;">Uma folha de estilos externa é quando você tem seu CSS escrito em um arquivo separado com uma extensão </span></font>.css</code>, e você o refere dentro de um elemento <code><link></code> do HTML:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>My CSS experiment</title> + <link rel="stylesheet" href="styles.css"> + </head> + <body> + <h1>Hello World!</h1> + <p>This is my first CSS example</p> + </body> +</html></pre> + +<p>O arquivo CSS deve se parecer com algo nesse estilo:</p> + +<pre class="brush: css notranslate">h1 { + color: blue; + background-color: yellow; + border: 1px solid black; +} + +p { + color: red; +}</pre> + +<p>O atributo <code>href</code> do elemento {{htmlelement("link")}}, precisa fazer referência a um arquivo em nosso sistema de arquivos.</p> + +<p>No exemplo abaixo, o arquivo CSS está na mesma pasta que o documento HTML, mas você pode colocá-lo em outro lugar e reajustar o caminho marcado para encontrá-lo, como a seguir: </p> + +<pre class="brush: html notranslate"><!-- Inside a subdirectory called styles inside the current directory --> +<link rel="stylesheet" href="styles/style.css"> + +<!-- Inside a subdirectory called general, which is in a subdirectory called styles, inside the current directory --> +<link rel="stylesheet" href="styles/general/style.css"> + +<!-- Go up one directory level, then inside a subdirectory called styles --> +<link rel="stylesheet" href="../styles/style.css"></pre> + +<h3 id="Folha_de_estilos_interna">Folha de estilos interna</h3> + +<p>Uma folha de estilos interna é usada quando você não tem um arquivo CSS externo, mas, ao contrário, coloca seu CSS dentro de elemento {{htmlelement("style")}} localizado no {{htmlelement("head")}} do documento HTML.</p> + +<p>Deste modo, seu HTML se parecerá assim:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>My CSS experiment</title> + <style> + h1 { + color: blue; + background-color: yellow; + border: 1px solid black; + } + + p { + color: red; + } + </style> + </head> + <body> + <h1>Hello World!</h1> + <p>This is my first CSS example</p> + </body> +</html></pre> + +<p>Isso pode ser útil em algumas circunstâncias (talvez você esteja trabalhando em um sistema de gerenciamento de conteúdo - CMS - onde não tem permissão para modificar diretamente os arquivos CSS), entretanto isso não é tão eficiente quanto o uso de folhas de estilo externas — em um website, o CSS precisaria ser repetido em todas as páginas e atualizado em vários locais sempre que mudanças fossem necessárias.</p> + +<h3 id="Estilos_inline">Estilos inline</h3> + +<p>Estilos inline são declarações CSS que afetam apenas um determinado elemento, inserido em um atributo <code>style</code>:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>My CSS experiment</title> + </head> + <body> + <h1 style="color: blue;background-color: yellow;border: 1px solid black;">Hello World!</h1> + <p style="color:red;">This is my first CSS example</p> + </body> +</html></pre> + +<p><strong>Por favor, não utilize isso a menos que seja estritamente necessário!</strong> É péssimo para manutenção (você precisará atualizar a mesma informação diversas vezes em cada documento), além do que, mistura sua informação de estilização do CSS com sua informação de estrutura HTML, tornando seu código de difícil leitura e compreensão. Manter diferentes tipos de código separados torna o trabalho muito mais fácil para todos os que trabalham no código.</p> + +<p>Existem alguns lugares onde o estilo embutido é mais comum, ou mesmo aconselhável. Você pode ter que recorrer ao uso deles se seu ambiente de trabalho for realmente restritivo (talvez o seu CMS permita apenas que você edite o corpo do HTML). Você também os verá sendo muito usados em e-mails em HTML de modo a obter compatibilidade com o maior número possível de clientes de e-mail.</p> + +<h2 id="Playing_with_the_CSS_in_this_article">Playing with the CSS in this article</h2> + +<p>There is a lot of CSS to play with in this article. To do so, we'd recommend creating a new directory/folder on your computer, and inside it creating a copy of the following two files:</p> + +<p>index.html:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>My CSS experiments</title> + <link rel="stylesheet" href="styles.css"> + </head> + <body> + + <p>Create your test HTML here</p> + + </body> +</html></pre> + +<p>styles.css:</p> + +<pre class="brush: css notranslate">/* Create your test CSS here */ + +p { + color: red; +}</pre> + +<p>Then, when you come across some CSS you want to experiment with, replace the HTML <code><body></code> contents with some HTML to style, and start adding CSS to style it inside your CSS file.</p> + +<p>If you are not using a system where you can easily create files, you can instead use the interactive editor below to experiment.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/getting-started/experiment-sandbox.html", '100%', 800)}} </p> + +<p>Read on, and have fun!</p> + +<h2 id="Seletores">Seletores</h2> + +<p>Não é possível falar de CSS sem conhecer os seletores, e nós já descobrimos vários tipos diferentes no tutorial Começando com o Css. Um seletor é o modo pelo qual nós apontamos para alguma coisa no nosso documento HTML para aplicar os estilos à ela. Se os seus estilos não forem aplicados, então é provável que o seu seletor não esteja ligado aquilo que você pensa que ele deveria.</p> + +<p>Each CSS rule starts with a selector or a list of selectors in order to tell the browser which element or elements the rules should apply to. All of the following are examples of valid selectors, or lists of selectors.</p> + +<pre class="brush: css notranslate">h1 +a:link +.manythings +#onething +* +.box p +.box p:first-child +h1, h2, .intro</pre> + +<p><strong>Try creating some CSS rules that use the above selectors, and some HTML to be styled by them. If you don't know what some of the above syntax means, try searching for it on MDN!</strong></p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You will learn a lot more about selectors in our <a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">CSS selectors</a> tutorials, in the next module.</p> +</div> + +<h3 id="Specificity">Specificity</h3> + +<p>There will often be scenarios where two selectors could select the same HTML element. Consider the stylesheet below where I have a rule with a <code>p</code> selector that will set paragraphs to blue, and also a class that will set selected elements red.</p> + +<pre class="brush: css notranslate">.special { + color: red; +} + +p { + color: blue; +}</pre> + +<p>Let's say that in our HTML document we have a paragraph with a class of <code>special</code>. Both rules could apply, so which one wins? What color do you think our paragraph will become?</p> + +<pre class="brush: html notranslate"><p class="special">What color am I?</p></pre> + +<p>The CSS language has rules to control which rule will win in the event of a collision — these are called <strong>cascade</strong> and <strong>specificity</strong>. In the below code block we have defined two rules for the <code>p</code> selector, but the paragraph ends up being colored blue. This is because the declaration that sets it to blue appears later in the stylesheet, and later styles override earlier ones. This is the cascade in action.</p> + +<pre class="brush: css notranslate">p { + color: red; +} + +p { + color: blue; +}</pre> + +<p>However, in the case of our earlier block with the class selector and the element selector, the class will win, making the paragraph red — even thought it appears earlier in the stylesheet. A class is described as being more specific, or having more specificity than the element selector, so it wins.</p> + +<p><strong>Try the above experiment for yourself — add the HTML to your experiment, then add the two <code>p { ... }</code> rules to your stylesheet. Next, change the first <code>p</code> selector to <code>.special</code> to see how it changes the styling.</strong></p> + +<p>The rules of specificity and the cascade can seem a little complicated at first and are easier to understand once you have built up further CSS knowledge. In our <a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">Cascade and inheritance</a> article, which you'll get to in the next module, I'll explain this in detail, including how to calculate specificity. For now, remember that this exists, and that sometimes CSS might not apply like you expect it to because something else in your stylesheet has a higher specificity. Identifying that more than one rule could apply to an element is the first step in fixing such issues.</p> + +<h2 id="Propriedades_e_valores">Propriedades e valores</h2> + +<p>At its most basic level, CSS consists of two building blocks:</p> + +<ul> + <li><strong>Properties</strong>: Human-readable identifiers that indicate which stylistic features (e.g. <code><a href="/en-US/docs/Web/CSS/font-size">font-size</a></code>, <code><a href="/en-US/docs/Web/CSS/width">width</a></code>, <code><a href="/en-US/docs/Web/CSS/background-color">background-color</a></code>) you want to change.</li> + <li><strong>Values</strong>: Each specified property is given a value, which indicates how you want to change those stylistic features (e.g. what you want to change the font, width or background color to.)</li> +</ul> + +<p>The below image highlights a single property and value. The property name is <code>color</code>, and the value <code>blue</code>.</p> + +<p><img alt="A declaration highlighted in the CSS" src="https://mdn.mozillademos.org/files/16498/declaration.png" style="border: 1px solid #cccccc; display: block; height: 218px; margin: 0 auto; width: 471px;"></p> + +<p>A property paired with a value is called a <em>CSS declaration</em>. CSS declarations are put within <em>CSS Declaration Blocks</em>. This next image shows our CSS with the declaration block highlighted.</p> + +<p><img alt="A highlighted declaration block" src="https://mdn.mozillademos.org/files/16499/declaration-block.png" style="border: 1px solid #cccccc; display: block; height: 218px; margin: 0 auto; width: 471px;"></p> + +<p>Finally, CSS declaration blocks are paired with <em>selectors</em> to produce <em>CSS Rulesets</em> (or <em>CSS Rules</em>). Our image contains two rules, one for the <code>h1</code> selector and one for the <code>p</code> selector. The rule for <code>h1</code> is highlighted.</p> + +<p><img alt="The rule for h1 highlighted" src="https://mdn.mozillademos.org/files/16500/rules.png" style="border: 1px solid #cccccc; display: block; height: 218px; margin: 0 auto; width: 471px;"></p> + +<p>Setting CSS properties to specific values is the core function of the CSS language. The CSS engine calculates which declarations apply to every single element of a page in order to appropriately lay it out and style it. What is important to remember is that both properties and values are case-sensitive in CSS. The property and value in each pair is separated by a colon (<code>:</code>).</p> + +<p><strong>Try looking up different values of the following properties, and writing CSS rules that apply them to different HTML elements: </strong></p> + +<ul> + <li><strong>{{cssxref("font-size")}}</strong></li> + <li><strong>{{cssxref("width")}}</strong></li> + <li><strong>{{cssxref("background-color")}}</strong></li> + <li><strong>{{cssxref("color")}}</strong></li> + <li><strong>{{cssxref("border")}}</strong></li> +</ul> + +<div class="warning"> +<p><strong>Important</strong>: If a property is unknown or if a value is not valid for a given property, the declaration is deemed <em>invalid</em> and is completely ignored by the browser's CSS engine.</p> +</div> + +<div class="warning"> +<p><strong>Important</strong>: In CSS (and other web standards), US spelling has been agreed on as the standard to stick to where language uncertainty arises. For example, <code>color</code> should <em>always</em> be spelled <code>color</code>. <code>colour</code> won't work.</p> +</div> + +<h3 id="Functions">Functions</h3> + +<p>While most values are relatively simple keywords or numeric values, there are some possible values which take the form of a function. An example would be the <code>calc()</code> function. This function allows you to do simple math from within your CSS, for example:</p> + +<div id="calc_example"> +<pre class="brush: html notranslate"><div class="outer"><div class="box">The inner box is 90% - 30px.</div></div></pre> + +<pre class="brush: css notranslate">.outer { + border: 5px solid black; +} + +.box { + padding: 10px; + width: calc(90% - 30px); + background-color: rebeccapurple; + color: white; +}</pre> +</div> + +<p>This renders like so:</p> + +<p>{{EmbedLiveSample('calc_example', '100%', 200)}}</p> + +<p>A function consists of the function name, and then some brackets into which the allowed values for that function are placed. In the case of the <code>calc()</code> example above I am asking for the width of this box to be 90% of the containing block width, minus 30 pixels. This isn't something I can calculate ahead of time and just enter the value into the CSS, as I don't know what 90% will be. As with all values, the relevant page on MDN will have usage examples so you can see how the function works.</p> + +<p>Another example would be the various values for {{cssxref("transform")}}, such as <code>rotate()</code>.</p> + +<div id="transform_example"> +<pre class="brush: html notranslate"><div class="box"></div></pre> + +<pre class="brush: css notranslate">.box { + margin: 30px; + width: 100px; + height: 100px; + background-color: rebeccapurple; + transform: rotate(0.8turn) +}</pre> +</div> + +<p>The output from the above code looks like this:</p> + +<p>{{EmbedLiveSample('transform_example', '100%', 200)}}</p> + +<p><strong>Try looking up different values of the following properties, and writing CSS rules that apply them to different HTML elements: </strong></p> + +<ul> + <li><strong>{{cssxref("transform")}}</strong></li> + <li><strong>{{cssxref("background-image")}}, in particular gradient values</strong></li> + <li><strong>{{cssxref("color")}}, in particular rgb/rgba/hsl/hsla values</strong></li> +</ul> + +<h2 id="rules">@rules</h2> + +<p>As yet, we have not encountered <code><a href="/en-US/docs/Web/CSS/At-rule">@rules</a></code> (pronounced "at-rules"). These are special rules giving CSS some instruction on how to behave. Some <code>@rules</code> are simple with the rule name and a value. For example, to import an additional stylesheet into your main CSS stylesheet you can use <code>@import</code>:</p> + +<pre class="brush: css notranslate">@import 'styles2.css';</pre> + +<p>One of the most common <code>@rules</code> you will come across is <code>@media</code>, which allows you to use <a href="/en-US/docs/Web/CSS/Media_Queries">media queries</a> to apply CSS only when certain conditions are true (e.g. when the screen resolution is above a certain amount, or the screen is wider than a certain width).</p> + +<p>In the below CSS, we have a stylesheet that gives the <code><body></code> element a pink background color. However, we then use <code>@media</code> to create a section of our stylesheet that will only be applied in browsers with a viewport wider than 30em. If the browser is wider than 30em then the background color will be blue.</p> + +<pre class="brush: css notranslate">body { + background-color: pink; +} + +@media (min-width: 30em) { + body { + background-color: blue; + } +}</pre> + +<p>You will encounter other <code>@rules</code> throughout these tutorials.</p> + +<p><strong>See if you can add a media query to your CSS that changes styles based on the viewport width. Change the width of your browser window to see the result.</strong></p> + +<h2 id="Shorthands">Shorthands</h2> + +<p>Some properties like {{cssxref("font")}}, {{cssxref("background")}}, {{cssxref("padding")}}, {{cssxref("border")}}, and {{cssxref("margin")}} are called <strong>shorthand properties</strong> — this is because they allow you to set several property values in a single line, saving time and making your code neater in the process.</p> + +<p>For example, this line:</p> + +<pre class="brush: css notranslate">/* In 4-value shorthands like padding and margin, the values are applied + in the order top, right, bottom, left (clockwise from the top). There are also other + shorthand types, for example 2-value shorthands, which set padding/margin + for top/bottom, then left/right */ +padding: 10px 15px 15px 5px;</pre> + +<p>Does the same thing as all these together:</p> + +<pre class="brush: css notranslate">padding-top: 10px; +padding-right: 15px; +padding-bottom: 15px; +padding-left: 5px;</pre> + +<p>Whereas this line:</p> + +<pre class="brush: css notranslate">background: red url(bg-graphic.png) 10px 10px repeat-x fixed;</pre> + +<p>Does the same thing as all these together:</p> + +<pre class="brush: css notranslate">background-color: red; +background-image: url(bg-graphic.png); +background-position: 10px 10px; +background-repeat: repeat-x; +background-scroll: fixed;</pre> + +<p>We won't attempt to teach these exhaustively now — you'll come across many examples later on in the course, and you are advised to look up the shorthand property names in our <a href="/en-US/docs/Web/CSS/Reference">CSS reference</a> to find out more.</p> + +<p><strong>Try adding the above declarations to your CSS to see how it affects the styling of your HTML. Try experimenting with some different values.</strong></p> + +<div class="blockIndicator warning"> +<p><strong>Warning</strong>: While shorthands often allow you to miss out values, they will then reset any values that you do not include to their initial values. This ensures that a sensible set of values are used. However, this might be confusing if you were expecting the shorthand to only change the values you passed in.</p> +</div> + +<h2 id="Comments">Comments</h2> + +<p>As with HTML, you are encouraged to make comments in your CSS, to help you understand how your code works when coming back to it after several months, and to help others coming to the code to work on it understand it.</p> + +<p>Comments in CSS begin with <code>/*</code> and end with <code>*/</code>. In the below code block I have used comments to mark the start of different distinct code sections. This is useful to help you navigate your codebase as it gets larger — you can search for the comments in your code editor.</p> + +<pre class="brush: css notranslate">/* Handle basic element styling */ +/* -------------------------------------------------------------------------------------------- */ +body { + font: 1em/150% Helvetica, Arial, sans-serif; + padding: 1em; + margin: 0 auto; + max-width: 33em; +} + +@media (min-width: 70em) { + /* Let's special case the global font size. On large screen or window, + we increase the font size for better readability */ + body { + font-size: 130%; + } +} + +h1 {font-size: 1.5em;} + +/* Handle specific elements nested in the DOM */ +/* -------------------------------------------------------------------------------------------- */ +div p, #id:first-line { + background-color: red; + background-style: none +} + +div p{ + margin: 0; + padding: 1em; +} + +div p + p { + padding-top: 0; +}</pre> + +<p>Comments are also useful for temporarily <em>commenting out</em> certain parts of the code for testing purposes, for example if you are trying to find which part of your code is causing an error. In the next example I have commented out the rules for the <code>.special</code> selector.</p> + +<pre class="brush: css notranslate">/*.special { + color: red; +}*/ + +p { + color: blue; +}</pre> + +<p><strong>Add some comments to your CSS, to get used to using them.</strong></p> + +<h2 id="Whitespace">Whitespace</h2> + +<p>White space means actual spaces, tabs and new lines. In the same manner as HTML, the browser tends to ignore much of the whitespace inside your CSS; a lot of the whitespace is just there to aid readability.</p> + +<p>In our first example below we have each declaration (and rule start/end) on its own line — this is arguably a good way to write CSS, as it makes it easy to maintain and understand:</p> + +<pre class="brush: css notranslate">body { + font: 1em/150% Helvetica, Arial, sans-serif; + padding: 1em; + margin: 0 auto; + max-width: 33em; +} + +@media (min-width: 70em) { + body { + font-size: 130%; + } +} + +h1 { + font-size: 1.5em; +} + +div p, +#id:first-line { + background-color: red; + background-style: none +} + +div p { + margin: 0; + padding: 1em; +} + +div p + p { + padding-top: 0; +} +</pre> + +<p id="Very_compact">You could write exactly the same CSS like so, with most of the whitespace removed — this is functionally identical to the first example, but I'm sure you'll agree that it is somewhat harder to read:</p> + +<pre class="brush: css notranslate">body {font: 1em/150% Helvetica, Arial, sans-serif; padding: 1em; margin: 0 auto; max-width: 33em;} +@media (min-width: 70em) { body {font-size: 130%;} } + +h1 {font-size: 1.5em;} + +div p, #id:first-line {background-color: red; background-style: none} +div p {margin: 0; padding: 1em;} +div p + p {padding-top: 0;} +</pre> + +<p>The code layout you choose is usually a personal preference, although when you start to work in teams, you may find that the existing team has its own styleguide that specifies an agreed convention to follow.</p> + +<p>The whitespace you do need to be careful of in CSS is the whitespace between the properties and their values. For example, the following declarations are valid CSS:</p> + +<pre class="brush: css notranslate">margin: 0 auto; +padding-left: 10px;</pre> + +<p>But the following are invalid:</p> + +<pre class="brush: css notranslate">margin: 0auto; +padding- left: 10px;</pre> + +<p><code>0auto</code> is not recognised as a valid value for the <code>margin</code> property (<code>0</code> and <code>auto</code> are two separate values,) and the browser does not recognise <code>padding-</code> as a valid property. So you should always make sure to separate distinct values from one another by at least a space, but keep property names and property values together as single unbroken strings.</p> + +<p><strong>Try playing with whitespace inside your CSS, to see what breaks things and what doesn't.</strong></p> + +<h2 id="Whats_next">What's next?</h2> + +<p>It's useful to understand a little about how the browser takes your HTML and CSS and turns it into a webpage, so in the next article — <a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_works">How CSS works</a> — we will take a look at that process.</p> + +<p>{{PreviousMenuNext("Learn/CSS/First_steps/Getting_started", "Learn/CSS/First_steps/How_CSS_works", "Learn/CSS/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/First_steps/What_is_CSS">O que é CSS?</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Getting_started">Começando com CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_is_structured">Como o CSS é estruturad</a>o</li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_works">Como o CSS funciona</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">Usando seu novo conhecimento</a></li> +</ol> diff --git a/files/pt-br/learn/css/first_steps/how_css_works/index.html b/files/pt-br/learn/css/first_steps/how_css_works/index.html new file mode 100644 index 0000000000..55bc0f1978 --- /dev/null +++ b/files/pt-br/learn/css/first_steps/how_css_works/index.html @@ -0,0 +1,161 @@ +--- +title: Como funciona o CSS +slug: Learn/CSS/First_steps/How_CSS_works +tags: + - CSS + - DOM + - Iniciante + - aprenda +translation_of: Learn/CSS/First_steps/How_CSS_works +--- +<p>{{LearnSidebar}}<br> + {{PreviousMenuNext("Learn/CSS/First_steps/How_CSS_is_structured", "Learn/CSS/First_steps/Using_your_new_knowledge", "Learn/CSS/First_steps")}}</p> + +<p class="summary">Nós aprendemos o básico de CSS, porque e como escrever simples folhas de estílo. Nesta lição, nós daremos uma olhada em como um navegador transforma um CSS e HTML em uma página da web.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisito:</th> + <td>Alfabetização em computação básica, <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Installing_basic_software">softwares básicos instalados</a>, conhecimento básico sobre <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Dealing_with_files">trabalhar com arquivos</a>, e o básico de HTML (estude <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introdução ao HTML</a>.)</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender o básico sobre como o CSS e o HTML são interpretados pelo navegador (que em seu nome original chama-se browser do inglês), e o que acontece quando um browser encontra regras CSS mas não as compreende.</td> + </tr> + </tbody> +</table> + +<h2 id="Como_o_CSS_funciona">Como o CSS funciona?</h2> + +<p>Quando um navegador redenriza um documento, ele combina o documento com suas informações de estilo. E o documento é processado em estágios, nos quais estão listados abaixo. É sugerível ter em mente que esta é uma versão simplificada do que ocorre quando um navegador redenriza uma página web, e que diferentes navegadores podem manipular estes processos de diferentes formas. De toda forma, esta listagem é muito aproximada do processo comum feito pela maioria dos navegadores.</p> + +<ol> + <li>O navegador carrega o HTML (e.g. que é recebido pela internet).</li> + <li>Ele então converte o {{Glossary("HTML")}} para um {{Glossary("DOM")}} (<em>Document Object Model</em>). O DOM representa o documento na memória do computador. O DOM será também melhor detalhado na próxima seção.</li> + <li>O navegador então requisita a maioria dos recursos que estão lincados no documento HTML, elementos como imagens encorporadas e vídeos, e também, folhas de estilo CSS. O código em JavaScript é manipulado um pouco mais tarde durante o processo, e não falaremos muito sobre a manipulação do JavaScript agora para mantermos as coisas simples.</li> + <li>O navegador analisa o CSS encontrado (fetched) e interpreta as diferentes regras por meio de seus diferentes tipos de seletores em diferentes baldes (buckets), tais como elementos (ex: h1, h2), classes (.myElement), ID (#myNav), e outros mais. Baseado nos seletores encontrados, o navegador insere as regras de estilização que devem ser aplicadas para cada node no DOM, e anexa o estilo para os elementos como foram especificados nas folhas de estilização (este processo intermediário é chamado de render tree ou árvore de renderização).</li> + <li>A árvore de renderização é organizada na estrutura e deve aparecer depois das regras de estilo serem aplicadas ao documento.</li> + <li>O visual de visualização da página é por fim mostrado na tela (este estágio é chamado de <em>painting</em> ou pintura).</li> +</ol> + +<p>O diagrama a seguir também apresenta uma visão simples do processo.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/11781/rendering.svg" style="height: auto; max-width: 635px; width: 100%;"></p> + +<h2 id="Sobre_o_DOM">Sobre o DOM</h2> + +<p>Um DOM uma estrutura árborea (tree-like). Cada elemento, atributo, ou fragmento de texto na linguagem de marcação (markup language) torna-se um {{Glossary("Node/DOM","DOM node (nó ou ponto de intersecção)")}} na estrutura de árvore. Os nodes (nós) são definidos por meio do relacionamento com outros nodes presentes DOM. Alguns elementos são pais ou superiores a elementos dentro de si (child node, ou em português, nós filhos ou nós secundários), e child nodes possuem elementos irmãos.</p> + +<p>Compreender o DOM ajuda você organizar, debugar e manter seu CSS porque o DOM é onde seu CSS e o conteúdo do documento são combinados. Quando você começa a trabalhar com as DevTools do browser você estará navegando os elementos do DOM como itens ordenados selecionáveis para assim decidir quais regras de estilização aplicar.</p> + +<h2 id="Uma_representação_prática_do_DOM">Uma representação prática do DOM</h2> + +<p>Ao invés de um longa e chata explicação, vamos observar um exemplo para vermos como um trecho real de um documento HTML é convertido em um DOM.</p> + +<p>Pegue o seguinte código HTML:</p> + +<pre class="brush: html notranslate"><p> + Let's use: + <span>Cascading</span> + <span>Style</span> + <span>Sheets</span> +</p> +</pre> + +<p>No DOM, o node (nó) especifica nosso elementro <code><p></code> como um elemento pai. Seus filhos são um text node e a árvore de nós que corresponde ao nossos elementos <code><span></code>. Os nós <code>SPAN</code> são também elementos pais, tendo os text nodes (textos dentro de si) como seus filhos:</p> + +<pre class="notranslate">P +├─ "Let's use:" +├─ SPAN +| └─ "Cascading" +├─ SPAN +| └─ "Style" +└─ SPAN + └─ "Sheets" +</pre> + +<p>Esta é a forma como um browser interpreta o nosso trecho de documento HTML acima apresentado — O browser renderiza a árvore DOM e nos retorna uma saída no browser da seguinte forma:</p> + +<p>{{EmbedLiveSample('A_real_DOM_representation', '100%', 55)}}</p> + +<div class="hidden"> +<pre class="brush: css notranslate">p {margin:0;}</pre> +</div> + +<h2 id="Aplicando_CSS_ao_DOM">Aplicando CSS ao DOM</h2> + +<p>Vamos adicionar um curto CSS ao nosso documento, para estiliza-lo. Novamente, usamos o trecho HTML seguinte:</p> + +<pre class="brush: html notranslate"><p> + Let's use: + <span>Cascading</span> + <span>Style</span> + <span>Sheets</span> +</p></pre> + +<p>Vamos supor que aplicamos o seguinte CSS a ele:</p> + +<pre class="brush: css notranslate">span { + border: 1px solid black; + background-color: lime; +}</pre> + +<p>O browser irá interpretar o HTML e criar um DOM baseado nele. Como a única regra de estilização CSS disponível possui um seletor <code>span</code>, o browser fará a combinação do CSS rapidamente! Ele irá aplicar a regra de estilo para cada um da árvore <code><span></code>s, e então paint (pintar) o resultado final na tela.</p> + +<p>Ao atualizar há a seguinte saída:</p> + +<p>{{EmbedLiveSample('Applying_CSS_to_the_DOM', '100%', 55)}}</p> + +<p>Em nosso artigo <a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Debugging CSS</a> no próximo módulo nós estaremos usando as DevTools do browser para debugar problemas no CSS, e aprenderemos mais sobre como o navegador interpreta o CSS.</p> + +<h2 id="O_que_acontece_se_um_navegador_não_entende_o_CSS_encontrado">O que acontece se um navegador não entende o CSS encontrado?</h2> + +<p><a href="/en-US/docs/Learn/CSS/First_steps/What_is_CSS#Browser_support">Em uma lição anterior</a>, eu mencionei que navegadores não implementam todo o novo CSS ao mesmo tempo. Em adição, muitas pessoas não usam a versão mais recente de um navegador. Dado que o CSS é processado o tempo todo, e que portanto está adiantado em relação ao que os browsers podem reconhecer, você pode imaginar o que acontece se um browser encontra um seletor ou uma declaração CSS que ele não reconhece.</p> + +<p>A resposta é que ele não faz nada e vai para o próximo conteúdo em CSS!</p> + +<p>Se um browser está analisando suas regras, e econtra uma porpriedade ou valor que ele não entende, ele o ignora e segue para a próxima declaração. Ele vai fazer isto se você cometeu algum erro ou digitou incorretamente uma propriedade ou valor, ou se tal propriedade ou valor é recente e o browser ainda não o processa.</p> + +<p>Similarmente, se um browser encontra um seletor que não comprrende, ele o ignorará e seguirá para a próxima regra.</p> + +<p>No exemplo abaixo usei a grafia em inglês britânico para a propriedade cor, o que a torna inválida e portanto ela não é reconhecida. Por isso, o parágrafo não recebe a coloração azul. Todos os outros CSS foram aplicados, no entanto, apenas aquele que foi considerado inválido foi ignorado.</p> + +<div id="Skipping_example"> +<pre class="brush: html notranslate"><p> Quero que este texto esteja grande, em negrito, e azul.</p></pre> + +<pre class="brush: css notranslate">p { + font-weight: bold; + colour: blue; /* grafia incorreta da propriedade cor */ + font-size: 200%; +}</pre> +</div> + +<p>{{EmbedLiveSample('Skipping_example', '100%', 200)}}</p> + +<p>Este comportamento é bastante útil. Ele significa qeu você pode usar o novo CSS como uma melhoria, sabendo que não ocorrerá um erro se ele não for completamente compreendido - o browser ou vai entender esta característica ou não. Em conjunto com a maneira que a cascata funciona, e o fato que browsers usarão o último CSS que eles encontrarem numa folha de estilos quando você possui duas regras com a mesma especificidade, Você pode oferecer alternativas para browsers que não processa CSS mais novos.</p> + +<p>Isto funciona particularmente bem quando você usa um valor que é relativamente recente e que não é processado em todo lugar. Por exemplo, alguns browsers antigos não processam <code>calc()</code> como um valor. Eu posso dar um recuo com uma largura em pixels para um box, e então seguir e dar uma largura com o valor de <code>100% - 50px</code> com <code>calc()</code>. Browsers antigos irão utilizar a versão em pixels, ignorando a linha que trata de <code>calc()</code>, já que eles não a compreendem. Browsers mais novos irão interpretar inicialmente a linha que utiliza pixels, para em seguida a sobrepor com a linha utilizando <code>calc()</code> conforme ela aparece na cascata.</p> + +<pre class="brush: css notranslate">.box { + width: 500px; + width: calc(100% - 50px); +}</pre> + +<p>Iremos visualizar várias outras maneiras de auxiliar diferentes browsers em lições futuras.</p> + +<h2 id="E_por_último">E por último</h2> + +<p>Você está quase encerrando este módulo; só temos mais uma tarefa para fazer. No próximo artigo, você utilizará seu novo conhecimento para reestilizar um exemplo, testando seus aprendizados de CSS no processo.</p> + +<p>{{PreviousMenuNext("Learn/CSS/First_steps/How_CSS_is_structured", "Learn/CSS/First_steps/Using_your_new_knowledge", "Learn/CSS/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/First_steps/What_is_CSS">O que é CSS?</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Getting_started">Começando com CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_is_structured">Como o CSS é estruturado</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_works">Como o CSS funciona</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">Utilizando seu novo conhecimento</a></li> +</ol> diff --git a/files/pt-br/learn/css/first_steps/index.html b/files/pt-br/learn/css/first_steps/index.html new file mode 100644 index 0000000000..a15ff4c7b3 --- /dev/null +++ b/files/pt-br/learn/css/first_steps/index.html @@ -0,0 +1,56 @@ +--- +title: Primeiros passos com CSS +slug: Learn/CSS/First_steps +tags: + - Beginner + - CSS + - Iniciante + - Landing + - Learn + - Module + - Primeiros passos + - aprenda + - first steps +translation_of: Learn/CSS/First_steps +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">CSS ( Planilhas de estilo em cascata) é usada para estilizar e arranjar páginas web — por exemplo, para alterar a fonte, cor, tamanho e espaçamento do seu conteúdo, separá-lo em multiplas colunas, ou então adicionar animações e outras implementações decorativas. Esse módulo provê um começo sutil em seu caminho pelo domínio do CSS com o básico de como ele funciona, como é a aprência da sintaxe e como você pode começar a utilizá-lo para estilizar seu HTML.</p> + +<h2 id="Pré-requisitos">Pré-requisitos</h2> + +<p>Antes de iniciar este módulo, você deve ter:</p> + +<ol> + <li>Familiaridade básica com o uso de computadores e utilização da internet passivamente (Ex: vendo e consumindo o conteúdo.)</li> + <li>Um ambiente de trabalho básico configurado conforme detalhado em <a href="https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/Installing_basic_software/pt-BR/docs/">Instalando Software Básico</a> e um entendimento de como criar e gerenciar arquivos, conforme detalhado em <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Getting_started_with_the_web/Dealing_with_files">Lidando com Arquivos</a>.</li> + <li>Familiaridade básica com HTML, como discutido no módulo <a href="https://developer.mozilla.org/pt-BR/docs/Learn/HTML/Introduction_to_HTML">Introdução ao HTML</a>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Se você está trabalhando em um computador/tablet/ou outro dispostivo onde você não tem habilidade para criar seus próprios arquivos, você poderá tentar (a maioria) os exemplos de códigos em um programa online de codificação como <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guias">Guias</h2> + +<p>Este módulo contém os seguintes artigos, que o guiarão através de toda a teoria básica do CSS e fornecerão oportunidades para você testar algumas habilidades.</p> + +<dl> + <dt><a href="/en-US/docs/Learn/CSS/First_steps/What_is_CSS">O que é CSS?</a></dt> + <dd><strong>{{Glossary("CSS")}}</strong> (Cascading Style Sheets) permite que você crie páginas web com ótima aparência. Mas como isso funciona por debaixo dos panos? Este artigo explica o que é CSS, com um exemplo simples de sintaxe, e também cobre alguns termos importantes sobre a linguagem.</dd> + <dt><a href="/en-US/docs/Learn/CSS/First_steps/Getting_started">Iniciando com CSS</a></dt> + <dd>Neste artigo, pegaremos um documento HTML simples e aplicaremos CSS, aprendendo algumas coisas práticas sobre a linguagem ao longo do caminho.</dd> + <dt><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_is_structured">Como CSS é estruturado</a></dt> + <dd>Agora que você tem uma idéia sobre o que é CSS e o básico sobre como usá-lo, é hora de analisar um pouco mais a fundo a estrutura da própria linguagem. Já conhecemos muitos dos conceitos discutidos aqui; você pode retornar a este para recapitular se achar confusos os conceitos posteriores.</dd> + <dt><a href="/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">Como CSS funciona</a></dt> + <dd>Aprendemos o básico do CSS, para que serve e como escrever folhas de estilo simples(Cascading Style Sheets - CSS). Neste exercício, veremos como um navegador utiliza CSS e HTML, e os transforma em uma página da web.</dd> + <dt><a href="/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">Usando seu novo conhecimento</a></dt> + <dd>Com o que aprendeu nas poucas lições anteriores, você já deve estar achando que pode formatar simples documentos de textos usando CSS, para adicionar seu próprio estilo neles. Este artigo te dará a chance de fazê-lo.</dd> +</dl> + +<h2 id="Veja_também">Veja também</h2> + +<dl> + <dt><a href="https://teach.mozilla.org/activities/intermediate-web-lit/">Conhecimento Intermerdiário da Web 1: Introdução ao CSS</a></dt> + <dd>Um excelente curso básico da Mozilla que explora e testa muitas das habilidades mencionadas no módulo Introdução ao CSS. Aprenda sobre o estilo de elementos HTML em uma página web, seletores de CSS, atributos e valores.</dd> +</dl> diff --git a/files/pt-br/learn/css/first_steps/iniciando/index.html b/files/pt-br/learn/css/first_steps/iniciando/index.html new file mode 100644 index 0000000000..a9a5218e98 --- /dev/null +++ b/files/pt-br/learn/css/first_steps/iniciando/index.html @@ -0,0 +1,265 @@ +--- +title: Iniciando com CSS +slug: Learn/CSS/First_steps/Iniciando +tags: + - Aprender + - CSS + - Classes + - Elementos + - Estado + - Iniciante + - Seletores + - Sintaxe +translation_of: Learn/CSS/First_steps/Getting_started +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/First_steps/What_is_CSS", "Learn/CSS/First_steps/How_CSS_is_structured", "Learn/CSS/First_steps")}}</div> + +<p class="summary">Neste artigo iremos pegar um simples documento HTML e aplicar o CSS nele, aprendendo algumas coisas práticas sobre a linguagem no decorrer do processo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row"><strong>pré-requisito</strong>s:</th> + <td> + <p>Conhecimento básico sobre computador, <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Installing_basic_software">softwares básicos instalados</a>, conhecimento básico de <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Dealing_with_files">como trabalhar com arquivos</a>, e conhecimento básico sobre HTML (estude <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML">Introdução ao HTML</a>.)</p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender os fundamentos que vinculam um documento CSS a um arquivo HTML, e ser capaz de estilizar um texto simples com CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="Iniciando_com_algum_HTML">Iniciando com algum HTML</h2> + +<p>Nosso ponto de partida e um documento HTML. Você pode copiar o código abaixo se desejar trabalhar no seu próprio computador. Salve-o como <code>index.html</code> em uma pasta, no seu computador.</p> + +<pre class="brush: html notranslate"><!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>Getting started with CSS</title> +</head> + +<body> + + <h1>I am a level one heading</h1> + + <p>This is a paragraph of text. In the text is a <span>span element</span> +and also a <a href="http://example.com">link</a>.</p> + + <p>This is the second paragraph. It contains an <em>emphasized</em> element.</p> + + <ul> + <li>Item one</li> + <li>Item two</li> + <li>Item <em>three</em></li> + </ul> + +</body> + +</html> +</pre> + +<div class="blockIndicator note"> +<p><strong>Observação</strong>: Se você está lendo isso em um dispositivo móvel ou em um ambiente onde não possa criar arquivos, não se preocupe — editores de código ao vivo estão disponíveis abaixo para permitir que você escreva o código de exemplo aqui, nesta página.</p> +</div> + +<h2 id="Adicionando_CSS_para_o_nosso_documento">Adicionando CSS para o nosso documento</h2> + +<p>A primeira coisa que precisamos fazer é falar para o HTML que temos algumas regras CSS que desejamos usar. Há três formas diferentes de aplicar CSS a um documento HTML que você normalmente vai encontrar, contudo, por enquanto, iremos olhar para o mais habitual e útil – vincular o CSS a partir do cabeçalho do seu documento.</p> + +<p>Crie um arquivo na mesma pasta em que se encontra o seu documento HTML e salve-o como <code>style.css</code>. A extensão <code>.css</code> nos informa que se trata de um arquivo CSS.</p> + +<p>Para ligar o <code>style.css</code> ao <code>index.html</code> adicione a seguinte linha em algum lugar dentro do {{htmlelement("head")}} do documento HTML:</p> + +<pre class="brush: html notranslate"><link rel="stylesheet" href="styles.css"></pre> + +<p>Este {{htmlelement("link")}} elemento diz ao navegador que temos uma folha de estilo, usando o atributo <code>rel</code>, e a localização desse arquivo como o valor do atributo <code>href</code>. Você pode testar se esse CSS funciona adicionando regras ao <code>styles.css</code>. Usando o seu editor de código, adicione as linhas seguintes ao seu arquivo CSS:</p> + +<pre class="brush: css notranslate">h1 { + color: red; +}</pre> + +<p>Salve os seus arquivos HTML e CSS e atualize a página no seu navegador. O nível de cabeçalho um, no topo do documento, deve estar agora em vermelho. Se tudo estiver correto, parabéns! - Você teve sucesso ao aplicar CSS a um documento HTML. Se nada aconteceu, observe cuidadosamente se você digitou tudo certo.</p> + +<p>Você pode continuar trabalhando no <code>styles.css</code> localmente, ou pode usar nosso editor interativo abaixo pra continuar com este tutorial. O editor interativo age como se o CSS no primeiro painel estivesse vinculado ao documento HTML, assim como fizemos com o documento acima.</p> + +<h2 id="Estilizando_elementos_HTML">Estilizando elementos HTML</h2> + +<p>Fazendo o nosso cabeçalho ficar vermelho, demonstramos que podemos pegar e estilizar um elemento HTML. Fazemos isso especificando um seletor de elemento — Isto é, um seletor que combina diretamente com o nome do elemento HTML. Para especificar todos os parágrafos no documento, você usaria o seletor <code>p</code>. Para tornar todos os parágragos verdes, você usaria:</p> + +<pre class="brush: css notranslate">p { + color: green; +}</pre> + +<p>Você pode especificar múltiplos seletores, separando-os com virgula. Se eu quero que todos os parágrafos e todos os itens da lista se tornem verdes, então minha regra se parecerá com isto:</p> + +<pre class="brush: css notranslate">p, li { + color: green; +}</pre> + +<p>Experimente isso no editor interativo abaixo (edit the code boxes), ou no seu arquivo CSS local.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/getting-started/started1.html", '100%', 900)}} </p> + +<h2 id="Alterando_o_comportamento_padrão_dos_elementos">Alterando o comportamento padrão dos elementos</h2> + +<p>Quando olhamos para um documento HTML bem marcado, até algo tão simples como o nosso exemplo, podemos ver como o navegador está tornando o HTML legível adicionando algum estilo padrão. Títulos são grandes e em negritos, nossa lista possui marcadores. Isso acontece porque navegadores tem uma folha de estilo interna contendo estilo padrão, a qual eles aplicam para toda a página por padrão; sem eles, todo o texto seria executado em conjunto e teríamos que estilizar tudo do princípio. Todos os modernos navegadores mostram conteúdo HTML por padrão, da mesma maneira.</p> + +<p>Contudo, você frequentemente irá desejar algo diferente do que foi escolhido pelo navegador. Isso pode ser feito simplesmente escolhendo o elemento HTML que você quer mudar, e usando uma regra CSS para alterar a forma como ele se parece. Um bom exemplo é o nosso <code><ul></code>, uma lista não ordenada. Ele tem uma lista marcada, e, se decido não escolher essa marcação, posso removê-los fazendo assim:</p> + +<pre class="brush: css notranslate">li { + list-style-type: none; +}</pre> + +<p>Experimente adicionar isto ao seu CSS agora.</p> + +<p>A propriedade <code>list-style-type</code> é uma boa propriedade para se ver no MDN para ver quais valores são suportados. Dê uma olhada na página para <code><a href="/en-US/docs/Web/CSS/list-style-type">list-style-type</a></code> e encontrará um exemplo interativo no topo da página para experimentar alguns valores diferentes nele, todos os valores permitidos são detalhados mais abaixo na página.</p> + +<p>Olhando para essa página você descobrirá que, além de remover a marcação da lista, que você também pode alterá-los — Teste mudá-los para marcação quadrada, usando valores de <code>square</code>.</p> + +<h2 id="Incluindo_uma_classe">Incluindo uma classe</h2> + +<p>Até agora, temos estilizado elementos baseado em seus nomes HTML. isto funciona enquanto você desejar que todos os elementos desse tipo, no seu documento, se pareçam o mesmo. Na maioria das vezes, isso não é o caso, e, então, você precisará encontrar uma maneira de selecionar um subconjunto de elementos sem alterar os outros. A maneira mais comum de fazer isso é adicionar uma classe ao seu elemento HTML e especificar essa classe.</p> + +<p>No seu documento HTML, adicione um <a href="/en-US/docs/Web/HTML/Global_attributes/class">atributo de classe</a> ao segundo item da lista. Sua lista se parecerá, agora, assim:</p> + +<pre class="brush: html notranslate"><ul> + <li>Item one</li> + <li <strong>class="special"</strong>>Item two</li> + <li>Item <em>three</em></li> +</ul></pre> + +<p>No seu CSS, você pode especificar a classe <code>special</code> criando um seletor que inicia com um caractere de ponto final. Adicione o seguinte código ao seu arquivo CSS:</p> + +<pre class="brush: css notranslate">.special { + color: orange; + font-weight: bold; +}</pre> + +<p>Salve e recarregue a página no navegador, para visualizar o resultado.</p> + +<p>Você pode aplicar a classe <code>special</code> para qualquer elemento na sua página que desejar ter a mesma aparência o item dessa lista. Por exemplo, pode-se querer que o <code><span></code>, no parágrafo, também se torne laranja e em negrito. Experimente adicionar uma <code>class</code> de <code>special</code> a ele, em seguida, recarregue a sua página e veja o que acontece.</p> + +<p>Algumas vezes, verá regras com um seletor que lista o seletor do elemento HTML junto com uma classe:</p> + +<pre class="brush: css notranslate">li.special { + color: orange; + font-weight: bold; +}</pre> + +<p>Essa sintaxe significa "pegue qualquer elemento<code>li</code> que tenha uma classe <code>special</code>". Se você fizesse isso, não seria mais possível aplicar a classe a um <code><span></code> ou outro elemento, simplesmente adicionando a classe a ele; você teria que adicionar esse elemento à lista de seletores, assim:</p> + +<pre class="brush: css notranslate">li.special, +span.special { + color: orange; + font-weight: bold; +}</pre> + +<p>Como pode imaginar, algumas classes podem ser aplicadas a muitos elementos e você não quer ter que editar seu CSS a cada vez que algo novo precisar assumir esse estilo. Portanto, as vezes é melhor ignorar o lemento e simplesmente se referir à classe, a menos que você queira criar algumas regras especiais para um elemento em particular, e, talvez, queira ter certeza que eles não serão aplicados aos outros.</p> + +<h2 id="Estilizando_coisas_baseadas_em_sua_localização_no_documento">Estilizando coisas baseadas em sua localização no documento</h2> + +<p>Há momentos quando você desejará que algo se pareça diferente, baseado onde ele está no documento. Existem vários seletores que podem lhe ajudar aqui, mas, por enquanto, iremos olhar apenas alguns. No nosso documento estão dois elementos <code><em></code> — um dentro de um parágrafo e o outro dentro do item de lista. Para selecionar apenas um <code><em></code> aninhado dentro de um elemento <code><li></code> posso usar um seletor chamado <strong>combinador descendente</strong>, a qual simplesmente, assume a forma de um espaço entre dois outros seletores.</p> + +<p>Adicione a seguinte regra a sua folha de estilo.</p> + +<pre class="brush: css notranslate">li em { + color: rebeccapurple; +}</pre> + +<p>Este seletor selecionará qualquer elemento <code><em></code> que está dentro (<span class="tlid-translation translation" lang="pt"><span title="">um descendente de</span></span>) um <code><li></code>. Deste modo, no seu documento de exemplo, você deve achar que o <code><em></code> no terceiro item da lista agora está roxo, mas o que está dentro do parágrafo permanece inalterado.</p> + +<p>Outra coisa que você pode gostar de experimentar é estilizar um parágrafo quando ele vem diretamente após um título no mesmo nível de hierarquia no HTML. <span class="tlid-translation translation" lang="pt"><span title="">Para isso, coloque um</span></span> <code>+</code> (<span class="tlid-translation translation" lang="pt"><span title="">um <strong>combinador irmão adjacente</strong></span></span>) entre os seletores.</p> + +<p>Experimente adicionar esta regra à sua folha de estilo também:</p> + +<pre class="brush: css notranslate">h1 + p { + font-size: 200%; +}</pre> + +<p>O exemplo ativo abaixo inclui as duas regras acima. Verifique adicionando uma regra para tornar um span vermelho, se ele está dentro de um parágrafo. Você saberá se fez certo quando o span no primeiro parágrafo ficar vermelho, mas o do primeiro item da lista não mudar de cor.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/getting-started/started2.html", '100%', 1100)}}</p> + +<div class="blockIndicator note"> +<p><strong>Observação</strong>: Como pode ver, CSS nos dá várias maneiras de especificar elementos, e temos somente arranhado a superfície até agora! Analisaremos adequadamente todos esses seletores e muitos outros, nos nossos artigos <a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Seletores</a> posteriormente neste curso.</p> +</div> + +<h2 id="Estilizando_coisas_baseadas_no_estado">Estilizando coisas baseadas no estado</h2> + +<p>O tipo final de estilo, que vamos dar uma olhada neste tutorial, é a habilidade de estilizar coisas com base em seu estado. Um exemplo direto disso é quando estilizamos links. Quando aplicamos um estilo a um link, precisamos especificar o elemento <code><a href="/en-US/docs/Web/HTML/Element/a"><a></a></code> (âncora). Isto possui diferentes estados, dependendo se ele foi visitado, se não foi visitado, se o mouse está passando por ele, se foi teclado ou no processo de ser clicado (ativado). Você pode usar CSS para especificar estes diferentes estados — o CSS abaixo estiliza links não visitados com a cor rosa e links visitados com a cor verde.</p> + +<pre class="brush: css notranslate">a:link { + color: pink; +} + +a:visited { + color: green; +}</pre> + +<p>Você pode alterar a aparência do link quando o usuário passa o mouse sobre ele. Por exemplo, removendo o sublinhado, o que é realizado na próxima regra:</p> + +<pre class="brush: css notranslate">a:hover { + text-decoration: none; +}</pre> + +<p>No exemplo ativo abaixo, você pode brincar com diferentes valores para os vários estados do link. Adicionei as regras acima, e agora perceba que a cor rosa é bastante clara e difícil de ler. — porque não mudar isso para uma cor melhor? Pode deixá-los em negrito?</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/getting-started/started3.html", '100%', 900)}} </p> + +<p>Removemos o sublinhado do nosso link ao passar o mouse. Pode-se remover os sublinhados de todos os estados de um link. Vale lembrar, no entanto, que em um site real, você deseja garantir que os visitantes saibam que um link é um link. Deixar o sublinhado no lugar pode ser uma pista importante para as pessoas perceberem que é possível clicar em algum texto dentro de um parágrafo — esse é o comportamento ao qual estão acostumados. Como tudo em CSS, existe o potencial de tornar o documento menos acessível com suas alterações — procuraremos destacar possíveis armadilhas em locais apropriados.</p> + +<div class="blockIndicator note"> +<p><strong>Observação</strong>: Você verá frequentemente menção de <a href="/en-US/docs/Learn/Accessibility">acessibilidade</a> nessas lições e no MDN. Quando falamos sobre acessibilidade, estamos nos referindo aos requerimentos para a nossa página web ser compreensível e utilizável por todos.</p> + +<p>Seu visitante pode muito bem estar em um computador com um mouse defeituoso, ou um dispositivo móvel com uma tela sensível ao toque. Ou eles podem estar usando um leitor de tela, que lê o conteúdo do documento, ou podem precisar de muito texto grande, ou estar navegando no site apenas usando o teclado.</p> + +<p>Um documento HTML simples é geralmente acessível a todos — Ao começar a estilizar esse documento, é importante que você não o rone menos acessível.</p> +</div> + +<h2 id="Combinando_seletores_e_combinadores">Combinando seletores e combinadores</h2> + +<p>Vale ressaltar que você pode combinar vários seletores e combinadores. Até agora, vimos assim:</p> + +<pre class="brush: css notranslate">/* selects any <span> that is inside a <p>, which is inside an <article> */ +article p span { ... } + +/* selects any <p> that comes directly after a <ul>, which comes directly after an <h1> */ +h1 + ul + p { ... }</pre> + +<p>Você pode combinar multiplos tipos juntos, também. Experimente acrescentar o seguinte código:</p> + +<pre class="brush: css notranslate">body h1 + p .special { + color: yellow; + background-color: black; + padding: 5px; +}</pre> + +<p>Isso estilizará qualquer elemento com a classe <code>special</code>, a qual está dentro de um <code><p></code>, que vem logo após um <code><h1></code>, que, por sua vez, está dentro de um <code><body></code>. Ufa!</p> + +<p>No HTML original que forncemos, o único elemento estilizado é <code><span class="special"></code>.</p> + +<p>Não se preocupe se isto parece complicado no momento — em breve, você começará a entender como escreve mais CSS.</p> + +<h2 id="Empacotando">Empacotando</h2> + +<p>Neste tutorial, demos uma olhada na quantidade de maneiras as quais pode-se estilizar um documento usando CSS. Estaremos desenvolvendo esse conhecimento ao longo da caminhada através das Lições. No entanto, agora, você já sabe o suficiente para estilizar o texto, aplicar CSS com base em diferentes maneiras de especificar elementos no documento e procurar propriedades e valores na documentação do MDN.</p> + +<p>Na próxima lição, veremos como o CSS é estruturado.</p> + +<p>{{PreviousMenuNext("Learn/CSS/First_steps/What_is_CSS", "Learn/CSS/First_steps/How_CSS_is_structured", "Learn/CSS/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/First_steps/What_is_CSS">O que é CSS?</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Getting_started">Começando com CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_is_structured">Como o CSS é estruturado</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_works">Como o CSS funciona</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">Usando o seu novo conhecimento</a></li> +</ol> diff --git a/files/pt-br/learn/css/first_steps/o_que_e_css/index.html b/files/pt-br/learn/css/first_steps/o_que_e_css/index.html new file mode 100644 index 0000000000..41980dfee6 --- /dev/null +++ b/files/pt-br/learn/css/first_steps/o_que_e_css/index.html @@ -0,0 +1,127 @@ +--- +title: O que é CSS? +slug: Learn/CSS/First_steps/O_que_e_CSS +tags: + - Aprender + - CSS + - Iniciante + - Introdução ao CSS + - Módulos + - Sintaxe + - especificação +translation_of: Learn/CSS/First_steps/What_is_CSS +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/CSS/First_steps/Getting_started", "Learn/CSS/First_steps")}}</div> + +<p class="summary"><strong>{{Glossary("CSS")}}</strong> (Folhas de Estilo em Cascata) permite a você criar páginas web agradáveis, mas como isso funciona por baixo dos panos? Este artigo explica o que é CSS, com um exemplo de sintaxe simples, e, também, trata alguns conceitos-chaves sobre a linguagem.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimento básico sobre computador, <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Installing_basic_software">softwares básicos instalados</a>, conhecimento básico de <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Dealing_with_files">como trabalhar com arquivos</a>, e conhecimento básico sobre HTML (estude <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML">Introdução ao HTML</a>.)</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender o que é CSS.</td> + </tr> + </tbody> +</table> + +<p>No módulo <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introdução ao HTML</a> vimos o que é HTML, e como ele é usado para fazer marcação de documentos. Estes documentos serão legíveis em um navegador web. Títulos serão mais largos do que textos comuns, parágrafos quebram em uma nova linha e tendo espaços entre eles. Links são coloridos e sublinhados para distingui-los do resto do texto. O que você está vendo é o estilo padrão do navegador - vários estilos básicos que o navegador aplica ao HTML, para garantir que ele será legível mesmo se não for explicitamente estilizado pelo autor da página web.</p> + +<p><img alt="The default styles used by a browser" src="https://mdn.mozillademos.org/files/16493/html-example.png" style="border: 1px solid #cccccc; height: 594px; width: 1385px;"></p> + +<p>No entanto, a web seria um lugar chato se todos os web sites tivessem estilos iguais ao mostrado na imagem acima. Usando CSS você pode controlar exatamente a aparência dos elementos HTML no navegador, apresentando a sua marcação com o design que desejar.</p> + +<h2 id="Para_que_serve_o_CSS">Para que serve o CSS?</h2> + +<p>Como falamos antes, CSS é uma linguagem para especificar como documentos são apresentados aos usuários — como eles são estilizados, dispostos etc.</p> + +<p>Um <strong>documento</strong> é normalmente um arquivo texto estruturado usando uma linguagem de marcação — {{Glossary("HTML")}} é a linguagem de marcação mais comum, mas você também pode encontrar outras, como {{Glossary("SVG")}} ou {{Glossary("XML")}}.</p> + +<p><strong>Apresentar</strong> um documento para um usuário significa convertê-lo para um formato utilizável pelo seu público. {{Glossary("browser","Browsers")}}, como {{Glossary("Mozilla Firefox","Firefox")}}, {{Glossary("Google Chrome","Chrome")}}, ou {{Glossary("Microsoft Edge","Edge")}} , são projetados para apresentar documentos visualmente, por exemplo, um uma tela de computador, projetor ou impressora.</p> + +<div class="blockIndicator note"> +<p><strong>Observação</strong>: Um navegador web é as vezes chamado de {{Glossary("User agent","user agent")}}, o que, basicamente, significa um programa de computador que representa uma pessoa por trás do sistema. Navegadores web são o principal tipo de agente do usuário que nos referimos quando falamos sobre CSS, contudo, ele não é o único. Há outros agentes de usuário disponíveis — tais como aqueles que convertem documentos HTML e CSS para PDF a serem impressos.</p> +</div> + +<p>O CSS pode ser usado para estilizar um documento muito básico de texto — por exemplo, alterando a <a href="/en-US/docs/Web/CSS/color_value">cor</a> e <a href="/en-US/docs/Web/CSS/font-size">tamanho</a> dos títulos e links. Pode ser usado para criar layout — por exemplo, <a href="/en-US/docs/Web/CSS/Layout_cookbook/Column_layouts">transformando uma simples coluna de texto em um layout</a> com uma área de conteúdo principal e um sidebar (barra lateral) para as informações relacionadas. Pode até ser usado para efeitos tais como <a href="/en-US/docs/Web/CSS/CSS_Animations">animação</a>. Dê uma olhada nos links deste parágrafo, para ver exemplos específicos.</p> + +<h2 id="Sintaxe_CSS">Sintaxe CSS</h2> + +<p>CSS é uma linguagem baseada em regras. — Você define regras especificando grupos de estilo que devem ser aplicados para elementos particulares ou grupos de elementos na sua página web. Por exemplo, "Quero que o título principal, na minha página, seja mostrado como um texto grande e de cor vermelha.".</p> + +<p>O código seguinte mostra uma regra CSS muito simples, que chegaria perto do estilo descrito acima:</p> + +<pre class="brush: css">h1 { + color: red; + font-size: 5em; +}</pre> + +<p>A regra é aberta com um {{Glossary("CSS Selector", "selector")}} . Isso <em>seleciona</em> o elemento HTML que vamos estilizar. Neste caso, estamos estilizando títulos de nível um ({{htmlelement("h1")}}).</p> + +<p>Temos, então, um conjunto de chaves <code>{ }</code>. Dentro deles, haverá uma ou mais <strong>declarações</strong>, que tomam a forma de pares <strong>propriedade</strong> e <strong>valor</strong>. Cada par especifica uma propriedade do(s) elemento(s) que estamos selecionando e, em seguida, então um valor que gostaríamos de atribuir à propriedade</p> + +<p>Antes dos dois pontos, temos a propriedade, e, depois, o valor. CSS {{Glossary("property/CSS","properties")}} possui diferentes valores permitidos, dependendo de qual propriedade está sendo especificado. Em nosso exemplo, temos a propriedade <code>color</code>, que pode tomar vários <a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units#Color">valores para cor</a>. Também temos a propriedade <code>font-size</code>. Essa propriedade pode ter vários <a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units#Numbers_lengths_and_percentages">unidades de tamanho</a> como um valor.</p> + +<p>Uma folha de estilo CSS conterá muitas regras tais como essa, escrita uma após a outra.</p> + +<pre class="brush: css">h1 { + color: red; + font-size: 5em; +} + +p { + color: black; +}</pre> + +<p>Você constatará que rapidamente aprende alguns valores, enquanto outros precisará pesquisar. As páginas de propriedades individuais no MDN dá a você uma maneira rápida de procurar propriedades e seus respectivos valores, quando você esquecer, ou desejar saber quais valores pode usar.</p> + +<div class="blockIndicator note"> +<p><strong>Observação</strong>: Você pode achar links para todas as páginas de propriedades CSS (junto com outros recursos CSS) listados no MDN <a href="/en-US/docs/Web/CSS/Reference">referência CSS</a>. Alternativamente, você deve se acostumar a pesquisar por "mdn <em>css-feature-name</em>" no seu motor de busca favorito sempre que precisar procurar mais informações sobre uma característica CSS. Por exemplo, experimente pesquisar por "mdn color" e "mdn<em> </em>font-size"!</p> +</div> + +<h2 id="Módulos_CSS">Módulos CSS</h2> + +<p>Como existem tantas coisas que você pode estilizar com CSS, a linguagem é dividida em módulos. Verá referência a esses módulos a medida que explora o MDN e muita das páginas da documentação são organizadas em torno de um módulo em particular. Por exemplo, poderia dar uma olhada na referência MDN para os módulos <a href="/en-US/docs/Web/CSS/CSS_Backgrounds_and_Borders">Backgrounds and Borders</a> para descobrir qual é o seu objetivo, e quais diferentes propriedades e outras características ele contém. Você também encontrará links para a especificação CSS que define a tecnologia (veja abaixo).</p> + +<p>Nesse ponto você não precisa se preocupar muito sobre como o CSS é estruturado. No entanto, isso pode tornar fácil achar informação se, por exemplo, você estiver ciente de que uma determinada propriedade provavelmente será encontrada entre outras coisas semelhantes e estiver, portanto, provavelmente na mesma especificação. </p> + +<p>Para um exemplo específico, vamos voltar ao módulo Backgrounds e Borders — você pode achar que isso tem um senso lógico para as propriedades <code><a href="/en-US/docs/Web/CSS/background-color">background-color</a></code> e <code><a href="/en-US/docs/Web/CSS/border-color">border-color</a></code> serem definidas neste módulo. E, você está certo!</p> + +<h3 id="Especificações_CSS">Especificações CSS</h3> + +<p>Todas as tecnologias de padrões web (HTML, CSS, JavaScript, etc.) são definidos em documentos gigantes chamados especificações (ou simplesmente "specs"), que são publicados por organizações de padrões (tais como {{glossary("W3C")}}, {{glossary("WHATWG")}}, {{glossary("ECMA")}}, ou {{glossary("Khronos")}}) e definem precisamente como essas tecnologias devem se comportar.</p> + +<p>Com CSS não é diferente — ele é desenvolvido por um grupo dentro do W3C chamado <a href="https://www.w3.org/Style/CSS/">CSS Working Group</a>. Esse grupo é formado por representantes de fornecedores de navegadores web e outras companhias que tem interesse em CSS. Também existe outras pessoas, conhecidas como peritos convidados<em> (invited experts</em>), que agem como vozes independentes; eles não são associados como um membro de alguma organização.</p> + +<p>Novas características CSS são desenvolvidas, ou especificadas, pelo CSS Working Group. As vezes, porque um navegador em particular está interessado em alguma capacidade, outras vezes, porque designers web e desenvolvedores estão perguntando por uma característica, e, algumas vezes, porque o Working Group em si tem identificado uma necessidade. O CSS está em constante desenvolvimento, com novas peculiaridades ficando disponíveis. Contudo, uma ideia chave sobre CSS é que todos trabalham pesado para nunca alterar as coisas de uma maneira que não quebrem os sites antigos. Um site construído no ano 2000, usando um CSS limitado da época, deverá ainda ser utilizável em um navegador moderno!</p> + +<p>Como iniciante no CSS, é provável que você ache as especificações CSS impressionantes — eles são direcionados a engenheiros para implementar suporte aos recursos nos agentes de usuário (navegadores), não para desenvolvedores lerem com o intuito de entender CSS. Muitos desenvolvedores experientes preferem consultar a documentação do MDN ou outros tutoriais. No entanto, vale a pena saber que eles existem, entender a relação entre o CSS que você usa, suporte ao navegador (veja abaixo), e os specs (especificações).</p> + +<h2 id="Suporte_do_navegador">Suporte do navegador</h2> + +<p>Uma vez que o CSS tenha sido especificado, então se torna útil para nós, em termos de desenvolvimento de páginas web, apenas se um ou mais navegadores implementá-los. Isso significa que o código foi escrito para transformar as instruções do nosso arquivo CSS em algo que possa ser mostrado na tela. Vamos olhar um pouco mais esse processo nas lições <a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_works">Como o CSS funciona</a>. É inusitado implementarem uma característica ao mesmo tempo, e, geralmente, existe uma lacuna na qual se pode usar parte do CSS em alguns navegadores e em outros não. Por esse motivo, ser capaz de verificar o estado da implemtação é útil. Para cada página de propriedade no MDN, pode-se ver o estado dela, que se esta interessado. Assim, você saberá se pode usá-la em uma página.</p> + +<p>A seguir, é apresentado o gráfico de dados compat para propriedade CSS <code><a href="/en-US/docs/Web/CSS/font-family">font-family</a></code>.</p> + +<p>{{Compat("css.properties.font-family")}}</p> + +<h2 id="A_seguir">A seguir</h2> + +<p>Agora que você tem algum entendimento do que o CSS é, vamos ao <a href="/en-US/docs/Learn/CSS/First_steps/Getting_started">Iniciando com CSS</a>, onde pode começar a escrever alguma coisa, você mesmo.</p> + +<p>{{NextMenu("Learn/CSS/First_steps/Getting_started", "Learn/CSS/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ol> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps/What_is_CSS">O que é CSS?</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps/Getting_started">Começando com CSS</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps/How_CSS_is_structured">Como o CSS é estruturado</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps/How_CSS_works">Como o CSS funciona</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">Usando o seu novo conhecimento</a></li> +</ol> diff --git a/files/pt-br/learn/css/first_steps/using_your_new_knowledge/index.html b/files/pt-br/learn/css/first_steps/using_your_new_knowledge/index.html new file mode 100644 index 0000000000..848524cba3 --- /dev/null +++ b/files/pt-br/learn/css/first_steps/using_your_new_knowledge/index.html @@ -0,0 +1,96 @@ +--- +title: Using your new knowledge +slug: Learn/CSS/First_steps/Using_your_new_knowledge +translation_of: Learn/CSS/First_steps/Using_your_new_knowledge +--- +<p>{{LearnSidebar}}{{PreviousMenu("Learn/CSS/First_steps/How_CSS_works", "Learn/CSS/First_steps")}}</p> + +<p class="summary">Com o que você aprendeu nas últimas lições, você deve perceber que pode formatar simples documentos de texto utilizando CSS, implementado seu próprio estilo neles. Esta avaliação lhe dá a oportunidade de fazer exatamente isto.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Antes de tentar esta avaliação você deve ter passado pelo resto do módulo básico de CSS, além de também possuir uma compreensão básica de HTML (estude <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introdução ao HTML</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Trabalhar um pouco de CSS e testar seus novos conhecimentos.</td> + </tr> + </tbody> +</table> + +<h2 id="Ponto_de_partida">Ponto de partida</h2> + +<p>Você pode trabalhar com editor ao vivo abaixo, ou pode fazer o <a href="https://github.com/mdn/css-examples/blob/master/learn/getting-started/biog-download.html/">download do ponto de partida</a> para trabalhar em seu próprio editor de texto. Esta é uma única página de HTML, além do ponto de partida no head do documento. Se preferir, você pode transferir este CSS para um arquivo separado quando criar o exemplo no seu computador. Ou ainda, você pode utilizar uma ferramenta online como por exemplo, o <a href="https://codepen.io/" rel="noopener">CodePen</a>, <a href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, ou <a href="https://glitch.com/" rel="noopener">Glitch</a> para realizar estas tarefas..</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Se ficar emperrado, nos procure por ajuda — veja a seção <a href="/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge#Assessment_or_further_help">Assessment or further help</a> no final da página.</p> +</div> + +<h2 id="Trabalhando_com_CSS">Trabalhando com CSS</h2> + +<p>O seguite exemplo mostra uma biografia, o qual foi estilizado com CSS. As propriedades CSS que eu usei foram as mencionadas abaixo — cada uma está lincada a sua página de propriedades em MDN, a qual dará mais exemplos do uso dela.</p> + +<ul> + <li>{{cssxref("font-family")}}</li> + <li>{{cssxref("color")}}</li> + <li>{{cssxref("border-bottom")}}</li> + <li>{{cssxref("font-weight")}}</li> + <li>{{cssxref("font-size")}}</li> + <li>{{cssxref("text-decoration")}}</li> +</ul> + +<p>Eu usei uma mistura de seletores, estilizando elementos como h1 e h2, mas também criando uma classe para o título da profissão e estilizando ela.</p> + +<p>Use CSS para mudar como esta biografia aparece, alterando valores das propriedades que eu utilizei.</p> + +<ol> + <li>Faça o cabeçalho rosa, usando a chave de cor CSS <code>hotpink</code>.</li> + <li>Dê ao cabeçalho um pontilhado de tamanho 10px {{cssxref("border-bottom")}} e que utiliza a chave de cor CSS <code>purple</code>.</li> + <li>Faça o cabeçalho nível 2 em itálico.</li> + <li>Dê ao <code>ul</code> usado para informações de contato uma {{cssxref("background-color")}} <code>#eeeeee</code>, e uma {{cssxref("border")}} roxa sólida com de tamanho 5px. Implemente um {{cssxref("padding")}} para empurrar o conteúdo para longe da borda.</li> + <li>Torne os links <code>verdes</code> ao passar o mouse por cima deles.</li> +</ol> + +<p>Você deve acabar com algo parecido com esta imagem.</p> + +<p><img alt="Screenshot of how the example should look after completing the assessment." src="https://mdn.mozillademos.org/files/17035/learn-css-basics-assessment.png" style="height: 1199px; width: 1104px;"></p> + +<p>Após isto, tente pesquisar algumas propriedades não mencionadas nesta página em <a href="/en-US/docs/Web/CSS/Reference">MDN CSS referências</a> e se aventure!</p> + +<p>Lembre-se de que não há resosta errada aqui — neste momento de seu aprendizado, você pode se dar ao luxo de de se divertir um pouco.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/getting-started/biog.html", '100%', 1600)}} </p> + +<h2 id="Assessment_or_further_help">Assessment or further help</h2> + +<p>Se gostaria de ter seu trabalho avaliado, ou se ficou emperrado e gostaria de ajuda:</p> + +<ol> + <li>Coloque seu trabalho num editor de texto compartilhado online tal como o <a href="https://codepen.io/" rel="noopener">CodePen</a>, <a href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, ou <a href="https://glitch.com/" rel="noopener">Glitch</a>.</li> + <li>Escreva um post perguntando por avaliação e/ou ajuda em <a class="external external-icon" href="https://discourse.mozilla.org/c/mdn/learn" rel="noopener">MDN Discourse forum Learning category</a>. Seu post deve incluir: + <ul> + <li>Um título descritivo, tal como "Avaliação desejada para primeiros passos em CSS".</li> + <li>Detalhes do que você já tentou, e o que gostaria que ós fizéssemos, p.e. se você está emperrado e precisa de ajuda, ou se deseja uma avalição.</li> + <li>Um link para o exemplo que você deseja ser avaliadao ou precisa de ajuda, em um editor online compartilhado (como mencionado no passo 1 acima). Esta é uma boa prática a se desenvolver — é muito difícil ajudar alguém com um problema de computação se não é possível ver o código dessa pessoa.</li> + <li>Um link para a atual págia de tarefa ou avaliaçãopara que possamos ver a questão que você está com dúvida.</li> + </ul> + </li> +</ol> + +<h2 id="O_que_vem_a_seguir">O que vem a seguir?</h2> + +<p>Parabéns por terminar seu primeiro módulo. Agora você deve ter uma boa compreensão geral de CSS, e ser capaz de entender boa parte do que acontece numa folha de estilos. No próximo módulo, <a href="/en-US/docs/Learn/CSS/Building_blocks">CSS building blocks</a>, iremos dar uma olhada com mais profundidade em várias áreas chave.</p> + +<p>{{PreviousMenu("Learn/CSS/First_steps/How_CSS_works", "Learn/CSS/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ol> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps/What_is_CSS">O que é CSS?</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps/Getting_started">Começando com CSS</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps/How_CSS_is_structured">Como o CSS é estruturado</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps/How_CSS_works">Como o CSS funciona</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">Utilizando seu novo conhecimento</a></li> +</ol> diff --git a/files/pt-br/learn/css/howto/css_perguntas_frequentes/index.html b/files/pt-br/learn/css/howto/css_perguntas_frequentes/index.html new file mode 100644 index 0000000000..f3febd4637 --- /dev/null +++ b/files/pt-br/learn/css/howto/css_perguntas_frequentes/index.html @@ -0,0 +1,245 @@ +--- +title: CSS - Perguntas frequentes +slug: Learn/CSS/Howto/CSS_Perguntas_Frequentes +tags: + - CSS + - Exemplo + - FAQ + - Guía + - Perguntas + - Perguntas Frequentes + - Web +translation_of: Learn/CSS/Howto/CSS_FAQ +--- +<h2 id="Por_que_meu_CSS_que_é_válido_não_é_renderizado_corretamente">Por que meu CSS, que é válido, não é renderizado corretamente?</h2> + +<p>Navegadores usam a declaração de <code>DOCTYPE</code> para decidir se devem exibir o documento usando um modo compatível com os padrões da web ou com padrões de navegadores antigos. Usar corretamente a declaração de um <code>DOCTYPE</code> moderno no início do seu documento HTML melhorará a forma como o navegador trata os padrões utilizados no documento.</p> + +<p>Navegadores modernos possuem dois principais modos de renderização:</p> + +<ul> + <li><em>Modo de peculiaridades (Quirks Mode)</em>: Também chamado de modo retrocompatível, permite que páginas antigas sejam renderizadas como seus autores pretendiam, seguindo regras de renderização não-padronizadas geralmente encontradas em navegadores antigos. Documentos com uma declaração <code>DOCTYPE</code> incompleta, incorreta, que não tenham uma declaração <code>DOCTYPE</code> ou não tenham uma declaração comumente utilizada antes de 2001 serão renderizados deste modo.</li> + <li><em>Modo de padrões (Standards Mode)</em>: Neste modo o navegador tenta seguir os padrões W3C estritamente, ignorando peculiaridades encontradas em documentos designados a navegadores antigos. Espera-se que novas páginas HTML sejam desenvolvidas para navegadores que seguem os padrões da W3C, e como resultado disso, páginas com uma declaração de <code>DOCTYPE</code> moderna serão renderizadas deste modo.</li> +</ul> + +<p>Navegadores baseados na engine Gecko possuem um terceiro modo de renderização; <em><a href="/en-US/docs/Gecko's_"Almost_Standards"_Mode" title="Gecko's_"Almost_Standards"_Mode">Modo de "quase padrões" (Almost Standards Mode</a>)</em>, que renderiza as páginas seguindo regras do <em>Modo de padrões</em>, porém considerando algumas poucas peculiaridades encontradas em páginas para navegadores antigos.</p> + +<p>Esta é uma lista das declarações de <code>DOCTYPE</code> mais usadas e que acionarão o modo de padrões ou de "quase padrões":</p> + +<pre><!DOCTYPE html> <code>/* Este é o doctype HTML5. Levando em consideração que + navegadores modernos possuem um parser de HTML5, o + uso desta declaração é recomendada */</code> + +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" +"http://www.w3.org/TR/html4/loose.dtd"> + +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" +"http://www.w3.org/TR/html4/strict.dtd"> + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +</pre> + +<p>Sempre que possível, use a declaração de <code>DOCTYPE</code> HTML5.</p> + +<h2 id="My_CSS_is_valid.2C_but_not_correctly_rendered" name="My_CSS_is_valid.2C_but_not_correctly_rendered">Por que meu CSS, que é válido, não é renderizado?</h2> + +<p>Abaixo temos algumas das possíveis causas:</p> + +<ul> + <li>O caminho para o arquivo CSS está incorreto.</li> + <li>Para ser aplicado, uma folha de estilos CSS deve ser servido ao navegador com o tipo MIME <code>text/css. </code>Caso o servidor não sirva a folha de estilos com este tipo, as regras CSS não serão interpretadas e aplicadas aos elementos no documento.</li> +</ul> + +<h2 id="Difference_between_id_and_class" name="Difference_between_id_and_class">Qual a diferença entre <code>id</code> e <code>class</code>?</h2> + +<p>Elementos HTML podem ter um atributo <code>id</code> e/ou um atributo <code>class. </code>O atributo <code>id</code> designa um nome ao elemento ao qual este é aplicado, e para que a marcação seja válida, deverá haver no documento apenas um elemento com o nome designado (Por exemplo: Caso você designe o nome <em>janela</em> a um elemento, nenhum outro elemento poderá ter o nome <em>janela</em><font face="consolas, Liberation Mono, courier, monospace">)</font>.</p> + +<p>O atributo <code>class</code> designa um ou vários nomes de classes as quais um elemento pertence. Diferentemente do valor designado no atributo <code>id</code>, os nomes designados em <code>class</code> podem ser reutilizados em outros elementos no documento. De qualquer forma, CSS permite que você aplique estilos tanto para uma <code>id</code> particular quanto para <code>classes</code>.</p> + +<p>Algumas dicas de quando usar <code>id</code> e quando usar <code>class:</code></p> + +<ul> + <li>Utilize classes para estilizar elementos quando você pretender atribuir as mesmas regras de estilização a diversos elementos num documento. Mesmo que você tenha apenas um elemento no momento, utilize classes para sua estilização caso você pretenda reutilizar as mesmas regras em elementos criados futuramente.</li> + <li>Utilize ids quando você precisar restringir regras de estilização a um determinado bloco ou elemento. Como ids não devem sepetidas num documento, as regras de estilo designadas a uma <code>id</code> serão aplicadas apenas àquele elemento.</li> +</ul> + +<p>Geralmente é recomendável que se utilize classes sempre que possível, utilizando ids apenas quando absolutamente necessário para usos específicos (como conectar um <code>label</code> a um elemento de formulário, ou para estilizar elementos que necessicam ser semanticamente únicos). Abaixo estão descritas algumas vantagens em utilizar classes como forma principal de estilização:</p> + +<ul> + <li>Usar classes torna seu código extensível — Mesmo que você tenha apenas um elemento a ser estilizado agora, você pode querer adicionar as mesmas regras a outros elementos futuramente.</li> + <li>Classes permitem que você estilize diversos elementos. Sendo assim, classes podem ajudar a desenvolver folhas de estilo menores; mais enchutas, já que regras podem ser facilmente reutilizadas entre elementos. Isso não só ajuda na manutenção da folha de estilo, como também agiliza a renderização de páginas, principalmente em conexões lentas.</li> + <li>Seletores de classes tem menor <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Cascade_and_inheritance#Specificity">especificidade</a> do que seletores de id, o que torna as regras de estilização mais fáceis de serem sobrepostas.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Veja <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Selectors">Seletores</a> para mais informações.</p> +</div> + +<h2 id="Restoring_the_default_property_value" name="Restoring_the_default_property_value">Como eu redefino o valor padrão de uma propriedade?</h2> + +<p>Inicialmente CSS não propiciava a diretiva "default" e a única forma de redefinir o valor padrão de uma propriedade era expliciatamente redeclarando aquela propriedade. Por exemplo:</p> + +<pre class="brush: css">/* A cor padrão do cabeçalho é preta */ +h1 { color: red; } +h1 { color: black; }</pre> + +<p>Isso mudou com CSS 2; a diretiva <a href="/es/CSS/initial" title="initial">initial</a> agora é um valor válido para uma propriedade CSS. Ela redefine tal propriedade para seu valor padrão, o qual é definido nas especificações CSS para tal propriedade.</p> + +<pre class="brush: css">/* A cor padrão do cabeçalho é preta */ +h1 { color: red; } +h1 { color: initial; }</pre> + +<h2 id="Derived_styles" name="Derived_styles">Como eu derivo um estilo de outro?</h2> + +<p>CSS não exatamente permite que um estilo seja definido com os termos de outro. (Veja <a href="http://archivist.incutio.com/viewlist/css-discuss/2685">as notas de Eric Meyer sobre a posição do grupo de trabalho a respeito do assunto</a>). Entretanto, é possível atingir o mesmo efeito designando diversas classes a um elemento, e <a href="/en-US/docs/Web/CSS/Using_CSS_variables">Variáveis CSS </a>agora providenciam uma forma de definir informações sobre um estilo em um lugar e reutilizar estas informações em diversos outros lugares.</p> + +<h2 id="Assigning_multiple_classes" name="Assigning_multiple_classes">Como eu aplico diversas classes a um elemento?</h2> + +<p>Elementos HTML podem ter diversas classes designadas a si, com as classes sendo listadas no atributo <code>class</code>, tendo um espaço em branco separando cada uma.</p> + +<pre class="brush: html"><style type="text/css"> + .news { background: black; color: white; } + .today { font-weight: bold; } +</style> + +<div class="news today"> +... content of today's news ... +</div> +</pre> + +<p>Caso a mesma propriedade seja declara em mais de uma regra, o conflito é resolvido primeiro pela ordem de especificidade e depois através da ordem das declarações CSS, com o último valor definido da propriedade sendo considerado. A ordem em que o nome das classes aparece no atributo <code>class</code> é irrelevante.</p> + +<h2 id="Style_rules_that_don.27t_work" name="Style_rules_that_don.27t_work">Por que minhas regras de estilização não funcionam corretamente?</h2> + +<p>Regras de estilização, mesmo que sejam semanticamente corretas, podem não ser aplicadas em determinadas situações. Você pode utilizar o visualizador de regras CSS do <a href="/en-US/docs/DOM_Inspector" title="DOM_Inspector">Inspetor de DOM</a> para resolver problemas deste tipo, mas as ocasiões mais frequentes onde regras de estilização são ignoradas estão listadas abaixo.</p> + +<h3 id="HTML_elements_hierarchy" name="HTML_elements_hierarchy">Hierarquia dos elementos HTML</h3> + +<p>A forma como estilos CSS são aplicados a elementos HTML depende também da hierarquia dos elementos HTML. É importante lembrar que a regra aplicada a um descendente sobrepõe a regra do pai, independente de qualquer especificidade ou prioridade das regras CSS.</p> + +<pre class="brush: html"><style type="text/css"> + .news { color: black; } + .corpName { font-weight: bold; color: red; } +</style> + +<!-- O texto do item news é preto, mas o nome da corporação é vermelho e em negrito --> +<div class="news"> + (Reuters) <span class="corpName">General Electric</span> (GE.NYS) announced on Thursday... +</div> +</pre> + +<p>No caso de hierarquias HTML complexas, se uma regra parece ser ignorada, verifique se o elemento está dentro de outro elemento com um estilo diferente.</p> + +<h3 id="Explicitly_re-defined_style_rule" name="Explicitly_re-defined_style_rule">Regra de estilização explicitamente redefinida</h3> + +<p>Em folhas de estilo CSS, a ordem <strong><u>é</u></strong> importante. Se você definir uma propriedade e logo depois redefinir a mesma propriedade, a última regra definida será considerada.</p> + +<pre class="brush: html"><style> + #stockTicker { font-weight: bold; } + .stockSymbol { color: red; } + /* outras regras */ + /* outras regras */ + /* outras regras */ + .stockSymbol { font-weight: normal; } +</style> + +<!-- Boa parte do texto está em negrito, exceto "GE", que é vermelho e não está em negrito --> +<div id="stockTicker"> + NYS: <span class="stockSymbol">GE</span> +1.0 ... +</div> +</pre> + +<p>Para evitar que este tipo de problema, tente definir regras apenas uma vez para um determinado seletor e agrupe as regras para aquele seletor.</p> + +<h3 id="Use_of_a_shorthand_property" name="Use_of_a_shorthand_property">Uso de uma propriedade reduzida</h3> + +<p>Utilizar propriedades reduzidas para definir regra de estilização é interessante pois permite definir diversas propriedade de uma regra em uma sintaxe compacta e que permite otimizar o tamanho da folha de estilos. Utilizar propriedades reduzidas para definir apenas uma propriedade é permitido, mas deve ser lembrado que atributos da propriedade não definidos são redefinidos para seu valor padrão. Ou seja, isso pode acabar sobrepondo regras anteriormente definidas implicitamente..</p> + +<pre class="brush: html"><style> + #stockTicker { font-size: 12px; font-family: Verdana; font-weight: bold; } + .stockSymbol { font: 14px Arial; color: red; } +</style> + +<div id="stockTicker"> + NYS: <span class="stockSymbol">GE</span> +1.0 ... +</div> +</pre> + +<p>No exemplo anterior o problema ocorre em regras pertencentes a diferentes elementos. Mas também poderia acontecer para o mesmo elemento, pois a ordem das regras <strong><u>é</u></strong> importante.</p> + +<pre class="brush: css">#stockTicker { + font-weight: bold; + font: 12px Verdana; /* font-weight agora está definido como "normal" */ +} +</pre> + +<h3 id="Use_of_the_.2A_selector" name="Use_of_the_.2A_selector">Uso do seletor <code>*</code></h3> + +<p>O seletor curinga <code>*</code> faz referência a qualquer elemento, e deve ser usado com cuidado.</p> + +<pre class="brush: html"><style> + body * { font-weight: normal; } + #stockTicker { font: 12px Verdana; } + .corpName { font-weight: bold; } + .stockUp { color: red; } +</style> + +<div id="section"> + NYS: <span class="corpName"><span class="stockUp">GE</span></span> +1.0 ... +</div> +</pre> + +<p>No exemplo acima, o seletor * aplica a regra para todos os elementos dentro de <code>body</code>, em qualquer nível hierarquico, incluindo a classe <code>.stockUp</code>. Sendo assim a regra <code>font-weight: bold;</code> aplicada à classe <code>.corpName</code> é sobreposta por <code>font-weight: normal;</code> aplicada a todos os elementos dentro de <code>body</code>.</p> + +<p>O uso do seletor * também deve ser minimizado por ser um seletor lento, especialmente quando não utilizado como o primeiro elemento de um seletor. Este seletor deve ser evitado o máximo possível.</p> + +<h3 id="Specificity_in_CSS" name="Specificity_in_CSS">Especificidade em CSS</h3> + +<p>Quando multiplas regras são aplicadas a um elemento, a regra a ser renderizada depende de sua <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Cascade_and_inheritance#Specificity" title="Specificity">especificidade</a>. O estilo <em>inline</em> (regras de estilo definidas no atributo <code>style</code> de um elemento HTML) tem a mais alta especificidade e irá sobrepor qualquer seletor. Seletores de ID tem a segunda mais alta especificidade, com seletores de classes vindo logo após e, eventualmente, seletores de elementos (tags). Tendo isso em mente, a cor do texto da {{htmlelement("div")}} abaixo terá a cor vermelha.</p> + +<pre class="brush: html"><style> + div { color: black; } + #orange { color: orange; } + .green { color: green; } +</style> + +<div id="orange" class="green" style="color: red;">Isso é vermelho</div> +</pre> + +<p>As regras se tornam mais complicadas quando o seletor tem diversas partes. Informações mais detalhadas sobre como a especificidade de seletores é calculada podem ser encontradas nas <a href="http://www.w3.org/TR/CSS21/cascade.html#specificity">Especificações CSS 2.1, capítulo 6.4.3</a>.</p> + +<h2 id="What_do_the_-moz-.2A_properties_do.3F" name="What_do_the_-moz-.2A_properties_do.3F">O que as propriedades -moz-*, -ms-*, -webkit-*, -o-* e -khtml-* fazem?</h2> + +<p>Estas propriedades, chamadas <em>propriedades prefixadas</em>, são extenções ao padrão CSS. Elas permitem o uso de recursos experimentais e fora dos padrões em navegadores sem poluir o namespace convencional, prevenindo que incompatibilidades entre implementações experimentais e fora dos padrões surjam quando os padrões CSS forem expandidos.</p> + +<p>Apesar do vasto uso na web, o uso de propriedades prefixadas não é recomendado em ambiente de produção. O uso indiscriminado de funcionalidades experimentais ou não-padrão pode causar problemas de compatibilidade futuros (como uma funcionalidade experimental mudando de nome, ou tendo o mesmo nome de uma outro funcionalidade que no passado tinha uma finalidade completamente diferente) e não renderizar páginas de forma correta em diferentes navegadores. Outro problema muito comum encontrado pelo uso indiscriminado de propriedades prefixadas é a declaração de regras que acabam se tornando exclusivas para determinadas engines, quebrando a renderização em outros navegadores, mesmo estes navegadores dando suporte à propriedade padrão não-prefixada (Por exemplo, apenas a propriedade <code>-webkit-border-radius</code> sendo usada em uma regra ao invés de <code>border-radius</code>, que é suportada por todos os navegadores, inclusive os baseados em webkit).</p> + +<p>Para amenizar os problemas de incompatibilidade gerados pelo uso de propriedades prefixadas (principalmente <code>-webkit-</code>), foi estabelecido o <a href="https://compat.spec.whatwg.org/">Compatibility Living Standard</a>, o qual sugere um conjunto de propriedades <code>-webkit-</code> que navegadores (mesmo não utilizando a engine webkit) devem suportar. Outra medida que vem sendo tomada por desenvolvedores de navegadores é abandonar o suporte a propriedades prefixadas em versões estáveis dos navegadores, mantendo suporte a tais propriedades apenas em<em>Nightly Builds </em>e similares, desencorajando o uso em ambiente de produção.</p> + +<p>Caso você precise usar propriedades prefixadas em seu trabalho, você deve declarar primeiramente as propriedades prefixadas e, por último, declarar a versão padrão não-prefixada da propriedade anteriormente declara, garantindo que o navegador utilize a versão especificada nos padrões assim que suportado. Por exemplo:</p> + +<pre class="brush: css line-numbers language-css"><code class="language-css"><span class="property token">-ms-transform</span><span class="punctuation token">:</span> <span class="function token">rotate</span><span class="punctuation token">(</span><span class="number token">90</span>deg<span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="property token">-webkit-transform</span><span class="punctuation token">:</span> <span class="function token">rotate</span><span class="punctuation token">(</span><span class="number token">90</span>deg<span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="property token">transform</span><span class="punctuation token">:</span> <span class="function token">rotate</span><span class="punctuation token">(</span><span class="number token">90</span>deg<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<div class="note"> +<p><strong>Nota</strong>: Para mais informações em como lhe dar com propriedades prefixadas, veja <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS#Handling_CSS_prefixes">Lidando com problemas comuns em HTML e CSS — Lidando com prefixos CSS</a> do nosso módulo <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing">Teste Cross-browsing</a>.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Veja a página <a href="/en-US/docs/CSS/CSS_Reference/Mozilla_Extensions" title="CSS Reference/Mozilla Extensions">Extenções CSS Mozilla</a> para mais informações sobre propriedades CSS prefixadas da Mozilla.</p> +</div> + +<h2 id="Como_z-index_está_relacionado_a_posicionamento">Como <code>z-index</code> está relacionado a posicionamento?</h2> + +<p>A propriedade <code>z-index</code> especifica a ordem dos elementos da pilha.</p> + +<p>Um elemento com z-index/ordem na pilha maior sempre será renderizado à frente de um elemento com um z-index/ordem de pilha menor. <code>z-index</code> funcionará apenas em elementos que tenham uma posição especificada (Ou seja, só funcionará caso o elemento tenha <code>position:absolute</code>, <code>position:relative</code> ou <code>position:fixed</code>).</p> + +<div class="note"> +<p><strong>Nota</strong>: Para mais informações, veja nosso artigo de aprendizado sobre <a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Posicionamento</a>, e em particular a seção <a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning#Introducing_z-index">Introduzindo z-index</a>.</p> +</div> diff --git a/files/pt-br/learn/css/howto/index.html b/files/pt-br/learn/css/howto/index.html new file mode 100644 index 0000000000..01e5fe9373 --- /dev/null +++ b/files/pt-br/learn/css/howto/index.html @@ -0,0 +1,92 @@ +--- +title: Use CSS to solve common problems +slug: Learn/CSS/Howto +tags: + - Beginner + - CSS + - Learn + - NeedsTranslation + - TopicStub +translation_of: Learn/CSS/Howto +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">The following links point to solutions to common everyday problems you'll need to solve with CSS.</p> + +<h2 id="Common_use_cases">Common use cases</h2> + +<div class="column-container"> +<div class="column-half"> +<h3 id="Basics">Basics</h3> + +<ul> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/How_CSS_works#How_to_apply_your_CSS_to_your_HTML">How to apply CSS to HTML</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Syntax#White_space">How to use whitespace in CSS</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Syntax#Comments">How to write comments in CSS</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Selectors#Simple_selectors">How to select elements via element name, class or ID</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Selectors#Attribute_selectors">How to select elements via attribute name and content</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Selectors#Pseudo-classes">How to use pseudo-classes</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Selectors#Pseudo-elements">How to use pseudo-elements</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Selectors#Multiple_selectors_on_one_rule">How to apply multiple selectors to the same rule</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Values_and_units#Colors">How to specify colors in CSS</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Debugging_CSS#Inspecting_the_DOM_and_CSS">How to debug CSS in the browser</a></li> +</ul> + +<h3 id="CSS_and_text">CSS and text</h3> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Fundamentals">How to style text</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_lists">How to customize a list of elements</a></li> + <li><a href="/en-US/Learn/CSS/Styling_text/Styling_links">How to style links</a></li> + <li><a href="/en-US/Learn/CSS/Styling_text/Fundamentals#Text_drop_shadows">How to add shadows to text</a></li> +</ul> +</div> + +<div class="column-half"> +<h3 id="Boxes_and_layouts">Boxes and layouts</h3> + +<ul> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Box_model#Box_properties">How to size CSS boxes</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Box_model#Overflow">How to control overflowing content</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Box_model#Background_clip">How to control the part of a CSS box that the background is drawn under</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Box_model#Types_of_CSS_boxes">How do I define inline, block, and inline-block?</a></li> + <li><a href="/en-US/docs/Learn/CSS/Howto/create_fancy_boxes">How to create fancy boxes</a> (also see the <a href="/en-US/docs/Learn/CSS/Styling_boxes">Styling boxes</a> module, generally).</li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Box_model#Background_clip">How to use <code>background-clip</code> to control how much of the box your background image covers</a>.</li> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Box_model_recap#Changing_the_box_model_completely">How to change the box model completely using <code>box-sizing</code></a></li> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Backgrounds">How to control backgrounds</a></li> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Borders">How to control borders</a></li> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Styling_tables">How to style an HTML table</a></li> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Advanced_box_effects#Box_shadows">How to add shadows to boxes</a></li> +</ul> +</div> +</div> + +<h2 id="Uncommon_or_advanced_techniques">Uncommon or advanced techniques</h2> + +<p>Beyond the basics, CSS is allows very advanced design techniques. These articles help you tackle the hardest use cases you may face.</p> + +<h3 id="General">General</h3> + +<ul> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Cascade_and_inheritance#Specificity">How to calculate specificity of a CSS selector</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Cascade_and_inheritance#Controlling_inheritance">How to control inheritance in CSS</a></li> +</ul> + +<h3 id="Advanced_effects">Advanced effects</h3> + +<ul> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Advanced_box_effects#Filters">How to use filters in CSS</a></li> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Advanced_box_effects#Blend_modes">How to use blend modes in CSS</a></li> +</ul> + +<h3 id="Layout">Layout</h3> + +<ul> + <li><a href="/en-US/docs/Web/Guide/CSS/Flexible_boxes">Using CSS flexible boxes</a></li> + <li><a href="/en-US/docs/Web/Guide/CSS/Using_multi-column_layouts" title="/en-US/docs/Web/Guide/CSS/Using_multi-column_layouts">Using CSS multi-column layouts</a></li> + <li><a href="/en-US/docs/Web/Guide/CSS/Getting_started/Content">Using CSS generated content</a></li> +</ul> + +<h2 id="See_also">See also</h2> + +<p><a href="/en-US/docs/Learn/CSS/Howto/CSS_FAQ">CSS FAQ</a> — A collection of smaller bits of information, covering a variety of topics from debugging to selector usage.</p> diff --git a/files/pt-br/learn/javascript/asynchronous/conceitos/index.html b/files/pt-br/learn/javascript/asynchronous/conceitos/index.html new file mode 100644 index 0000000000..f2e6759f41 --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/conceitos/index.html @@ -0,0 +1,155 @@ +--- +title: Conceitos gerais da programação assíncrona +slug: Learn/JavaScript/Asynchronous/Conceitos +translation_of: Learn/JavaScript/Asynchronous/Concepts +--- +<div>{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}}</div> + +<p>Neste artigo, nós vamos ver um número de conceitos importantes relativos à programação assíncrona e como ela se parece em navegadores modernos e em JavaScript. Você deve entender estes conceitos antes de trabalhar com outros artigos neste módulo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimentos básicos de informática e compreensão dos fundamentos de JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender os conceitos básicos da programação assíncrona e como ela se manifesta em navegadores e JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Assíncrono">Assíncrono?</h2> + +<p>Normalmente, o código de um programa é executado de forma direta, com uma coisa acontecendo por vez. Se uma função depende do resultado de outra função, ela tem que esperar o retorno do resultado, e até que isso aconteça, o programa inteiro praticamente para de funcionar da perspectiva do usuário.</p> + +<p>Usuários do Mac, por exemplo, conseguem ver isso como o cursor giratório em arco-íris (ou "beachball", como normalmente é chamado). Este cursor é o jeito do sistema operacional dizer: "o programa atual que você está usando teve que parar e esperar algo terminar de ser executado, e estava demorando tanto que fiquei preocupado se você estava pensando no que aconteceu."</p> + +<p><img alt="Multi-colored macOS beachball busy spinner" src="https://mdn.mozillademos.org/files/16577/beachball.jpg" style="display: block; float: left; height: 256px; margin: 0px 30px 0px 0px; width: 250px;"></p> + +<p>Essa é uma situação frustrante, e não faz bom uso do poder de processamento do computador — especialmente em uma era em que computadores tem múltiplos núcleos de processamento disponíveis. Não há sentido em ficar esperando por algo quando você pode deixar outra tarefa ser executada em um núcleo de processador diferente e deixar que ele te avise quando terminar. Isso te permite fazer mais coisas por enquanto, o que é a base da <strong>programação assincrona</strong>. Depende do ambiente de programação que você está usando (navegadores da Web, no caso de desenvolvimento da Web) para fornecer APIs que permitem executar essas tarefas de forma assíncrona.</p> + +<h2 id="Bloqueio_de_código">Bloqueio de código</h2> + +<p>Técnicas <strong>async</strong> (assíncronas) são muito úteis, principalmente na programação web. Quando um aplicativo web é executado em um navegador e executa um pedaço de código rigoroso sem retornar o controle para o navegador, ele pode parecer que travou. Isso é chamado de <strong>blocking</strong>; o navegador está bloqueado de continuar a manusear a entrada do usuário e de realizar outras tarefas até que o aplicativo web retorne o controle do processador.</p> + +<p>Vamos dar uma olhadinha em alguns exemplos para que você entenda o blocking.</p> + +<p>No nosso exemplo <a href="https://github.com/mdn/learning-area/tree/master/javascript/asynchronous/introducing/simple-sync.html">simple-sync.html</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync.html">veja aqui</a>), nós adicionamos um evento de click em um botão para que, quando clicado, ele executa uma tarefa pesada (calcula 10 milhões de datas e depois imprime a última delas no console) e depois adiciona um parágrafo no DOM:</p> + +<pre class="brush: js notranslate">const btn = document.querySelector('button'); +btn.addEventListener('click', () => { + let myDate; + for(let i = 0; i < 10000000; i++) { + let date = new Date(); + myDate = date + } + + console.log(myDate); + + let pElem = document.createElement('p'); + pElem.textContent = 'This is a newly-added paragraph.'; + document.body.appendChild(pElem); +});</pre> + +<p>Quando o exemplo for executado, abra seu console JavaScript e depois clique no botão — você verá qua o parágrafo não aparece até que o programa termine de calcular as datas e imprimir a última no console. O código é executado na ordem em que ele aparece na fonte, e a operação seguinte só é executada depois que a primeira for terminada.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: O exemplo anterior não é muito realistico. Você nunca calcularia 10 milhões de datas em um aplicativo real! Mas isso serve par te dar um apoio sobre o assunto.</p> +</div> + +<p>No nosso segundo exemplo <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync-ui-blocking.html">simple-sync-ui-blocking.html</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync-ui-blocking.html">veja aqui</a>), nós simulamos algo mais realistico que você pode encontrar em uma página real. Nós bloqueamos a interatividade do usuário na renderização da UI. Neste exemplo, nós temos dois botões:</p> + +<ul> + <li>Um botão "Fill canvas" que quando for clicado renderiza 1 milhão de círculos azuis no elemento {{htmlelement("canvas")}} .</li> + <li>Um botão "Clique-me" que mostra um alerta quando clicado.</li> +</ul> + +<pre class="brush: js notranslate">function expensiveOperation() { + for(let i = 0; i < 1000000; i++) { + ctx.fillStyle = 'rgba(0,0,255, 0.2)'; + ctx.beginPath(); + ctx.arc(random(0, canvas.width), random(0, canvas.height), 10, degToRad(0), degToRad(360), false); + ctx.fill() + } +} + +fillBtn.addEventListener('click', expensiveOperation); + +alertBtn.addEventListener('click', () => + alert('You clicked me!') +);</pre> + +<p>Se você clicar no primeiro botão e imediatamente no segundo, você verá que a mensagem de alerta não aparece até que os círculos sejam totalmente renderizados. A primeira operação bloqueia a segunda até a sua finalização.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: OK, no nosso caso, isso é ruim e estamos bloqueando o código de propósito, mas isso é um problema comum que desenvolvedores de aplicativos reais sempre tentam resolver.</p> +</div> + +<p>E por quê isso acontece? A resposta é que o JavaScript é <strong>single threaded</strong>. E é neste ponto que precisamos introduzir a você o conceito de <strong>threads</strong>.</p> + +<h2 id="Threads">Threads</h2> + +<p>Uma <strong>thread</strong> é basicamente um único processo que um programa pode usar para concluir tarefas. Cada thread só pode fazer uma tarefa de cada vez:</p> + +<pre class="notranslate">Tarefa A --> Tarefa B --> Tarefa C</pre> + +<p>Cada tarefa será executada sequencialmente; uma tarefa tem que ser concluída antes que a próxima possa ser iniciada.</p> + +<p>Como foi dito anteriormente, muitos computadores possuem múltiplos núcleos, para que possam fazer múltiplas coisas de uma vez só. Linguagens de programação que podem suportar múltiplas threads podem usar múltiplos processadores para concluir múltiplas tarefas simultâneamente:</p> + +<pre class="notranslate">Thread 1: Tarefa A --> Tarefa B +Thread 2: Tarefa C --> Tarefa D</pre> + +<h3 id="JavaScript_é_single_threaded">JavaScript é single threaded</h3> + +<p>JavaScript é tradicionalmente single-threaded. Mesmo com múltiplos núcleos de processamento, você só pode fazê-lo executar tarefas em uma única thread, chamada de <strong>main thread</strong> (thread principal). Nosso exemplo de cima é executado assim:</p> + +<pre class="notranslate">Main thread: Renderizar circulos no canvas --> Mostrar alert()</pre> + +<p>Depois de um tempo, o JavaScript ganhou algumas ferramentas para ajudar em tais problemas. As <a href="/en-US/docs/Web/API/Web_Workers_API">Web workers</a> te permitem mandar parte do processamento do JavaScript para uma thread separada. Você geralmente usaria uma worker para executar um processo pesado para que a UI não seja bloqueada.</p> + +<pre class="notranslate"> Main thread: Tarefa A --> Tarefa C +Worker thread: Tarefa pesada B</pre> + +<p>Com isso em mente, dê uma olhada em <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync-worker.html">simple-sync-worker.html</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync-worker.html">veja aqui</a>), com o seu console JavaScript aberto. Isso é uma nova versão do nosso exemplo que calcula 10 milhões de datas em uma tread worker separada. Agora, quando você clica no botão, o navegador é capaz de mostrar o parágrafo antes que as datas sejam terminadas. A primeira opreção não bloqueia a segunda.</p> + +<h2 id="Código_assíncrono">Código assíncrono</h2> + +<p>Web workers podem ser bem úteis, mas elas tem as suas limitações. Uma delas é que elas não são capazes de acessar a {{Glossary("DOM")}} — você não pode fazer com que uma worker faça algo diretamente para atualizar a UI. Nós não poderíamos renderizar nossos 1 milhão de círculos azuis na nossa worker; basicamente ela pode apenas fazer cálculos de números.</p> + +<p>O segundo problema é que, mesmo que o código executado em uma worker não cause um bloqueio, ele ainda é um código síncrono. Isso se torna um problema quando uma função depende dos resultados de processos anteriores para funcionar. Considere os diagramas a seguir:</p> + +<pre class="notranslate">Main thread: Tarefa A --> Tarefa B</pre> + +<p>Nesse caso, digamos que a tarefa A está fazendo algo como pegar uma imagem do servidor e que a tarefa B faz algo com essa imagem, como colocar um filtro nela. Se você iniciar a tarefa A e depois tentar executar a tarefa B imediatamente, você obterá um erro, porque a imagem não estará disponível ainda.</p> + +<pre class="notranslate"> Main thread: Tarefa A --> Tarefa B --> |Tarefa D| +Worker thread: Tarefa C ---------------> | |</pre> + +<p>Neste caso, digamos que a tarefa D faz uso dos resultados das tarefas B e C. Se nós pudermos garantir que esses resultados estejam disponíveis ao mesmo tempo, então tudo talvez esteja bem, mas isso não é garantido. Se a tarefa D tentar ser executada quando um dos resultados não estiver disponível, ela retornará um erro.</p> + +<p>Para consertarmos tais problemas, os browsers nos permitem executar certas operações de modo assíncrono. Recursos como <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a> te permitem executar uma operação e depois esperar pelo resultado antes de executar outra operação: </p> + +<pre class="notranslate">Main thread: Tarefa A Tarefa B + Promise: |___operação async___|</pre> + +<p>Já que a operação está acontecendo em outro lugar, a main thread não está bloqueada enquanto a operação assíncrona está sendo processada.</p> + +<p>Nós vamos começar a olhar em como podemos escrever código assíncrono no próximo artigo.</p> + +<h2 id="Conclusão">Conclusão</h2> + +<p>O design moderno de software gira em torno do uso de programação assíncrona, para permitir que os programas façam mais de uma coisa por vez. Ao usar APIs mais novas e mais poderosas, você encontrará mais casos em que a única maneira de fazer as coisas é assincronamente. Costumava ser difícil escrever código assíncrono. Ainda é preciso se acostumar, mas ficou muito mais fácil. No restante deste módulo, exploraremos ainda mais por que o código assíncrono é importante e como projetar o código que evita alguns dos problemas descritos acima.</p> + +<h2 id="Nesse_módulo">Nesse módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">Conceitos gerais da programação assíncrona</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introduzindo o JavaScript assíncrono</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Timeouts e intervalos</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Código elegante usando as Promises</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Facilitando a programação async com async e await</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Escolhendo a abordagem certa</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/asynchronous/escolhendo_abordagem_correta/index.html b/files/pt-br/learn/javascript/asynchronous/escolhendo_abordagem_correta/index.html new file mode 100644 index 0000000000..254bc41a99 --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/escolhendo_abordagem_correta/index.html @@ -0,0 +1,523 @@ +--- +title: Escolhendo a abordagem correta +slug: Learn/JavaScript/Asynchronous/Escolhendo_abordagem_correta +translation_of: Learn/JavaScript/Asynchronous/Choosing_the_right_approach +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}</div> + +<p>To finish this module off, we'll provide a brief discussion of the different coding techniques and features we've discussed throughout, looking at which one you should use when, with recommendations and reminders of common pitfalls where appropriate. We'll probably add to this resource as time goes on.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>Basic computer literacy, a reasonable understanding of JavaScript fundamentals.</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>To be able to make a sound choice of when to use different asynchronous programming techniques.</td> + </tr> + </tbody> +</table> + +<h2 id="Asynchronous_callbacks">Asynchronous callbacks</h2> + +<p>Generally found in old-style APIs, involves a function being passed into another function as a parameter, which is then invoked when an asynchronous operation has been completed, so that the callback can in turn do something with the result. This is the precursor to promises; it's not as efficient or flexible. Use only when necessary.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + </thead> + <tbody> + <tr> + <td>No</td> + <td>Yes (recursive callbacks)</td> + <td>Yes (nested callbacks)</td> + <td>No</td> + </tr> + </tbody> +</table> + +<h3 id="Code_example">Code example</h3> + +<p>An example that loads a resource via the <a href="/en-US/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code> API</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html">run it live</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html">see the source</a>):</p> + +<pre class="brush: js notranslate">function loadAsset(url, type, callback) { + let xhr = new XMLHttpRequest(); + xhr.open('GET', url); + xhr.responseType = type; + + xhr.onload = function() { + callback(xhr.response); + }; + + xhr.send(); +} + +function displayImage(blob) { + let objectURL = URL.createObjectURL(blob); + + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +} + +loadAsset('coffee.jpg', 'blob', displayImage);</pre> + +<h3 id="Pitfalls">Pitfalls</h3> + +<ul> + <li>Nested callbacks can be cumbersome and hard to read (i.e. "callback hell").</li> + <li>Failure callbacks need to be called once for each level of nesting, whereas with promises you can just use a single <code>.catch()</code> block to handle the errors for the entire chain.</li> + <li>Async callbacks just aren't very graceful.</li> + <li>Promise callbacks are always called in the strict order they are placed in the event queue; async callbacks aren't.</li> + <li>Async callbacks lose full control of how the function will be executed when passed to a third-party library.</li> +</ul> + +<h3 id="Browser_compatibility">Browser compatibility</h3> + +<p>Really good general support, although the exact support for callbacks in APIs depends on the particular API. Refer to the reference documentation for the API you're using for more specific support info.</p> + +<h3 id="Further_information">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a>, in particular <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing#Async_callbacks">Async callbacks</a></li> +</ul> + +<h2 id="setTimeout">setTimeout()</h2> + +<p><code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code> is a method that allows you to run a function after an arbitrary amount of time has passed.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + <tr> + <td>Yes</td> + <td>Yes (recursive timeouts)</td> + <td>Yes (nested timeouts)</td> + <td>No</td> + </tr> + </thead> +</table> + +<h3 id="Code_example_2">Code example</h3> + +<p>Here the browser will wait two seconds before executing the anonymous function, then will display the alert message (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">see it running live</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">see the source code</a>):</p> + +<pre class="brush: js notranslate">let myGreeting = setTimeout(function() { + alert('Hello, Mr. Universe!'); +}, 2000)</pre> + +<h3 id="Pitfalls_2">Pitfalls</h3> + +<p>You can use recursive <code>setTimeout()</code> calls to run a function repeatedly in a similar fashion to <code>setInterval()</code>, using code like this:</p> + +<pre class="brush: js notranslate">let i = 1; +setTimeout(function run() { + console.log(i); + i++; + + setTimeout(run, 100); +}, 100);</pre> + +<p>There is a difference between recursive <code>setTimeout()</code> and <code>setInterval()</code>:</p> + +<ul> + <li>Recursive <code>setTimeout()</code> guarantees at least the specified amount of time (100ms in this example) will elapse between the executions; the code will run and then wait 100 milliseconds before it runs again. The interval will be the same regardless of how long the code takes to run.</li> + <li>With <code>setInterval()</code>, the interval we choose <em>includes</em> the time taken to execute the code we want to run in. Let's say that the code takes 40 milliseconds to run — the interval then ends up being only 60 milliseconds.</li> +</ul> + +<p>When your code has the potential to take longer to run than the time interval you’ve assigned, it’s better to use recursive <code>setTimeout()</code> — this will keep the time interval constant between executions regardless of how long the code takes to execute, and you won't get errors.</p> + +<h3 id="Browser_compatibility_2">Browser compatibility</h3> + +<p>{{Compat("api.WindowOrWorkerGlobalScope.setTimeout")}}</p> + +<h3 id="Further_information_2">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a>, in particular <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals#setTimeout()">setTimeout()</a></li> + <li><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout() reference</a></li> +</ul> + +<h2 id="setInterval">setInterval()</h2> + +<p><code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></code> is a method that allows you to run a function repeatedly with a set interval of time between each execution. Not as efficient as <code><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></code>, but allows you to choose a running rate/frame rate.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + <tr> + <td>No</td> + <td>Yes</td> + <td>No (unless it is the same one)</td> + <td>No</td> + </tr> + </thead> +</table> + +<h3 id="Code_example_3">Code example</h3> + +<p>The following function creates a new <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date">Date()</a></code> object, extracts a time string out of it using <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString">toLocaleTimeString()</a></code>, and then displays it in the UI. We then run it once per second using <code>setInterval()</code>, creating the effect of a digital clock that updates once per second (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">see this live</a>, and also <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">see the source</a>):</p> + +<pre class="brush: js notranslate">function displayTime() { + let date = new Date(); + let time = date.toLocaleTimeString(); + document.getElementById('demo').textContent = time; +} + +const createClock = setInterval(displayTime, 1000);</pre> + +<h3 id="Pitfalls_3">Pitfalls</h3> + +<ul> + <li>The frame rate isn't optimized for the system the animation is running on, and can be somewhat inefficient. Unless you need to choose a specific (slower) framerate, it is generally better to use <code>requestAnimationFrame()</code>.</li> +</ul> + +<h3 id="Browser_compatibility_3">Browser compatibility</h3> + +<p>{{Compat("api.WindowOrWorkerGlobalScope.setInterval")}}</p> + +<h3 id="Further_information_3">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a>, in particular <a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></li> + <li><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval() reference</a></li> +</ul> + +<h2 id="requestAnimationFrame">requestAnimationFrame()</h2> + +<p><code><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></code> is a method that allows you to run a function repeatedly, and efficiently, at the best framerate available given the current browser/system. You should, if at all possible, use this instead of <code>setInterval()</code>/recursive <code>setTimeout()</code>, unless you need a specific framerate.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + <tr> + <td>No</td> + <td>Yes</td> + <td>No (unless it is the same one)</td> + <td>No</td> + </tr> + </thead> +</table> + +<h3 id="Code_example_4">Code example</h3> + +<p>A simple animated spinner; you can find this <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">example live on GitHub</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">source code</a> also):</p> + +<pre class="brush: js notranslate">const spinner = document.querySelector('div'); +let rotateCount = 0; +let startTime = null; +let rAF; + +function draw(timestamp) { + if(!startTime) { + startTime = timestamp; + } + + rotateCount = (timestamp - startTime) / 3; + + if(rotateCount > 359) { + rotateCount %= 360; + } + + spinner.style.transform = 'rotate(' + rotateCount + 'deg)'; + + rAF = requestAnimationFrame(draw); +} + +draw();</pre> + +<h3 id="Pitfalls_4">Pitfalls</h3> + +<ul> + <li>You can't choose a specific framerate with <code>requestAnimationFrame()</code>. If you need to run your animation at a slower framerate, you'll need to use <code>setInterval()</code> or recursive <code>setTimeout()</code>.</li> +</ul> + +<h3 id="Browser_compatibility_4">Browser compatibility</h3> + +<p>{{Compat("api.Window.requestAnimationFrame")}}</p> + +<h3 id="Further_information_4">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a>, in particular <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals#requestAnimationFrame()">requestAnimationFrame()</a></li> + <li><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame() reference</a></li> +</ul> + +<h2 id="Promises">Promises</h2> + +<p><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a> are a JavaScript feature that allows you to run asynchronous operations and wait until it is definitely complete before running another operation based on its result. Promises are the backbone of modern asynchronous JavaScript.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + <tr> + <td>No</td> + <td>No</td> + <td>Yes</td> + <td>See <code>Promise.all()</code>, below</td> + </tr> + </thead> +</table> + +<h3 id="Code_example_5">Code example</h3> + +<p>The following code fetches an image from the server and displays it inside an {{htmlelement("img")}} element; <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/simple-fetch-chained.html">see it live also</a>, and see also <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch-chained.html">the source code</a>:</p> + +<pre class="brush: js notranslate">fetch('coffee.jpg') +.then(response => response.blob()) +.then(myBlob => { + let objectURL = URL.createObjectURL(myBlob); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +}) +.catch(e => { + console.log('There has been a problem with your fetch operation: ' + e.message); +});</pre> + +<h3 id="Pitfalls_5">Pitfalls</h3> + +<p>Promise chains can be complex and hard to parse. If you nest a number of promises, you can end up with similar troubles to callback hell. For example:</p> + +<pre class="brush: js notranslate">remotedb.allDocs({ + include_docs: true, + attachments: true +}).then(function (result) { + let docs = result.rows; + docs.forEach(function(element) { + localdb.put(element.doc).then(function(response) { + alert("Pulled doc with id " + element.doc._id + " and added to local db."); + }).catch(function (err) { + if (err.name == 'conflict') { + localdb.get(element.doc._id).then(function (resp) { + localdb.remove(resp._id, resp._rev).then(function (resp) { +// et cetera...</pre> + +<p>It is better to use the chaining power of promises to go with a flatter, easier to parse structure:</p> + +<pre class="brush: js notranslate">remotedb.allDocs(...).then(function (resultOfAllDocs) { + return localdb.put(...); +}).then(function (resultOfPut) { + return localdb.get(...); +}).then(function (resultOfGet) { + return localdb.put(...); +}).catch(function (err) { + console.log(err); +});</pre> + +<p>or even:</p> + +<pre class="brush: js notranslate">remotedb.allDocs(...) +.then(resultOfAllDocs => { + return localdb.put(...); +}) +.then(resultOfPut => { + return localdb.get(...); +}) +.then(resultOfGet => { + return localdb.put(...); +}) +.catch(err => console.log(err));</pre> + +<p>That covers a lot of the basics. For a much more complete treatment, see the excellent <a href="https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html">We have a problem with promises</a>, by Nolan Lawson.</p> + +<h3 id="Browser_compatibility_5">Browser compatibility</h3> + +<p>{{Compat("javascript.builtins.Promise")}}</p> + +<h3 id="Further_information_5">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Using_promises">Using promises</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise reference</a></li> +</ul> + +<h2 id="Promise.all">Promise.all()</h2> + +<p>A JavaScript feature that allows you to wait for multiple promises to complete before then running a further operation based on the results of all the other promises.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + <tr> + <td>No</td> + <td>No</td> + <td>No</td> + <td>Yes</td> + </tr> + </thead> +</table> + +<h3 id="Code_example_6">Code example</h3> + +<p>The following example fetches several resources from the server, and uses <code>Promise.all()</code> to wait for all of them to be available before then displaying all of them — <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-all.html">see it live</a>, and see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html">source code</a>:</p> + +<pre class="brush: js notranslate">function fetchAndDecode(url, type) { + // Returning the top level promise, so the result of the entire chain is returned out of the function + return fetch(url).then(response => { + // Depending on what type of file is being fetched, use the relevant function to decode its contents + if(type === 'blob') { + return response.blob(); + } else if(type === 'text') { + return response.text(); + } + }) + .catch(e => { + console.log(`There has been a problem with your fetch operation for resource "${url}": ` + e.message); + }); +} + +// Call the fetchAndDecode() method to fetch the images and the text, and store their promises in variables +let coffee = fetchAndDecode('coffee.jpg', 'blob'); +let tea = fetchAndDecode('tea.jpg', 'blob'); +let description = fetchAndDecode('description.txt', 'text'); + +// Use Promise.all() to run code only when all three function calls have resolved +Promise.all([coffee, tea, description]).then(values => { + console.log(values); + // Store each value returned from the promises in separate variables; create object URLs from the blobs + let objectURL1 = URL.createObjectURL(values[0]); + let objectURL2 = URL.createObjectURL(values[1]); + let descText = values[2]; + + // Display the images in <img> elements + let image1 = document.createElement('img'); + let image2 = document.createElement('img'); + image1.src = objectURL1; + image2.src = objectURL2; + document.body.appendChild(image1); + document.body.appendChild(image2); + + // Display the text in a paragraph + let para = document.createElement('p'); + para.textContent = descText; + document.body.appendChild(para); +});</pre> + +<h3 id="Pitfalls_6">Pitfalls</h3> + +<ul> + <li>If a <code>Promise.all()</code> rejects, then one or more of the promises you are feeding into it inside its array parameter must be rejecting, or might not be returning promises at all. You need to check each one to see what they returned. </li> +</ul> + +<h3 id="Browser_compatibility_6">Browser compatibility</h3> + +<p>{{Compat("javascript.builtins.Promise.all")}}</p> + +<h3 id="Further_information_6">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises#Running_code_in_response_to_multiple_promises_fulfilling">Running code in response to multiple promises fulfilling</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all">Promise.all() reference</a></li> +</ul> + +<h2 id="Asyncawait">Async/await</h2> + +<p>Syntactic sugar built on top of promises that allows you to run asynchronous operations using syntax that's more like writing synchronous callback code.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + <tr> + <td>No</td> + <td>No</td> + <td>Yes</td> + <td>Yes (in combination with <code>Promise.all()</code>)</td> + </tr> + </thead> +</table> + +<h3 id="Code_example_7">Code example</h3> + +<p>The following example is a refactor of the simple promise example we saw earlier that fetches and displays an image, written using async/await (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-refactored-fetch.html">see it live</a>, and see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-refactored-fetch.html">source code</a>):</p> + +<pre class="brush: js notranslate">async function myFetch() { + let response = await fetch('coffee.jpg'); + let myBlob = await response.blob(); + + let objectURL = URL.createObjectURL(myBlob); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +} + +myFetch();</pre> + +<h3 id="Pitfalls_7">Pitfalls</h3> + +<ul> + <li>You can't use the <code>await</code> operator inside a non-<code>async</code> function, or in the top level context of your code. This can sometimes result in an extra function wrapper needing to be created, which can be slightly frustrating in some circumstances. But it is worth it most of the time.</li> + <li>Browser support for async/await is not as good as that for promises. If you want to use async/await but are concerned about older browser support, you could consider using the <a href="https://babeljs.io/">BabelJS</a> library — this allows you to write your applications using the latest JavaScript and let Babel figure out what changes if any are needed for your user’s browsers.</li> +</ul> + +<h3 id="Browser_compatibility_7">Browser compatibility</h3> + +<p>{{Compat("javascript.statements.async_function")}}</p> + +<h3 id="Further_information_7">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Making asynchronous programming easier with async and await</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/async_function">Async function reference</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/await">Await operator reference</a></li> +</ul> + +<p>{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">General asynchronous programming concepts</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Making asynchronous programming easier with async and await</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choosing the right approach</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/asynchronous/index.html b/files/pt-br/learn/javascript/asynchronous/index.html new file mode 100644 index 0000000000..67c3f8e466 --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/index.html @@ -0,0 +1,67 @@ +--- +title: JavaScript Assíncrono +slug: Learn/JavaScript/Asynchronous +tags: + - Beginner + - CodingScripting + - Guide + - Guía + - Iniciante + - JavaScript + - Landing + - NeedsTranslation + - Promises + - TopicStub + - async + - asynchronous + - await + - callbacks + - requestAnimationFrame + - setInterval + - setTimeout +translation_of: Learn/JavaScript/Asynchronous +--- +<div>{{LearnSidebar}}</div> + + + +<div><span class="seoSummary">Neste módulo vamos entender {{Glossary("JavaScript")}} <a href="/pt-BR/docs/Glossario/Assincrono">Assíncrono</a></span><span class="seoSummary">, porque isso é importante e como pode ser usado para lidar com operações potencialmente bloqueantes, como a busca de recursos em um servidor remoto.</span></div> + +<h2 id="Pre_requisitos">Pre requisitos</h2> + +<p>Javascript Assíncrono é um tópico razoavelmente avançado e é aconselhada a leitura dos módulos <a href="/pt-BR/docs/Learn/JavaScript/First_steps">Primeiros Passos com Javascript</a> e <a href="/pt-BR/docs/Aprender/JavaScript/Elementos_construtivos">Elementos construtivos do Javascript</a> antes de continuar.</p> + +<p>Se você não estiver familiarizado com os conceitos de programação assíncrona, a sugestão é iniciar com o artigo <a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Conceitos">Conceitos gerais da programação assíncrona</a> desse módulo. Caso contrário, você pode provavelmente pular para o módulo <a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Introdu%C3%A7%C3%A3o">Introdução ao Javascript Assíncrono</a>.</p> + +<div class="note"> +<p><strong>Note</strong>: Se você está estudando a partir de um computador/tablet/ outro dispositivo onde não é capaz de criar seus próprios arquivos, é possível executar os códigos de exemplo (a maioria deles) em plataformas como <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guias">Guias</h2> + +<dl> + <dt><a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Conceitos">Conceitos gerais da programação assíncrona</a></dt> + <dd> + <p>Nesse artigo vamos explorar um número de conceitos importantes relacionados à programação assíncrona e como aparece nos browsers Web. Você deve entender estes conceitos antes de seguir adiante através dos outros artigos neste módulo.</p> + </dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Introdu%C3%A7%C3%A3o">Introdução ao Javascript Assíncrono</a></dt> + <dd>Nesse artigo vamos recapitular brevemente os problemas associados ao Javascript síncrono e introduzir algumas das diferentes técnicas do Javascript assícrono que irá encontrar mais a frente, mostrando como essas técnicas podem nos ajudar a resolver tais problemas.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Javascript assícrono cooperativo: Timeouts e intervalos</a></dt> + <dd>Aqui contemplamos os métodos tradicionais que o Javascript possui disponível para executar código de forma assíncrona após decorrido um certo periodo de tempo ou em um intervalo regular (e.g. um determinado número de vezes por segundo), discutir sua utilidade e perceber alguns problemas inerentes a eles.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Promises">Manipulando elegantemente operações assíncronas com Promises</a></dt> + <dd>Promises são um novo recurso da linguagem Javascript que permitem adiar ações até que a ação anterior esteja concluída ou responder com falha. Isso é extremamente útil para montar uma sequência de operações para que funcione corretamente. Este artigo lhe orienta como as Promises funcionam, onde verá elas sendo utilizadas em <a href="/pt-BR/docs/WebAPI">WebAPIs</a>. Também aprenderá como escrever suas próprias promises.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Facilitando a programação assícrona com async e await</a></dt> + <dd>Promises podem ser um pouco complexas de construir e entender. Por esse motivo, os navegadores modernos implementado funções <code>async</code> e o operador <code>await.</code> O primeiro permite que funções padrão se comportem implicitamente de forma assíncrona com promises, enquanto que o último pode ser usado dentro de funções <code>async</code> para esperar por 'promessas' antes que a função continue. Isso faz com que o encadeamento de 'promessas' seja mais fácil de ler.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Escolhendo_abordagem_correta">Escolhendo a abordagem correta</a></dt> + <dd>Para concluir este módulo, vamos considerar as diferentes técnicas de programação e as features que abordamos do começo ao fim, considerando quais e quando utilizar, com recomendações e advertências das armadilhas mais comuns.</dd> +</dl> + +<h2 id="Veja_Também">Veja Também</h2> + +<ul> + <li><a href="https://eloquentjavascript.net/11_async.html">Programação Assícrona</a> do livro online <a href="https://eloquentjavascript.net/">Eloquent JavaScript</a>, por Marijn Haverbeke.</li> +</ul> + +<div class="note"> +<p><strong>Nota do tradutor</strong>: A segunda edição do <em>Eloquent Javascript</em> foi traduzida pela comunidade brasileira do Javascript e está disponível em <a href="https://github.com/braziljs/eloquente-javascript">Javascript Eloquente - 2ª Edição</a>. Até o momento da tradução deste artigo, a comunidade está trabalhando na conclusão da 3ª edição.</p> +</div> diff --git a/files/pt-br/learn/javascript/asynchronous/introdução/index.html b/files/pt-br/learn/javascript/asynchronous/introdução/index.html new file mode 100644 index 0000000000..b95a88d35c --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/introdução/index.html @@ -0,0 +1,283 @@ +--- +title: Introdução ao JavaScript Async +slug: Learn/JavaScript/Asynchronous/Introdução +translation_of: Learn/JavaScript/Asynchronous/Introducing +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}</div> + +<div>Neste artigo nós recapitulamos brevemente os problemas que são associados com o JavaScript síncrono, e dar uma primeira olhada em algumas das diferentes técnicas assíncronas que você vai encontrar, mostrando como elas podem nos ajudar a resolver tais problemas.</div> + +<div></div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimentos básicos de informática e sobre os fundamentos do JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ganhar familiaridade com o que é o Js assíncrono e como ele se difere do Js síncrono.</td> + </tr> + </tbody> +</table> + +<h2 id="JavaScript_síncrono">JavaScript síncrono</h2> + +<p>Para entendermos o que é o <strong>{{Glossary("asynchronous")}}</strong> JavaScript, nós primeiro temos que ter certeza que entedemos o que é o <strong>{{Glossary("synchronous")}}</strong> JavaScript. Essa seção revê um pouco das informações que nós vimos no artigo anterior.</p> + +<p>Muitas das funcionalidades que nós vimos em áreas anteriores são síncronas — você executa um código, e o reultado é retornado assim que o navegador puder. Vamos ver um exemplo simples (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/basic-function.html">veja aqui</a>, e <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/basic-function.html">veja o código fonte</a>):</p> + +<pre class="brush: js">const btn = document.querySelector('button'); +btn.addEventListener('click', () => { + alert('Você clicou em mim!'); + + let pElem = document.createElement('p'); + pElem.textContent = 'Este é um novo parágrafo adicionado'; + document.body.appendChild(pElem); +}); +</pre> + +<p>Neste bloco, as linhas são executadas uma após a outra:</p> + +<ol> + <li>Nós damos referência à um elemento {{htmlelement("button")}} que já está disponível na DOM.</li> + <li>Nós adicionamos um evento de <code><a href="/en-US/docs/Web/API/Element/click_event">click</a></code>, e quando ele for clicado ele fará o seguinte: + <ol> + <li>Mostrar uma mensagem no <code><a href="/en-US/docs/Web/API/Window/alert">alert()</a></code>.</li> + <li>Uma vez que o alert for dispensado, nós criamos um elemento {{htmlelement("p")}}.</li> + <li>Depois nós o preenchemos com um texto.</li> + <li>E finalmente, o adicionamos no body.</li> + </ol> + </li> +</ol> + +<p>Enquanro cada operação é processada, nada mais pode acontecer — a renderização é pausada. Isso acontece porque o JavaScript opera em uma única thread (<a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts#JavaScript_is_single_threaded">JavaScript é single threaded</a>). Apenas uma coisa pode acontecer por vez, em uma única thread principal, e tudo é bloqueado até que a operação seja concluída.</p> + +<p>Então, no exemplo acima, depois que você tenha clicado no botão, o parágrafo não vai aparecer até que o botão OK do alert seja pressionado. Tente isso com o botão a seguir:</p> + +<div class="hidden"> +<pre class="brush: html"><<span class="pl-ent">button</span>>Clique em mim</<span class="pl-ent">button</span>></pre> +</div> + +<p>{{EmbedLiveSample('Synchronous_JavaScript', '100%', '70px')}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: É importante lembrar que, mesmo sendo muito útil para demonstar uma situação de blocking, o <code><a href="/en-US/docs/Web/API/Window/alert">alert()</a></code> não é de bom uso em aplicativos reais.</p> +</div> + +<h2 id="Asynchronous_JavaScript">Asynchronous JavaScript</h2> + +<p>Por razões esclarecidas anteriormente (e.g. relativas ao blocking), muitas funcionalidades de APIs da Web agora usam código assíncrono na execução, especialmente aquelas que acessam ou buscam algum tipo de recurso de um dispositivo externo, como pegar um arquivo da rede, acessar um banco de dados e retornar dados dele, acessar uma stream de uma web cam, ou transmitir uma tela para um dispositivo VR.</p> + +<p>Por que é tão difícil trabalhar com isso usando códigos síncronos? Vamos dar uma olhada em um exemplo rápido. Quando você pega uma imagem de um servidor, você não pode retornar o resultado imediatamente. Isso significa que o pseudocódigo a seguir não poderia funcionar:</p> + +<pre class="brush: js">let resposta = fetch('myImage.png'); +let blob = resposta.blob(); +// Mostra sua imagem na UI</pre> + +<p>Isso acontece por que você não sabe quanto tempo a imagem levará para ser baixada, então quando você executar a segunda linha, ela vai resultar em um erro (provalvelmente sempre) porque a <code>resposta</code> não estará disponível ainda. Você precisa que o seu código espere até que a <code>resposta</code> seja retornada antes de fazer algo com ela.</p> + +<p>Existem dois tipos principais de estilo de código assíncrono que você encontrará no código JavaScript, as callbacks com um estilo old-school e código em um estilo das promises mais recente. Nas seções abaixo, revisaremos cada um deles por vez.</p> + +<h2 id="Callbacks_assíncronas">Callbacks assíncronas</h2> + +<p>Callback são funções que são passada como parâmetros na chamada de outra função que vai executar código por trás do panos. Quando esse código por trás dos panos terminar de ser executado, a função callback será chamada para te informar que a tarefa foi finalizada ou que algo do seu interesse aconteceu. O uso das callbacks é um pouco antiquado agora, mas você ainda pode vê-las em um número de APIs comumente usadas.</p> + +<p>Um exemplo de uma callback async é o segundo parâmetro do método {{domxref("EventTarget.addEventListener", "addEventListener()")}} (como vimos em ação anteriormente):</p> + +<pre class="brush: js">btn.addEventListener('click', () => { + alert('Você clicou em mim!'); + + let pElem = document.createElement('p'); + pElem.textContent = 'Este é um novo parágrafo.'; + document.body.appendChild(pElem); +});</pre> + +<p>O primeiro parâmetro é o tipo de evento a ser executado e o segundo parâmetro é uma função callback que é chamada quando o evento é disparado.</p> + +<p>Quando passamos uma função callback como um parâmetro em outra função, nós apenas estamos passando a rêferencia da função como argumento, ou seja, a função callback <strong>não</strong><strong> é</strong> executada imediatamente. Ela é chamada de volta assíncronamente dentro do corpo da função que a contém, que é responsável por executar a função callback quando for necessário.</p> + +<p>Você pode escrever a sua própria função que contém uma callback facilmente. Vamos dar uma olhada em outro exemplo que carrega uma arquivo usando a <a href="/en-US/docs/Web/API/XMLHttpRequest">API <code>XMLHttpRequest</code> </a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html">veja aqui</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html">veja o código fonte</a>):</p> + +<pre class="brush: js">function loadAsset(url, type, callback) { + let xhr = new XMLHttpRequest(); + xhr.open('GET', url); + xhr.responseType = type; + + xhr.onload = function() { + callback(xhr.response); + }; + + xhr.send(); +} + +function displayImage(blob) { + let objectURL = URL.createObjectURL(blob); + + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +} + +loadAsset('coffee.jpg', 'blob', displayImage);</pre> + +<p>Aqui nós criamos uma função <code>displayImage()</code> que simplesmente representa um blob que foi passada à ela como uma URL de objeto, e depois cria uma imagem para mostrar a URL, adicionando-a ao <code><body></code> do documento. Entretando, nós criamos depois uma função <code>loadAsset()</code> que pega uma callback como parâmetro, junto com uma URL a ser buscada e um tipo para o conteúdo. Ela usa o <code>XMLHttpRequest</code> (abreviação: "XHR") para buscar o recurso na URL dada, para depois passar a resposta para a callback para fazer algo com isso. Neste caso a callback está esperando o XHR terminar de baixar o recurso (usando o manipulador de eventos <code><a href="/en-US/docs/Web/API/XMLHttpRequestEventTarget/onload">onload</a></code>) antes de passá-lo para a callback.</p> + +<p>Callback são versáteis — elas não apenas lhe permitem controlar a ordem em que as funções são executadas e quais dados são passados entre elas, elas também podem passar dados para diferentes funçoes dependendo das circunstâncias. Então você pode ter ações diferentes para executar na resposta baixada, como <code>processJSON()</code>, <code>displayText()</code>, etc.</p> + +<p>Note que nem todas as callback são assíncronas — algumas são executadas de um modo síncrono. Um exemplo é quando nós usamos o método {{jsxref("Array.prototype.forEach()")}} para iterar sobre os itens de uma array (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/foreach.html">veja aqui</a>, e a <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/foreach.html">fonte</a>):</p> + +<pre class="brush: js">const gods = ['Apollo', 'Artemis', 'Ares', 'Zeus']; + +gods.forEach(function (eachName, index){ + console.log(index + '. ' + eachName); +});</pre> + +<p>Neste exemplo nós iteramos sobra uma array de Deuses Gregos e imprimos o índice e seus valores no console. O parâmetro de <code>forEach()</code> é uma callback function, que por si só toma dois parâmetros: uma refêrencia ao nome da array e e os valores dos índices. Entretanto, ela não espera por algo para fazer a execução, pois isso acontece imediatamente</p> + +<h2 id="Promises">Promises</h2> + +<p>Promises são uma nova maneira de escrever código assíncrono que você verá em APIs Web modernas. Um bom exemplo disso é a API <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch">fetch()</a></code>, que é basicamente uma versão mais moderna e eficiente de {{domxref("XMLHttpRequest")}}. Vamos dar uma olhada em um exemplo rápido, do nosso artigo de <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Pegando dados do servidor</a>:</p> + +<pre class="brush: js">fetch('products.json').then(function(response) { + return response.json(); +}).then(function(json) { + products = json; + initialize(); +}).catch(function(err) { + console.log('Fetch problem: ' + err.message); +});</pre> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Você pode encontrar a versão finalizada no GitHub (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store-xhr/can-script.js">veja aqui</a>, e também <a href="https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store-xhr/">seja a execução</a>).</p> +</div> + +<p>Aqui nós vemos <code>fetch</code><code>()</code> pegando um único parâmetro — a URL de um recurso que você quer pegar da rede — e retornando uma <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promise</a>. A promise é um objeto que representa a conclusão ou falha da operação assíncrona. Ela represente um estado intermediário, por assim dizer. É praticamente o jetio do navegador de dizer "Eu prometo voltar para você com a resposta o mais rápido possível", daí o nome "promessa".</p> + +<p>Você pode levar um tempo para se acostumar com esse conceito; Ele se parece um pouco com o {{interwiki("wikipedia", "Gato de Schrödinger")}} em ação. Nenhum dos possíveis resultados aconteceu ainda, então a operação fetch está esperando pelo resultado do navegador que vai completar a operação em algum ponto no futuro.</p> + +<p>Nós temos três blocos de código encadeados ao fim do <code>fetch()</code>:</p> + +<ul> + <li>Dois blocos <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">then()</a></code>. Ambos contém uma função callback que será executada se a operação anterior for executada, então você pode fazer algo com o resultado. Cada bloco <code>.then()</code> retorna outra promise, o que significa que você pode encadear múltiplos blocos <code>.then()</code> um ao outro, para que múltiplas operações assíncronas possam ser executadas uma atrás da outra.</li> + <li>O bloco <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch">catch()</a></code> no final será executado em casos em que erros ocorrem quando um dos <code>.then()</code> falhe — de um modo similar aos blocos <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/try...catch">try...catch</a></code> síncronos, um objeto de erro fica disponível dentro do <code>catch()</code>, e pode ser usado para reportar erros que ocorreram. Note que o bloco <code>try...catch</code> não funcionará com promises, embora funcione com <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">async/await</a>, como você aprenderá mais adiante.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Você vai aprender mais sobre promises mais tarde no módulo, então não se preocupe se você não entendeu muito bem.</p> +</div> + +<h3 id="A_fila_de_eventos">A fila de eventos</h3> + +<p>Operações assíncronas como as promises são colocadas em uma <strong>fila de eventos</strong>, que é executada depois que a main thread terminar de ser processada. As operações serão completadas assim que for possível e depois retornam seus resultados para o ambiente JavaScript.</p> + +<h3 id="Promises_versus_callbacks">Promises versus callbacks</h3> + +<p>As promises tem algumas semelhanças com as callbacks. Elas são basicamente um objeto retornado em que você vincula funções callback, ao invés de passar as callbacks para uma função.</p> + +<p>Entretanto, as promises são feitas especificamente para lidarmos com operações async, e ter muitas vantagens sobre as velhas callbacks:</p> + +<ul> + <li>Você pode encadear múltiplas operações assíncronas usando múltiplos blocos <code>.then()</code>, passando o resultado de uma delas como o resultado como parâmetro da próxima operação. Isso é muito mais difícil de se fazer usando as callback, que normalmente termina em algo chamado de <a href="http://callbackhell.com/">callback hell</a>.</li> + <li>As callbacks das promises sempre são chamadas na ordem estrita em quesão colocadas na fila de eventos.</li> + <li>O tratamento de erros é muito melhor — todos os erros são tratados por um único bloco <code>.catch()</code> no final do encadeamento, ao invés de ser tratado individualmente em cada função callback.</li> + <li>Promessas evitam inversão de controle. Ao contrário das callbacks, que perdem totalmente o controle de como a função será executada quando passada para uma biblioteca de terceiros.</li> +</ul> + +<h2 id="A_natureza_do_código_assíncrono">A natureza do código assíncrono</h2> + +<p>Vamos explorar um exemplo que ilustra a natureza do código assíncrono, mostrando o que pode acontecer quando nós não estamos cientes da ordem de execução e dos problemas em tentar tratar código async como código síncrono. O exemplo a seguir é muito similar ao que vimos antes (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync.html">veja aqui</a>, e <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html">a fonte</a>). Uma diferença e que nós icluimos um número de declarações {{domxref("console.log()")}} para ilustrar na ordem que você pensa que o código fosse executado.</p> + +<pre class="brush: js">console.log ('Starting'); +let image; + +fetch('coffee.jpg').then((response) => { + console.log('It worked :)') + return response.blob(); +}).then((myBlob) => { + let objectURL = URL.createObjectURL(myBlob); + image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +}).catch((error) => { + console.log('There has been a problem with your fetch operation: ' + error.message); +}); + +console.log ('All done!');</pre> + +<p>O navegador vai começar a executar o código, veja a primeira declaração <code>console.log()</code>(<code>Starting</code>) e a execute, e depois crie a variável <code>image</code>.</p> + +<p>Depois a segunda linha vai começar a ser executada começando com o bloco <code>fetch()</code>, mas desde que <code>fetch()</code> é executado assíncronamente sem bloquear nada, a execução do código continua mesmo depois do código promise, alcançando a última declaração <code>console.log()</code>(<code>All done!</code>) e imprimindo a no console.</p> + +<p>Uma vez que o bloco <code>fetch()</code> tenha terminado a sua execução e retornado seu resultado com os blocos <code>.then()</code>, nós finalmente veremos a segunda mensagem <code>console.log()</code> (<code>It worked :)</code>) appear. Então as mensagens aparecem nessa ordem:</p> + +<ul> + <li>Starting</li> + <li>All done!</li> + <li>It worked :)</li> +</ul> + +<p>Se isso te deixa confuso, então considere o exemplo a seguir:</p> + +<pre class="brush: js">console.log("registering click handler"); + +button.addEventListener('click', () => { + console.log("get click"); +}); + +console.log("all done");</pre> + +<p>Isso é bem similar no comportamento — a primeira e a terceira mensagens <code>console.log()</code> são mostradas imediatamente, mas a segunda está bloqueada até alguém clique no botão. O exemplo anterior funciona da mesma forma, exceto que no caso a segunda mensagem está bloqueada na promise pegando um recurso e depois o mostra na tela.</p> + +<p>Em um exemplo mais superficial, esse tipo de configuração poderia causar um problema — você não pode incluir um bloco async que retorna um resultado, que depois depende de um código síncrono. Você não pode garantir que a função async vai retornar antes que o navegador processou o bloco síncrono.</p> + +<p>Para ver isso em ação, tente fazer uma cópia local do <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html">nosso exemplo</a>, e mudar o terceiro <code>console.log()</code> para o seguinte:</p> + +<pre class="brush: js">console.log ('Tudo Feito! ' + image.src + 'mostrada.');</pre> + +<p>Agora você deve ter um erro no seu console ao invés da terceira mensagem:</p> + +<pre><span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body">TypeError: image is undefined; can't access its "src" property</span></span></span></pre> + +<p>Isso acontece porque o navegador tenta executar o terceiro <code>console.log()</code> e o bloco <code>fetch()</code> não terminou de ser executado e não foi dado um valor para a variável <code>image</code>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>:Por razões de segurança, você não pode usar o <code>fetch()</code> com arquivos do seu sistema local (ou executar operações localmente); para executar o exemplo acima você teria que rodá-lo em um <a href="/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server">servidor local</a>.</p> +</div> + +<h2 id="Aprendizado_ativo_faça_tudo_async!">Aprendizado ativo: faça tudo async!</h2> + +<p>Faça que o exemplo problemático de <code>fetch()</code> imprima três mensagens <code>console.log()</code> na tela na ordem desejada, você pode fazer a útima declaração <code>console.log()</code> assíncrona também. Isso pode ser feito colocando ela em outro bloco <code>.then()</code> encadeamo no final do segundo bloco, ou por simplesmente movê-lo para dentro do segundo bloco <code>then()</code>.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you get stuck, you can <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync-fixed.html">find an answer here</a> (see it <a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync-fixed.html">running live</a> also). You can also find a lot more information on promises in our <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a> guide, later on in the module.</p> +</div> + +<h2 id="Conclusion">Conclusion</h2> + +<p>In its most basic form, JavaScript is a synchronous, blocking, single-threaded language, in which only one operation can be in progress at a time. But web browsers define functions and APIs that allow us to register functions that should not be executed synchronously, and should instead be invoked asynchronously when some kind of event occurs (the passage of time, the user's interaction with the mouse, or the arrival of data over the network, for example). This means that you can let your code do several things at the same time without stopping or blocking your main thread.</p> + +<p>Whether we want to run code synchronously or asynchronously will depend on what we're trying to do.</p> + +<p>There are times when we want things to load and happen right away. For example when applying some user-defined styles to a webpage you'll want the styles to be applied as soon as possible.</p> + +<p>If we're running an operation that takes time however, like querying a database and using the results to populate templates, it is better to push this off the main thread and complete the task asynchronously. Over time, you'll learn when it makes more sense to choose an asynchronous technique over a synchronous one.</p> + +<ul> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">General asynchronous programming concepts</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Making asynchronous programming easier with async and await</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choosing the right approach</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/asynchronous/promises/index.html b/files/pt-br/learn/javascript/asynchronous/promises/index.html new file mode 100644 index 0000000000..1fdd746d9d --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/promises/index.html @@ -0,0 +1,586 @@ +--- +title: Programação elegante com Promises +slug: Learn/JavaScript/Asynchronous/Promises +translation_of: Learn/JavaScript/Asynchronous/Promises +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}</div> + +<p class="summary"><strong>Promises </strong>são uma nova implementação do JavaScript que permite você adiar ações até que determinada ação finalize. Isso é realmente bastante útil para uma sequência de operações assíncronas trabalharem corretamente. Neste artigo irá mostrar para você como Promises trabalham, como elas são usadas em web APIs e como escrever a sua Promise.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Conhecimentos básicos em informática, um básico entendimento do JavaScript e seus fundamentos.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender promises e como elas funcionam.</td> + </tr> + </tbody> +</table> + + + +<h2 id="O_que_são_promises">O que são promises?</h2> + +<p>Nós vimos apenas um resumo do que são <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a> até agora, a partir daqui iremos explorar mais a fundo sobre elas.</p> + +<p>Essencialmente, uma Promise é um objeto que representa um estado intermediário de uma operação — de fato, uma <em>promessa</em> que um resultado irá ser retornado em um ponto no futuro, mas isso não é garantia de que o resultado estará disponível, ou a promise falhará, o código será executado em ordem para fazer alguma coisa que o resultado seja sucesso, ou tratar uma falha.</p> + +<p>Generally you are less interested in the amount of time an async operation will take to return its result (unless of course it takes <em>far</em> too long!), and more interested in being able to respond to it being returned, whenever that is. And of course, it's nice that it doesn't block the rest of the code execution.</p> + +<p>One of the most common engagements you'll have with promises is with web APIs that return a promise. Let's consider a hypothetical video chat application. The application has a window with a list of the user's friends, and clicking on a button next to a user starts a video call to that user.</p> + +<p>That button's handler calls {{domxref("MediaDevices.getUserMedia", "getUserMedia()")}} in order to get access to the user's camera and microphone. Since <code>getUserMedia()</code> has to ensure that the user has permission to use those devices <em>and</em> ask the user which microphone to use and which camera to use (or whether to be a voice only call, among other possible options), it can block until not only all of those decisions are made, but also the camera and microphone have been engaged. In addition, the user may not respond immediately to these permission requests. This can potentially take a long time.</p> + +<p>Since the call to <code>getUserMedia()</code> is made from the browser's main thread, the entire browser is blocked until <code>getUserMedia()</code> returns! Obviously, that's not an acceptable option; without promises, everything in the browser becomes unusable until the user decides what to do about the camera and microphone. So instead of waiting for the user, getting the chosen devices enabled, and directly returning the {{domxref("MediaStream")}} for the stream created from the selected sources, <code>getUserMedia()</code> returns a {{jsxref("promise")}} which is resolved with the {{domxref("MediaStream")}} once it's available.</p> + +<p>The code that the video chat application would use might look something like this:</p> + +<pre class="brush: js notranslate">function handleCallButton(evt) { + setStatusMessage("Calling..."); + navigator.mediaDevices.getUserMedia({video: true, audio: true}) + .then(chatStream => { + selfViewElem.srcObject = chatStream; + chatStream.getTracks().forEach(track => myPeerConnection.addTrack(track, chatStream)); + setStatusMessage("Connected"); + }).catch(err => { + setStatusMessage("Failed to connect"); + }); +} +</pre> + +<p>This function starts by using a function called <code>setStatusMessage()</code> to update a status display with the message "Calling...", indicating that a call is being attempted. It then calls <code>getUserMedia()</code>, asking for a stream that has both video and audio tracks, then once that's been obtained, sets up a video element to show the stream coming from the camera as a "self view," then takes each of the stream's tracks and adds them to the <a href="/en-US/docs/Web/API/WebRTC_API">WebRTC</a> {{domxref("RTCPeerConnection")}} representing a connection to another user. After that, the status display is updated to say "Connected".</p> + +<p>If <code>getUserMedia()</code> fails, the <code>catch</code> block runs. This uses <code>setStatusMessage()</code> to update the status box to indicate that an error occurred.</p> + +<p>The important thing here is that the <code>getUserMedia()</code> call returns almost immediately, even if the camera stream hasn't been obtained yet. Even if the <code>handleCallButton()</code> function has already returned to the code that called it, when <code>getUserMedia()</code> has finished working, it calls the handler you provide. As long as the app doesn't assume that streaming has begun, it can just keep on running.</p> + +<div class="blockIndicator note"> +<p><strong>Note:</strong> You can learn more about this somewhat advanced topic, if you're interested, in the article <a href="/docs/Web/API/WebRTC_API/Signaling_and_video_calling">Signaling and video calling</a>. Code similar to this, but much more complete, is used in that example.</p> +</div> + +<h2 id="The_trouble_with_callbacks">The trouble with callbacks</h2> + +<p>To fully understand why promises are a good thing, it helps to think back to old-style callbacks, and to appreciate why they are problematic.</p> + +<p>Let's talk about ordering pizza as an analogy. There are certain steps that you have to take for your order to be successful, which don't really make sense to try to execute out of order, or in order but before each previous step has quite finished:</p> + +<ol> + <li>You choose what toppings you want. This can take a while if you are indecisive, and may fail if you just can't make up your mind, or decide to get a curry instead.</li> + <li>You then place your order. This can take a while to return a pizza, and may fail if the restaurant does not have the required ingredients to cook it.</li> + <li>You then collect your pizza and eat. This might fail if, say, you forgot your wallet so can't pay for the pizza!</li> +</ol> + +<p>With old-style <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing#Callbacks">callbacks</a>, a pseudo-code representation of the above functionality might look something like this:</p> + +<pre class="brush: js notranslate">chooseToppings(function(toppings) { + placeOrder(toppings, function(order) { + collectOrder(order, function(pizza) { + eatPizza(pizza); + }, failureCallback); + }, failureCallback); +}, failureCallback);</pre> + +<p>This is messy and hard to read (often referred to as "callback hell"), requires the <code>failureCallback()</code> to be called multiple times (once for each nested function), with other issues besides.</p> + +<h3 id="Improvements_with_promises">Improvements with promises</h3> + +<p>Promises make situations like the above much easier to write, parse, and run. If we represented the above pseudo-code using asynchronous promises instead, we'd end up with something like this:</p> + +<pre class="brush: js notranslate">chooseToppings() +.then(function(toppings) { + return placeOrder(toppings); +}) +.then(function(order) { + return collectOrder(order); +}) +.then(function(pizza) { + eatPizza(pizza); +}) +.catch(failureCallback);</pre> + +<p>This is much better — it is easier to see what is going on, we only need a single <code>.catch()</code> block to handle all the errors, it doesn't block the main thread (so we can keep playing video games while we wait for the pizza to be ready to collect), and each operation is guaranteed to wait for previous operations to complete before running. We're able to chain multiple asynchronous actions to occur one after another this way because each <code>.then()</code> block returns a new promise that resolves when the <code>.then()</code> block is done running. Clever, right?</p> + +<p>Using arrow functions, you can simplify the code even further:</p> + +<pre class="brush: js notranslate">chooseToppings() +.then(toppings => + placeOrder(toppings) +) +.then(order => + collectOrder(order) +) +.then(pizza => + eatPizza(pizza) +) +.catch(failureCallback);</pre> + +<p>Or even this:</p> + +<pre class="brush: js notranslate">chooseToppings() +.then(toppings => placeOrder(toppings)) +.then(order => collectOrder(order)) +.then(pizza => eatPizza(pizza)) +.catch(failureCallback);</pre> + +<p>This works because with arrow functions <code>() => x</code> is valid shorthand for <code>() => { return x; }</code>.</p> + +<p>You could even do this, since the functions just pass their arguments directly, so there isn't any need for that extra layer of functions:</p> + +<pre class="brush: js notranslate">chooseToppings().then(placeOrder).then(collectOrder).then(eatPizza).catch(failureCallback);</pre> + +<p>This is not quite as easy to read, however, and this syntax might not be usable if your blocks are more complex than what we've shown here.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You can make further improvements with <code>async</code>/<code>await</code> syntax, which we'll dig into in the next article.</p> +</div> + +<p>At their most basic, promises are similar to event listeners, but with a few differences:</p> + +<ul> + <li>A promise can only succeed or fail once. It cannot succeed or fail twice and it cannot switch from success to failure or vice versa once the operation has completed.</li> + <li>If a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called, even though the event took place earlier.</li> +</ul> + +<h2 id="Explaining_basic_promise_syntax_A_real_example">Explaining basic promise syntax: A real example</h2> + +<p>Promises are important to understand because most modern Web APIs use them for functions that perform potentially lengthy tasks. To use modern web technologies you'll need to use promises. Later on in the chapter we'll look at how to write your own promise, but for now we'll look at some simple examples that you'll encounter in Web APIs.</p> + +<p>In the first example, we'll use the <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch">fetch()</a></code> method to fetch an image from the web, the {{domxref("Body.blob", "blob()")}} method to transform the fetch response's raw body contents into a {{domxref("Blob")}} object, and then display that blob inside an {{htmlelement("img")}} element. This is very similar to the example we looked at in the <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing#Asynchronous_JavaScript">first article of the series</a>, but we'll do it a bit differently as we get you building your own promise-based code.</p> + +<ol> + <li> + <p>First of all, download our <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">simple HTML template</a> and the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/coffee.jpg">sample image file</a> that we'll fetch.</p> + </li> + <li> + <p>Add a {{htmlelement("script")}} element at the bottom of the HTML {{htmlelement("body")}}.</p> + </li> + <li> + <p>Inside your {{HTMLElement("script")}} element, add the following line:</p> + + <pre class="brush: js notranslate">let promise = fetch('coffee.jpg');</pre> + + <p>This calls the <code>fetch()</code> method, passing it the URL of the image to fetch from the network as a parameter. This can also take an options object as a optional second parameter, but we are just using the simplest version for now. We are storing the promise object returned by <code>fetch()</code> inside a variable called <code>promise</code>. As we said before, this object represents an intermediate state that is initially neither success or failure — the official term for a promise in this state is <strong>pending</strong>.</p> + </li> + <li> + <p>To respond to the successful completion of the operation whenever that occurs (in this case, when a {{domxref("Response")}} is returned), we invoke the <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">.then()</a></code> method of the promise object. The callback inside the <code>.then()</code> block (referred to as the <strong>executor</strong>) runs only when the promise call completes successfully and returns the {{domxref("Response")}} object — in promise-speak, when it has been <strong>fulfilled</strong>. It is passed the returned {{domxref("Response")}} object as a parameter.</p> + + <div class="blockIndicator note"> + <p><strong>Note</strong>: The way that a <code>.then()</code> block works is similar to when you add an event listener to an object using <code>AddEventListener()</code>. It doesn't run until an event occurs (when the promise fulfills). The most notable difference is that a .then() will only run once for each time it is used, whereas an event listener could be invoked multiple times.</p> + </div> + + <p>We immediately run the <code>blob()</code> method on this response to ensure that the response body is fully downloaded, and when it is available transform it into a <code>Blob</code> object that we can do something with. The result of this is returned like so:</p> + + <pre class="brush: js notranslate">response => response.blob()</pre> + + <p>which is shorthand for</p> + + <pre class="brush: js notranslate">function(response) { + return response.blob(); +}</pre> + + <p>OK, enough explanation for now. Add the following line below your first line of JavaScript.</p> + + <pre class="brush: js notranslate">let promise2 = promise.then(response => response.blob());</pre> + </li> + <li> + <p>Each call to <code>.then()</code> creates a new promise. This is very useful; because the <code>blob()</code> method also returns a promise, we can handle the <code>Blob</code> object it returns on fulfillment by invoking the <code>.then()</code> method of the second promise. Because we want to do something a bit more complex to the blob than just run a single method on it and return the result, we'll need to wrap the function body in curly braces this time (otherwise it'll throw an error).</p> + + <p>Add the following to the end of your code:</p> + + <pre class="brush: js notranslate">let promise3 = promise2.then(myBlob => { + +})</pre> + </li> + <li> + <p>Now let's fill in the body of the executor function. Add the following lines inside the curly braces:</p> + + <pre class="brush: js notranslate">let objectURL = URL.createObjectURL(myBlob); +let image = document.createElement('img'); +image.src = objectURL; +document.body.appendChild(image);</pre> + + <p>Here we are running the {{domxref("URL.createObjectURL()")}} method, passing it as a parameter the <code>Blob</code> returned when the second promise fulfills. This will return a URL pointing to the object. Then we create an {{htmlelement("img")}} element, set its <code>src</code> attribute to equal the object URL and append it to the DOM, so the image will display on the page!</p> + </li> +</ol> + +<p>If you save the HTML file you've just created and load it in your browser, you'll see that the image is displayed in the page as expected. Good work!</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You will probably notice that these examples are somewhat contrived. You could just do away with the whole <code>fetch()</code> and <code>blob()</code> chain, and just create an <code><img></code> element and set its <code>src</code> attribute value to the URL of the image file, <code>coffee.jpg</code>. We did however pick this example because it demonstrates promises in a nice simple fashion, rather than for its real world appropriateness.</p> +</div> + +<h3 id="Responding_to_failure">Responding to failure</h3> + +<p>There is something missing — currently there is nothing to explicitly handle errors if one of the promises fails (<strong>rejects</strong>, in promise-speak). We can add error handling by running the <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch">.catch()</a></code> method of the previous promise. Add this now:</p> + +<pre class="brush: js notranslate">let errorCase = promise3.catch(e => { + console.log('There has been a problem with your fetch operation: ' + e.message); +});</pre> + +<p>To see this in action, try misspelling the URL to the image and reloading the page. The error will be reported in the console of your browser's developer tools.</p> + +<p>This doesn't do much more than it would if you just didn't bother including the <code>.catch()</code> block at all, but think about it — this allows us to control error handling exactly how we want. In a real app, your <code>.catch()</code> block could retry fetching the image, or show a default image, or prompt the user to provide a different image URL, or whatever.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You can see <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/simple-fetch.html">our version of the example live</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch.html">source code</a> also).</p> +</div> + +<h3 id="Chaining_the_blocks_together">Chaining the blocks together</h3> + +<p>This is a very longhand way of writing this out; we've deliberately done this to help you understand what is going on clearly. As shown earlier on in the article, you can chain together <code>.then()</code> blocks (and also <code>.catch()</code> blocks). The above code could also be written like this (see also <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch-chained.html">simple-fetch-chained.html</a> on GitHub):</p> + +<pre class="brush: js notranslate">fetch('coffee.jpg') +.then(response => response.blob()) +.then(myBlob => { + let objectURL = URL.createObjectURL(myBlob); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +}) +.catch(e => { + console.log('There has been a problem with your fetch operation: ' + e.message); +});</pre> + +<p>Bear in mind that the value returned by a fulfilled promise becomes the parameter passed to the next <code>.then()</code> block's executor function.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: <code>.then()</code>/<code>.catch()</code> blocks in promises are basically the async equivalent of a <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/try...catch">try...catch</a></code> block in sync code. Bear in mind that synchronous <code>try...catch</code> won't work in async code.</p> +</div> + +<h2 id="Promise_terminology_recap">Promise terminology recap</h2> + +<p>There was a lot to cover in the above section, so let's go back over it quickly to give you a <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises#Promise_terminology_recap">short guide that you can bookmark</a> and use to refresh your memory in the future. You should also go over the above section again a few more time to make sure these concepts stick.</p> + +<ol> + <li>When a promise is created, it is neither in a success or failure state. It is said to be <strong>pending</strong>.</li> + <li>When a promise returns, it is said to be <strong>resolved</strong>. + <ol> + <li>A successfully resolved promise is said to be <strong>fulfilled</strong>. It returns a value, which can be accessed by chaining a <code>.then()</code> block onto the end of the promise chain. The executor function inside the <code>.then()</code> block will contain the promise's return value.</li> + <li>An unsuccessful resolved promise is said to be <strong>rejected</strong>. It returns a <strong>reason</strong>, an error message stating why the promise was rejected. This reason can be accessed by chaining a <code>.catch()</code> block onto the end of the promise chain.</li> + </ol> + </li> +</ol> + +<h2 id="Running_code_in_response_to_multiple_promises_fulfilling">Running code in response to multiple promises fulfilling</h2> + +<p>The above example showed us some of the real basics of using promises. Now let's look at some more advanced features. For a start, chaining processes to occur one after the other is all fine, but what if you want to run some code only after a whole bunch of promises have <em>all</em> fulfilled?</p> + +<p>You can do this with the ingeniously named <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all">Promise.all()</a></code> static method. This takes an array of promises as an input parameter and returns a new <code>Promise</code> object that will fulfill only if and when <em>all</em> promises in the array fulfill. It looks something like this:</p> + +<pre class="brush: js notranslate">Promise.all([a, b, c]).then(values => { + ... +});</pre> + +<p>If they all fulfill, then chained <code>.then()</code> block's executor function will be passed an array containing all those results as a parameter. If any of the promises passed to <code>Promise.all()</code> reject, the whole block will reject.</p> + +<p>This can be very useful. Imagine that we’re fetching information to dynamically populate a UI feature on our page with content. In many cases, it makes sense to receive all the data and only then show the complete content, rather than displaying partial information.</p> + +<p>Let's build another example to show this in action.</p> + +<ol> + <li> + <p>Download a fresh copy of our <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">page template</a>, and again put a <code><script></code> element just before the closing <code></body></code> tag.</p> + </li> + <li> + <p>Download our source files (<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/coffee.jpg">coffee.jpg</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/tea.jpg">tea.jpg</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/description.txt">description.txt</a>), or feel free to substitute your own.</p> + </li> + <li> + <p>In our script we'll first define a function that returns the promises we want to send to <code>Promise.all()</code>. This would be easy if we just wanted to run the <code>Promise.all()</code> block in response to three <code>fetch()</code> operations completing. We could just do something like:</p> + + <pre class="brush: js notranslate">let a = fetch(url1); +let b = fetch(url2); +let c = fetch(url3); + +Promise.all([a, b, c]).then(values => { + ... +});</pre> + + <p>When the promise is fulfilled, the <code>values</code> passed into the fullfillment handler would contain three <code>Response</code> objects, one for each of the <code>fetch()</code> operations that have completed.</p> + + <p>However, we don't want to do this. Our code doesn't care when the <code>fetch()</code> operations are done. Instead, what we want is the loaded data. That means we want to run the <code>Promise.all()</code> block when we get back usable blobs representing the images, and a usable text string. We can write a function that does this; add the following inside your <code><script></code> element:</p> + + <pre class="brush: js notranslate">function fetchAndDecode(url, type) { + return fetch(url).then(response => { + if (type === 'blob') { + return response.blob(); + } else if (type === 'text') { + return response.text(); + } + }) + .catch(e => { + console.log('There has been a problem with your fetch operation: ' + e.message); + }); +}</pre> + + <p>This looks a bit complex, so let's run through it step by step:</p> + + <ol> + <li>First of all we define the function, passing it a URL and a string representing the type of resource it is fetching.</li> + <li>Inside the function body, we have a similar structure to what we saw in the first example — we call the <code>fetch()</code> function to fetch the resource at the specified URL, then chain it onto another promise that returns the decoded (or "read") response body. This was always the <code>blob()</code> method in the previous example.</li> + <li>However, two things are different here: + <ul> + <li>First of all, the second promise we return is different depending on what the <code>type</code> value is. Inside the executor function we include a simple <code>if ... else if</code> statement to return a different promise depending on what type of file we need to decode (in this case we've got a choice of <code>blob</code> or <code>text</code>, but it would be easy to extend this to deal with other types as well).</li> + <li>Second, we have added the <code>return</code> keyword before the <code>fetch()</code> call. The effect this has is to run the entire chain and then run the final result (i.e. the promise returned by <code>blob()</code> or <code>text()</code>) as the return value of the function we've just defined. In effect, the <code>return</code> statements pass the results back up the chain to the top.</li> + </ul> + </li> + <li> + <p>At the end of the block, we chain on a <code>.catch()</code> call, to handle any error cases that may come up with any of the promises passed in the array to <code>.all()</code>. If any of the promises reject, the catch block will let you know which one had a problem. The <code>.all()</code> block (see below) will still fulfill, but just won't display the resources that had problems. If you wanted the <code>.all</code> to reject, you'd have to chain the <code>.catch()</code> block on to the end of there instead.</p> + </li> + </ol> + + <p>The code inside the function body is async and promise-based, therefore in effect the entire function acts like a promise — convenient.</p> + </li> + <li> + <p>Next, we call our function three times to begin the process of fetching and decoding the images and text, and store each of the returned promises in a variable. Add the following below your previous code:</p> + + <pre class="brush: js notranslate">let coffee = fetchAndDecode('coffee.jpg', 'blob'); +let tea = fetchAndDecode('tea.jpg', 'blob'); +let description = fetchAndDecode('description.txt', 'text');</pre> + </li> + <li> + <p>Next, we will define a <code>Promise.all()</code> block to run some code only when all three of the promises stored above have successfully fulfilled. To begin with, add a block with an empty executor inside the <code>.then()</code> call, like so:</p> + + <pre class="brush: js notranslate">Promise.all([coffee, tea, description]).then(values => { + +});</pre> + + <p>You can see that it takes an array containing the promises as a parameter. The executor will only run when all three promises resolve; when that happens, it will be passed an array containing the results from the individual promises (i.e. the decoded response bodies), kind of like [coffee-results, tea-results, description-results].</p> + </li> + <li> + <p>Last of all, add the following inside the executor. Here we use some fairly simple sync code to store the results in separate variables (creating object URLs from the blobs), then display the images and text on the page.</p> + + <pre class="brush: js notranslate">console.log(values); +// Store each value returned from the promises in separate variables; create object URLs from the blobs +let objectURL1 = URL.createObjectURL(values[0]); +let objectURL2 = URL.createObjectURL(values[1]); +let descText = values[2]; + +// Display the images in <img> elements +let image1 = document.createElement('img'); +let image2 = document.createElement('img'); +image1.src = objectURL1; +image2.src = objectURL2; +document.body.appendChild(image1); +document.body.appendChild(image2); + +// Display the text in a paragraph +let para = document.createElement('p'); +para.textContent = descText; +document.body.appendChild(para);</pre> + </li> + <li> + <p>Save and refresh and you should see your UI components all loaded, albeit in a not particularly attractive way!</p> + </li> +</ol> + +<p>The code we provided here for displaying the items is fairly rudimentary, but works as an explainer for now.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you get stuck, you can compare your version of the code to ours, to see what it is meant to look like — <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-all.html">see it live</a>, and see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html">source code</a>.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you were improving this code, you might want to loop through a list of items to display, fetching and decoding each one, and then loop through the results inside <code>Promise.all()</code>, running a different function to display each one depending on what the type of code was. This would make it work for any number of items, not just three.</p> + +<p>In addition, you could determine what the type of file is being fetched without needing an explicit <code>type</code> property. You could for example check the {{HTTPHeader("Content-Type")}} HTTP header of the response in each case using <code><a href="/en-US/docs/Web/API/Headers/get">response.headers.get("content-type")</a></code>, and then react accordingly.</p> +</div> + +<h2 id="Running_some_final_code_after_a_promise_fulfillsrejects">Running some final code after a promise fulfills/rejects</h2> + +<p>There will be cases where you want to run a final block of code after a promise completes, regardless of whether it fulfilled or rejected. Previously you'd have to include the same code in both the <code>.then()</code> and <code>.catch()</code> callbacks, for example:</p> + +<pre class="brush: js notranslate">myPromise +.then(response => { + doSomething(response); + runFinalCode(); +}) +.catch(e => { + returnError(e); + runFinalCode(); +});</pre> + +<p>In more recent modern browsers, the <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally">.finally()</a></code> method is available, which can be chained onto the end of your regular promise chain allowing you to cut down on code repetition and do things more elegantly. The above code can now be written as follows:</p> + +<pre class="brush: js notranslate">myPromise +.then(response => { + doSomething(response); +}) +.catch(e => { + returnError(e); +}) +.finally(() => { + runFinalCode(); +});</pre> + +<p>For a real example, take a look at our <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-finally.html">promise-finally.html demo</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-finally.html">source code</a> also). This works exactly the same as the <code>Promise.all()</code> demo we looked at in the above section, except that in the <code>fetchAndDecode()</code> function we chain a <code>finally()</code> call on to the end of the chain:</p> + +<pre class="brush: js notranslate">function fetchAndDecode(url, type) { + return fetch(url).then(response => { + if(type === 'blob') { + return response.blob(); + } else if(type === 'text') { + return response.text(); + } + }) + .catch(e => { + console.log(`There has been a problem with your fetch operation for resource "${url}": ` + e.message); + }) + .finally(() => { + console.log(`fetch attempt for "${url}" finished.`); + }); +}</pre> + +<p>This logs a simple message to the console to tell us when each fetch attempt has finished.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: <code>finally()</code> allows you to write async equivalents to try/catch/finally in async code.</p> +</div> + +<h2 id="Building_your_own_custom_promises">Building your own custom promises</h2> + +<p>The good news is that, in a way, you've already built your own promises. When you've chained multiple promises together with <code>.then()</code> blocks, or otherwise combined them to create custom functionality, you are already making your own custom async promise-based functions. Take our <code>fetchAndDecode()</code> function from the previous examples, for example.</p> + +<p>Combining different promise-based APIs together to create custom functionality is by far the most common way you'll do custom things with promises, and shows the flexibility and power of basing most modern APIs around the same principle. There is another way, however.</p> + +<h3 id="Using_the_Promise_constructor">Using the Promise() constructor</h3> + +<p>It is possible to build your own promises using the <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise()</a></code> constructor. The main situation in which you'll want to do this is when you've got code based on an an old-school asynchronous API that is not promise-based, which you want to promis-ify. This comes in handy when you need to use existing, older project code, libraries, or frameworks along with modern promise-based code.</p> + +<p>Let's have a look at a simple example to get you started — here we wrap a <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code> call with a promise — this runs a function after two seconds that resolves the promise (using the passed <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve">resolve()</a></code> call) with a string of "Success!".</p> + +<pre class="brush: js notranslate">let timeoutPromise = new Promise((resolve, reject) => { + setTimeout(function(){ + resolve('Success!'); + }, 2000); +});</pre> + +<p><code>resolve()</code> and <code>reject()</code> are functions that you call to fulfill or reject the newly-created promise. In this case, the promise fulfills with a string of "Success!".</p> + +<p>So when you call this promise, you can chain a <code>.then()</code> block onto the end of it and it will be passed a string of "Success!". In the below code we simply alert that message:</p> + +<pre class="brush: js notranslate">timeoutPromise +.then((message) => { + alert(message); +})</pre> + +<p>or even just</p> + +<pre class="brush: js notranslate">timeoutPromise.then(alert); +</pre> + +<p>Try <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/custom-promise.html">running this live</a> to see the result (also see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/custom-promise.html">source code</a>).</p> + +<p>The above example is not very flexible — the promise can only ever fulfill with a single string, and it doesn't have any kind of <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject">reject()</a></code> condition specified (admittedly, <code>setTimeout()</code> doesn't really have a fail condition, so it doesn't matter for this simple example).</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: Why <code>resolve()</code>, and not <code>fulfill()</code>? The answer we'll give you for now is <em>it's complicated</em>.</p> +</div> + +<h3 id="Rejecting_a_custom_promise">Rejecting a custom promise</h3> + +<p>We can create a promise that rejects using the <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject">reject()</a></code> method — just like <code>resolve()</code>, this takes a single value, but in this case it is the reason to reject with, i.e., the error that will be passed into the <code>.catch()</code> block.</p> + +<p>Let's extend the previous example to have some <code>reject()</code> conditions as well as allowing different messages to be passed upon success.</p> + +<p>Take a copy of the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/custom-promise.html">previous example</a>, and replace the existing <code>timeoutPromise()</code> definition with this:</p> + +<pre class="brush: js notranslate">function timeoutPromise(message, interval) { + return new Promise((resolve, reject) => { + if (message === '' || typeof message !== 'string') { + reject('Message is empty or not a string'); + } else if (interval < 0 || typeof interval !== 'number') { + reject('Interval is negative or not a number'); + } else { + setTimeout(function(){ + resolve(message); + }, interval); + } + }); +};</pre> + +<p>Here we are passing two methods into a custom function — a message to do something with, and the time interval to pass before doing the thing. Inside the function we then return a new <code>Promise</code> object — invoking the function will return the promise we want to use.</p> + +<p>Inside the Promise constructor, we do a number of checks inside <code>if ... else</code> structures:</p> + +<ol> + <li>First of all we check to see if the message is appropriate for being alerted. If it is an empty string or not a string at all, we reject the promise with a suitable error message.</li> + <li>Next, we check to see if the interval is an appropriate interval value. If it is negative or not a number, we reject the promise with a suitable error message.</li> + <li>Finally, if the parameters both look OK, we resolve the promise with the specified message after the specified interval has passed using <code>setTimeout()</code>.</li> +</ol> + +<p>Since the <code>timeoutPromise()</code> function returns a <code>Promise</code>, we can chain <code>.then()</code>, <code>.catch()</code>, etc. onto it to make use of its functionality. Let's use it now — replace the previous <code>timeoutPromise</code> usage with this one:</p> + +<pre class="brush: js notranslate">timeoutPromise('Hello there!', 1000) +.then(message => { + alert(message); +}) +.catch(e => { + console.log('Error: ' + e); +});</pre> + +<p>When you save and run the code as is, after one second you'll get the message alerted. Now try setting the message to an empty string or the interval to a negative number, for example, and you'll be able to see the promise reject with the appropriate error messages! You could also try doing something else with the resolved message rather than just alerting it.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You can find our version of this example on GitHub as <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/custom-promise2.html">custom-promise2.html</a> (see also the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/custom-promise2.html">source code</a>).</p> +</div> + +<h3 id="A_more_real-world_example">A more real-world example</h3> + +<p>The above example was kept deliberately simple to make the concepts easy to understand, but it is not really very async. The asynchronous nature is basically faked using <code>setTimeout()</code>, although it does still show that promises are useful for creating a custom function with sensible flow of operations, good error handling, etc.</p> + +<p>One example we'd like to invite you to study, which does show a useful async application of the <code>Promise()</code> constructor, is <a href="https://github.com/jakearchibald/idb/">Jake Archibald's idb library</a>. This takes the <a href="/en-US/docs/Web/API/IndexedDB_API">IndexedDB API</a>, which is an old-style callback-based API for storing and retrieving data on the client-side, and allows you to use it with promises. If you look at the <a href="https://github.com/jakearchibald/idb/blob/master/lib/idb.js">main library file</a> you'll see the same kind of techniques we discussed above being used there. The following block converts the basic request model used by many IndexedDB methods to use promises:</p> + +<pre class="brush: js notranslate">function promisifyRequest(request) { + return new Promise(function(resolve, reject) { + request.onsuccess = function() { + resolve(request.result); + }; + + request.onerror = function() { + reject(request.error); + }; + }); +}</pre> + +<p>This works by adding a couple of event handlers that fulfill and reject the promise at appropriate times:</p> + +<ul> + <li>When the <code><a href="/en-US/docs/Web/API/IDBRequest">request</a></code>'s <a href="/en-US/docs/Web/API/IDBRequest/success_event"><code>success</code> event</a> fires, the <code><a href="/en-US/docs/Web/API/IDBRequest/onsuccess">onsuccess</a></code> handler fulfills the promise with the request <code><a href="/en-US/docs/Web/API/IDBRequest/result">result</a></code>.</li> + <li>When the <code><a href="/en-US/docs/Web/API/IDBRequest">request</a></code>'s <a href="/en-US/docs/Web/API/IDBRequest/error_event"><code>error</code> event</a> fires, the <code><a href="/en-US/docs/Web/API/IDBRequest/onerror">onerror</a></code> handler rejects the promise with the request <code><a href="/en-US/docs/Web/API/IDBRequest/error">error</a></code>.</li> +</ul> + +<h2 id="Conclusion">Conclusion</h2> + +<p>Promises are a good way to build asynchronous applications when we don’t know the return value of a function or how long it will take to return. They make it easier to express and reason about sequences of asynchronous operations without deeply nested callbacks, and they support a style of error handling that is similar to the synchronous <code>try...catch</code> statement.</p> + +<p>Promises work in the latest versions of all modern browsers; the only place where promise support will be a problem is in Opera Mini and IE11 and earlier versions.</p> + +<p>We didn't touch on all promise features in this article, just the most interesting and useful ones. As you start to learn more about promises, you'll come across further features and techniques.</p> + +<p>Most modern Web APIs are promise-based, so you'll need to understand promises to get the most out of them. Among those APIs are <a href="/en-US/docs/Web/API/WebRTC_API">WebRTC</a>, <a href="/en-US/docs/Web/API/Web_Audio_API">Web Audio API</a>, <a href="/en-US/docs/Web/API/Media_Streams_API">Media Capture and Streams</a>, and many more. Promises will be more and more important as time goes on, so learning to use and understand them is an important step in learning modern JavaScript.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise()</a></code></li> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Using_promises">Using promises</a></li> + <li><a href="https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html">We have a problem with promises</a> by Nolan Lawson</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">General asynchronous programming concepts</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Making asynchronous programming easier with async and await</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choosing the right approach</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/asynchronous/timeouts_and_intervals/index.html b/files/pt-br/learn/javascript/asynchronous/timeouts_and_intervals/index.html new file mode 100644 index 0000000000..2c399201e5 --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/timeouts_and_intervals/index.html @@ -0,0 +1,624 @@ +--- +title: Timeouts e intervalos +slug: Learn/JavaScript/Asynchronous/Timeouts_and_intervals +translation_of: Learn/JavaScript/Asynchronous/Timeouts_and_intervals +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous")}}</div> + +<p class="summary">Este tutorial é sobre os métodos tradicionais que o JavaScript tem disponíveis para executar códigos assíncronamente depois que um dado período de tempo tenha passado, ou em um intervalo (um número de segundos por segundo), discute suas utilidades e considera seus problemas.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Entendimento básico sobre informáticas e fundamentos do JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender loops e intervalos assíncronos e para o que eles servem.</td> + </tr> + </tbody> +</table> + +<h2 id="Introdução">Introdução</h2> + +<p>Por um longo tempo, a plataforma web tem oferecido à programadores JavaScript um número de funções que permitem que eles executem código assíncronamente depois de um determinado intervalo de tempo, e executar um bloco de código de modo assíncrono repetidamente até que você o mande parar.</p> + +<p>Essas funções são:</p> + +<dl> + <dt><code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code></dt> + <dd>Executa um bloco específico uma vez depois de um determinado tempo</dd> + <dt><code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></code></dt> + <dd>Executa um bloco específico repetidamente com um intervalo fixo entre cada chamada.</dd> + <dt><code><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></code></dt> + <dd>Uma versão moderna de <code>setInterval()</code>. Ela executa um bloc de código específico antes do navegador renderizar a tela novamento, permitindo que seja executada em uma taxa de quadros adequada, independentemente do ambiente em que está sendo executado.</dd> +</dl> + +<p>O código executado por estas funções é executado na main thread (depois do dado intervalo).</p> + +<div> +<p>É importante saber que você pode (e irá) executar outros códigos antes que uma chamada <code>setTimeout()</code> é executada, ou entre iterações de <code>setInterval()</code>. Dependendo de como essas operações são intensas, elas podem atrasar o seu código async ainda mais, já que o código async só é executado depois que a main thread terminar seu processamento (ou seja, quando a fila estiver vazia). Você aprenderá mais sobre isso enquanto fazemos nosso progresso neste artigo.</p> +</div> + +<p>De qualquer forma, essas funções são usadas para executar animações constantes e outros processamentos em um web site ou aplicação. Nas seções a seguir, nós vamos te mostrar como elas podem ser usadas.</p> + +<h2 id="setTimeout">setTimeout()</h2> + +<p>Como foi dito anteriormente, o <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code> executa um bloco de código particular depois que um determinado período de tempo passou. Ele toma os seguintes parâmetros:</p> + +<ul> + <li>Uma função a ser executada, ou uma referência de uma função definida em outro lugar.</li> + <li>Um número representando o intervalo de tempo em milissegundos (1000 milissegundos equivalem a 1 segundo) para esperar antes de executar o código. Se você especificar um valor de 0 (ou simplesmente omitir o valor), a função será executada assim que possível (mas não imediatamente).</li> + <li>Zero ou mais valores que representam quaisquer parâmetros que você quiser passar para a função quando ela for executada.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>NOTA:</strong> O tempos especificafo <strong>não</strong> é o tempo garantido de execução, mas sim o tempo míniimo de execução. As callback que você passa para essas funções não podem ser executadas até que a main thread esteja vazia.</p> + +<p>Como consequência, códigos como <code>setTimeout(fn, 0)</code><em> </em>serão executados assim que a fila estiver vazia, <strong>não</strong> imediatamente. Se você executar código como <code>setTimeout(fn, 0)</code> e depois imediatamente executar um loop que conta de 1 a 10 bilhões, sua callback será executada depois de alguns segundos.</p> +</div> + +<p>No exemplo a seguir, o navegador vai esperar dois segundos antes de executar a função anônima, e depois vai mostrar a mensagem de alerta (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">veja aqui</a>, e <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">veja o código</a>):</p> + +<pre class="brush: js notranslate">let myGreeting = setTimeout(function() { + alert('Hello, Mr. Universe!'); +}, 2000)</pre> + +<p>As funções especificadas não tem que ser anônimas. Você pode dar o nome da função, e até mesmo definir ela em outro lugar e passar uma referência para o timeout <code>setTimeout()</code>. As versões a seguir do código são equivalentes à primeira:</p> + +<pre class="brush: js notranslate">// With a named function +let myGreeting = setTimeout(function sayHi() { + alert('Hello, Mr. Universe!'); +}, 2000) + +// With a function defined separately +function sayHi() { + alert('Hello Mr. Universe!'); +} + +let myGreeting = setTimeout(sayHi, 2000);</pre> + +<p>Isso pode ser útil se você tem uma função que precisa ser chamada de um timeout e também em resposta à um evento, por exemplo. Mas também pode servir para manter seu código organizado, especialmente se a callback timetout é mais do que algumas linhas de código.</p> + +<p><code>setTimeout()</code> retorna um valor identificador que pode ser usado para se referir ao timeout depois, como em quando você que pará-lo. Veja {{anch("Cancelando timetous")}} (abaixo) e aprenda como fazer isso.</p> + +<h3 id="Passando_parâmetros_para_uma_função_setTimeout">Passando parâmetros para uma função setTimeout()</h3> + +<p>Quaisquer parâmetros que você quiser passar para a função sendo executada dentro do <code>setTimeout()</code> devem ser passados como parâmetros adicionais no final da lista.</p> + +<p>Por exemplo, você pode mudar a função anterior para que ela diga oi para qualquer nome que foi passada para ela:</p> + +<pre class="brush: js notranslate">function sayHi(who) { + alert(`Hello ${who}!`); +}</pre> + +<p>Agora, você pode passar o nome da pessoa no <code>setTimeout()</code> como um terceiro parâmetro:</p> + +<pre class="brush: js notranslate">let myGreeting = setTimeout(sayHi, 2000, 'Mr. Universe');</pre> + +<h3 id="Cancelando_timeouts">Cancelando timeouts</h3> + +<p>Finalmente, se um timeout foi criado, você pode cancelá-lo antes que o tempo especificado tenha passado chamando <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearTimeout">clearTimeout()</a></code>, passando para o identificador a chamada <code>setTimeout()</code> como um parâmetreo. então para cancelar o timeout acima, você fará isso:</p> + +<pre class="brush: js notranslate">clearTimeout(myGreeting);</pre> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Veja <code><a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/greeter-app.html">greeter-app.html</a></code> para uma demonstração mais desenvolvida que te permite colocar o nome da pessoa a dizer oi em um formulário, e cancelar a saudação usando um botão separado (<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/greeter-app.html">veja aqui o código fonte</a>).</p> +</div> + +<h2 id="setInterval">setInterval()</h2> + +<p><code>setTimeout()</code> funciona perfeitamento quando você precisa executar algum código depois de um período de tempo. Mas o que acontece quando voc~e precisa executar o código de novo e de novo — por exemplo, no caso de uma animação?</p> + +<p>É aí que o <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></code> entra. Ele funciona de uma maneira muito similar à <code>setTimeout()</code>, exceto que a função que você passar como primeiro parâmetro é executada repetidamente em não menos que um número determinado de milissegundos dado no segundo parâmetro, ao invés de apenas uma vez. Você também pode passar qualquer parâmetro sendo executado como um parâmetro subsequente da chamada de <code>setInterval()</code>.</p> + +<p>Vamos dar uma olhada em um exemplo. A função a seguir cria um novo objeto <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date">Date()</a></code>, tira uma string de tempo usando <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString">toLocaleTimeString()</a></code>, e depois a mostra naUI. Em seguida, ela executa a função uma vez por segundo usando <code>setInterval()</code>, criando o efeito de um relógio digital que é atualizado uma vez por segundo (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">veja aqui</a>, e também <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">veja o código</a>):</p> + +<pre class="brush: js notranslate">function displayTime() { + let date = new Date(); + let time = date.toLocaleTimeString(); + document.getElementById('demo').textContent = time; +} + +const createClock = setInterval(displayTime, 1000);</pre> + +<p>Assim como o <code>setTimeout()</code>, o <code>setInterval()</code> também retorna um valor identificador que você pode usar depois para cancelar o intervalo.</p> + +<h3 id="Cancelando_intervalos">Cancelando intervalos</h3> + +<p><code>setInterval()</code> continua sua execução para sempre, a menos que você faça algo sobre isso. Você provavelmente quer um jeito de parar tais tarefas, do contrário você pode acabar com error quando o navegador não puder completar outras versões futuras da tarefa, ou se a animação acabar. Você pode fazer isso do mesmo jeito que você para timeouts — passando o identificador retornado por <code>setInterval()</code> para a função <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearInterval">clearInterval()</a></code>:</p> + +<pre class="brush: js notranslate">const myInterval = setInterval(myFunction, 2000); + +clearInterval(myInterval);</pre> + +<h4 id="Aprendizado_ativo_Criando_seu_próprio_cronômetro!">Aprendizado ativo: Criando seu próprio cronômetro!</h4> + +<p>Com tudo isso dito, nós temos um desafio para você. Faça uma cópia do nosso exemplo <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">setInterval-clock.html</a></code>, e o modifique para criar seu próprio cronômetro.</p> + +<p>Você precisa mostrar um tempo na tela como antes, mas nesse ememplo você vai precisar de:</p> + +<ul> + <li>Um botão de início para fazer o cronômetro começar a contar.</li> + <li>Um botâo de parar para parar ou pausar o tempo.</li> + <li>Um botão de "reset" para resetar o tempo em 0.</li> + <li>O display do tempo para mostrar o número de sgundos passados.</li> +</ul> + +<p>Here's a few hints for you:</p> + +<ul> + <li>You can structure and style the button markup however you like; just make sure you use semantic HTML, with hooks to allow you to grab the button references using JavaScript.</li> + <li>You probably want to create a variable that starts at <code>0</code>, then increments by one every second using a constant loop.</li> + <li>It is easier to create this example without using a <code>Date()</code> object, like we've done in our version, but less accurate — you can't guarantee that the callback will fire after exactly <code>1000</code>ms. A more accurate way would be to run <code>startTime = Date.now()</code> to get a timestamp of exactly when the user clicked the start button, and then do <code>Date.now() - startTime</code> to get the number of milliseconds after the start button was clicked.</li> + <li>You also want to calculate the number of hours, minutes, and seconds as separate values, and then show them together in a string after each loop iteration. From the second counter, you can work out each of these.</li> + <li>How would you calculate them? Have a think about it: + <ul> + <li>The number of seconds in an hour is <code>3600</code>.</li> + <li>The number of minutes will be the amount of seconds left over when all of the hours have been removed, divided by <code>60</code>.</li> + <li>The number of seconds will be the amount of seconds left over when all of the minutes have been removed.</li> + </ul> + </li> + <li>You'll want to include a leading zero on your display values if the amount is less than <code>10</code>, so it looks more like a traditional clock/watch.</li> + <li>To pause the stopwatch, you'll want to clear the interval. To reset it, you'll want to set the counter back to <code>0</code>, clear the interval, and then immediately update the display.</li> + <li>You probably ought to disable the start button after pressing it once, and enable it again after you've stopped/reset it. Otherwise multiple presses of the start button will apply multiple <code>setInterval()</code>s to the clock, leading to wrong behavior.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you get stuck, you can <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-stopwatch.html">find our version here</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-stopwatch.html">source code</a> also).</p> +</div> + +<h2 id="Coisas_para_se_manter_em_mente_sobre_o_setTimeout_e_o_setInterval">Coisas para se manter em mente sobre o setTimeout() e o setInterval()</h2> + +<p>Existem algumas coisinhas que devemos sempre lembrar quando estamos trabalhando com <code>setTimeout()</code> e<code>setInterval()</code>:</p> + +<h3 id="Timeouts_recursivos">Timeouts recursivos</h3> + +<p>Há outra maneira de usar o <code>setTimeout()</code>: você pode chamá-lo recusivamnete para executar o mesmo código repetidas vezes, ao invés de usar o <code>setInterval()</code>.</p> + +<p>O exemplo abaixo usa um <code>setTimeout()</code> recursivo para executar a função passada a cada <code>100</code> millissegundos:</p> + +<pre class="brush: js notranslate">let i = 1; + +setTimeout(function run() { + console.log(i); + i++; + setTimeout(run, 100); +}, 100);</pre> + +<p>Compare the above example to the following one — this uses <code>setInterval()</code> to accomplish the same effect:</p> + +<pre class="brush: js notranslate">let i = 1; + +setInterval(function run() { + console.log(i); + i++ +}, 100);</pre> + +<h4 id="Qual_a_diferença_entre_o_setTimeout_recursivo_e_o_setInterval">Qual a diferença entre o <code>setTimeout()</code> recursivo e o <code>setInterval()</code>?</h4> + +<p>A diferença entre as duas versões é bem sútil.</p> + +<ul> + <li>O <code>setTimeout()</code> recursivo garante que o mesmo intervalo entre as execuções (por exemplo, <code>100</code>ms no exemplo acima). O código será executado, depois esperar <code>100</code> milissegundos antes de fazer isso de novo— então o intervalo será o mesmo, idependente do tempo que o código leva para ser executado.</li> + <li>O exemplo usando <code>setInterval()</code> faz as coisas um pouco diferentes.O intervalo escolhido inclui o tempo necessário para executar o código que você deseja executar. Digamos que o código leva <code>40</code> milissegundos de execução — o intervalo acaba levando apenas <code>60</code> milissegundos.</li> + <li>Quando usamos o <code>setTimeout()</code> recursivamente, cada iteração pode calcular um delay diferente antes de executar a próxima iteração. Em outras palavras, o valor do segundo parâmetro pode especificar um tempo diferente em milissegundos para esperar antes de rodar o código de novo.</li> +</ul> + +<p>Quando seu código tem o potencial para levar mais tempo do que lhe foi atribuido, é melhor usar o <code>setTimeout()</code> recursivo — isso irá manter o intervalo de tempo constant entre execuções independente do quanto tempo o código levar para ser executado, e você não terá erros.</p> + +<h3 id="Timeouts_imediatos">Timeouts imediatos</h3> + +<p>Usar zero como o valor para <code>setTimeout()</code> faz a execução da callback ser o mais rápido o possível, mas apenas depois que a main thread for terminada.</p> + +<p>Por exemplo, o código abaixo (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/zero-settimeout.html">veja funcionar aqui</a>) mostra um alert que contém um <code>"Hello"</code>, depois um alert que contém <code>"World"</code> assim que você clicar em OK no primeiro alerta.</p> + +<pre class="brush: js notranslate">setTimeout(function() { + alert('World'); +}, 0); + +alert('Hello');</pre> + +<p>Isso pode ser útil em casos onde você quer fazer um bloco de código ser executado assim que a main thread acabar o seu processamento — colocar no loop de eventos async, assim ele vai ser executado logo depois.</p> + +<h3 id="Cancelando_com_clearTimeout_ou_clearInterval">Cancelando com clearTimeout() ou clearInterval()</h3> + +<p><code>clearTimeout()</code> e <code>clearInterval()</code> usam a mesma lista de entradas para cancelamento. Isso significa que você pode usar os dois para cancelar um <code>setTimeout()</code> ou <code>setInterval()</code>.</p> + +<p>Mas mesmo assim, você deve usar o <code>clearTimeout()</code> para entradas <code>setTimeout()</code> e <code>clearInterval()</code> para entradas <code>setInterval()</code>. Isso evita confusões.</p> + +<h2 id="requestAnimationFrame">requestAnimationFrame()</h2> + +<p><code><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></code> é uma função de loop especializada criada para executar animações com eficiência no navegador. Ela é basicamente a versão moderna de <code>setInterval()</code> — ela executa um bloco de código específico antes que o navegador renove o display, permitindo que uma animação seja executada em um framerate adequado independente do ambiente em que está sendo executada.</p> + +<p>Ela foi criada em resposta à problemas ocorridos com <code>setInterval()</code>, que por exemplo não roda em uma taxa de quadros otimizada para o dispositivo, e às vezes diminui os frames, continua a rodar mesmo se a guia não esiver ativa ou se a animação for rolada para fora da página, etc.</p> + +<p>(<a href="http://creativejs.com/resources/requestanimationframe/index.html">Leia mais sobre isso em CreativeJS</a>.)</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Você pode encontrar exemplos do uso de <code>requestAnimationFrame()</code> em outros lugares do curso — por exemplo em <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Drawing graphics</a>, e <a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a>.</p> +</div> + +<p>O método toma como argumentos uma callback a ser invocada antes da renovação. Esse é o padrão geral que você verá usado em:</p> + +<pre class="brush: js notranslate">function draw() { + // Drawing code goes here + requestAnimationFrame(draw); +} + +draw();</pre> + +<p>A ideia é definir uma função em que sua animação é atualizada (e.g. seus spritas se movem, a pontuação é atuializada, dados são recarregados, etc). Depois, você inicia o processo. No final do bloco da função você chama <code>requestAnimationFrame()</code> com a referência da função passada como parâmetro, e isso instrui o navegador a chamar a função de novo na próxima renovação. Isso é executado continuamente, já que o código está chamando <code>requestAnimationFrame()</code> recursivamente.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Se você quer realizar algum tipo de animação na DOM constantemente, <a href="/en-US/docs/Web/CSS/CSS_Animations">Animações CSS</a> são provavelemente mais rápidas. elas são calculadas diretamente pelo código interno do navegador, ao invés de JavaScript.</p> + +<p>Se, no entanto, você está fazendo algo mais complexo e envolvendo objetos que não são diretamente assessados da DOM (como <a href="/en-US/docs/Web/API/Canvas_API">2D Canvas API</a> ou objetos <a href="/en-US/docs/Web/API/WebGL_API">WebGL</a>), <code>requestAnimationFrame()</code> é a melhor opção na maioria dos casos</p> +</div> + +<h3 id="Qual_a_velocidade_da_sua_animação">Qual a velocidade da sua animação?</h3> + +<p>A suavidade da sua animação é diretamente dependente na frame rate da sua animação e é medida em frames per second (fps). The smoothness of your animation is directly dependent on your animation's frame rate and it is measured in frames per second (fps). Quanto maior esse número, mais suave será a sua animação, até certo ponto.</p> + +<p>Já que a maioria das tela tem uma taxa de atualização de 60Hz, a frame rate mais rápida que você pode ter é de 60fps quando trabalhando com web browsers. No entanto, mais frames significa mais processamento, o que pode ser causar uma queda de quadros e travamento.</p> + +<p>Se você tem um monitos com uma taxa de atualização de 60Hz e você quer atingir 60FPS você tem pelo menos 16.7 milissegundos (<code>1000 / 60</code>) para executar sua animação em cada frame. Isso é um lembrete de que você vai precisar estar atento à quantidade de código que você vai tentar executar em cada iteração do loop de animação.</p> + +<p><code>requestAnimationFrame()</code> sempre tenta ficar o mais próximo possível de 60 FPS. Às vezes, isso não é possível — se você tem uma animação bem complexa e você está executando ela em um computador lento, sua frame rate será menor. Em todos os casos, o <code>requestAnimationFrame()</code> sempre vai fazer o melhor que pode com o que ele tem dísponivel.</p> + +<h3 id="Como_o_requestAnimationFrame_se_diferencia_de_setInterval_e_setTimeout">Como o requestAnimationFrame() se diferencia de setInterval() e setTimeout()?</h3> + +<p>Vamos falar um pouco sobre como o método <code>requestAnimationFrame()</code> se diferencia dos outros métodos vistos anteriormente. Olhando com o código anterior:</p> + +<pre class="brush: js notranslate">function draw() { + // Drawing code goes here + requestAnimationFrame(draw); +} + +draw();</pre> + +<p>Vamos ver isso usando o <code>setInterval()</code>:</p> + +<pre class="brush: js notranslate">function draw() { + // Drawing code goes here +} + +setInterval(draw, 17);</pre> + +<p>Como foi dito anteriormente, você não especifica um intervalo de tempo para <code>requestAnimationFrame()</code>. O método se executa o mais rápido e suave o possível nas condições atuais. O navegador também não perde tempo executando uma animação se ela está fora da tela por algum motivo, etc.</p> + +<p><code>setInterval()</code>, por outro lado, exige que um intervalo de tempo seja especificado. Nós chegamos ao valor final de 17 por meio da formula <em>1000 milliseconds / 60Hz</em>, e depois arredondamos o resultado. Arredondar é uma boa ideia; se você tivesse arredondado para baixo, o navegador pode tentar executar a animação mais rápido do que 60 FPS, e não faria nenhuma diferênça na suavidade da animação de qualquer forma. Como foi dito antes, 60Hz é a taxa de atualização padrão.</p> + +<h3 id="Incluindo_um_timestamp">Incluindo um timestamp</h3> + +<p>A callback passada para a função <code>requestAnimationFrame()</code> pode ser dada um parâmetro támbem: um valor <em>timestamp</em>, que representa o tempo desde que o <code>requestAnimationFrame()</code> começou a rodar.</p> + +<p>Isso é útil, permite que você execute coisas em um tempo específico e em passo constante, independente do quão rápido ou lento é o seu dispositivo. O padão geral que você usaria se parece um pouco com isso:</p> + +<pre class="brush: js notranslate">let startTime = null; + +function draw(timestamp) { + if (!startTime) { + startTime = timestamp; + } + + currentTime = timestamp - startTime; + + // Do something based on current time + + requestAnimationFrame(draw); +} + +draw();</pre> + +<h3 id="Suporte_do_navegador">Suporte do navegador</h3> + +<p><code>requestAnimationFrame()</code> é suportado em navegadores mais recentes do que <code>setInterval()</code>/<code>setTimeout()</code>. Curiosamente, está disponível no Internet Explorer 10 e além.</p> + +<p>Então, você não precisa dar suporte para versões mais velhas do IE, não há poruqe não usar o <code>requestAnimationFrame()</code>.</p> + +<h3 id="Um_exemplo_simples">Um exemplo simples</h3> + +<p>Enough with the theory! Let's build your own personal <code>requestAnimationFrame()</code> example. You're going to create a simple "spinner animation"—the kind you might see displayed in an app when it is busy connecting to the server, etc.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: In a real world example, you should probably use CSS animations to run this kind of simple animation. However, this kind of example is very useful to demonstrate <code>requestAnimationFrame()</code> usage, and you'd be more likely to use this kind of technique when doing something more complex such as updating the display of a game on each frame.</p> +</div> + +<ol> + <li> + <p>Grab a basic HTML template (<a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">such as this one</a>).</p> + </li> + <li> + <p>Put an empty {{htmlelement("div")}} element inside the {{htmlelement("body")}}, then add a ↻ character inside it. This is circular arrow character will act as our spinner for this example.</p> + </li> + <li> + <p>Apply the following CSS to the HTML template (in whatever way you prefer). This sets a red background on the page, sets the <code><body></code> height to <code>100%</code> of the {{htmlelement("html")}} height, and centers the <code><div></code> inside the <code><body></code>, horizontally and vertically.</p> + + <pre class="brush: css notranslate">html { + background-color: white; + height: 100%; +} + +body { + height: inherit; + background-color: red; + margin: 0; + display: flex; + justify-content: center; + align-items: center; +} + +div { + display: inline-block; + font-size: 10rem; +}</pre> + </li> + <li> + <p>Insert a {{htmlelement("script")}} element just above the <code></body></code> tag.</p> + </li> + <li> + <p>Insert the following JavaScript inside your <code><script></code> element. Here, you're storing a reference to the <code><div></code> inside a constant, setting a <code>rotateCount</code> variable to <code>0</code>, setting an uninitialized variable that will later be used to contain a reference to the <code>requestAnimationFrame()</code> call, and setting a <code>startTime</code> variable to <code>null</code>, which will later be used to store the start time of the <code>requestAnimationFrame()</code>.</p> + + <pre class="brush: js notranslate">const spinner = document.querySelector('div'); +let rotateCount = 0; +let startTime = null; +let rAF; +</pre> + </li> + <li> + <p>Below the previous code, insert a <code>draw()</code> function that will be used to contain our animation code, which includes the <code>timestamp</code> parameter:</p> + + <pre class="brush: js notranslate">function draw(timestamp) { + +}</pre> + </li> + <li> + <p>Inside <code>draw()</code>, add the following lines. They will define the start time if it is not defined already (this will only happen on the first loop iteration), and set the <code>rotateCount</code> to a value to rotate the spinner by (the current timestamp, take the starting timestamp, divided by three so it doesn't go too fast):</p> + + <pre class="brush: js notranslate"> if (!startTime) { + startTime = timestamp; + } + + rotateCount = (timestamp - startTime) / 3; +</pre> + </li> + <li> + <p>Below the previous line inside <code>draw()</code>, add the following block — this checks to see if the value of <code>rotateCount</code> is above <code>359</code> (e.g. <code>360</code>, a full circle). If so, it sets the value to its modulo of 360 (i.e. the remainder left over when the value is divided by <code>360</code>) so the circle animation can continue uninterrupted, at a sensible, low value. Note that this isn't strictly necessary, but it is easier to work with values of 0–359 degrees than values like <code>"128000 degrees"</code>.</p> + + <pre class="brush: js notranslate">if (rotateCount > 359) { + rotateCount %= 360; +}</pre> + </li> + <li>Next, below the previous block add the following line to actually rotate the spinner: + <pre class="brush: js notranslate">spinner.style.transform = `rotate(${rotateCount}deg)`;</pre> + </li> + <li> + <p>At the very bottom inside the <code>draw()</code> function, insert the following line. This is the key to the whole operation — you are setting the variable defined earlier to an active <code>requestAnimation()</code> call, which takes the <code>draw()</code> function as its parameter. This starts the animation off, constantly running the <code>draw()</code> function at a rate as near 60 FPS as possible.</p> + + <pre class="brush: js notranslate">rAF = requestAnimationFrame(draw);</pre> + </li> +</ol> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You can find this <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">example live on GitHub</a>. (You can see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">source code</a>, also.)</p> +</div> + +<h3 id="Clearing_a_requestAnimationFrame_call">Clearing a requestAnimationFrame() call</h3> + +<p>Clearing a <code>requestAnimationFrame()</code> call can be done by calling the corresponding <code>cancelAnimationFrame()</code> method. (Note that the function name starts with "cancel", not "clear" as with the "set..." methods.) </p> + +<p>Just pass it the value returned by the <code>requestAnimationFrame()</code> call to cancel, which you stored in the variable <code>rAF</code>:</p> + +<pre class="brush: js notranslate">cancelAnimationFrame(rAF);</pre> + +<h3 id="Active_learning_Starting_and_stopping_our_spinner">Active learning: Starting and stopping our spinner</h3> + +<p>In this exercise, we'd like you to test out the <code>cancelAnimationFrame()</code> method by taking our previous example and updating it, adding an event listener to start and stop the spinner when the mouse is clicked anywhere on the page.</p> + +<p>Some hints:</p> + +<ul> + <li>A <code>click</code> event handler can be added to most elements, including the document <code><body></code>. It makes more sense to put it on the <code><body></code> element if you want to maximize the clickable area — the event bubbles up to its child elements.</li> + <li>You'll want to add a tracking variable to check whether the spinner is spinning or not, clearing the animation frame if it is, and calling it again if it isn't.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: Try this yourself first; if you get really stuck, check out of our <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/start-and-stop-spinner.html">live example</a> and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/start-and-stop-spinner.html">source code</a>.</p> +</div> + +<h3 id="Throttling_a_requestAnimationFrame_animation">Throttling a requestAnimationFrame() animation</h3> + +<p>One limitation of <code>requestAnimationFrame()</code> is that you can't choose your frame rate. This isn't a problem most of the time, as generally you want your animation to run as smoothly as possible. But what about when you want to create an old school, 8-bit-style animation?</p> + +<p>This was a problem, for example, in the Monkey Island-inspired walking animation from our <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Drawing Graphics</a> article:</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/7_canvas_walking_animation.html", '100%', 260)}}</p> + +<p>In this example, you have to animate both the position of the character on the screen, and the sprite being shown. There are only 6 frames in the sprite's animation. If you showed a different sprite frame for every frame displayed on the screen by <code>requestAnimationFrame()</code>, Guybrush would move his limbs too fast and the animation would look ridiculous. This example therefore throttles the rate at which the sprite cycles its frames using the following code:</p> + +<pre class="brush: js notranslate">if (posX % 13 === 0) { + if (sprite === 5) { + sprite = 0; + } else { + sprite++; + } +}</pre> + +<p>So the code only cycles the sprite once every 13 animation frames.</p> + +<p>...Actually, it's about every 6.5 frames, as we update <code>posX</code> (character's position on the screen) by two each frame:</p> + +<pre class="brush: js notranslate">if (posX > width/2) { + newStartPos = -( (width/2) + 102 ); + posX = Math.ceil(newStartPos / 13) * 13; + console.log(posX); +} else { + posX += 2; +}</pre> + +<p>This is the code that calculates how to update the position in each animation frame.</p> + +<p>The method you use to throttle your animation will depend on your particular code. For instance, in the earlier spinner example, you could make it appear to move slower by only increasing <code>rotateCount</code> by one on each frame, instead of two.</p> + +<h2 id="Active_learning_a_reaction_game">Active learning: a reaction game</h2> + +<p>For the final section of this article, you'll create a 2-player reaction game. The game will have two players, one of whom controls the game using the <kbd>A</kbd> key, and the other with the <kbd>L</kbd> key.</p> + +<p>When the <em>Start</em> button is pressed, a spinner like the one we saw earlier is displayed for a random amount of time between 5 and 10 seconds. After that time, a message will appear saying <code>"PLAYERS GO!!"</code> — once this happens, the first player to press their control button will win the game.</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/asynchronous/loops-and-intervals/reaction-game.html", '100%', 500)}}</p> + +<p>Let's work through this:</p> + +<ol> + <li> + <p>First of all, download the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/reaction-game-starter.html">starter file for the app</a>. This contains the finished HTML structure and CSS styling, giving us a game board that shows the two players' information (as seen above), but with the spinner and results paragraph displayed on top of one another. You just have to write the JavaScript code.</p> + </li> + <li> + <p>Inside the empty {{htmlelement("script")}} element on your page, start by adding the following lines of code that define some constants and variables you'll need in the rest of the code:</p> + + <pre class="brush: js notranslate">const spinner = document.querySelector('.spinner p'); +const spinnerContainer = document.querySelector('.spinner'); +let rotateCount = 0; +let startTime = null; +let rAF; +const btn = document.querySelector('button'); +const result = document.querySelector('.result');</pre> + + <p>In order, these are:</p> + + <ol> + <li>A reference to the spinner, so you can animate it.</li> + <li>A reference to the {{htmlelement("div")}} element that contains the spinner, used for showing and hiding it.</li> + <li>A rotate count. This determines how much you want to show the spinner rotated on each frame of the animation.</li> + <li>A null start time. This will be populated with a start time when the spinner starts spinning.</li> + <li>An uninitialized variable to later store the {{domxref("Window.requestAnimationFrame", "requestAnimationFrame()")}} call that animates the spinner.</li> + <li>A reference to the Start button.</li> + <li>A reference to the results paragraph.</li> + </ol> + </li> + <li> + <p>Next, below the previous lines of code, add the following function. It simply takes two numbers and returns a random number between the two. You'll need this to generate a random timeout interval later on.</p> + + <pre class="brush: js notranslate">function random(min,max) { + var num = Math.floor(Math.random()*(max-min)) + min; + return num; +}</pre> + </li> + <li> + <p>Next add the <code>draw()</code> function, which animates the spinner. This is very similar to the version from the simple spinner example, earlier:</p> + + <pre class="brush: js notranslate">function draw(timestamp) { + if(!startTime) { + startTime = timestamp; + } + + rotateCount = (timestamp - startTime) / 3; + + if(rotateCount > 359) { + rotateCount %= 360; + } + + spinner.style.transform = 'rotate(' + rotateCount + 'deg)'; + rAF = requestAnimationFrame(draw); +}</pre> + </li> + <li> + <p>Now it is time to set up the initial state of the app when the page first loads. Add the following two lines, which simply hide the results paragraph and spinner container using <code>display: none;</code>.</p> + + <pre class="brush: js notranslate">result.style.display = 'none'; +spinnerContainer.style.display = 'none';</pre> + </li> + <li> + <p>Next, define a <code>reset()</code> function, which sets the app back to the original state required to start the game again after it has been played. Add the following at the bottom of your code:</p> + + <pre class="brush: js notranslate">function reset() { + btn.style.display = 'block'; + result.textContent = ''; + result.style.display = 'none'; +}</pre> + </li> + <li> + <p>Okay, enough preparation! It's time to make the game playable! Add the following block to your code. The <code>start()</code> function calls <code>draw()</code> to start the spinner spinning and display it in the UI, hides the <em>Start</em> button so you can't mess up the game by starting it multiple times concurrently, and runs a <code>setTimeout()</code> call that runs a <code>setEndgame()</code> function after a random interval between 5 and 10 seconds has passed. The following block also adds an event listener to your button to run the <code>start()</code> function when it is clicked.</p> + + <pre class="brush: js notranslate">btn.addEventListener('click', start); + +function start() { + draw(); + spinnerContainer.style.display = 'block'; + btn.style.display = 'none'; + setTimeout(setEndgame, random(5000,10000)); +}</pre> + + <div class="blockIndicator note"> + <p><strong>Note</strong>: You'll see this example is calling <code>setTimeout()</code> without storing the return value. (So, not <code>let myTimeout = setTimeout(functionName, interval)</code>.) </p> + + <p>This works just fine, as long as you don't need to clear your interval/timeout at any point. If you do, you'll need to save the returned identifier!</p> + </div> + + <p>The net result of the previous code is that when the <em>Start</em> button is pressed, the spinner is shown and the players are made to wait a random amount of time before they are asked to press their button. This last part is handled by the <code>setEndgame()</code> function, which you'll define next.</p> + </li> + <li> + <p>Add the following function to your code next:</p> + + <pre class="brush: js notranslate">function setEndgame() { + cancelAnimationFrame(rAF); + spinnerContainer.style.display = 'none'; + result.style.display = 'block'; + result.textContent = 'PLAYERS GO!!'; + + document.addEventListener('keydown', keyHandler); + + function keyHandler(e) { + console.log(e.key); + if(e.key === 'a') { + result.textContent = 'Player 1 won!!'; + } else if(e.key === 'l') { + result.textContent = 'Player 2 won!!'; + } + + document.removeEventListener('keydown', keyHandler); + setTimeout(reset, 5000); + }; +}</pre> + + <p>Stepping through this:</p> + + <ol> + <li>First, cancel the spinner animation with {{domxref("window.cancelAnimationFrame", "cancelAnimationFrame()")}} (it is always good to clean up unneeded processes), and hide the spinner container.</li> + <li>Next, display the results paragraph and set its text content to "PLAYERS GO!!" to signal to the players that they can now press their button to win.</li> + <li>Attach a <code><a href="/en-US/docs/Web/API/Document/keydown_event">keydown</a></code> event listener to the document. When any button is pressed down, the <code>keyHandler()</code> function is run.</li> + <li>Inside <code>keyHandler()</code>, the code includes the event object as a parameter (represented by <code>e</code>) — its {{domxref("KeyboardEvent.key", "key")}} property contains the key that was just pressed, and you can use this to respond to specific key presses with specific actions.</li> + <li>Log <code>e.key</code> to the console, which is a useful way of finding out the <code>key</code> value of different keys you are pressing.</li> + <li>When <code>e.key</code> is "a", display a message to say that Player 1 won, and when <code>e.key</code> is "l", display a message to say Player 2 won. (<strong>Note:</strong> This will only work with lowercase a and l — if an uppercase A or L is submitted (the key plus <kbd>Shift</kbd>), it is counted as a different key!)</li> + <li>Regardless of which one of the player control keys was pressed, remove the <code>keydown</code> event listener using {{domxref("EventTarget.removeEventListener", "removeEventListener()")}} so that once the winning press has happened, no more keyboard input is possible to mess up the final game result. You also use <code>setTimeout()</code> to call <code>reset()</code> after 5 seconds — as explained earlier, this function resets the game back to its original state so that a new game can be started.</li> + </ol> + </li> +</ol> + +<p>That's it—you're all done!</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you get stuck, check out <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/reaction-game.html">our version of the reaction game</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/reaction-game.html">source code</a> also).</p> +</div> + +<h2 id="Conclusion">Conclusion</h2> + +<p>So that's it — all the essentials of async loops and intervals covered in one article. You'll find these methods useful in a lot of situations, but take care not to overuse them! Because they still run on the main thread, heavy and intensive callbacks (especially those that manipulate the DOM) can really slow down a page if you're not careful.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">General asynchronous programming concepts</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Making asynchronous programming easier with async and await</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choosing the right approach</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/first_steps/a_first_splash/index.html b/files/pt-br/learn/javascript/first_steps/a_first_splash/index.html new file mode 100644 index 0000000000..1d5498ab11 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/a_first_splash/index.html @@ -0,0 +1,683 @@ +--- +title: Um primeiro mergulho no JavaScript +slug: Learn/JavaScript/First_steps/A_first_splash +translation_of: Learn/JavaScript/First_steps/A_first_splash +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Agora você poderá aprender um pouco sobre a Teoria do Javascript e o que você poderá fazer com ele. Nós vamos lhe fornecer aqui um Curso rápido sobre as características básicas do JavaScript através de um tutorial completamente prático. Você irá construir um simples jogo de "Adivinhe o número", passo a passo. </p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimentos básicos de informática, uma compreensão básica de HTML e CSS, uma compreensão do que é JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Ter um primeiro bit de experiência em escrever um pouco de JavaScript, e adquirir pelo menos uma compreensão básica do que envolve escrever um programa em JavaScript.</p> + </td> + </tr> + </tbody> +</table> + +<p>Nós não esperamos que você entenda todo o código imediatamente - Apenas queremos ensinar-lhe os melhores conceitos por enquanto e dar a você uma idéia de como o JavaScript (e outras linguagens de programação) funcionam. Em artigos posteriores você vai rever todos esses recursos com muito mais detalhes!</p> + +<div class="note"> +<p><strong>Nota</strong>: Muitos dos recursos de código que você verá no JavaScript são iguais aos de outra linguagem de programação - funções, loops, etc. A sintaxe do código parece diferente, mas os conceitos ainda são praticamente os mesmos.</p> +</div> + +<h2 id="Pensando_como_um_Programador">Pensando como um Programador</h2> + +<p>Uma das coisas mais difíceis de aprender na programação não é a sintaxe que você precisa aprender, mas como aplicá-la para resolver problemas do mundo real. Você precisa começar a pensar como um programador - isso geralmente envolve olhar para as descrições do que seu programa precisa fazer e analisar como eles podem ser aplicados na solução real (prática), quais recursos de código são necessários para alcançar esse objetivo, e como fazê-los trabalhar em conjunto.</p> + +<p>Isso requer um mistura de trabalho duro, experiência com a sintaxe de programação utilizada e prática, além de um pouco de criatividade, é claro. Quanto mais você programa, melhor programador se torna. Nós não prometemos transformar seu cérebro em um "cérebro de programador" em 5 minutos, mas vamos te dar todas as oportunidades para pensar na prática como um programador ao longo deste curso. </p> + +<p>Com isso em mente, vejamos o exemplo que estaremos construindo neste artigo e analisaremos o processo geral de dissecá-lo em tarefas tangíveis.</p> + +<p> </p> + +<h2 id="Exemplo_—_Jogo_adivinhe_um_número">Exemplo — Jogo adivinhe um número</h2> + +<p>Neste artigo vamos mostrar a você como construir este simples jogo, que pode ser visto abaixo:</p> + +<div class="hidden"> +<h6 id="Top_hidden_code">Top hidden code</h6> + +<p> </p> + +<pre class="brush: html"><!DOCTYPE html> +<html> + +<head> + <meta charset="utf-8"> + <title>Jogo adivinhe o número</title> + <style> + html { + font-family: sans-serif; + } + + body { + width: 50%; + max-width: 800px; + min-width: 480px; + margin: 0 auto; + } + + .lastResult { + color: white; + padding: 3px; + } + </style> +</head> + +<body> + <h1>Jogo Adivinhe um número</h1> + <p>Selecionamos um número aleatório entre 1 e 100. Veja se consegue adivinhar em 10 chances ou menos. Lhe diremos se seu palpite está com valor alto ou baixo.</p> + <div class="form"> <label for="guessField">Digite seu palpite: </label><input type="text" id="guessField" class="guessField"> <input type="submit" value="Enviar palpite" class="guessSubmit"> </div> + <div class="resultParas"> + <p class="guesses"></p> + <p class="lastResult"></p> + <p class="lowOrHi"></p> + </div> +</body> +<script> + // Seu JavaScipt vem aqui + var randomNumber = Math.floor(Math.random() * 100) + 1; + var guesses = document.querySelector('.guesses'); + var lastResult = document.querySelector('.lastResult'); + var lowOrHi = document.querySelector('.lowOrHi'); + var guessSubmit = document.querySelector('.guessSubmit'); + var guessField = document.querySelector('.guessField'); + var guessCount = 1; + var resetButton; + + function checkGuess() { + var userGuess = Number(guessField.value); + if (guessCount === 1) { + guesses.textContent = 'Palpites anteriores: '; + } + + guesses.textContent += userGuess + ' '; + + if (userGuess === randomNumber) { + lastResult.textContent = 'Parabéns! Seu número está certo!'; + lastResult.style.backgroundColor = 'green'; + lowOrHi.textContent = ''; + setGameOver(); + } else if (guessCount === 10) { + lastResult.textContent = '!!!FIM DE JOGO!!!'; + lowOrHi.textContent = ''; + setGameOver(); + } else { + lastResult.textContent = 'Errado!'; + lastResult.style.backgroundColor = 'red'; + if(userGuess < randomNumber) { + lowOrHi.textContent='Seu palpite está muito baixo!' ; + } else if(userGuess > randomNumber) { + lowOrHi.textContent = 'Seu palpite está muito alto!'; + } + } + + guessCount++; + guessField.value = ''; + } + + guessSubmit.addEventListener('click', checkGuess); + + function setGameOver() { + guessField.disabled = true; + guessSubmit.disabled = true; + resetButton = document.createElement('button'); + resetButton.textContent = 'Iniciar novo jogo'; + document.body.appendChild(resetButton); + resetButton.addEventListener('click', resetGame); + } + + function resetGame() { + guessCount = 1; + var resetParas = document.querySelectorAll('.resultParas p'); + for(var i = 0 ; i < resetParas.length ; i++) { + resetParas[i].textContent=''; + } + + resetButton.parentNode.removeChild(resetButton); + guessField.disabled = false; + guessSubmit.disabled = false; + guessField.value=''; + guessField.focus(); + lastResult.style.backgroundColor='white'; + randomNumber=Math.floor(Math.random() * 100) + 1; + } +</script> + +</html></pre> + +<p> </p> +</div> + +<p>{{ EmbedLiveSample('Top_hidden_code', '100%', 320) }}</p> + +<p>Vá em frente e jogue por um tempo para se familiarizar com o jogo antes de continuar.</p> + +<p>Vamos imaginar que o seu chefe te deu as seguintes diretrizes para criar este jogo:</p> + +<blockquote> +<p>Quero que você crie um jogo simples do tipo adivinhe um número. Ele deve gerar um número aleatório de 1 a 100, depois desafiar o jogador a adivinhar o número em 10 rodadas. A cada rodada deve ser dito ao jogador se ele está certo ou errado, se estiver errado, deve ser dito se o palpite é muito baixo ou muito alto. Também deve ser mostrado ao jogador os números que ele tentou adivinhar anteriormente. O jogo termina se o jogador acertar o número ou acabarem o número de tentativas. Quando o jogo acabar, deve ser dado ao jogador a opção de jogar novamente.</p> +</blockquote> + +<p>Olhando para o enunciado, a primeira coisa que devemos fazer é quebrá-lo em pequenas tarefas, da forma mais parecida com o pensamento de um programador quanto possível:</p> + +<ol> + <li>Gerar um número aleatório entre 1 e 100.</li> + <li>Gravar o número do turno que o jogador está. Iniciar em 1.</li> + <li>Dar ao jogador uma forma de adivinhar o número.</li> + <li>Após a tentativa ter sido submetida, primeiro gravar em algum lugar para que o usuário possa ver as tentativas anteriores.</li> + <li>Depois, verificar se o palpite está correto.</li> + <li>Se estiver correto: + <ol> + <li>Escrever mensagem de parabéns.</li> + <li>Impedir que o jogador insira mais respostas (isso pode bugar o jogo).</li> + <li>Mostrar controle que permita ao jogador reiniciar o jogo.</li> + </ol> + </li> + <li>Se o palpite estiver errado e o jogador ainda tem turnos sobrando: + <ol> + <li>Dizer ao jogador que ele está errado.</li> + <li>Permitir que ele insira outra resposta.</li> + <li>Incrementar o número do turno em 1.</li> + </ol> + </li> + <li>Se o jogador está errado mas não tem turnos sobrando: + <ol> + <li>Dizer ao jogador que o jogo acabou.</li> + <li>Impedir que o jogador insira mais respostas (isso pode bugar o jogo).</li> + <li>Mostrar controle que permita ao jogador reiniciar o jogo.</li> + </ol> + </li> + <li>Quando reiniciar, tenha certeza de resetar todas as variáveis e a interface do jogo, então volte para o passo 1.</li> +</ol> + +<p>Então vamos em frente, olhando como podemos transformar esses passos em código, construindo esse exemplo e explorando as ferramentas do JavaScript ao longo do caminho.</p> + +<h3 id="Configuração_Inicial">Configuração Inicial</h3> + +<p>Para iniciar este tutorial, gostaríamos que você fizesse uma cópia do arquivo <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/first-splash/jogo-advinhe-o-numero-inicio.html">jogo-adivinhe-o-numero-inicio.html</a> (<a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/first-splash/jogo-advinhe-o-numero-inicio.html">ver demonstração</a>). Abra-o em um editor de texto e também no seu browser. No momento você vai apenas ver um simples cabeçalho, parágrafo de instruções e um formulário para entrada de informações, mas o formulário não fará nada por enquanto.</p> + +<p>O lugar em que começaremos a escrever nosso código será dentro da tag {{htmlelement("script")}} na parte inferior do HTML:</p> + +<pre class="brush: html"><script> + + // Seu JavaScript vai aqui + +</script> +</pre> + +<h3 id="Adicionando_variáveis_para_armazenar_nossos_dados">Adicionando variáveis para armazenar nossos dados</h3> + +<p>Vamos começar. Primeiramente, adicione as seguintes linhas na sua tag {{htmlelement("script")}} :</p> + +<pre class="brush: js">var numeroAleatorio= Math.floor(Math.random() * 100) + 1; + +var palpites = document.querySelector('.palpites'); +var ultimoResultado = document.querySelector('.ultimoResultado'); +var baixoOuAlto = document.querySelector('.baixoOuAlto'); + +var envioPalpite = document.querySelector('.envioPalpite'); +var campoPalpite = document.querySelector('.campoPalpite'); + +var contagemPalpites = 1; +var botaoReinicio;</pre> + +<p>Aqui estamos setando as variáveis que precisamos para guardar os dados que nosso programa irá utilizar. Variáveis são basicamente recipientes para valores (como números, ou strings ou textos). Variáveis são criadas com a palavra-chave <code>var</code> seguida de um nome para sua variável. Você pode atribuir um valor para sua variável com um sinal de igual (<code>=</code>) seguido do valor que você quer dar a ela.</p> + +<p>No nosso exemplo:</p> + +<ul> + <li>À primeira variável — <code>numeroAleatorio</code> — é atribuído um número aleatório entre 1 e 100, calculado usando um algoritmo matemático.</li> + <li>As próximas três variáveis são criadas para guardar uma referência para os parágrafos resultantes em nosso HTML, e são usadas para inserir valores nos parágrafos no código: + <pre class="brush: html"><p class="palpites"></p> +<p class="ultimoResultado"></p> +<p class="baixoOuAlto"></p></pre> + </li> + <li>As próximas duas variáveis armazenam referências para o campo de texto e o botão de envio e são usados para controlar o envio do palpite. + <pre class="brush: html"><label for="campoPalpite">Digite seu palpite: </label><input type="text" id="campoPalpite" class="campoPalpite"> +<input type="submit" value="Enviar palpite" class="envioPalpite"></pre> + </li> + <li>As últimas duas variáveis (contagemPalpites e botaoReinicio) são usadas para armazenar a contagem dos palpites do usuário, e o outro é uma referência para o botão de reset, que não existe ainda (mas irá existir).</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Você irá aprender muito mais sobre variáveis a partir do <a href="https://developer.mozilla.org/en-US/docs/user:chrisdavidmills/variables">próximo artigo</a>.</p> +</div> + +<h3 id="Funções">Funções</h3> + +<p>Em seguida, adicione o seguinte código abaixo do JavaScript anterior:</p> + +<pre class="brush: js">function conferirPalpite() { + alert('Eu sou um placeholder'); +}</pre> + +<p>Funções são blocos reutilizáveis de código que você pode escrever uma vez e executá-lo de novo e de novo, eliminando a necessidade de repetir o código todas as vezes. Isso é realmente útil. Há várias formas de se definir funções, mas, por agora, vamos nos concentrar em um tipo simples. Aqui nós definimos uma função usando a palavra chave <code>function</code>, seguida de um nome, com parênteses colocados na sequência. Depois disso nós colocamos duas chaves (<code>{ }</code>). Dentro das chaves vai todo o código que queremos executar sempre que chamarmos a função.</p> + +<p>O código é executado digitando o nome da função seguido pelos parênteses.</p> + +<p>Tente salvar o seu código agora e atualizá-lo no navegador.</p> + +<p>Vá até o <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console JavaScript</a>, e insirá a seguinte linha:</p> + +<pre class="brush: js">conferirPalpite();</pre> + +<p>Você deverá ver um alerta aparecer dizendo "Eu sou um placeholder"; nós definimos uma função em nosso código que cria um alerta a qualquer hora em que a chamarmos.</p> + +<div class="note"> +<p><strong>Nota</strong>: Você irá aprender muito mais sobre funções mais tarde no curso.</p> +</div> + +<h3 id="Operadores">Operadores</h3> + +<p>Os operadores JavaScript nos permite realizar testes, fazer cálculos matemáticos, unir sequências de texto, e outras coisas do tipo.</p> + +<p>Vamos salvar nosso código e atualizar a página exibida em nosso navegador. Abra o <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console JavaScript</a> se você ainda não o tiver aberto, para que possamos digitar os exemplos mostrados abaixo — digite cada um exatamente como mostrado na coluna "Exemplo", pressionando Return/Enter na sequência, e veja quais resultados são retornados. Se você não tiver fácil acesso às ferramentas de desenvolvimento do navegador você pode sempre utilizar o console embutido simples, como no exemplo abaixo:</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Console JavaScript</title> + <style> + * { + box-sizing: border-box; + } + + html { + background-color: #0C323D; + color: #809089; + font-family: monospace; + } + + body { + max-width: 700px; + } + + p { + margin: 0; + width: 1%; + padding: 0 1%; + font-size: 16px; + line-height: 1.5; + float: left; + } + + .input p { + margin-right: 1%; + } + + .output p { + width: 100%; + } + + .input input { + width: 96%; + float: left; + border: none; + font-size: 16px; + line-height: 1.5; + font-family: monospace; + padding: 0; + background: #0C323D; + color: #809089; + } + + div { + clear: both; + } + + </style> + </head> + <body> + + + </body> + + <script> + var geval = eval; + + function createInput() { + var inputDiv = document.createElement('div'); + var inputPara = document.createElement('p'); + var inputForm = document.createElement('input'); + + inputDiv.setAttribute('class','input'); + inputPara.textContent = '>'; + inputDiv.appendChild(inputPara); + inputDiv.appendChild(inputForm); + document.body.appendChild(inputDiv); + inputDiv.focus(); + + inputForm.addEventListener('change', executeCode); + } + + function executeCode(e) { + try { + var result = geval(e.target.value); + } catch(e) { + var result = 'error — ' + e.message; + } + + var outputDiv = document.createElement('div'); + var outputPara = document.createElement('p'); + + outputDiv.setAttribute('class','output'); + outputPara.textContent = 'Result: ' + result; + outputDiv.appendChild(outputPara); + document.body.appendChild(outputDiv); + + e.target.disabled = true; + e.target.parentNode.style.opacity = '0.5'; + + createInput() + } + + createInput(); + + </script> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 300) }}</p> + +<p>Primeiro vamos ver os operadores matemáticos, como por exemplo:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operador</th> + <th scope="col">Nome</th> + <th scope="col">Exemplo</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>+</code></td> + <td>Adição</td> + <td><code>6 + 9</code></td> + </tr> + <tr> + <td><code>-</code></td> + <td>Subtração</td> + <td><code>20 - 15</code></td> + </tr> + <tr> + <td><code>*</code></td> + <td>Multiplicação</td> + <td><code>3 * 7</code></td> + </tr> + <tr> + <td><code>/</code></td> + <td>Divisão</td> + <td><code>10 / 5</code></td> + </tr> + </tbody> +</table> + +<p>Você também pode usar o operador <code>+</code> para unir sequências de texto (isso é chamado de concatenação em programação). Tente inserir as seguintes linhas:</p> + +<pre class="brush: js">var nome = 'Bingo'; +nome; +var ola = ' diz olá!'; +ola; +var cumprimento = nome + ola; +cumprimento;</pre> + +<p>Há também alguns atalhos para operadores disponíveis, chamados de operadores de atribuição ampliada (ou atribuição composta). Por exemplo, se você quer adicionar uma nova sequência de texto à uma existente e retornar o resultado, você pode fazer o seguinte:</p> + +<pre class="brush: js">nome += ' diz olá!';</pre> + +<p>Isso é equivalente a:</p> + +<pre class="brush: js">nome = nome + ' diz olá!';</pre> + +<p>Quando estamos rodando testes de verdadeiro/falso (por exemplo, condicinais internas — veja {{anch("Conditionals", "abaixo")}}, usamos operadores de comparação, por exemplo:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operador</th> + <th scope="col">Nome</th> + <th scope="col">Exemplo</th> + </tr> + <tr> + <td><code>===</code></td> + <td>Igualdade estrita (é estritamente o mesmo?)</td> + <td><code>5 === 2 + 4</code></td> + </tr> + <tr> + <td><code>!==</code></td> + <td>Não-igualdade (não é o mesmo?)</td> + <td><code>'Chris' !== 'Ch' + 'ris'</code></td> + </tr> + <tr> + <td><code><</code></td> + <td>Menor que</td> + <td><code>10 < 6</code></td> + </tr> + <tr> + <td><code>></code></td> + <td>Maior que</td> + <td><code>10 > 20</code></td> + </tr> + </thead> +</table> + +<h3 id="Condicionais">Condicionais</h3> + +<p>Voltando à nossa função <code>conferirPalpite()</code>, imagino que seja seguro dizer que não queremos que ela apenas exiba uma mensagem de teste (placeholder). Nós queremos verificar se o palpite do jogador está correto ou não, e responder apropriadamente.</p> + +<p>Neste ponto, substitua sua função <code>conferirPalpite()</code> atual por esta versão:</p> + +<pre class="brush: js">function conferirPalpite() { + var palpiteUsuario = Number(campoPalpite.value); + if (contagemPalpites === 1) { + palpites.textContent = 'Palpites anteriores: '; + } + palpites.textContent += palpiteUsuario + ' '; + + if (palpiteUsuario === numeroAleatorio) { + ultimoResultado.textContent = 'Parabéns! Você acertou!'; + ultimoResultado.style.backgroundColor = 'green'; + baixoOuAlto.textContent = ''; + configFimDeJogo(); + } else if (contagemPalpites === 10) { + ultimoResultado.textContent = '!!!FIM DE JOGO!!!'; + baixoOuAlto.textContent = ''; + configFimDeJogo(); + } else { + ultimoResultado.textContent = 'Errado!'; + ultimoResultado.style.backgroundColor = 'red'; + if(palpiteUsuario < numeroAleatorio) { + baixoOuAlto.textContent = 'Seu palpite está muito baixo!'; + } else if(palpiteUsuario > numeroAleatorio) { + baixoOuAlto.textContent = 'Seu palpite está muito alto!'; + } + } + + contagemPalpites++; + campoPalpite.value = ''; + campoPalpite.focus(); +}</pre> + +<p>Isso é bastante código — ufa! Vamos abordar cada seção e explicar o que faz.</p> + +<ul> + <li>A primeira linha (linha 2 no código acima) declara uma variável chamada <code>palpiteUsuario</code> e define seu valor igual ao valor inserido pelo jogador no campo de texto. Nós também rodamos esse valor através do método embutido <code>Number()</code>, apenas para ter certeza de que o valor inserido é um número.</li> + <li>Em seguida, encontramos nosso primero bloco de código condicional (linhas 3–5 no código acima). Um bloco de código condicional lhe permite executar código seletivamente, dependendo se uma condição é verdadeira ou não. Se parece um pouco com uma função, mas não é. A forma mais simples de um bloco condicional começa com a palavra chave <code>if</code>, depois os parênteses, depois as chaves. Dentro dos parênteses nós incluímos um teste. Se o teste retornar <code>true</code>(verdadeiro), o código dentro das chaves é executado. Caso contrário, não é executado, e seguimos para a próxima parte do código. Neste caso, o teste está verificando se a variável <code>contagemPalpites</code> é igual a <code>1</code> (isto é, se essa é ou não a primeira tentativa do jogador): + <pre class="brush: js">contagemPalpites === 1</pre> + Se a condição for verdadeira, nós tornamos o conteúdo do parágrafo de palpites, <code><p class="palpites"></p></code> igual a "Palpites anteriores: ". Caso contrário, o texto não é exibido.</li> + <li>A linha 6 acrescenta o valor atual de <code>palpiteUsuario</code> ao final do parágrafo <code>palpites</code>, mais um espaço em branco para que haja espaçamento entre cada palpite mostrado.</li> + <li>O próximo bloco (linhas 8–24 acima) fazem as seguintes conferências: + <ul> + <li>O primeiro <code>if(){ }</code> confere se o palpite do jogador é igual ao número aleatório (<code>numeroAleatorio</code>) definido no topo do nosso JavaScript. Se for, o jogador adivinhou corretamente o número e venceu o jogo. Então mostramos ao jogador uma mensagem de parabenização com uma agradável cor verde, limpamos o conteúdo do parágrado que informa sobre o palpite ser alto ou baixo <code><p class="baixoOuAlto"></p></code>, e executamos uma função chamada <code>configFimDeJogo()</code>, que iremos discutir mais tarde.</li> + <li>Agora nós encadeamos outro teste ao final deste anterior usando uma estrutura <code>else if(){ }</code>. Este confere se o palpite do jogador é sua última tentativa. Se for, o programa faz o mesmo que no bloco anterior, porém com uma mensagem de fim de jogo ao invés do texto de parabeninzação.</li> + <li>O bloco final encadeado ao final do código (<code>else { }</code>) contém código que só é executado se nenhum dos outros dois testes retornar verdadeiro (ou seja, o jogador não acertou o número, porém ainda tem mais tentativas restantes). Neste caso nós dizemos a ele que está errado, e então rodamos outro teste condicional para checar se o palpite foi maior ou menor do que a resposta certa, exibindo então uma mensagem apropriada para informá-lo se foi maior ou menor.</li> + </ul> + </li> + <li>As próximas três linhas da função (linhas 26–28) nos deixa preparados para o próximo palpite ser submetido. Nós somamos 1 à variável <code>contagemPalpites</code> para que o jogador use sua tentativa (<code>++</code> é uma operação de incremento — incrementa em 1), e o campo de texto do formulário de inserção seja esvaziado e focado novamente, pronto para que o próximo palpite seja inserido.</li> +</ul> + +<h3 id="Eventos">Eventos</h3> + +<p>Neste ponto temos uma função <code>conferirPalpite()</code> bem implementada, mas ela não irá fazer nada pois nós não a chamamos ainda. Idealmente nós queremos que ela seja acionada quando o botão "Enviar palpite" for pressionado, e para fazer isso precisamos usar um evento. Eventos são ações que acontencem no navegador, como um botão sendo clicado, ou uma página carregada, ou um vídeo tocando; ações as quais podemos responder executando blocos de código. Os construtores que monitoram os acontecimentos de eventos são chamados de <strong>event listeners</strong>, e os blocos de código executados em resposta ao acontecimento do evento são chamados de <strong>event handlers</strong>.</p> + +<p>Adicione a seguinte linha abaixo da chave de fechamento da sua função <code>conferirPalpite()</code>:</p> + +<pre class="brush: js">envioPalpite.addEventListener('click', conferirPalpite);</pre> + +<p>Aqui nós estamos adicionando um <em>event listener</em> ao botão <code>envioPalpite</code>. Esse é um método que aceita a inserção de dois valores (chamados de argumentos) — o tipo de envento que estamos monitorando (neste caso o evento <code>click</code>) como um <em>string</em> (sequência de texto), e o código que queremos executar quando o evento ocorrer (neste caso a função <code>conferirPalpite()</code> — note que não temos que especificar os parênteses quando estivermos escrevendo dentro de {{domxref("EventTarget.addEventListener", "addEventListener()")}}).</p> + +<p>Tente agora salvar e atualizar seu código, e seu exemplo deve funcionar agora, até um ponto. O único problema agora é que se você acertar o palpite ou ficar sem mais tentativas o jogo irá falhar, porque ainda não definimos a função <code>configFimDeJogo()</code> que deve ser executada uma vez que o jogo terminar. Vamos adicionar agora o código restante e completar a funcionalidade do nosso exemplo.</p> + +<h3 id="Finalizando_a_funcionalidade_do_jogo">Finalizando a funcionalidade do jogo</h3> + +<p>Vamos adicionar a função <code>configFimDeJogo()</code> ao final do nosso código e então explorá-lo. Adicione agora isso, abaixo do restante do seu JavaScript:</p> + +<pre class="brush: js">function configFimDeJogo() { + campoPalpite.disabled = true; + envioPalpite.disabled = true; + botaoReinicio = document.createElement('button'); + botaoReinicio.textContent = 'Iniciar novo jogo'; + document.body.appendChild(botaoReinicio); + botaoReinicio.addEventListener('click', reiniciarJogo); +}</pre> + +<ul> + <li>As primeiras duas linhas desabilitam a entrada de texto do formulário e o clique do botão, definindo a propriedade <em>disabled</em> (desabilitado) de cada um como <code>true</code> (verdadeiro). Isso é necessário, pois se não o fizermos, o usuário poderia submeter mais palpites depois do jogo ter terminado, o que iria bagunçar as coisas.</li> + <li>As próximas três linhas geram um novo elemento {{htmlelement("button")}}, define o texto de seu rótulo como "Iniciar novo jogo", e o adiciona ao final do nosso HTML existente.</li> + <li>A linha final define um monitor de evento (<em>event listener</em>) em nosso botão, para que quando seja clicado, uma função chamada <code>reiniciarJogo()</code> seja executada.</li> +</ul> + +<p>Agora precisamos definir essa função também! Adicione o seguinte código, novamente ao final do nosso JavaScript:</p> + +<pre class="brush: js">function reiniciarJogo() { + contagemPalpites = 1; + + var reiniciarParas = document.querySelectorAll('.resultadoParas p'); + for (var i = 0 ; i < reiniciarParas.length ; i++) { + reiniciarParas[i].textContent = ''; + } + + botaoReinicio.parentNode.removeChild(botaoReinicio); + + campoPalpite.disabled = false; + envioPalpite.disabled = false; + campoPalpite.value = ''; + campoPalpite.focus(); + + ultimoResultado.style.backgroundColor = 'white'; + + numeroAleatorio = Math.floor(Math.random() * 100) + 1; +}</pre> + +<p>Esse longo bloco de código redefine completamente tudo do modo como era no início do jogo, para que o jogador possa jogá-lo novamente. Ele:</p> + +<ul> + <li>Coloca o valor da variável <code>contagemPalpites</code> novamente igual a 1.</li> + <li>Limpa todos os parágrafos de informativos.</li> + <li>Remove o botão resete do nosso código.</li> + <li>Habilita os elementos do formulários, esvazia e direciona o foco ao campo de texto, pronto para que um novo palpite seja inserido.</li> + <li>Remove a cor de fundo do parágrafo <code>ultimoResultado</code>.</li> + <li>Gera um novo número aleatório para que o jogador não esteja tentando adivinhar o mesmo número novamente!</li> +</ul> + +<p><strong>Neste ponto você deve ter um jogo (simples) completamente funcional — parabéns!</strong></p> + +<p>Tudo o que temos que fazer agora neste artigo é falar sobre alguns outros recursos importantes que você já viu, mesmo que não os tenha notado ainda.</p> + +<h3 id="Loops">Loops</h3> + +<p>Uma parte do código acima que precisamos olhar mais detalhadamente é o loop <a href="/en-US/docs/Web/JavaScript/Reference/Statements/for">for</a>. Loop é um conceito muito importante em programação, que permite a você continuar executando um pedaço do código repetidamente, até que determinada condição seja satisfeita.</p> + +<p>Para começar, vá novamente até o <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console JavaScript</a> do seu navegador, e insira o seguinte:</p> + +<pre class="brush: js">for (var i = 1 ; i < 21 ; i++) { console.log(i) }</pre> + +<p>O que aconteceu? Os números de 1 a 20 foram exibidos no seu console. Isso acontece por causa do loop. Um loop <code>for</code> utiliza a inserção de três valores (argumentos):</p> + +<ol> + <li><strong>Um valor inicial</strong>: Nesse caso estamos iniciando a contagem em 1, mas poderia ser qualquer outro número que quisesse utilizar. Você pode substituir <code>i</code> por qualquer número que quiser também, mas <code>i</code> é utilizado por convenção porque é curto e fácil de lembrar.</li> + <li><strong>Uma condição de saída</strong>: Aqui nós especificamos <code>i < 21</code> — o loop irá continuar rodando até que <code>i</code> não seja mais menor que 21. Quando <code>i</code> alcançar 21, o loop não será mais executado.</li> + <li><strong>Incremento</strong>: Nós especificamos <code>i++</code>, que siginifica "adicione 1 à i". O loop irá rodar uma vez para cada valor de <code>i</code>, até que <code>i</code> alcance o valor de 21 (como abordado acima). Nesse caso, nós estamos simplesmente imprimindo o valor de <code>i</code> no console em cada iteração usando {{domxref("Console.log", "console.log()")}}.</li> +</ol> + +<p>Agora vamos olhar o loop em nosso jogo de adivinhar o número — o código seguinte pode ser encontrado dentro da função <code>reiniciarJogo()</code>:</p> + +<pre class="brush: js">var reiniciarParas = document.querySelectorAll('.resultadoParas p'); +for (var i = 0 ; i < reiniciarParas.length ; i++) { + reiniciarParas[i].textContent = ''; +}</pre> + +<p>Esse código cria uma variável contendo uma lista de todos os parágrafos dentro de <code><div class="resultadoParas"></code> usando o método {{domxref("Document.querySelectorAll", "querySelectorAll()")}}, e então faz o loop em cada um, removendo o conteúdo de texto dos mesmos.</p> + +<h3 id="Uma_pequena_discussão_sobre_objetos">Uma pequena discussão sobre objetos</h3> + +<p>Vamos adicionar uma melhoria final antes de chegarmos a essa discussão. Adicione a linha seguinte logo abaixo da linha <code>var botaoReinicio;</code> próximo ao topo do seu JavaScript, em seguida salve nosso arquivo:</p> + +<pre class="brush: js">campoPalpite.focus();</pre> + +<p>Essa linha usa o método {{domxref("HTMLElement.focus", "focus()")}} para automaticamente colocar o cursor dentro campo de texto do {{htmlelement("input")}} assim que a página carrega, significando que o usuário já pode começar a digitar o primeiro palpite, e não precisa clicar no campo do formulário primeiro. É apenas uma pequena adição, mas melhora a usabilidade — dando ao usuário uma boa dica visual do que ele deve fazer para jogar o jogo.</p> + +<p>Vamos analisar o que está acontencedo aqui com um pouco mais de detalhes. Em JavaScript, tudo é um objeto. Um objeto é uma coleção de funcionalidades relacionadas armazenadas em um único agrupamento. Você pode criar seus próprios objetos, mas isso é bastante avançado e nós não iremos abordar até mais tarde no curso. Por agora, vamos apenas discutir brevemente os objetos pré-construídos presentes em seu navegador, que lhe permite fazer várias coisas úteis.</p> + +<p>Neste caso particular, nós primeiro criamos a variável <code>campoPalpite</code> que armazena uma referência ao campo de inserção de texto do formulário em nosso HTML — a linha seguinte pode ser achada entre nossas declarações de variáveis próximas ao topo:</p> + +<pre class="brush: js">var campoPalpite = document.querySelector('.campoPalpite');</pre> + +<p>Para pegar essa referência, usamos o método {{domxref("document.querySelector", "querySelector()")}} do objeto {{domxref("document")}}. <code>querySelector()</code> pega um pedaço de informação — um <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Selectors">seletor CSS</a> que seleciona o elemento ao qual você quer referenciar.</p> + +<p>Como agora <code>campoPalpite</code> contém referência ao elemento {{htmlelement("input")}}, ele terá agora acesso a um número de propriedades (basicamente variáveis armazenadas dentro de objetos, sendo que alguns não podem ter seus valores alterados) e métodos (basicamente, funções armazenadas dentro de objetos). Um método disponível para elementos de inserção <code><input></code>, é o <code>focus()</code>, então agora podemos usar essa linha para focar o campo de inserção de texto:</p> + +<pre class="brush: js">campoPalpite.focus();</pre> + +<p>Variáveis que não contém referências a elementos de formulário não terão <code>focus()</code> disponível para elas. Por exemplo, a variável <code>palpites</code> contém referência de um elemento {{htmlelement("p")}}, e <code>contagemPalpites</code> contém um número.</p> + +<h3 id="Brincando_com_objetos_do_navegador">Brincando com objetos do navegador</h3> + +<p>Vamos brincar um pouco com alguns objetos do navegador.</p> + +<ol> + <li>Primeiro abra seu programa em um navegador.</li> + <li>Em seguida, abra as <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">ferramentas de desenvolvimento do navegador</a>, e certifique-se de que a aba do console JavaScript esteja aberta.</li> + <li>Digite <code>campoPalpite</code> e o console irá lhe mostrar que a variável contém um elemento {{htmlelement("input")}}. Você também irá notar que o console completa automaticamente os nomes de objetos existentes dentro do ambiente de execução, incluindo suas variáveis! + <ol> + <li>Agora digite o seguinte: + <pre class="brush: js">campoPalpite.value = 'Olá';</pre> + A propriedade <code>value</code> representa o valor atual inserido no campo de texto. Você verá que inserindo esse comando, nós mudamos o valor desse objeto!</li> + </ol> + </li> + <li>Agora tente digitar <code>palpites</code> e pressione <em>return</em>. O console irá mostrar que a variável contém um elemento {{htmlelement("p")}}.</li> + <li>Agora tente inserir a linha seguinte: + <pre class="brush: js">palpites.value</pre> + O navegador irá retornar <code>undefined</code>, porque <code>value</code> não existe em parágrafos.</li> + <li>Para mudar o texto dentro de um parágrafo, você precisa da propriedade {{domxref("Node.textContent", "textContent")}}. Tente isso: + <pre class="brush: js">palpites.textContent = 'Onde está meu parágrafo?';</pre> + </li> + <li>Agora algo divertido. Tente inserir as linhas abaixo, uma por uma: + <pre class="brush: js">palpites.style.backgroundColor = 'yellow'; +palpites.style.fontSize = '200%'; +palpites.style.padding = '10px'; +palpites.style.boxShadow = '3px 3px 6px black';</pre> + Cada elemento em uma página tem uma propriedade <code>style</code>, que contém um objeto no qual estão inseridos em suas propriedades todos os estilos incorporados de CSS aplicados ao respectivo elemento. Isso nos permite configurar dinamicamente novos estilos CSS nos elementos usando JavaScript.</li> +</ol> + +<h2 id="Finalizado_por_enquanto...">Finalizado por enquanto...</h2> + +<p>Então é isso, para construir o exemplo — você chegou ao final, muito bem! Teste o resultado do seu código, ou <a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/first-splash/jogo-advinhe-o-numero.html">jogue com nossa versão finalizada aqui</a>. Se você não conseguir fazer o exemplo funcionar, compare com o <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/first-splash/jogo-advinhe-o-numero.html">código fonte</a>.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}}</p> diff --git a/files/pt-br/learn/javascript/first_steps/arrays/index.html b/files/pt-br/learn/javascript/first_steps/arrays/index.html new file mode 100644 index 0000000000..823b4c21f7 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/arrays/index.html @@ -0,0 +1,662 @@ +--- +title: Arrays +slug: Learn/JavaScript/First_steps/Arrays +translation_of: Learn/JavaScript/First_steps/Arrays +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Neste artigo final do módulo, nós vamos dar uma olhada em arrays - um elegante meio de armazenar uma lista de itens em uma mesmo variável. Aqui nós vemos o porquê isto é útil, depois exploraremos como criar uma array, recuperar, adicionar e remover itens armazenados em uma array, e mais.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Leitura básica sobre computadores, um básico entendimento de HTML e CSS, e conhecimento sobre o que é JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender o que é array e como manipular ela em JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="O_que_é_uma_array">O que é uma array?</h2> + +<p>Arrays são geralmente descritas como "lista de objetos"; elas são basicamente objetos que contem múltiplos valores armazenados em uma lista. Um objeto array pode ser armazenado em variáveis e ser tratado de forma muito similar a qualquer outro tipo de valor, a diferença está em podermos acessar cada valor dentro da lista individualmente, e fazer super úteis e eficientes coisas com a lista, como laço através da lista e fazer a mesma coisa para cada valor. Talvez nós pegamos uma série de produtos e seus preços armazenados em uma array, e nós queremos fazer um laço através de todos eles e mostrar em um recibo, enquanto somamos todos os preços e mostramos o preço total ao final.</p> + +<p>Se nós não tivessemos arrays, teríamos que armazenar cada item em uma variável separada, então chamar o código para mostrar e adicionar separadamente cada item. Isto seria muito mais longo de escrever, menos eficiente e mais suscetível a erros. Se nós temos 10 itens para adicionar na fatura, isto é ruim o bastante, mas e se fosse 100 itens ou 1000? Nós vamos retornar a este exemplo mais tarde neste artigo.</p> + +<p>Como no artigo anterior, vamos aprender o básico de arrays introduzindo com alguns exemplos dentro de um console JavaScript. Nós fornecemos um abaixo (você também pode <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">abrir este console</a> em uma aba separada ou janela, ou usar o <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console de desenvolvedor do navegador</a> se preferir).</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>JavaScript console</title> + <style> + * { + box-sizing: border-box; + } + + html { + background-color: #0C323D; + color: #809089; + font-family: monospace; + } + + body { + max-width: 700px; + } + + p { + margin: 0; + width: 1%; + padding: 0 1%; + font-size: 16px; + line-height: 1.5; + float: left; + } + + .input p { + margin-right: 1%; + } + + .output p { + width: 100%; + } + + .input input { + width: 96%; + float: left; + border: none; + font-size: 16px; + line-height: 1.5; + font-family: monospace; + padding: 0; + background: #0C323D; + color: #809089; + } + + div { + clear: both; + } + + </style> + </head> + <body> + + + </body> + + <script> + var geval = eval; + function createInput() { + var inputDiv = document.createElement('div'); + var inputPara = document.createElement('p'); + var inputForm = document.createElement('input'); + + inputDiv.setAttribute('class','input'); + inputPara.textContent = '>'; + inputDiv.appendChild(inputPara); + inputDiv.appendChild(inputForm); + document.body.appendChild(inputDiv); + + if(document.querySelectorAll('div').length > 1) { + inputForm.focus(); + } + + inputForm.addEventListener('change', executeCode); + } + + function executeCode(e) { + try { + var result = geval(e.target.value); + } catch(e) { + var result = 'error — ' + e.message; + } + + var outputDiv = document.createElement('div'); + var outputPara = document.createElement('p'); + + outputDiv.setAttribute('class','output'); + outputPara.textContent = 'Result: ' + result; + outputDiv.appendChild(outputPara); + document.body.appendChild(outputDiv); + + e.target.disabled = true; + e.target.parentNode.style.opacity = '0.5'; + + createInput() + } + + createInput(); + + </script> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Criando_uma_array">Criando uma array</h3> + +<p>Arrays são contruídas de colchetes, os quais contém uma lista de itens separada por vírgulas.</p> + +<ol> + <li>Vamos supor que queremos armazenar uma lista de compras em uma array — nós temos algo como o seguinte. Digite as linhas abaixo no seu console: + <pre class="brush: js">var shopping = ['bread', 'milk', 'cheese', 'hummus', 'noodles']; +shopping;</pre> + </li> + <li>Neste caso, cada item na array é uma string, mas tenha em mente que você pode armazenar qualquer item em uma array — string, número, objeto, outra variável, até outra array. Você pode também misturar e combinar tipos de itens — eles não têm que ser todos números, strings, etc. Tente isto: + <pre class="brush: js">var sequence = [1, 1, 2, 3, 5, 8, 13]; +var random = ['tree', 795, [0, 1, 2]];</pre> + </li> + <li>Tente criar um par de arrays você mesmo, antes de seguir em frente.</li> +</ol> + +<h3 id="Acessando_e_modificando_itens_de_uma_array">Acessando e modificando itens de uma array</h3> + +<p>Você pode acessar itens individuais em uma array usando a notação de colchetes, da mesma forma que você <a href="/en-US/Learn/JavaScript/First_steps/Useful_string_methods#Retrieving_a_specific_string_character">acessa as letras em uma string</a>.</p> + +<ol> + <li>Digite o seguinte no seu console: + <pre class="brush: js">shopping[0]; +// returns "bread"</pre> + </li> + <li>Você também pode modificar um item em uma array simplesmente dando um novo valor ao item. Tente isto: + <pre class="brush: js">shopping[0] = 'tahini'; +shopping; +// shopping vai retornar agora [ "tahini", "milk", "cheese", "hummus", "noodles" ]</pre> + + <div class="note"><strong>Note</strong>: Nós dissemos isto antes, mas como lembrete — computadores começam a contar do 0!</div> + </li> + <li>Note que uma array dentro de uma array é chamada de array multidimensional. Você pode acessar um item dentro de uma array que está localizada dentro de outra array, colocando dois conjuntos de colchetes juntos. Por exemplo, para acessar um dos itens dentro de uma array, que é o terceiro item dentro da array <code>random</code> (veja a seção anterior), nós podemos fazer algo tipo isto: + <pre class="brush: js">random[2][2];</pre> + </li> + <li>Antes de continuar, faça algumas modificações nos exemplos, crie seus próprios arrays e veja o que funciona e o que não funciona. Divirta-se!</li> +</ol> + +<h3 id="Encontrando_o_comprimento_de_uma_array">Encontrando o comprimento de uma array</h3> + +<p>Você pode encontrar o comprimento de uma array (quantos itens existem nela) exatamente do mesmo jeito que você encontra o comprimento (em caracteres) de uma string — usando a propriedade {{jsxref("Array.prototype.length","length")}}. Tente o seguinte:</p> + +<pre class="brush: js">sequence.length; +// deve retornar 7</pre> + +<p>Isto tem outras funcionalidades, mas é mais comum usar em um laço para seguir todos os itens em uma array. Então, por exemplo:</p> + +<pre class="brush: js">var sequence = [1, 1, 2, 3, 5, 8, 13]; +for (var i = 0; i < sequence.length; i++) { + console.log(sequence[i]); +}</pre> + +<p>Você irá aprender sobre laços propriamente em um artigo futuro, mas, brevemente, este código está dizendo:</p> + +<ol> + <li>Comece o laço no item número 0 na array.</li> + <li>Pare o laço no item de número igual ao comprimento da array. Isto funcionará para uma array de qualquer tamanho, mas neste caso vai parar o laço no item 7 (isto é bom, como o último item — que nós queremos que o laço cubra — é 6.</li> + <li>Para cada item, imprima no console do navegador com <code><a href="/en-US/docs/Web/API/Console/log">console.log()</a></code>.</li> +</ol> + +<h2 id="Alguns_métodos_úteis_em_array">Alguns métodos úteis em array</h2> + +<p>Nesta seção vamos ver alguns métodos relacionados a array úteis que nos permitem dividir strings em itens de array e vice-versa, e adicionar novos itens em arrays.</p> + +<h3 id="Convertendo_entre_strings_e_arrays">Convertendo entre strings e arrays</h3> + +<p>Frequentemente você vai se deparar com alguns dados contidos em uma grande e longa string, e você pode querer separar os itens em uma forma mais útil e então manipular eles, como mostrar em uma tabela. Para fazer isto, nós podemos usar o método {{jsxref("String.prototype.split()","split()")}}. Nesta forma mais simples, ela pega um parâmetro solitário, o caracter que você deseja separar da string e retorna o restante antes e depois do item separado na array.</p> + +<div class="note"> +<p><strong>Nota</strong>: Ok, isto é tecnicamente um método de string, não um método de array, mas nós podemos colocar em arrays já que cai bem.</p> +</div> + +<ol> + <li>Vamos brincar com isto para ver como funciona. Primeiro, crie uma string no seu console: + <pre class="brush: js">var myData = 'Manchester,London,Liverpool,Birmingham,Leeds,Carlisle';</pre> + </li> + <li>Agora vamos dividir isto em cada vírgula: + <pre class="brush: js">var myArray = myData.split(','); +myArray;</pre> + </li> + <li>Finalmente, tentamos encontrar o comprimento da sua nova array, e recuperar alguns itens dela: + <pre class="brush: js">myArray.length; +myArray[0]; // the first item in the array +myArray[1]; // the second item in the array +myArray[myArray.length-1]; // the last item in the array</pre> + </li> + <li>Você também pode ir no sentido oposto usando o método {{jsxref("Array.prototype.join()","join()")}}. Tente o seguinte: + <pre class="brush: js">var myNewString = myArray.join(','); +myNewString;</pre> + </li> + <li>Outro jeito de converter uma array em uma string é usar o método {{jsxref("Array.prototype.toString()","toString()")}}. <code>toString()</code> é indiscutivelmente mais simples <code>join()</code> pois não necessita um parâmetro, mas mais limitado. Com <code>join()</code> você pode especificar diferentes separadores (tente o passo 4 com um caracter diferente da vírgula). + <pre class="brush: js">var dogNames = ['Rocket','Flash','Bella','Slugger']; +dogNames.toString(); //Rocket,Flash,Bella,Slugger</pre> + </li> +</ol> + +<h3 id="Adicionando_e_removendo_itens_de_arrays">Adicionando e removendo itens de arrays</h3> + +<p>Nós ainda não falamos sobre adicionar e remover itens de uma array — vamos dar uma olhada agora. Nós vamos usar a array <code>myArray</code> que acabamos de criar na última seção. Se você não viu a última seção, primeiro crie a array no seu console:</p> + +<pre class="brush: js">var myArray = ['Manchester', 'London', 'Liverpool', 'Birmingham', 'Leeds', 'Carlisle'];</pre> + +<p>Antes de tudo, para adicionar ou remover um item no final de uma array, nós podemos usar {{jsxref("Array.prototype.push()","push()")}} e {{jsxref("Array.prototype.pop()","pop()")}} respectivamente.</p> + +<ol> + <li>note que você precisa para incluir um ou mais itens ao final da sua array. Tente isto: + <pre class="brush: js">myArray.push('Cardiff'); +myArray; +myArray.push('Bradford', 'Brighton'); +myArray; +</pre> + </li> + <li>O novo comprimento da array é retornado quando a chamada do método completa. Se você quer armazenar o novo comprimento da array em uma variável, você poderia fazer algo como isto: + <pre class="brush: js">var newLength = myArray.push('Bristol'); +myArray; +newLength;</pre> + </li> + <li>Removendo o último item da array é tão simples como um <code>pop()</code> nele. Tente isto: + <pre class="brush: js">myArray.pop();</pre> + </li> + <li>O item que foi removido é retornado quando a chamada do método completa. Para salvar o item em uma nova variável, você poderia fazer isto: + <pre class="brush: js">var removedItem = myArray.pop(); +myArray; +removedItem;</pre> + </li> +</ol> + +<p>{{jsxref("Array.prototype.unshift()","unshift()")}} e {{jsxref("Array.prototype.shift()","shift()")}} funciona exatamente do mesmo modo que <code>push()</code> e <code>pop()</code>, respectivamente, exceto que eles funcionam no começo da array, não no final.</p> + +<ol> + <li>Primeiro <code>unshift()</code> — tente os seguintes comandos: + + <pre class="brush: js">myArray.unshift('Edinburgh'); +myArray;</pre> + </li> + <li>Agora <code>shift()</code>;Tente estes! + <pre class="brush: js">var removedItem = myArray.shift(); +myArray; +removedItem;</pre> + </li> +</ol> + +<h2 id="Aprendizado_ativo_Imprimindo_aqueles_produtos!">Aprendizado ativo: Imprimindo aqueles produtos!</h2> + +<p>Vamos retornar ao exemplo que descrevemos antes — imprimindo nomes de produtos e preços em uma fatura, então totalizando os preços e imprindindo eles ao final. No exemplo editável abaixo há comentários contendo números — cada um deles marcam um lugar onde você tem que acidionar algo ao código. Eles são como segue:</p> + +<ol> + <li>Abaixo do comentário <code>// number 1</code> está um número de strings, cada uma contendo um nome de produto e preço separado por uma vírgula. Nós gostaríamos que você colocasse eles dentro de uma array e armazenasse eles na array chamada <code>products</code>.</li> + <li>Na mesma linha o comentário <code>// number 2 </code>está no começo de um laço for. Nesta linha nós temos <code>i<=0</code>, o qual é um teste condicional que faz o <a href="/en-US/Learn/JavaScript/First_steps/A_first_splash#Loops">laço for</a> parar imediatamente, porque está dizendo "pare quando <code>i</code> for menor ou igual a 0", e <code>i</code> começa em 0. Nós gostaríamos de substituir isto com um teste condicional que termina o laço quando o <code>i </code>for menor que o tamanho da array <code>products</code>.</li> + <li>Logo abaixo do comentário <code>// number 3 </code>nós queremos que você escreva uma linha de código que divide o item da array (<code>name:price</code>) em dois itens separados, um contendo somente o nome e outro só com o preço. Se você não tem certeza de como fazer isto, consulte o artigo <a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos úteis em string </a>para alguma ajuda, ou ainda melhor, veja a seção {{anch("Converting between strings and arrays")}} neste artigo.</li> + <li>Como parte da linha de código acima, você também quer converter o preço de string para número. Se você não se lembra como fazer isto, veja o <a href="/en-US/Learn/JavaScript/First_steps/Strings#Numbers_versus_strings">artigo primeiras strings</a>.</li> + <li>Há uma variável chamada <code>total </code>que é criada e atribuída o valor 0 no começo do código. Dentro do loop (abaixo <code>// number 4</code>) nós queremos que você escreva uma linha que adicione o preço atual ao total em cada iteração do laço, então ao final do código o preço total é impresso na fatura. Você pode precisar de um <a href="/en-US/Learn/JavaScript/First_steps/Math#Assignment_operators">operador aritiméticos </a>para isto.</li> + <li>Nós queremos que você mude a linha logo abaixo de <code>// number 5</code> para que a variável <code>itemText</code> seja igual a "nome do item atual - $preço do item atual", por exemplo "Shoes - $23.99" em cada caso, então a informação correta para cada item é impressa na fatura. Esta é uma simples concatenação de string, a qual deveria ser familiar para você.</li> +</ol> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html"><h2>Live output</h2> + +<div class="output" style="min-height: 150px;"> + +<ul> + +</ul> + +<p></p> + +</div> + +<h2>Editable code</h2> + +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="playable-code" style="height: 410px;width: 95%"> +var list = document.querySelector('.output ul'); +var totalBox = document.querySelector('.output p'); +var total = 0; +list.innerHTML = ''; +totalBox.textContent = ''; +// number 1 + 'Underpants:6.99' + 'Socks:5.99' + 'T-shirt:14.99' + 'Trousers:31.99' + 'Shoes:23.99'; + +for (var i = 0; i <= 0; i++) { // number 2 + // number 3 + + // number 4 + + // number 5 + itemText = 0; + + var listItem = document.createElement('li'); + listItem.textContent = itemText; + list.appendChild(listItem); +} + +totalBox.textContent = 'Total: $' + total.toFixed(2); +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nvar totalBox = document.querySelector(\'.output p\');\nvar total = 0;\nlist.innerHTML = \'\';\ntotalBox.textContent = \'\';\n\nvar products = [\'Underpants:6.99\',\n \'Socks:5.99\',\n \'T-shirt:14.99\',\n \'Trousers:31.99\',\n \'Shoes:23.99\'];\n\nfor(var i = 0; i < products.length; i++) {\n var subArray = products[i].split(\':\');\n var name = subArray[0];\n var price = Number(subArray[1]);\n total += price;\n itemText = name + \' — $\' + price;\n\n var listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n}\n\ntotalBox.textContent = \'Total: $\' + total.toFixed(2);'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> + +<pre class="brush: css">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background-color: #f5f9fa; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', '100%', 730, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Aprendizado_ativo_Top_5_buscadores">Aprendizado ativo: Top 5 buscadores</h2> + +<p>Um bom uso para os métodos de array como {{jsxref("Array.prototype.push()","push()")}} e {{jsxref("Array.prototype.pop()","pop()")}} está quando você está mantendo um registro de itens atuais ativos em um aplicativo web. Em uma cena animada, por exemplo, você pode ter uma array de objetos representando o gráfico de fundo mostrado atualmente, e você pode querer somente mostrar 50 por vez, para performace ou alguma razão de ordem. Como novos objetos são criados e adicionados na array, os antigos podem ser deletados da array para manter o número desejado.</p> + +<p>Neste exemplo nós vamos mostrar um uso bem mais simples — aqui nós estamos dando a você um falso site de busca, com uma caixa de busca. A idéia é que quando termos são digitados na caixa de busca, os 5 principais termos de busca anterior sejam mostrados na lista. Quando o número de termos passar de 5, o último termo começa sendo deletado. A cada vez um novo termo é adicionado ao topo, então os 5 termos anteriores são sempre mostrados.</p> + +<div class="note"> +<p><strong>Nota</strong>: Em um aplicativo de busca real, você seria, provavelmente, habilitado a clicar nos termos anteriores para retornar às pesquisas, e isto iria mostrar o reusltado atual! Nós estamos só mantendo simples, por agora.</p> +</div> + +<p>Para completar o aplicativo, nós precisamos que você:</p> + +<ol> + <li>Adicione uma linha abaixo do comentário <code>// number 1</code> que adicione o valor digitado atual na busca ao começo da array. Isto pode ser recuperado usando <code>searchInput.value</code>.</li> + <li>Adicione uma linha abaixo do comentário <code>// number 2</code> que remova o último valor no fim da array.</li> +</ol> + +<div class="hidden"> +<h6 id="Playable_code_2">Playable code 2</h6> + +<pre class="brush: html"><h2>Live output</h2> +<div class="output" style="min-height: 150px;"> + +<input type="text"><button>Search</button> + +<ul> + +</ul> + +</div> + +<h2>Editable code</h2> + +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + + +<textarea id="code" class="playable-code" style="height: 370px; width: 95%"> +var list = document.querySelector('.output ul'); +var searchInput = document.querySelector('.output input'); +var searchBtn = document.querySelector('.output button'); + +list.innerHTML = ''; + +var myHistory = []; + +searchBtn.onclick = function() { + // we will only allow a term to be entered if the search input isn't empty + if (searchInput.value !== '') { + // number 1 + + // empty the list so that we don't display duplicate entries + // the display is regenerated every time a search term is entered. + list.innerHTML = ''; + + // loop through the array, and display all the search terms in the list + for (var i = 0; i < myHistory.length; i++) { + itemText = myHistory[i]; + var listItem = document.createElement('li'); + listItem.textContent = itemText; + list.appendChild(listItem); + } + + // If the array length is 5 or more, remove the oldest search term + if (myHistory.length >= 5) { + // number 2 + + } + + // empty the search input and focus it, ready for the next term to be entered + searchInput.value = ''; + searchInput.focus(); + } +} +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div></pre> + +<pre class="brush: css">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nvar searchInput = document.querySelector(\'.output input\');\nvar searchBtn = document.querySelector(\'.output button\');\n\nlist.innerHTML = \'\';\n\nvar myHistory= [];\n\nsearchBtn.onclick = function() {\n if(searchInput.value !== \'\') {\n myHistory.unshift(searchInput.value);\n\n list.innerHTML = \'\';\n\n for(var i = 0; i < myHistory.length; i++) {\n itemText = myHistory[i];\n var listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n }\n\n if(myHistory.length >= 5) {\n myHistory.pop();\n }\n\n searchInput.value = \'\';\n searchInput.focus();\n }\n}'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', '100%', 700, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Conclusão">Conclusão</h2> + +<p>Depois de ler este artigo, nós temos certeza que você concordará que arrays parecem muito úteis; você verá elas surgirem em todo lugar em JavaScript, frequentemente associadas com laços para fazer a mesma coisa para cada item de uma array. Nós estaremos ensinando a você todo o básico que há para saber sobre laços no próximo módulo, mas por agora você deve se dar uma palmada de incentivo e dar uma bem merecida parada; você trabalhou durante todo os artigos neste módulo!</p> + +<p>A única coisa que resta a fazer é trabalhar na avaliação deste módulo, a qual vai testar seu entendimento dos artigos anteriores a este.</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Indexed_collections">Coleções indexadas</a> — um guia avançado guia de arrays e seus primos,<em> typed arrays</em>.</li> + <li>{{jsxref("Array")}} — a página de referência <code>Array</code> — para um guia de referência detalhado para as funcionalidades discutidas nesta página e muito mais.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript">O que é JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/A_first_splash">Um primeiro mergulho em JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong">O que deu errado? Resolvendo problemas no JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables">Armazenando as informações que você precisa — Variáveis</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math">Matemática básica em JavaScript — números e operadores</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings">Trabalhando com texto — strings em JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos úteis em String</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Silly_story_generator">Avaliação: geração de histórias bobas</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/first_steps/gerador_de_historias_bobas/index.html b/files/pt-br/learn/javascript/first_steps/gerador_de_historias_bobas/index.html new file mode 100644 index 0000000000..cc8a8cc542 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/gerador_de_historias_bobas/index.html @@ -0,0 +1,123 @@ +--- +title: Gerador de histórias bobas +slug: Learn/JavaScript/First_steps/Gerador_de_historias_bobas +translation_of: Learn/JavaScript/First_steps/Silly_story_generator +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Nesta avaliação, você será encarregado de utilizar parte do conhecimento que você adquiriu nos artigos deste módulo e aplicá-lo para criar um aplicativo divertido que gera histórias bobas aleatórias. Divirta-se!</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Antes de tentar esta avaliação, você já deve ter trabalhado com todos os artigos deste módulo.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Testar a compreensão dos fundamentos de JavaScript, como variáveis, números, operadores, cadeias de caracteres e matrizes.</td> + </tr> + </tbody> +</table> + +<h2 id="Ponto_de_partida">Ponto de partida</h2> + +<p>Para começar esta avaliação, você deve:</p> + +<ul> + <li><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/assessment-start/index.html">Pegue o arquivo HTML</a> para o exemplo e salve uma cópia local deste arquivo como index.html em um novo diretório em algum local do seu computador. Este arquivo ainda contém o CSS para estilizar o exemplo contido no arquivo.</li> + <li>Vá para a <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/assessment-start/raw-text.txt">página que contém o texto bruto</a> e matenha-a aberta em uma aba separada do navegador em algum lugar. Você precisará dela mais tarde.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Alternativamente, você pode utilizar um site como <a class="external external-icon" href="http://jsbin.com/">JSBin</a> ou <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> para fazer a sua avaliação. Você pode colar o HTML, CSS e javaScript em um desses editores online. Se o editor online que você estiver utilizando não possuir um painel separado para javaScript, sinta-se a vontade para inseri-lo em um elemento <script> dentro da página HTML.</p> +</div> + +<h2 id="Resumo_do_projeto">Resumo do projeto</h2> + +<p>Você recebeu algum HTML/CSS em bruto e algumas strings de texto e funções de JavaScript; Você precisa escrever o JavaScript necessário para transformar este em um programa funcional, que faz o seguinte:</p> + +<ul> + <li>Gera uma história boba quando o botão "Gerar história aleatória" é pressionado.</li> + <li>Substitui o nome padrão "Bob" na história com um nome personalizado, somente se um nome personalizado for inserido no campo de texto "Inserir nome personalizado" antes que o botão de geração seja pressionado.</li> + <li>Gera outra história boba aleatória se você pressionar novamente o botão (e novamente...)</li> +</ul> + +<p>A seguinte captura de tela mostra um exemplo do que o programa concluído deve produzir:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13667/assessment-1.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>Para dar-lhe mais uma ideia, <a href="http://mdn.github.io/learning-area/javascript/introduction-to-js-1/assessment-finished/">dê uma olhada no exemplo concluído</a> (sem espreitar o código fonte!)</p> + +<h2 id="Passos_para_completar">Passos para completar</h2> + +<p>As seções a seguir descrevem o que você precisa fazer.</p> + +<p>Configuração básica:</p> + +<ol> + <li>Crie um novo arquivo chamado main.js, no mesmo diretório que o arquivo index.html.</li> + <li>Aplique o arquivo JavaScript externo ao seu HTML inserindo um elemento {{htmlelement ("script")}} no seu HTML referenciando o main.js. Coloque-o antes da etiqueta de fechamento {{htmlelement("body")}}.</li> +</ol> + +<p>Variáveis e funções iniciais:</p> + +<ol> + <li>No arquivo de texto cru, copie todo o código abaixo do cabeçalho "1. COMPLETE VARIABLE AND FUNCTION DEFINITIONS" e cole-o no topo do arquivo main.js. Isso dá a você três variáveis que armazenam referências ao campo de texto "Inserir nome personalizado" (customName), o botão "Gerar história aleatória" (randomizar), E o elemento {{htmlelement ("p")}} na parte inferior do corpo HTML para onde a história será copiada (história), respectivamente. Além disso, você tem uma função chamada randomValueFromArray () que recebe um vetor e retorna um dos itens armazenados dentro do vetor aleatoriamente.</li> + <li>Agora, veja a segunda seção do arquivo de texto bruto - "2. RAW TEXT STRINGS". Ele contém strings de texto que atuarão como entrada em nosso programa. Gostaríamos que você armazenasse essas strings dentro de variáveis no main.js: + <ol> + <li>Armazene a primeira, grande e longa linha de texto dentro de uma variável chamada storyText.</li> + <li>Armazene o primeiro conjunto de três strings dentro de um vetor chamado insertX.</li> + <li>Armazene o segundo conjunto de três strings dentro de um vetor chamado insertY.</li> + <li>Armazene o terceiro conjunto de três strings dentro de um vetor chamado insertZ.</li> + </ol> + </li> +</ol> + +<p>Colocando o manipulador de eventos e a função incompleta:</p> + +<ol> + <li>Agora volte ao arquivo de texto bruto.</li> + <li>Copie o código encontrado abaixo do cabeçalho "3. EVENT LISTENER AND PARTIAL FUNCTION DEFINITION" E cole ele na parte inferior do arquivo main.js. Isto: + <ul> + <li>Adicione um ouvinte de evento de clique à variável randomize para que, quando o botão que ele representa, for clicado, a função <code>result()</code> seja executada.</li> + <li>Adicione a função <code>result()</code> parcialmente concluída ao seu código. Para o restante da avaliação, você estará preenchendo linhas dentro desta função para completá-la e fazê-la funcionar corretamente.</li> + </ul> + </li> +</ol> + +<p>Completando a função <code>result()</code>:</p> + +<ol> + <li>Crie uma nova variável chamada <code>newStory</code>, e defina seu valor como igual a <code>storyText</code>. Isso é necessário para que possamos criar uma nova história aleatória toda vez que o botão for pressionado e a função for executada. Se fizermos alterações diretamente no <code>storyText</code>, só poderemos gerar uma nova história uma vez.</li> + <li>Crie três novas variáveis chamadas <code>xItem</code>, <code>yItem</code>, e <code>zItem</code>, e torne-as iguais ao resultado da chamada da função <code>randomValueFromArray()</code> em seus três arrays (o resultado em cada caso será um item aleatório de cada array em que é chamado). Por exemplo, você pode chamar a função e fazer com que ela retorne uma string aleatória de <code>insertX</code> escrevendo <code>randomValueFromArray(insertX)</code>.</li> + <li>Em seguida, queremos substituir os três espaços reservados na variável <code>newStory</code> — <code>:insertx:</code>, <code>:inserty:</code>, e <code>:insertz:</code> — com strings armazenadas em <code>xItem</code>, <code>yItem</code>, e <code>zItem</code>. Existe um método de string específico que irá ajudá-lo aqui - em cada caso, faça a chamada para o método igual a <code>newStory</code>,então cada vez que é chamado, newStory é igual a si mesmo, mas com substituições feitas. Assim, cada vez que o botão é pressionado, esses espaços reservados são substituídos por uma string boba aleatória. Como uma dica adicional, o método em questão substitui apenas a primeira ocorrência da subseqüência de caracteres encontrada, portanto, talvez seja necessário fazer uma das chamadas duas vezes.</li> + <li>Dentro do primeiro bloco <code>if</code>, adicione outra chamada de método de substituição de string para substituir o nome 'Bob' encontrado na string <code>newStory</code> pela variável <code>name</code>. Neste bloco estamos dizendo "Se um valor foi inserido na entrada de texto <code>customName</code>, substitua Bob na história por esse nome personalizado ".</li> + <li>Dentro do segundo bloco <code>if</code>, estamos verificando se o botão de opção <code>uk</code> foi selecionado. Se assim for, converteremos os valores de peso e temperatura na história de libras e Fahrenheit em graus centígrados. O que você precisa fazer é o seguinte: + <ol> + <li>Procure as fórmulas para converter libras em pedras e Fahrenheit em centígrados.</li> + <li>Dentro da linha que define a variável <code>weight</code>, substitua 300 por um cálculo que converta 300 libras em pedras. Concatene <code>' stone'</code> no final do resultado da chamada geral <code>Math.round()</code>.</li> + <li>Dentro da linha que define a variável <code>temperature</code>, substitua 94 por um cálculo que converta 94 graus Fahrenheit em graus centígrados. Concatene <code>' centigrade'</code> no resultado da chamada geral <code>Math.round()</code>.</li> + <li>Apenas sob as duas definições de variáveis, adicione mais duas linhas de substituição de string que substituem '94 fahrenheit' pelo conteúdo da variável <code>temperature</code>, e '300 libras' com o conteúdo da variável <code>weight</code>.</li> + </ol> + </li> + <li>Finalmente, na segunda e última linha da função, torne a propriedade<code>textContent</code> da variável <code>story</code> (que faz referência ao parágrafo) igual a <code>newStory</code>.</li> +</ol> + +<h2 id="Dicas_e_sugestões">Dicas e sugestões</h2> + +<ul> + <li>Você não precisa editar o HTML de nenhuma maneira, exceto para adicionar o JavaScript ao seu HTML.</li> + <li>Se você não tiver certeza se o JavaScript é aplicado ao seu HTML corretamente, tente remover todo o restante do arquivo JavaScript temporariamente, adicionando um pouco de JavaScript que você sabe que criará um efeito óbvio, salvando e atualizando. Por exemplo, o seguinte transforma o plano de fundo do elemento {{htmlelement ("html")}} em vermelho - para que a janela inteira do navegador fique vermelha se o JavaScript for aplicado corretamente: + <pre class="brush: js">document.querySelector('html').style.backgroundColor = 'red';</pre> + </li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round">Math.round()</a> é um método JavaScript integrado que simplesmente arredonda o resultado de um cálculo para o número inteiro mais próximo.</li> +</ul> + +<h2 id="Avaliação">Avaliação</h2> + +<p>Se você estiver seguindo esta avaliação como parte de um curso organizado, você está apto a entregar seu trabalho ao seu professor/mentor para avaliação. Se você é auto-didata, então você pode consultar o guia de marcação com bastante facilidade perguntando no <a href="https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294">tópico do Discurso da área de aprendizagem</a>, ou no no canal <a href="irc://irc.mozilla.org/mdn">#mdn</a> IRC no <a href="https://wiki.mozilla.org/IRC">IRC Mozilla</a>. Tente realizar o exercício primeiro — não há nada a ganhar com a trapaça!</p> + +<p>{{PreviousMenu("Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</p> diff --git a/files/pt-br/learn/javascript/first_steps/index.html b/files/pt-br/learn/javascript/first_steps/index.html new file mode 100644 index 0000000000..a7b30d2ad0 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/index.html @@ -0,0 +1,73 @@ +--- +title: Primeiros passos com JavaScript +slug: Learn/JavaScript/First_steps +tags: + - Arrays + - Artigo + - Assessment + - Beginner + - CodingScripting + - Guia(2) + - Guide + - Iniciante + - JavaScript + - Landing + - Matrizes + - Module + - NeedsTranslation + - Numbers + - Operadores + - Operators + - TopicStub + - Variables + - maths + - strings +translation_of: Learn/JavaScript/First_steps +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Em nosso primeiro módulo de JavaScript, vamos responder algumas questões fundamentais como "o que é JavaScript?", "com o que se parece?", e "o que ele pode fazer?", antes de levá-lo a sua primeira experiência em escrever JavaScript. Depois disso, vamos discutir em detalhes algumas peças chaves, como variáveis, cadeias de caracteres (<em>strings</em>), números (<em>numbers</em>) e matrizes (<em>arrays</em>).</p> + +<h2 id="Pré-requisitos">Pré-requisitos</h2> + +<p>Antes de iniciar esse módulo, você não precisa de nenhum conhecimento prévio de JavaScript, mas você deve ter alguma familiaridade com HTML e CSS. Te recomendamos a estudar os seguintes módulos antes de começar com o JavaScript:</p> + +<ul> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Getting_started_with_the_web">Iniciando com a Web</a> (o que inclui uma <a href="/pt-BR/docs/Learn/Getting_started_with_the_web/JavaScript_basics">introdução rápida ao JavaScript</a>)</li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Web/Guide/HTML/Introduction">Introdução ao HTML</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/CSS/Introduction_to_CSS">Introdução ao CSS</a></li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Se você está trabalhando em um computador/tablet/outro dispositivo onde você não pode criar os seus próprio arquivos, você pode experimentar (em sua maioria) os códigos de exemplo em um programa de codificação online como <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guias">Guias</h2> + +<dl> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/What_is_JavaScript">O que é JavaScript?</a></dt> + <dd>Bem vindo ao curso para iniciantes em JavaScript do MDN! No primeiro artigo nós visualizaremos o JavaScript de uma perspectiva de alto nível, respondendo a questões como "o que é?" e "o que ele pode fazer?", permitindo-lhe entender confortavelmente o objetivo do JavaScript.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/A_first_splash">Um primeiro mergulho no JavaScript</a></dt> + <dd>Agora que você tem uma noção teórica do JavaScript e o que você pode fazer com ele, nós vamos lhe dar um curso intensivo sobre as funcionalidades básicas do JavaScript através de um tutorial completamente prático. Aqui você ira construir, passo a passo, um jogo simples de "Advinhe o número".</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/What_went_wrong">O que deu errado? Solucionando problemas em JavaScript</a></dt> + <dd>Quando você construiu o jogo "Adivinhe o número" no artigo anterior, talvez tenha notado que ele não funcionou. Nunca tema — este artigo visa preservá-lo de ter que arrancar seus cabelos devido a esses problemas por prover-lhe alguns exemplos simples de como consertar erros em programas JavaScript.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/Variables">Armazenando a informação necessária — Variáveis</a></dt> + <dd>Após ler os últimos artigos, você agora deve saber o que é o JavaScript, o que ele pode fazer para você, como usa-lo junto a com outras tecnologias web, e como sua funcionalidade principal se parece de um alto nível. Nesse artigo nós vamos ver o que é realmente básico, vendo como trabalhar com os mais básicos blocos de construção do JavaScript — Variáveis.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/Math">Matemática básica com JavaScript — números e operadores</a></dt> + <dd>Nesse ponto do curso nós iremos discutir matemática no JavaScript — como nós combinamos operadores e outras funcionalidades para manipular números para fazer nosso comando.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/Strings">Manuseando textos — cadeia de caracteres (strings) em JavaScript</a></dt> + <dd>Em seguida nós colocaremos nossa atenção em strings — isso é como pedaços de texto são chamados na programação. Nesse artigos nós vamos ver todas as coisas comuns que você realmente deve saber sobre strings quando estiver aprendendo JavaScript, como criar strings, manusear aspas nas strings, e juntando elas.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos úteis sobre cadeias de caracteres (strings)</a></dt> + <dd>Agora nós vemos o mais básico sobre strings, vamos começar a pensar sobre quais operações úteis nós podemos fazer com elas com os metótos internos, como por exemplos encontrar o tamanho do texto em uma strings, juntar e separar strings, substrituir um caractere de uma string e mais.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/Arrays">Matrizes</a></dt> + <dd>No artigo final desse módulo, nós iremos ver matrizes (arrays) — um jeito fácil de armazenar lista de dados em apenas um nome de variável. Aqui nós veremos o por quê disso ser útil, então exploraremos como criar uma matriz, retornar seus dados, adicionar e remover itens armazenas em um array, e mais além disso.</dd> +</dl> + +<h2 id="Avaliação">Avaliação</h2> + +<p>A avaliação seguinte vai testar o que você entendeu sobre o básico de JavaScript coberto pelos guias acima.</p> + +<dl> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/Silly_story_generator">Gerador de histórias bobas</a></dt> + <dd>Nessa avaliação você será a desafiado a usar seu conhecimento adquirido nesse módulo e aplicará criando um divertido aplicativo que gerará histórias bobas aleatórias. Divirta-se.</dd> +</dl> diff --git a/files/pt-br/learn/javascript/first_steps/matematica/index.html b/files/pt-br/learn/javascript/first_steps/matematica/index.html new file mode 100644 index 0000000000..fce74528f7 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/matematica/index.html @@ -0,0 +1,418 @@ +--- +title: Matemática básica no JavaScript — números e operadores +slug: Learn/JavaScript/First_steps/Matematica +tags: + - Artigo + - Código + - Guía + - Iniciante + - JavaScript + - Matemática + - Operadores + - Script + - aprenda + - aumentada + - incremento + - modulo +translation_of: Learn/JavaScript/First_steps/Math +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Neste ponto do curso estaremos discutindo matemática em JavaScript — Como podemos usar {{Glossary("Operador","operadores")}} e outros recursos para manipular números e fazer cálculos.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimento básico em informática, uma compreensão básica de HTML e CSS, uma compreensão do que é o JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ganhar familiaridade com o básico em matemática no JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Todo_mundo_ama_matemática">Todo mundo ama matemática</h2> + +<p>Ok, talvez não. Alguns de nós gostam de matemática, alguns de nós tem a odiado desde que tivemos que aprender a tabuada de multiplicação e divisão na escola, e alguns de nós estão em algum lugar no meio dos dois cenários. Mas nenhum de nós pode negar que a matemática é uma parte fundamental da vida sem a qual não poderíamos ir muito longe. Isso é especialmente verdadeiro quando estamos aprendendo a programar em JavaScript (ou em qualquer outra linguagem, diga-se de passagem) — muito do que fazemos se baseia no processamento de dados numéricos, cálculo de novos valores, etc. Assim você não ficará surpreso em aprender que o JavaScript tem uma configuração completa de funções matemáticas disponíveis.</p> + +<p>Este artigo discute apenas as partes básicas que você precisa saber agora.</p> + +<h3 id="Tipos_de_números">Tipos de números</h3> + +<p>Em programação, até mesmo o humilde sistema de números decimais que todos nós conhecemos tão bem é mais complicado do que você possa pensar. Usamos diferentes termos para descrever diferentes tipos de números decimais, por exemplo:</p> + +<ul> + <li><em><strong>Integers</strong> </em>(inteiros) são números inteiros, ex. 10, 400 ou -5.</li> + <li><strong>Números de ponto flutuante</strong><em> (floats)</em> tem pontos e casas decimais, por exemplo 12.5 e 56.7786543.</li> + <li><em><strong>Doubles</strong> </em>são tipos de <em>floats </em>que tem uma precisão maior do que os números de ponto flutuante padrões (significando que eles são mais precisos, possuindo uma grande quantidade de casas decimais).</li> +</ul> + +<p>Temos até mesmo diferentes tipos de sistemas numéricos! O decimal tem por base 10 (o que significa que ele usa um número entre 0–9 em cada casa), mas temos também algo como:</p> + +<ul> + <li><strong>Binário</strong> — A linguagem de menor level dos computadores; 0s e 1s.</li> + <li><strong>Octal</strong> — Base 8, usa um caractere entre 0–7 em cada coluna.</li> + <li><strong>Hexadecimal</strong> — Base 16, usa um caractere entre 0–9 e depois um entre a–f em cada coluna. Você pode já ter encontrado esses números anteriormente, trabahando com <a href="/pt-BR/docs/Aprender/CSS/Introduction_to_CSS/Valores_e_unidades#Valores_hexadecimais">cores no CSS</a>.</li> +</ul> + +<p><strong>Antes de se preocupar com seu cérebro estar derretendo, pare agora mesmo!</strong> Para um começo, vamos nos ater aos números decimais no decorrer desse curso; você raramente irá se deparar com a necessidade de começar a pensar sobre os outros tipos, se é que vai precisar algum dia.</p> + +<p>A segunda boa notícia é que, diferentemente de outras linguagens de programação, o JavaScript tem apenas um tipo de dados para números, você advinhou, {{jsxref("Number")}}. Isso significa que qualquer que seja o tipo de números com os quais você está lidando em JavaScript, você os manipula do mesmo jeito.</p> + +<h3 id="Tudo_é_número_para_mim">Tudo é número para mim</h3> + +<p>Vamos brincar rapidamente com alguns números para nos familiarizarmos com a sintaxe básica que precisamos. Insira os comandos listados abaixo em seu <a href="/pt-BR/docs/Learn/Common_questions/ferramentas_de_desenvolvimento_do_navegador">console JavaScript</a>, ou use o console simples incorporado abaixo, se preferir.</p> + +<p>{{EmbedGHLiveSample("learning-area-pt-br/javascript/introduction-to-js-1/variables/index.html", '100%', 300)}}</p> + +<p><strong><a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/variables/">Abra em uma nova janela</a></strong></p> + +<ol> + <li>Primeiramente, vamos declarar duas variáveis e as inicializar com um <em>integer</em> e um <em>float</em>, respectivamente, então digitaremos os nomes das variávei para verificar se está tudo em ordem: + + <pre class="brush: js notranslate">var meuInt = 5; +var meuFloat = 6.667; +meuInt; +meuFloat;</pre> + </li> + <li>Valores numéricos são inseridos sem aspas — tente declarar e inicializar mais duas variáveis contendo números antes de seguir em frente.</li> + <li>Agora vamos checar se nossas duas variáveis originais são do mesmo tipo de dados. Há um operador chamado {{jsxref("Operators/typeof", "typeof")}} no JavaScript que faz isso. Insira as duas linhas conforme mostradas abaixo: + <pre class="brush: js notranslate">typeof meuInt; +typeof meuFloat;</pre> + Você deve obter <code>"number"</code> de volta nos dois casos — isso torna as coisas muito mais fáceis para nós do que se diferentes tipos de números tivessem diferentes tipos de dados, e tivéssemos que lidar com eles em diferentes maneiras. Ufa!</li> +</ol> + +<h2 id="Operadores_aritméticos">Operadores aritméticos</h2> + +<p>São os operadores que utilizamos para fazer as operações aritiméticas básicas:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operador</th> + <th scope="col">Nome</th> + <th scope="col">Propósito</th> + <th scope="col">Exemplo</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>+</code></td> + <td>Adição</td> + <td>Adiciona um número a outro.</td> + <td><code>6 + 9</code></td> + </tr> + <tr> + <td><code>-</code></td> + <td>Subtração</td> + <td>Subtrai o número da direita do número da esquerda.</td> + <td><code>20 - 15</code></td> + </tr> + <tr> + <td><code>*</code></td> + <td>Multiplicação</td> + <td>Multiplica um número pelo outro.</td> + <td><code>3 * 7</code></td> + </tr> + <tr> + <td><code>/</code></td> + <td>Divisão</td> + <td>Divide o número da esquerda pelo número da direita.</td> + <td><code>10 / 5</code></td> + </tr> + <tr> + <td><code>%</code></td> + <td>Restante <em>(Remainder</em> - as vezes chamado de modulo)</td> + <td> + <p>Retorna o resto da divisão em números inteiros do número da esquerda pelo número da direita.</p> + </td> + <td><code>8 % 3</code> (retorna 2; como três cabe duas vezes em 8, deixando 2 como resto.)</td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>Nota</strong>: Você verá algumas vezes números envolvidos em aritimética chamados de {{Glossary("Operando", "operandos")}}.</p> +</div> + +<p>Nós provavelmente não precisamos ensinar a você como fazer matemática básica, mas gostaríamos de testar seu entendimento da sintaxe envolvida. Tente inserir os exemplos abaixo no seu <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console JavaScript</a>, ou use o console incorporado visto anteriormente, se preferir, para familiarizar-se com a sintaxe.</p> + +<ol> + <li>Primeiro tente inserir alguns exemplos simples por sua conta, como + <pre class="brush: js notranslate">10 + 7 +9 * 8 +60 % 3</pre> + </li> + <li>Você pode tentar declarar e inicializar alguns números dentro de variáveis, e tentar usá-los nas operações — as variáveis irão se comportar exatamente como os valores que elas armazenam para a finalidade das operações. Por exemplo: + <pre class="brush: js notranslate">var num1 = 10; +var num2 = 50; +9 * num1; +num2 / num1;</pre> + </li> + <li>Por último, nesta seção, tente inserir algumas expressões mais complexas, como: + <pre class="brush: js notranslate">5 + 10 * 3; +num2 % 9 * num1; +num2 + num1 / 8 + 2;</pre> + </li> +</ol> + +<p>Alguns dos exemplos do último bloco podem não ter retornado os valores que você estava esperando; a seção abaixo pode lhe explicar o porquê.</p> + +<h3 id="Precedência_de_operador">Precedência de operador</h3> + +<p>Vamos olhar para o último exemplo, assumindo que <code>num2</code> guarda o valor 50 e <code>num1</code> possui o valor 10 (como iniciado acima):</p> + +<pre class="brush: js notranslate">num2 + num1 / 8 + 2;</pre> + +<p>Como um ser humano, talvez você leia isso como <em>"50 mais 10 é igual a 60"</em>, depois <em>"8 mais 2 é igual a 10"</em>, e então <em>"60 dividido por 10 é igual a 6"</em>.</p> + +<p>No entanto seu navegador vai ler <em>"10 dividido por 8 é igual a 1.25"</em>, então <em>"50 mais 1.25 mais 2 é igual a 53.25"</em>.</p> + +<p>Isto acontence por causa da <strong>precedência de operadores</strong> — algumas operações serão aplicadas antes de outras quando calcularmos o resultado de uma soma (referida em programação como uma expressão). A precedência de operadores em JavaScript é semelhante ao ensinado nas aulas de matemática na escola — Multiplicação e divisão são realizados primeiro, depois a adição e subtração (a soma é sempre realizada da esquerda para a direita).</p> + +<p>Se você quiser substituir a precedência do operador, poderá colocar parênteses em volta das partes que desejar serem explicitamente tratadas primeiro. Então, para obter um resultado de 6, poderíamos fazer isso:</p> + +<pre class="brush: js notranslate">(num2 + num1) / (8 + 2);</pre> + +<p>Tente fazer e veja como fica.</p> + +<div class="note"> +<p><strong>Nota</strong>: Uma lista completa de todos os operadores JavaScript e suas precedências pode ser vista em <a href="/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Operator_precedence">Expressões e operadores</a>.</p> +</div> + +<h2 id="Operadores_de_incremento_e_decremento">Operadores de incremento e decremento</h2> + +<p>Às vezes você desejará adicionar ou subtrair, repetidamente, um valor de uma variável numérica. Convenientemente isto pode ser feito usando os operadores incremento <code>++</code> e decremento <code>--</code>. Usamos <code>++</code> em nosso jogo "Adivinhe o número" no primeiro artigo <a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/A_first_splash">Um primeiro mergulho no JavaScript</a>, quando adicionamos 1 ao nosso <code>contagemPalpites</code> para saber quantas adivinhações o usuário deixou após cada turno.</p> + +<pre class="brush: js notranslate">contagemPalpites++;</pre> + +<div class="note"> +<p><strong>Nota</strong>: Eles são mais comumente usado em <a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Lacos_e_iteracoes">Laços e iterações</a>, que será visto no curso mais tarde. Por exemplo, digamos que você queira passar por uma lista de preços e adicionar imposto sobre vendas a cada um deles. Você usaria um loop para passar por cada valor e fazer o cálculo necessário para adicionar o imposto sobre vendas em cada caso. O incrementador é usado para mover para o próximo valor quando necessário. Na verdade, fornecemos um exemplo simples mostrando como isso é feito - <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/maths/loop.html">verifique ao vivo</a> e observe o <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/maths/loop.html">código-fonte</a> para ver se consegue identificar os incrementadores! Veremos os <em>loops</em> detalhadamente mais adiante no curso.</p> +</div> + +<p>Vamos tentar brincar com eles no seu console. Para começar, note que você não pode aplicá-las diretamente a um número, o que pode parecer estranho, mas estamos atribuindo a variável um novo valor atualizado, não operando no próprio valor. O seguinte retornará um erro:</p> + +<pre class="brush: js notranslate">3++;</pre> + +<p>Então, você só pode incrementar uma variável existente. Tente isto: </p> + +<pre class="brush: js notranslate">var num1 = 4; +num1++;</pre> + +<p>Ok, segunda coisa estranha! Quando você fizer isso, verá um valor 4 retornado - isso ocorre porque o navegador retorna o valor atual e, <em>em seguida</em>, incrementa a variável. Você pode ver que ele foi incrementado se você retornar o valor da variável novamente:</p> + +<pre class="brush: js notranslate">num1;</pre> + +<p>Acontece a mesma coisa com <code>--</code> : tente o seguinte</p> + +<pre class="brush: js notranslate">var num2 = 6; +num2--; +num2;</pre> + +<div class="note"> +<p><strong>Nota</strong>: Você pode fazer o navegador fazer o contrário - incrementar/decrementar a variável e depois retornar o valor, colocando o operador no início da variável ao invés do final. Tente os exemplos acima novamente, mas desta vez use <code>++num1</code> e <code>--num2</code>.</p> +</div> + +<h2 id="Operadores_de_atribuição">Operadores de atribuição</h2> + +<p>Operadores de atribuição são os que atribuem um valor à uma variável. Nós já usamos o básico, <code>=</code>, muitas vezes, simplesmente atribuindo à variável do lado ersquerdo o valor indicado do lado direito do operador:</p> + +<pre class="brush: js notranslate">var x = 3; // x contém o valor 3 +var y = 4; // y contém o valor 4 +x = y; // x agora contém o mesmo valor de y, 4</pre> + +<p>Mas existem alguns tipos mais complexos, que fornecem atalhos úteis para manter seu código mais puro e mais eficiente. Os mais comuns estão listados abaixo:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operator</th> + <th scope="col">Name</th> + <th scope="col">Purpose</th> + <th scope="col">Example</th> + <th scope="col">Shortcut for</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>+=</code></td> + <td>Atribuição de adição</td> + <td>Adiciona o valor à direita ao valor da variável à esquerda e, em seguida, retorna o novo valor da variável</td> + <td><code>x = 3;<br> + x += 4;</code></td> + <td><code>x = 3;<br> + x = x + 4;</code></td> + </tr> + <tr> + <td><code>-=</code></td> + <td>Atribuição de subtração</td> + <td>Subtrai o valor à direita do valor da variável à esquerda e retorna o novo valor da variável</td> + <td><code>x = 6;<br> + x -= 3;</code></td> + <td><code>x = 6;<br> + x = x - 3;</code></td> + </tr> + <tr> + <td><code>*=</code></td> + <td>Atribuição de multiplicação</td> + <td>Multiplica o valor da variável à esquerda pelo valor à direita e retorna o novo valor da variável</td> + <td><code>x = 2;<br> + x *= 3;</code></td> + <td><code>x = 2;<br> + x = x * 3;</code></td> + </tr> + <tr> + <td><code>/=</code></td> + <td>Atribuição de divisão</td> + <td>Divide o valor da variável à esquerda pelo valor à direita e retorna o novo valor da variável</td> + <td><code>x = 10;<br> + x /= 5;</code></td> + <td><code>x = 10;<br> + x = x / 5;</code></td> + </tr> + </tbody> +</table> + +<p>Tente digitar alguns dos exemplos acima em seu console para ter uma ideia de como eles funcionam. Em cada caso, veja se você pode adivinhar qual é o valor antes de digitar a segunda linha.</p> + +<p>Note que você pode muito bem usar outros valores no lado direito de cada expressão, por exemplo:</p> + +<pre class="brush: js notranslate">var x = 3; // x contém o valor 3 +var y = 4; // y contém o valor 4 +x *= y; // x agora contém o valor 12</pre> + +<div class="note"> +<p><strong>Nota</strong>: Existem muitos <a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Expressions_and_Operators#operador_atribuicao">outros operadores de atribuição disponíveis</a>, mas estes são os básicos que você deve aprender agora.</p> +</div> + +<h2 id="Aprendizado_ativo_dimensionando_uma_canvas_box">Aprendizado ativo: dimensionando uma canvas box</h2> + +<p>Neste exercício, você manipulará alguns números e operadores para alterar o tamanho de uma caixa. A caixa é desenhada usando uma API do navegador chamada {{domxref("Canvas API", "", "", "true")}}. Não há necessidade de se preocupar sobre como isso funciona, apenas concentre-se na matemática por enquanto. A largura e altura da caixa (em pixels) são definidas pelas variáveis x e y, que recebem um valor inicial de 50.</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/editable_canvas.html", '100%', 520)}}</p> + +<p><strong><a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/maths/editable_canvas.html">Abrir em nova janela</a></strong></p> + +<p>Na caixa de código editável acima, há duas linhas marcadas com um comentário que gostaríamos que você atualizasse para aumentar/diminuir a caixa para determinados tamanhos, usando determinados operadores e/ou valores em cada caso. Vamos tentar o seguinte:</p> + +<ul> + <li>Altere a linha que calcula x para que a caixa ainda tenha 50px de largura, mas que 50 seja calculado usando os números 43 e 7 e um operador aritmético.</li> + <li>Altere a linha que calcula y tenha 75px de altura, mas que 75 seja calculado usando os números 25 e 3 e um operador aritmético.</li> + <li>Altere a linha que calcula x para que a caixa tenha 250px de largura, mas que 250 seja calculado usando dois números e o operador resto (modulo).</li> + <li>Altere a linha que calcula y para que a caixa tenha 150px de altura, mas que 150 seja calculado usando três números e os operadores de subtração e divisão.</li> + <li>Altere a linha que calcula x para que a caixa tenha 200px de largura, mas que 200 seja calculado usando o número 4 e um operador de atribuição.</li> + <li>Altere a linha que calcula y para que a caixa tenha 200px de altura, mas que 200 seja calculado usando os números 50 e 3, o operador de multiplicação e o operador de atribuição de adição.</li> +</ul> + +<p>Não se preocupe se você estragar totalmente o código. Você sempre pode pressionar o botão Reset para fazer as coisas funcionarem novamente. Depois de ter respondido corretamente a todas as perguntas acima, sinta-se à vontade para brincar um pouco com o código ou crie seus próprios desafios.</p> + +<h2 id="Operadores_de_comparação">Operadores de comparação</h2> + +<p>Às vezes, queremos executar testes verdadeiro / falso e, em seguida, agir de acordo, dependendo do resultado desse teste, para fazer isso, usamos <strong>operadores de comparação</strong>.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operator</th> + <th scope="col">Name</th> + <th scope="col">Purpose</th> + <th scope="col">Example</th> + </tr> + <tr> + <td><code>===</code></td> + <td>Igualdade estrita</td> + <td>Verifica se o valor da esquerda e o da direita são idênticos entre si.</td> + <td><code>5 === 2 + 4</code></td> + </tr> + <tr> + <td><code>!==</code></td> + <td>Não-igualdade-estrita</td> + <td>Verifica se o valor da esquerda e o da direita <strong>não </strong>são idênticos entre si.</td> + <td><code>5 !== 2 + 3</code></td> + </tr> + <tr> + <td><code><</code></td> + <td>Menor que</td> + <td>Verifica se o valor da esquerda é menor que o valor da direita.</td> + <td><code>10 < 6</code></td> + </tr> + <tr> + <td><code>></code></td> + <td>Maior que</td> + <td>Verifica se o valor da esquerda é maior que o valor da direita.</td> + <td><code>10 > 20</code></td> + </tr> + <tr> + <td><=</td> + <td>Menor ou igual que</td> + <td>Verifica se o valor da esquerda é menor que ou igual ao valor da direita.</td> + <td><code>3 <= 2</code></td> + </tr> + <tr> + <td>>=</td> + <td>Maior ou igual que</td> + <td>Verifica se o valor da esquerda é maior que ou igual ao valor da direita.</td> + <td><code>5 >= 4</code></td> + </tr> + </thead> +</table> + +<div class="note"> +<p><strong>Nota</strong>: Talvez você já tenha visto alguém usando <code>==</code> e<code>!=</code> afim de testar igualdade ou desigualdade em JavaScript. Estes são operadores válidos em JavaScript, mas que diferem de <code>===</code>/<code>!==</code>. As versões anteriores testam se os valores são os mesmos, mas não se os tipos de dados dos valores são os mesmos. As últimas versões estritas testam a igualdade de ambos os valores e seus tipos de dados. Elas tendem a resultar em menos erros, por isso recomendamos que você as use.</p> +</div> + +<p>Se você tentar inserir alguns desses valores em um console, verá que todos eles retornam <code>true</code>/<code>false</code> — aqueles booleanos que mencionamos no último artigo. Eles são muito úteis, pois nos permitem tomar decisões em nosso código, e eles são usados toda vez que queremos fazer uma escolha de algum tipo. Por exemplo, booleanos podem ser usados para:</p> + +<ul> + <li>Exibir o text label em um botão, dependendo se um recurso está ativado ou desativado</li> + <li>Exibir uma mensagem de 'game over' se um jogoa acabou ou uma mensagem de vitória se o jogo foi vencido</li> + <li>Exibir uma saudação sazonal correta, dependendo da época de festas</li> + <li>Aumentar ou diminuir o zoom do mapa, dependendo do nível de zoom selecionado</li> +</ul> + +<p>Veremos como codificar essa lógica quando examinarmos instruções condicionais em um artigo futuro. Por enquanto, vamos dar uma olhada em um exemplo rápido:</p> + +<pre class="brush: html notranslate"><button>Iniciar máquina</button> +<p>A máquina está parada.</p> +</pre> + +<pre class="brush: js notranslate">var btn = document.querySelector('button'); +var txt = document.querySelector('p'); + +btn.addEventListener('click', updateBtn); + +function updateBtn() { + if (btn.textContent === 'Iniciar máquina') { + btn.textContent = 'Parar máquina'; + txt.textContent = 'A máquina iniciou!'; + } else { + btn.textContent = 'Iniciar máquina'; + txt.textContent = 'A máquina está parada.'; + } +}</pre> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/conditional.html", '100%', 100)}}</p> + +<p><strong><a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/maths/conditional.html">Abrir em nova janela</a></strong></p> + +<p>Você pode ver o operador de igualdade sendo usado apenas dentro da função <code>updateBtn()</code>. Neste caso, não estamos testando se duas expressões matemáticas têm o mesmo valor, estamos testando se o conteúdo de texto de um botão contém uma certa string , mas ainda é o mesmo princípio em funcionamento. Se o botão estiver dizendo "Iniciar máquina" quando for pressionado, mudaremos o rótulo para "Parar máquina" e atualizaremos o rótulo conforme apropriado. Se o botão estiver dizendo "Parar máquina" quando for pressionado, nós trocamos a tela de volta.</p> + +<div class="note"> +<p><strong>Nota</strong>: Esse controle que troca entre dois estados geralmente é chamado de <strong>toggle</strong>. Ele alterna entre um estado e outro - acender, apagar, etc.</p> +</div> + +<h2 id="Resumo">Resumo</h2> + +<p>Neste artigo, cobrimos as informações fundamentais que você precisa saber sobre números em JavaScript, por enquanto. Você verá os números sendo usados de novo e de novo, durante todo o aprendizado de JavaScript. Portanto, é uma boa ideia tirar isso do caminho agora. Se você é uma daquelas pessoas que não gosta de matemática, pode se consolar com o fato de este capítulo ser muito curto.</p> + +<p>No próximo artigo, vamos explorar o texto e como o JavaScript nos permite manipulá-lo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Se você gosta de matemática e quer saber mais sobre como ela é implementada em JavaScriot, você pode encontrar muito mais detalhes na seção principal de JavaScript do MDN. Ótimos lugares para começar são os artigos <a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Numeros_e_datas">Números e datas</a> e <a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Expressions_and_Operators">Expressões e operadores</a> .</p> +</div> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}}</p> diff --git a/files/pt-br/learn/javascript/first_steps/o_que_e_javascript/index.html b/files/pt-br/learn/javascript/first_steps/o_que_e_javascript/index.html new file mode 100644 index 0000000000..771541b047 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/o_que_e_javascript/index.html @@ -0,0 +1,435 @@ +--- +title: O que é JavaScript? +slug: Learn/JavaScript/First_steps/O_que_e_JavaScript +tags: + - API + - Aprender + - Artigo + - Código Script + - Iniciante + - JavaScript + - Navegador + - Núcleo + - O que + - Script + - comentários + - externo + - inline + - 'l10n:prioridade' + - terceiros +translation_of: Learn/JavaScript/First_steps/What_is_JavaScript +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}</div> + +<p>Sejam bem-vindos ao curso de JavaScript para iniciantes do MDN! Neste primeiro artigo vamos fazer uma análise profunda da linguagem, respondendo questões como "O que é JavaScript?", e "O que ele faz?", para você se sentir confortável com a proposta da linguagem.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré requisitos:</th> + <td>Interação básica com o computador, entendimento básico de HTML e CSS.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Se familiarizar com a linguagem, com o que ela pode fazer, e como tudo isso pode ser utilizado em um website.</td> + </tr> + </tbody> +</table> + +<h2 id="Definição_de_alto_nível">Definição de alto nível</h2> + +<p>JavaScript é uma linguagem de programação que permite a você implementar itens complexos em páginas web — toda vez que uma página da web faz mais do que simplesmente mostrar a você informação estática — mostrando conteúdo que se atualiza em um intervalo de tempo, mapas interativos ou gráficos 2D/3D animados, etc. — você pode apostar que o JavaScript provavelmente está envolvido. É a terceira camada do bolo das tecnologias padrões da web, duas das quais (<a href="/en-US/docs/Learn/HTML">HTML</a> e <a href="/en-US/docs/Learn/CSS">CSS</a>) nós falamos com muito mais detalhes em outras partes da Área de Aprendizado.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13502/cake.png" style="display: block; margin: 0 auto;"></p> + +<ul> + <li>{{glossary("HTML")}} é a linguagem de marcação que nós usamos para estruturar e dar significado para o nosso conteúdo web. Por exemplo, definindo parágrafos, cabeçalhos, tabelas de conteúdo, ou inserindo imagens e vídeos na página.</li> + <li>{{glossary("CSS")}} é uma linguagem de regras de estilo que nós usamos para aplicar estilo ao nosso conteúdo HTML. Por exemplo, definindo cores de fundo e fontes, e posicionando nosso conteúdo em múltiplas colunas.</li> + <li>{{glossary("JavaScript")}} é uma linguagem de programação que permite a você criar conteúdo que se atualiza dinamicamente, controlar múltimídias, imagens animadas, e tudo o mais que há de intessante. Ok, não tudo, mas é maravilhoso o que você pode efetuar com algumas linhas de código JavaScript.</li> +</ul> + +<p>As três camadas ficam muito bem uma em cima da outra. Vamos exemplificar com um simples bloco de texto. Nós podemos marcá-lo usando HTML para dar estrutura e propósito: </p> + +<pre class="brush: html notranslate"><p>Jogador 1: Chris</p></pre> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15586/so-html.png" style="height: 28px; width: 118px;"></p> + +<p>Nós podemos adicionar um pouco de CSS na mistura, para deixar nosso parágrafo um pouco mais atraente:</p> + +<pre class="brush: css notranslate">p { + font-family: 'helvetica neue', helvetica, sans-serif; + letter-spacing: 1px; + text-transform: uppercase; + text-align: center; + border: 2px solid rgba(0,0,200,0.6); + background: rgba(0,0,200,0.3); + color: rgba(0,0,200,0.6); + box-shadow: 1px 1px 2px rgba(0,0,200,0.4); + border-radius: 10px; + padding: 3px 10px; + display: inline-block; + cursor:pointer; +}</pre> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15587/html-e-css.png" style="height: 48px; width: 208px;"></p> + +<p>E finalmente, nós podemos adicionar JavaScript para implementar um comportamento dinâmico:</p> + +<pre class="brush: js notranslate">const para = document.querySelector('p'); + +para.addEventListener('click', atualizarNome); + +function atualizarNome() { + var nome = prompt('Insira um novo nome'); + para.textContent = 'Jogador 1: ' + nome; +} +</pre> + +<p>{{ EmbedLiveSample('Definição_de_alto_nível', '100%', 80) }}</p> + +<p>Experimente clicar no botão acima para ver o que acontece (note também que você pode encontrar essa demonstração no GitHub — veja o <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/what-is-js/javascript-rotulo.html">código fonte</a> ou <a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/what-is-js/javascript-rotulo.html">veja funcionar</a>)!</p> + +<p>JavaScript pode fazer muito mais do que isso — vamos explorar com mais detalhes.</p> + +<h2 id="Então_o_que_ele_pode_realmente_fazer">Então o que ele pode realmente fazer?</h2> + +<p>O núcleo da linguagem JavaScript consiste em alguns benefícios comuns da programação que permite a você fazer coisas como:</p> + +<ul> + <li>Armazenar conteúdo útil em variáveis. No exemplo acima, a propósito, nós pedimos que um novo nome seja inserido e armazenamos o nome em uma variável chamada <code>nome</code>.</li> + <li>Operações com pedaços de texto (conhecidos como "strings" em programação). No exemplo acima, nós pegamos a string "Jogador 1: " e concatenamos (juntamos) com a variável <code>nome</code> para criar o texto completo "Jogador 1: Chris".</li> + <li>Executar o código em resposta a determinados eventos que ocorrem em uma página da Web. Nós usamos o {{Event("click")}} no nosso exemplo acima para que quando clicassem no botão, rodasse o código que atualiza o texto.</li> + <li>E muito mais!</li> +</ul> + +<p>O que é ainda mais empolgante é a funcionalidade construída no topo do núcleo da linguagem JavaScript. As APIs (Application Programming Interfaces - Interface de Programação de Aplicativos) proveem a você superpoderes extras para usar no seu código JavaScript.</p> + +<p>APIs são conjuntos prontos de blocos de construção de código que permitem que um desenvolvedor implemente programas que seriam difíceis ou impossíveis de implementar. Eles fazem o mesmo para a programação que os kits de móveis prontos para a construção de casas - é muito mais fácil pegar os painéis prontos e parafusá-los para formar uma estante de livros do que para elaborar o design, sair e encontrar a madeira, cortar todos os painéis no tamanho e formato certos, encontrar os parafusos de tamanho correto e <em> depois </em> montá-los para formar uma estante de livros.</p> + +<p>Elas geralmente se dividem em duas categorias.</p> + +<p><img alt="APIs de terceiros e APIs do navegador" src="https://mdn.mozillademos.org/files/14721/browser.png" style="display: block; height: 511px; margin: 0px auto; width: 815px;"></p> + +<p><strong>APIs de navegadores</strong> já vem implementadas no navegador, e são capazes de expor dados do ambiente do computador, ou fazer coisas complexas e úteis. Por exemplo:</p> + +<ul> + <li>A <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model">API DOM (Document Object Model)</a> permite a você manipular HTML e CSS, criando, removendo e mudando HTML, aplicando dinamicamente novos estilos para a sua página, etc. Toda vez que você vê uma janela pop-up aparecer em uma página, ou vê algum novo conteúdo sendo exibido (como nós vimos acima na nossa simples demonstração), isso é o DOM em ação.</li> + <li>A <a href="https://developer.mozilla.org/en-US/docs/Web/API/Geolocation">API de Geolocalização</a> recupera informações geográficas. É assim que o <a href="https://www.google.com/maps">Google Maps</a> consegue encontrar sua localização e colocar em um mapa.</li> + <li>As APIs <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API">Canvas</a> e <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API">WebGL</a> permite a você criar gráficos 2D e 3D animados. Há pessoas fazendo algumas coisas fantásticas usando essas tecnologias web — veja <a href="https://www.chromeexperiments.com/webgl">Chrome Experiments</a> e <a href="http://webglsamples.org/">webglsamples</a>.</li> + <li><a href="https://developer.mozilla.org/en-US/Apps/Fundamentals/Audio_and_video_delivery">APIs de áudio e vídeo</a> como {{domxref("HTMLMediaElement")}} e <a href="/en-US/docs/Web/API/WebRTC_API">WebRTC</a> permitem a você fazer coisas realmente interessantes com multimídia, tanto tocar música e vídeo em uma página da web, como capturar vídeos com a sua câmera e exibir no computador de outra pessoa (veja <a href="http://chrisdavidmills.github.io/snapshot/">Snapshot demo</a> para ter uma ideia).</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Muitas demonstrações acima não vão funcionar em navegadores antigos — quando você for experimentar, é uma boa ideia usar browsers modernos como Firefox, Edge ou Opera para ver o código funcionar. Você vai precisar estudar <a href="https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing">testes cross browser</a> com mais detalhes quando você estiver chegando perto de produzir código (código real que as pessoas vão usar).</p> +</div> + +<p><strong>APIs de terceiros</strong> não estão implementados no navegador automaticamente, e você geralmente tem que pegar seu código e informações em algum lugar da Web. Por exemplo:</p> + +<ul> + <li>A <a href="https://dev.twitter.com/overview/documentation">API do Twitter</a> permite a você fazer coisas como exibir seus últimos tweets no seu website.</li> + <li>A <a href="https://developers.google.com/maps/">API do Google Maps</a> permite a você inserir mapas customizados no seu site e outras diversas funcionalidades.</li> +</ul> + +<div class="note"> +<p><strong>Note</strong>: Essas APIs são avançadas e nós não vamos falar sobre nenhuma delas nesse módulo.Vo cê pode achar muito mais sobre elas em nosso módulo <a href="/pt-BR/docs/Learn/JavaScript/Client-side_web_APIs">APIs web no lado cliente</a>.</p> +</div> + +<p>Tem muito mais coisas disponíveis! Contudo, não fique animado ainda. Você não estará pronto para desenvolver o próximo Facebook, Google Maps ou Instagram depois de estudar JavaScript por 24 horas — há um monte de coisas básicas para estudar primeiro. E é por isso que você está aqui — vamos começar! </p> + +<h2 id="O_que_JavaScript_está_fazendo_na_sua_página_web">O que JavaScript está fazendo na sua página web?</h2> + +<p>Aqui nós vamos realmente começar a ver algum código, e enquanto fazemos isso vamos explorar o que realmente acontece quando você roda algum código JavaScript na sua página.</p> + +<p>Vamos recaptular brevemente a história do que acontece quando você carrega uma página web em um navegador (falamos sobre isso no nosso artigo <a href="/en-US/Learn/CSS/Introduction_to_CSS/How_CSS_works#How_does_CSS_actually_work">Como o CSS funciona</a>). Quando você carrega uma página web no seu navegador, você está executando seu código (o HTML, CSS e JavaScript) dentro de um ambiente de execução (a guia do navegador). Isso é como uma fábrica que pega a matéria prima (o código) e transforma em um produto (a página web).</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13504/execution.png" style="display: block; margin: 0 auto;"></p> + +<p>Um uso muito comum do JavaScript é modificar dinamicamente HTML e CSS para atualizar uma interface do usuário, por meio da API do Document Object Model (conforme mencionado acima). Observe que o código em seus documentos web geralmente é carregado e executado na ordem em que aparece na página. Se o JavaScript carregar e tentar executar antes do carregamento do HTML e CSS afetado, poderão ocorrer erros. Você aprenderá maneiras de contornar isso mais adiante neste artigo, na seção <a href="/pt-BR/docs/Learn/JavaScript/First_steps/What_is_JavaScript#Script_loading_strategies"> Estratégias de carregamento de scripts </a>.</p> + +<h3 id="Segurança_do_navegador">Segurança do navegador</h3> + +<p>Cada guia do navegador tem seu próprio espaço para executar código (esses espaços são chamados de "ambientes de execução", em termos técnicos) — isso significa que na maioria dos casos o código em cada guia está sendo executado separadamente, e o código em uma guia não pode afetar diretamente o código de outra guia — ou de outro website. Isso é uma boa medida de segurança — se esse não fosse o caso, então hackers poderiam começar a escrever código para roubar informações de outros websites, e fazer outras coisas más.</p> + +<div class="note"> +<p><strong>Nota</strong>: Há muitas maneiras de trocar código e conteúdo entre diferentes websites/guias de uma forma segura, mas são técnicas avançadas que não serão estudadas nesse curso.</p> +</div> + +<h3 id="Ordem_de_execução_do_JavaScript">Ordem de execução do JavaScript</h3> + +<p>Quando o navegador encontra um bloco de código JavaScript, ele geralmente executa na ordem, de cima para baixo. Isso significa que você precisa ter cuidado com a ordem na qual você coloca as coisas. Por exemplo, vamos voltar ao bloco JavaScript que nós vimos no primeiro exemplo:</p> + +<pre class="brush: js notranslate">const para = document.querySelector('p'); + +para.addEventListener('click', atualizarNome); + +function atualizarNome() { + ;et nome = prompt('Informe um novo nome:'); + para.textContent = 'Jogador 1: ' + nome; +}</pre> + +<p>Aqui nós estamos selecionando um parágrafo (linha 1) e anexando a ele um <em>event listener</em> (linha 3). Então, quando o parágrafo recebe um clique, o bloco de código <code>atualizarNome()</code> (linhas 5 a 8) é executado. O bloco de código <code>atualizarNome()</code>(esses tipos de bloco de código reutilizáveis são chamados "funções") pede ao usuário que informe um novo nome, e então insere esse nome no parágrafo, atualizando-o.</p> + +<p>Se você inverte a ordem das duas primeiras linhas de código, ele não fucionaria — em vez disso, você receberia um erro no console do navegador — <code>TypeError: para is undefined</code>. Isso significa que o objeto <code>para</code> não existe ainda, então nós não podemos adicionar <em>um event listener</em> a ele.</p> + +<div class="note"> +<p><strong>Nota</strong>: Esse é um erro muito comum — você precisa verificar se os objetos aos quais você se refere no seu código existem antes de você tentar anexar coisas a eles.</p> +</div> + +<h3 id="Código_interpretado_x_compilado">Código interpretado x compilado</h3> + +<p>Você pode ouvir os termos <strong>interpretado </strong>e <strong>compilado</strong> no contexto da programação. JavaScript é uma linguagem interpretada — o código é executado de cima para baixo e o resultado da execução do código é imediatamente retornado. Você não tem que transformar o código em algo diferente antes do navegador executa-lo.</p> + +<p>Linguagens compiladas, por outro lado, são transformadas (compiladas) em algo diferente antes que sejam executadas pelo computador. Por exemplo, C/C++ são compiladas em linguagem Assembly, e depois são executadas pelo computador.</p> + +<p>JavaScript é uma linguagem de programação leve e interpretada. O navegador recebe o código JavaScript em sua forma de texto original e executa o script a partir dele. Do ponto de vista técnico, a maioria dos intérpretes modernos de JavaScript realmente usa uma técnica chamada <strong>compilação just-in-time</strong> para melhorar o desempenho; o código-fonte JavaScript é compilado em um formato binário mais rápido enquanto o script está sendo usado, para que possa ser executado o mais rápido possível. No entanto, o JavaScript ainda é considerado uma linguagem interpretada, pois a compilação é manipulada em tempo de execução, e não antes.</p> + +<p>Há vantagens em ambos os tipos de linguagem, mas nós não iremos discutir no momento.</p> + +<h3 id="Lado_do_servidor_x_Lado_do_cliente">Lado do servidor x Lado do cliente</h3> + +<p>Você pode também ouvir os termos <strong>lado do servidor (<em>server-side</em>)</strong> e <strong>lado do cliente (<em>client-side</em>)</strong>, especialmente no contexto de desenvolvimento web. Códigos do lado do cliente são executados no computador do usuário — quando uma página web é visualizada, o código do lado do cliente é baixado, executado e exibido pelo navegador. Nesse módulo JavaScript nós estamos explicitamente falando sobre <strong>JavaScript do lado do cliente</strong>.</p> + +<p>Códigos do lado do servidor, por outro lado, são executados no servidor e o resultado da execução é baixado e exibido no navegador. Exemplos de linguagens do lado do servidor populares incluem PHP, Python, Ruby, e ASP.NET. E JavaScript! JavaScript também pode ser usada como uma linguagem <em>server</em><em>-side</em>, por exemplo, no popular ambiente Node.js — você pode encontrar mais sobre JavaScript do lado do servidor no nosso tópico <a href="/en-US/docs/Learn/Server-side">Websites dinâmicos - Programação do lado do servidor</a>.</p> + +<h3 id="Código_dinâmico_x_estático">Código dinâmico x estático</h3> + +<p>A palavra <strong>dinâmico</strong> é usada para descrever tanto o JavaScript <em>client-side </em>como o <em>server-side</em> — essa palavra se refere a habilidade de atualizar a exibição de uma página web/app para mostrar coisas diferentes em circunstâncias diferentes, gerando novo conteúdo como solicitado. Código do lado do servidor dinamicamente gera novo conteúdo no servidor, puxando dados de um banco de dados, enquanto que JavaScript do lado do cliente dinamicamente gera novo conteúdo dentro do navegador do cliente, como criar uma nova tabela HTML com dados recebidos do servidor e mostrar a tabela em uma página web exibida para o usuário. Os significados são ligeiramente diferente nos dois contextos, porém relacionados, e ambos (JavaScript <em>server-side</em> e <em>client-side</em>) geralmente trabalham juntos.</p> + +<p>Uma página web sem atualizações dinâmicas é chamada de <strong>estática</strong> — ela só mostra o mesmo conteúdo o tempo todo.</p> + +<h2 id="Como_você_adiciona_JavaScript_na_sua_página">Como você adiciona JavaScript na sua página?</h2> + +<p>O JavaScript é inserido na sua página de uma maneira similar ao CSS. Enquanto o CSS usa o elemento {{htmlelement("link")}} para aplicar folhas de estilo externas e o elemento {{htmlelement("style")}} para aplicar folhas de estilo internas, o JavaScript só precisa de um amigo no mundo do HTML — o elemento {{htmlelement("script")}}. Vamos aprender como funciona.</p> + +<h3 id="JavaScript_interno">JavaScript interno</h3> + +<ol> + <li>Antes de tudo, faça uma cópia local do nosso arquivo de exemplo <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/what-is-js/aplicando-javascript.html">aplicando-javascript.html</a>. Salve-o em alguma pasta, de uma forma sensata.</li> + <li>Abra o arquivo no seu navegador web e no seu editor de texto. Você verá que o HTML cria uma simples página web contendo um botão clicável.</li> + <li>Agora, vá até o seu editor de texto e adicione o código a seguir antes da tag de fechamento <code></body></code>: + <pre class="brush: html notranslate"><script> + + // O JavaScript fica aqui + +</script></pre> + </li> + <li>Agora nós vamos adicionar um pouco de JavaScript dentro do nosso elemento {{htmlelement("script")}} para que a página faça algo mais interessante — adicione o seguinte código abaixo da linha "// O JavaScript fica aqui": + <pre class="brush: js notranslate">function criarParagrafo() { + let para = document.createElement('p'); + para.textContent = 'Você clicou no botão!'; + document.body.appendChild(para); +} + +const botoes = document.querySelectorAll('button'); + +for(var i = 0; i < botoes.length ; i++) { + botoes[i].addEventListener('click', criarParagrafo); +}</pre> + </li> + <li>Salve seu arquivo e recarregue a página — agora você deveria ver que quando você clique no botão, um novo parágrafo é gerado e colocado logo abaixo.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Se seu exemplo não parece funcionar, leia cada passo novamente e confira que você fez tudo certo. Você salvou sua cópia local do código inicial como um arquivo .html? Você adicionou o elemento {{htmlelement("script")}} imediatamente antes da tag <code></body></code>? Você digitou o código JavaScript exatamente como ele está sendo mostrado? <strong>JavaScript é uma linguagem case sensitive (isso significa que a linguagem vê diferença entre letras maiúsculas e minúsculas) e muito confusa, então você precisa digitar a sintaxe exatamente como foi mostrada, senão não vai funcionar.</strong></p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Você pode ver essa versão no GitHub como <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/what-is-js/aplicando-javascript-interno.html">apicando-javascript-interno.html</a> (<a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/what-is-js/aplicando-javascript-interno.html">veja funcionar também</a>).</p> +</div> + +<h3 id="JavaScript_externo">JavaScript externo</h3> + +<p>Isso funciona muito bem, mas e se nós quiséssemos colocar nosso JavaScript em um arquivo externo? Vamos explorar isso agora.</p> + +<ol> + <li>Primeiro, crie um novo arquivo na mesma pasta que está o arquivo HTML de exemplo. Chame-o de <code>script.js</code> — tenha certeza de que o nome do arquivo tem a extensão <code>.js</code>, pois é assim que ele será reconhecido como JavaScript.</li> + <li>Agora substitua o elemento atual {{htmlelement("script")}} pelo seguinte código: + <pre class="brush: html notranslate"><script src="script.js" defer></script></pre> + </li> + <li>Em <code>script.js</code>, adidione o seguinte script: + <pre class="brush: js notranslate">function createParagraph() { + let para = document.createElement('p'); + para.textContent = 'Você clicou no botão!'; + document.body.appendChild(para); +} + +const buttons = document.querySelectorAll('button'); + +for(let i = 0; i < buttons.length ; i++) { + buttons[i].addEventListener('click', createParagraph); +}</pre> + </li> + <li>Salve e atualize seu navegador, e você deverá ver a mesma coisa! Funciona igualmente, mas agora nós temos o JavaScript em um arquivo externo. Isso é geralmente uma coisa boa em termos de organização de código, e faz com que seja possível reutilizar o código em múltiplos arquivos HTML. Além disso, o HTML fica mais legível sem grandes pedaços de script no meio dele.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Você pode ver essa versão no GitHub como <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/what-is-js/aplicando-javascript-externo.html">aplicando-javascript-externo.html</a> e <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/what-is-js/script.js">script.js</a> (<a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/what-is-js/aplicando-javascript-externo.html">veja funcionar também</a>).</p> +</div> + +<h3 id="Manipuladores_de_JavaScript_inline">Manipuladores de JavaScript inline</h3> + +<p>Note que às vezes você vai encontrar código JavaScript escrito dentro do HTML. Isso deve ser algo como:</p> + +<div id="inline_js_example"> +<pre class="brush: js example-bad notranslate">function criarParagrafo() { + let para = document.createElement('p'); + para.textContent = 'Você clicou o botao!'; + document.body.appendChild(para); +}</pre> + +<div id="inline_js_example"> +<pre class="brush: js example-bad notranslate"><button onclick="criarParagrafo()">Me clique!</button></pre> +</div> + +<p>Você pode tentar essa versão na nossa demonstração abaixo.</p> + +<p><iframe class="live-sample-frame hide-codepen-jsfiddle" frameborder="0" height="150" id="frame_inline_js_example" src="https://mdn.mozillademos.org/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript$samples/inline_js_example?revision=1640817" width="100%"></iframe></p> + +<p>Essa demonstração tem exatamente a mesma funcionalidade que vimos nas primeiras duas seções, exceto que o elemento {{htmlelement("button")}} inclui um manipulador <em>inline</em> <code>onclick</code> para fazer a função ser executada quando o botão é clicado.</p> + +<p><strong>Contudo, por favor, não faça isso.</strong> É uma má prática poluir seu HTML com JavaScript, e isso é ineficiente — você teria que incluir o atributo <code>onclick="criarParagrafo()"</code> em todo botão que você quisesse aplicar JavaScript.</p> + +<p>Usando uma estrutura feita de puro JavaScript permite a você selecionar todos os botões usando uma instrução. O código que nós usamos acima para servir a esse propósito se parece com isso:</p> + +<pre class="brush: js notranslate">const botoes = document.querySelectorAll('button'); + +for(var i = 0; i < botoes.length ; i++) { + botoes[i].addEventListener('click', criarParagrafo); +}</pre> + +<p>Isso talvez parece ser mais do que o atributo <code>onclick</code>, mas isso vai funcionar para todos os botões, não importa quantos tem na página, e quantos forem adicionados ou removidos. O JavaScript não precisará ser mudado.</p> + +<div class="note"> +<p><strong>Nota</strong>: Tente editar a sua versão do arquivo <code>aplicar-javascript.html</code>, adicionando alguns botões a mais. Quando você recarregar, você deverá ver que todos os botões, quando clicados, irão criar parágrafos. Agradável, não?</p> +</div> + +<h3 id="Estratégias_para_o_carregamento_de_scripts">Estratégias para o carregamento de scripts</h3> + +<p>Há um considerável número de problemas envolvendo o carregamento de scripts na ordem correta. Infelizmente, nada é tão simples quanto parece ser! Um problema comum é que todo o HTML de uma página é carregado na ordem em que ele aparece. Se você estiver usando Javascript para manipular alguns elementos da página (sendo mais preciso, manipular o <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents#The_document_object_model">Document Object Model</a>), seu código não irá funcionar caso o JavaScript for carregado e executado antes mesmo dos elementos HTML estarem disponíveis.</p> + +<p>Nos exemplos acima, tanto nos scripts internos ou externos, o JavaScript é carregado e acionado dentro do cabeçalho do documento, antes do corpo da página ser completamente carregado. Isso poderá causar algum erro. Assim, temos algumas soluções para isso.</p> + +<p>No exemplo interno, você pode ver essa estrutura em volta do código:</p> + +<pre class="brush: js notranslate">document.addEventListener("DOMContentLoaded", function() { + ... +});</pre> + +<p>Isso é um <em>event listener</em> (ouvidor de eventos<em>)</em>, que ouve e aguarda o disparo do evento "DOMContentLoaded" vindo do <em>browser</em>, evento este que significa que o corpo do HTML está completamente carregado e pronto. O código JavaScript que estiver dentro desse bloco não será executado até que o evento seja disparado, portanto, o erro será evitado (você irá <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">aprender sobre eventos</a> mais tarde).</p> + +<p>No exemplo externo, nós usamos um recurso moderno do JavaScript para resolver esse problema: Trata-se do atributo <code>defer</code>, que informa ao <em>browser</em> para continuar renderizando o conteúdo HTML uma vez que a tag <code><script></code> foi atingida.</p> + +<pre class="brush: js notranslate"><script src="script.js" defer></script></pre> + +<p>Neste caso, ambos script e HTML irão carregar de forma simultânea e o código irá funcionar.</p> + +<div class="note"> +<p><strong>Nota</strong>: No caso externo, nós não precisamos utilizar o evento <code>DOMContentLoaded</code> porque o atributo <code>defer</code> resolve o nosso problema. Nós não utilizamos <code>defer</code> como solução para os exemplos internos pois <code>defer</code> funciona apenas com scripts externos.</p> +</div> + +<p>Uma solução à moda antiga para esse problema era colocar o elemento script bem no final do body da página (antes da tag <code></body>)</code>. Com isso, os scripts iriam carregar logo após todo o conteúdo HTML. O problema com esse tipo de solução é que o carregamento/renderização do script seria completamente bloqueado até que todo o conteúdo HTML fosse analisado. Em sites de maior escala, com muitos scripts, essa solução causaria um grande problema de performance e deixaria o site lento. </p> + +<h4 id="async_e_defer">async e defer</h4> + +<p>Atualmente, há dois recursos bem modernos que podermos usar para evitar o problema com o bloqueio de scripts — <code>async</code> e <code>defer</code> (que vimos acima). Vamos ver as diferenças entre esses dois?</p> + +<p>Os scripts que são carregados usando o atributo <code>async</code> (veja abaixo) irão baixar o script sem bloquear a renderização da página e irão executar imediatamente após o script terminar de ser disponibilizado. Nesse modo você não tem garantia nenhuma que os scripts carregados irão rodar em uma ordem específica, mas saberá que dessa forma eles não irão impedir o carregamento do restante da página. O melhor uso para o <code>async</code> é quando os scripts de uma página rodam de forma independente entre si e também não dependem de nenhum outro script.</p> + +<p>Por exemplo, se você tiver os seguintes elementos script:</p> + +<pre class="brush: html notranslate"><script async src="js/vendor/jquery.js"></script> + +<script async src="js/script2.js"></script> + +<script async src="js/script3.js"></script></pre> + +<p>Você não pode garantir que o script. <code>jquery.js</code> carregará antes ou depois do <code>script2.js</code> e <code>script3.js</code> . Nesse caso, se alguma função desses scripts dependerem de algo vindo do <code>jquery</code>, ela produzirá um erro pois o <code>jquery</code> ainda não foi definido/carregado quando os scripts executaram essa função.</p> + +<p><code>async</code> deve ser usado quando houver muitos scripts rodando no <em>background</em>, e você precisa que estejam disponíveis o mais rápido possível. Por exemplo, talvez você tenha muitos arquivos de dados de um jogo para carregar que serão necessários assim que o jogo iniciar, mas por enquanto, você só quer entrar e ver a tela de carregamento, a do titulo do jogo e o <em>lobby</em>, sem ser bloqueado pelo carregamento desses scripts.</p> + +<p>Scripts que são carregados utilizando o atributo <code>defer</code> (veja abaixo) irão rodar exatamente na ordem em que aparecem na página e serão executados assim que o script e o conteúdo for baixado.</p> + +<pre class="brush: html notranslate"><script defer src="js/vendor/jquery.js"></script> + +<script defer src="js/script2.js"></script> + +<script defer src="js/script3.js"></script></pre> + +<p>Todos os scripts com o atributo <code>defer</code> irão carregar na ordem que aparecem na página. No segundo exemplo, podemos ter a certeza que o script <code>jquery.js</code> irá carregar antes do <code>script2.js</code> e <code>script3.js</code> e o <code>script2.js</code> irá carregar antes do <code>script3.js</code>. Os scripts não irão rodar sem que antes todo o conteúdo da página seja carregado, que no caso, é muito útil se os seus scripts dependem de um DOM completamente disponibilizado em tela (por exemplo, scripts que modificam um elemento).</p> + +<p>Resumindo:</p> + +<ul> + <li><code>async</code> e <code>defer</code> istruem o <em>browser</em> a baixar os scripts numa <em>thread </em>(processo)<em> </em>á parte, enquanto o resto da página (o DOM, etc.) está sendo baixado e disponibilizado de forma não bloqueante.</li> + <li>Se os seus scripts precisam rodar imediatamente, sem que dependam de outros para serem executados, use <code>async</code>.</li> + <li>Se seus scripts dependem de outros scripts ou do DOM completamente disponível em tela, carregue-os usando <code>defer</code> e coloque os elementos <code><script></code> na ordem exata que deseja que sejam carregados.</li> +</ul> + +<h2 id="Comentários">Comentários</h2> + +<p>Assim como HTML e CSS, é possível escrever comentários dentro do seu código JavaScript que serão ignorados pelo navegador, e existirão simplesmente para prover instruções aos seus colegas desenvolvedores sobre como o código funciona (e pra você, se você tiver que voltar ao seu código depois de 6 meses e não se lembrar do que fez). Comentários são muito úteis, e você deveria usá-los frequentemente, principalmente quando seus códigos forem muito grandes. Há dois tipos:</p> + +<ul> + <li>Um comentário de uma linha é escrito depois de duas barras. Por exemplo:</li> + <li> + <pre class="brush: js notranslate">// Eu sou um comentário</pre> + </li> + <li>Um comentário de múltiplas linhas é escrito entre os caracteres /* e */. Por exemplo: + <pre class="brush: js notranslate">/* + Eu também sou + um comentário +*/</pre> + </li> +</ul> + +<p>Então, por exemplo, você poderia fazer anotações na nossa última demonstração de código JavaScript, da seguinte forma:</p> + +<pre class="brush: js notranslate">// Função: Cria um novo parágrafo e o insere no fim do arquivo HTML. + +function criarParagrafo() { + var para = document.createElement('p'); + para.textContent = 'Você clicou no botão!'; + document.body.appendChild(para); +} + +/* + 1. Captura referências de todos os botões na página e armazena isso em um array. + 2. Vai até todos os botões e adiciona um event listener click a cada um deles. + + Quando cada botão é clicado, a função criarParagrafo() será executada. +*/ + +const botoes = document.querySelectorAll('button'); + +for(var i = 0; i < botoes.length ; i++) { + botoes[i].addEventListener('click', criarParagrafo); +}</pre> + +<div class="note"> +<p><strong>Nota</strong>: Em geral mais comentários são melhores que menos, porém você deve tomar cuidado para não adicionar comentários de mais tentando explicar o que uma variável é (o nome da sua variável deve ser mais intuitivo), ou tentando explicar uma operação simples (talvez seu código seja muito complicado denecessariamente).</p> +</div> + +<h2 id="Sumário">Sumário</h2> + +<p>Então, esse foi o seu primeiro passo no mundo do JavaScript. Nós iniciamos apenas com teoria, então te ensinamos porque usar JavaScript e que tipo de coisa você pode fazer com ele. Pelo caminho você viu alguns códigos de exemplo e aprendeu como JavaScript se encaixa com o resto do código do seu site, entre outras coisas.</p> + +<p>O JavaScript talvez pareça um pouco assustador agora, mas não se preocupe — nesse curso você será guiado passo a passo, e tudo vai começar a fazer sentido. No próximo artigo vamos <a href="/en-US/docs/Learn/JavaScript/Introduction_to_JavaScript_1/A_first_splash">mergulhar direto para a prática</a>, levando você a construir seu próprio código JavaScript.</p> + +<p>{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo:</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript">O que é JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/A_first_splash">O primeiro contato com JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong">O que deu errado? Resolvendo problemas com JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables">Armazenando a informação que você precisa - Variáveis</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math">Matemática básica em JavaScript — números e operadores</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings">Trabalhando com texto — strings em JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos úteis para strings</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Gerador_de_historias_bobas">Avaliação: Gerador de histórias bobas</a></li> +</ul> +</div> diff --git a/files/pt-br/learn/javascript/first_steps/strings/index.html b/files/pt-br/learn/javascript/first_steps/strings/index.html new file mode 100644 index 0000000000..299c6e33a8 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/strings/index.html @@ -0,0 +1,284 @@ +--- +title: Trabalhando com texto — strings em JavaScript +slug: Learn/JavaScript/First_steps/Strings +translation_of: Learn/JavaScript/First_steps/Strings +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Agora vamos dar atenção às strings - isto é como é chamado em programação qualquer parte de texto. Neste artigo nós veremos tudo que você realmente deve saber sobre strings quando está aprendendo JavaScript. Como criar, fazer citações e como juntar strings.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Computação básica, um entendimento básico de HTML e CSS, e sobre o que é JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ganhar familiaridade com o básico de strings em JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="O_poder_das_palavras">O poder das palavras</h2> + +<p>Palavras são muito importante para humanos - elas são uma grande parte de como nos comunicamos. Desde que a Web é largamente baseada em texto, projetada para permitir humanos a comunicar e compartilhar infomação, isto é útil para nós termos controle sobre como apresentar isso. {{glossary("HTML")}} fornece estrutura e significado para nosso texto, {{glossary("CSS")}} nos permite estilizar precisamente ele, e JavaScript contem um número de funcionalidades para manipular strings, criar mensagens de boas-vindas customizadas, mostrando rótulos quando preciso, sorteando termos de acordo como desejado e muito mais.</p> + +<p>Muitos dos programas que temos visto até agora no curso está envolvido em alguma parte com manipulação de string.</p> + +<h2 id="Strings_—_O_básico">Strings — O básico</h2> + +<p>Em um primeiro relance, strings são tratadas de forma parecida como números, mas quando vamos mais a fundo, você começa a ver algumas diferenças importantes. Vamos começar a entrar em linhas básicas no console para nos familiarizar. Nós vamos fornecer abaixo (você pode também <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">abrir isto no console</a> em uma guia ou janela separada, ou usar o <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console do navegador</a> se você preferir).</p> + +<div class="hidden"> +<h6 id="Código_oculto">Código oculto</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>JavaScript console</title> + <style> + * { + box-sizing: border-box; + } + + html { + background-color: #0C323D; + color: #809089; + font-family: monospace; + } + + body { + max-width: 700px; + } + + p { + margin: 0; + width: 1%; + padding: 0 1%; + font-size: 16px; + line-height: 1.5; + float: left; + } + + .input p { + margin-right: 1%; + } + + .output p { + width: 100%; + } + + .input input { + width: 96%; + float: left; + border: none; + font-size: 16px; + line-height: 1.5; + font-family: monospace; + padding: 0; + background: #0C323D; + color: #809089; + } + + div { + clear: both; + } + + </style> + </head> + <body> + + + </body> + + <script> + var geval = eval; + function createInput() { + var inputDiv = document.createElement('div'); + var inputPara = document.createElement('p'); + var inputForm = document.createElement('input'); + + inputDiv.setAttribute('class','input'); + inputPara.textContent = '>'; + inputDiv.appendChild(inputPara); + inputDiv.appendChild(inputForm); + document.body.appendChild(inputDiv); + + if(document.querySelectorAll('div').length > 1) { + inputForm.focus(); + } + + inputForm.addEventListener('change', executeCode); + } + + function executeCode(e) { + try { + var result = geval(e.target.value); + } catch(e) { + var result = 'error — ' + e.message; + } + + var outputDiv = document.createElement('div'); + var outputPara = document.createElement('p'); + + outputDiv.setAttribute('class','output'); + outputPara.textContent = 'Result: ' + result; + outputDiv.appendChild(outputPara); + document.body.appendChild(outputDiv); + + e.target.disabled = true; + e.target.parentNode.style.opacity = '0.5'; + + createInput() + } + + createInput(); + + </script> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Criando_uma_string">Criando uma string</h3> + +<ol> + <li>Para começar, digite as linhas seguintes: + <pre class="brush: js">var string = 'The revolution will not be televised.'; +string;</pre> + Como fizemos com números, nós declaramos uma variável, inicializando-a com um valor string, e então retornamos o valor. A única diferença aqui é que quando escrevemos uma string, você precisa colocá-la entre aspas.</li> + <li>Se você não fez isso, ou esqueceu uma das aspas, você recebeu um erro. Experimente digitar as linhas seguintes: + <pre class="brush: js example-bad">var badString = This is a test; +var badString = 'This is a test; +var badString = This is a test';</pre> + Estas linhas não funcionam porque todo texto sem aspas são interpretados como um nome de variável, propriedade do nome, palavra reservada ou algo assim. Se o navegador não puder encontrar, então um é erro é apresentado (ex.: "faltando; declaração anterior"). Se o navegador puder ver onde a string começa, mas não conseguir encontrar o fim, como indicado com as segundas aspas, é retornado um erro (com "string não terminada"). Se seu programa retorna tais erros, então volte e verifique todas suas strings para ter certeza que não faltam aspas.</li> + <li>O seguinte funcionará se você definiu previamente a variável <code>string</code> - tente isto agora: + <pre class="brush: js">var badString = string; +badString;</pre> + <code>badString</code> é agora definido para ter o mesmo valor de <code>string</code>.</li> +</ol> + +<h3 id="Aspas_simples_x_aspas_duplas">Aspas simples x aspas duplas</h3> + +<ol> + <li>Em JavaScript, você pode escolher aspas simples ou duplas para envolver suas strings. Ambas linhas abaixo funcionará bem: + <pre class="brush: js">var sgl = 'Single quotes.'; +var dbl = "Double quotes"; +sgl; +dbl;</pre> + </li> + <li>Há poucas diferenças entre as duas, e qual você usar é de preferência pessoal. Você deve escolher uma e permanecer nela, entretanto; diferentes aspas no código pode ser confuso, especialmente se você usa diferentes aspas na mesma string! O seguinte retornará erro: + <pre class="brush: js example-bad">var badQuotes = 'What on earth?";</pre> + </li> + <li>O navegador interpretará como a string não tivesse fechada, porque o outro tipo de aspas pode aparecer dentro da sua string. Por exemplo, ambos exemplos abaixo são okay: + <pre class="brush: js">var sglDbl = 'Would you eat a "fish supper"?'; +var dblSgl = "I'm feeling blue."; +sglDbl; +dblSgl;</pre> + </li> + <li>Entretanto, você não pode incluir o mesmo tipo de aspas dentro da sua string, se você usa para conter seu texto. O seguinte será um erro, como é confuso para o navegador onde a string termina: + <pre class="brush: js example-bad">var bigmouth = 'I've got no right to take my place...';</pre> + Isto nos leva muito bem ao nosso próximo assunto.</li> +</ol> + +<h3 id="Caracteres_de_escape_na_string">Caracteres de escape na string</h3> + +<p>Para corrigir o problema anterior, nós precisamos escapar o problema da aspa. Caracteres de escape significa que nós fazemos algo para ter certeza que eles são reconhecidos como texto, não parte do código. Em JavaScript, nós fazemos isso colocando uma barra invertida logo antes do caracter.Tente isso:</p> + +<pre class="brush: js">var bigmouth = 'I\'ve got no right to take my place...'; +bigmouth;</pre> + +<p>Isto funciona bem. Você pode escapar outros caracteres do mesmo jeito, ex.: <code>\"</code>, e há alguns códigos especiais também. Veja <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#Escape_notation">Notação de escape</a> para mais detalhes.</p> + +<h2 id="Concatenando_strings">Concatenando strings</h2> + +<ol> + <li>Concatenar é uma palavra chique da programação que significa "colocar junto". Para colocar strings juntas em JavaScript, usamos o operador (+), o mesmo usamos para adicionar números, mas neste contexto é algo diferente. Vamos tentar este exemplo no console. + <pre class="brush: js">var one = 'Hello, '; +var two = 'how are you?'; +var joined = one + two; +joined;</pre> + O resultado disso é uma variável chamada <code>joined</code>, que contém o valor "Hello, how are you?".</li> + <li>No último exemplo, nós somente juntamos duas strings, mas você pode fazer quantas quiser, contanto que inclua um <code>+</code> entre cada uma.Experimente isso: + <pre class="brush: js">var multiple = one + one + one + one + two; +multiple;</pre> + </li> + <li>Você pore usar um mix de variáveis e strings reais. Tente isso: + <pre class="brush: js">var response = one + 'I am fine — ' + two; +response;</pre> + </li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Quando você coloca uma string atual no seu código dentro de aspas simples ou duplas, é chamada uma <strong>string literal</strong>.</p> +</div> + +<h3 id="Concatenação_em_contexto">Concatenação em contexto</h3> + +<p>Vamos dar uma olhada na concatenação em ação — aqui está um exemplo do curso anterior:</p> + +<pre class="brush: html"><button>Pressione-me</button></pre> + +<pre class="brush: js">var button = document.querySelector('button'); + +button.onclick = function() { + var nome = prompt('Qual é o seu nome?'); + alert('Olá ' + nome + ', prazer em conhecê-lo!'); +}</pre> + +<p>{{ EmbedLiveSample('Concatenation_in_context', '100%', 50, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>Aqui estamos usando uma função {{domxref("Window.prompt()", "Window.prompt()")}} na linha 4, a qual pergunta ao usuário para responder uma questão via uma caixa de diálogo, então armazena o texto em uma variável — neste caso <code>nome</code>. Nós então usamos uma função {{domxref("Window.alert()", "Window.alert()")}} na linha 5 para mostrar outra caixa de diálogo contendo nossa string montada de duas strings literais e a variável <code>name</code>,via concatenação.</p> + +<h3 id="Números_x_strings">Números x strings</h3> + +<ol> + <li>Então o que acontece quando tentamos adicionar (ou concatenar) uma string e um número? Vamos tentar isso no console: + <pre class="brush: js">'Front ' + 242; +</pre> + Você pode esperar um erro disto, mas funciona correto. Tentando representar uma string como um número, realmente não faz sentido. Mas representando um número como string, faz. Então o navegador espertamente converte o número em string e concatena as duas.</li> + <li>Você pode fazer isto até com dois números — você pode forçar um número a ser string colocando ele entre aspas. Experimente o seguinte (nós estamos usando o operador <code>typeof</code> para checar o que a variável é, se um número ou string): + <pre class="brush: js">var myDate = '19' + '67'; +typeof myDate;</pre> + </li> + <li>Se você tem uma variável numérica que precisa converter em string, mas não mudar completamente, ou uma string e quer converter em número, você pode usar a construção seguinte: + <ul> + <li>O objeto {{jsxref("Number")}} converterá qualquer coisa passada em um número, se for possível. Tente o seguinte: + <pre class="brush: js">var myString = '123'; +var myNum = Number(myString); +typeof myNum;</pre> + </li> + <li>Por outro lado, todo número tem um método chamado <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString">toString()</a></code> que converterá para a string equivalente. Tente isto: + <pre class="brush: js">var myNum = 123; +var myString = myNum.toString(); +typeof myString;</pre> + </li> + </ul> + Estas construções podem ser bem úteis em algumas situações. Por exemplo, se o usuário colocar um número em um campo de texto, isso será uma string. Entretanto, se você quiser adicionar este número a algo, você precisa que seja um número, então você pode passar isto através do <code>Number()</code> para poder manipular.Nós fizemos exatamente isto no nosso <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/first-splash/number-guessing-game.html#L61">Number Guessing Game, in line 61</a>.</li> +</ol> + +<h2 id="Conclusão">Conclusão</h2> + +<p>Então isto é o basico sobre strings em JavaScript. No próximo artigo nós iremos continuar daqui, vendo alguns métodos de construção de strings disponíveis em JavaScript e como nós podemos usá-los para manipular nossa string da forma como quisermos.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}}</p> + + + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript">O que é JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/A_first_splash">Um primeiro mergulho em JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong">O que deu errado? Solução de erros em JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables">Armazenando a informação que você precisa — Variáveis</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math">Matemática básica em JavaScript — números e operadores</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings">Manipulando texto — strings em JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos úteis de strings</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Silly_story_generator">Avaliação: gerador de história boba</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/first_steps/teste_suas_habilidades_colon__variaveis/index.html b/files/pt-br/learn/javascript/first_steps/teste_suas_habilidades_colon__variaveis/index.html new file mode 100644 index 0000000000..1a14c86630 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/teste_suas_habilidades_colon__variaveis/index.html @@ -0,0 +1,85 @@ +--- +title: 'Teste suas habilidades: variáveis' +slug: 'Learn/JavaScript/First_steps/Teste_suas_habilidades:_variaveis' +tags: + - Aprender + - Habilidades + - Iniciante + - JavaScript + - Teste suas habilidades + - Variáveis +translation_of: 'Learn/JavaScript/First_steps/Test_your_skills:_variables' +--- +<div>{{learnsidebar}}</div> + +<p>O objetivo deste teste de habilidade é avaliar se você entendeu nosso artigo <a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Vari%C3%A1veis">Armazenando as informações que você precisa — Variáveis</a>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Você pode experimentar soluções nos editores interativos abaixo. No entanto, pode ser útil fazer o download do código e usar uma ferramenta on-line como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, ou <a href="https://glitch.com/">Glitch</a> para realizar as tarefas.<br> + <br> + Se você travar, peça ajuda — veja a seção {{anch("Assessment or further help")}} na parte inferior desta página.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: Nos exemplos abaixo, se houver um erro no seu código, ele será exibido no painel de resultados da página, para ajudá-lo a tentar descobrir a resposta (ou no console JavaScript do navegador, no caso da versão para download).</p> +</div> + +<h2 id="Variáveis_1">Variáveis 1</h2> + +<p>Nesta tarefa, queremos que você:</p> + +<ul> + <li>Declare uma variável chamada <code>meuNome</code>.</li> + <li>Inicialize <code>meuNome</code> com um valor adequado, em uma linha separada (você pode usar seu nome real ou qualquer outra coisa).</li> + <li>Declare uma variável chamada <code>minhaIdade</code> e inicialize-a com um valor, na mesma linha.</li> +</ul> + +<p>Tente atualizar o código ativo abaixo para recriar o exemplo final:</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/variables/variables1.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables1-download.html">Faça o download do ponto de partida</a> para esta tarefa funcionar em seu próprio editor ou em um editor online.</p> +</div> + +<h2 id="Variáveis_2">Variáveis 2</h2> + +<p>Nesta tarefa, você precisa adicionar uma nova linha para corrigir o valor armazenado na variável <code>meuNome</code> existente para seu próprio nome.</p> + +<p>Tente atualizar o código ativo abaixo para recriar o exemplo final:</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/variables/variables2.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables2-download.html">Faça o download do ponto de partida</a> para esta tarefa funcionar em seu próprio editor ou em um editor online.</p> +</div> + +<h2 id="Variáveis_3">Variáveis 3</h2> + +<p>A tarefa final por enquanto — neste caso, você recebe um código existente, que possui dois erros. O painel de resultados deve exibir o nome <code>Chris</code>, e uma declaração sobre quantos anos Chris terá daqui a 20 anos. Como você pode corrigir o problema e corrigir a saída?</p> + +<p>Tente atualizar o código ativo abaixo para recriar o exemplo final:</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/variables/variables3.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables3-download.html">Faça o download do ponto de partida</a> para esta tarefa funcionar em seu próprio editor ou em um editor online.</p> +</div> + +<h2 id="Avaliação_ou_ajuda_adicional">Avaliação ou ajuda adicional</h2> + +<p>Você pode praticar esses exemplos nos editores interativos acima.</p> + +<p>Se você gostaria que seu trabalho fosse avaliado, ou está travado e quer pedir ajuda:</p> + +<ol> + <li>Coloque seu trabalho em um editor compartilhável on-line, como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, ou <a href="https://glitch.com/">Glitch</a>. Você pode escrever o código você mesmo ou usar os arquivos de ponto de partida vinculados nas seções acima.</li> + <li>Escreva um post pedindo avaliação e/ou ajuda na categoria <a href="https://discourse.mozilla.org/c/mdn/learn">MDN Discourse forum Learning</a>. Seu post deve incluir: + <ul> + <li>Um título descritivo como "Avaliação desejada para o teste de habilidade Variáveis 1".</li> + <li>Detalhes do que você já tentou e o que gostaria que fizéssemos. Por exemplo, se você está travado e precisa de ajuda ou deseja uma avaliação.</li> + <li>Um link para o exemplo que você deseja que seja avaliado ou precisa de ajuda, em um editor compartilhável online (conforme mencionado na etapa 1 acima). Esta é uma boa prática para entrar - é muito difícil ajudar alguém com um problema de codificação se você não conseguir ver o código.</li> + <li>Um link para a página real de tarefas ou avaliações, para que possamos encontrar a pergunta com a qual você deseja ajuda.</li> + </ul> + </li> +</ol> diff --git a/files/pt-br/learn/javascript/first_steps/useful_string_methods/index.html b/files/pt-br/learn/javascript/first_steps/useful_string_methods/index.html new file mode 100644 index 0000000000..3304dd800e --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/useful_string_methods/index.html @@ -0,0 +1,484 @@ +--- +title: Métodos úteis de string +slug: Learn/JavaScript/First_steps/Useful_string_methods +translation_of: Learn/JavaScript/First_steps/Useful_string_methods +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Agora que nós vimos o básico de strings, vamos engatar a próxima marcha e começar a pensar sobre as operações úteis que podemos fazer em strings com métodos embutidos, como encontrar o comprimento de um string, unir e dividir sequências de caracteres, substituindo um caracter em uma string por outro, e muito mais.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimento básico de computador, uma compreensão básica de HTML e CSS, uma compreensão do que é o JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Entender que strings são objetos e aprender a usar alguns do métodos básicos disponíveis nesses objetos para manipular strings.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Strings_como_objetos">Strings como objetos</h2> + +<p>Como dissemos antes e diremos novamente — <em>tudo</em> é um objeto em JavaScript. Quando você cria um string, usando por exemplo</p> + +<pre class="brush: js">var string = 'This is my string';</pre> + +<p>sua variável torna-se uma instância do objeto string e, como resultado, tem um grande número de propriedades e métodos diponíveis para ela. Você pode ver isso se você for na página do objeto {{jsxref("String")}} e olhar para baixo na lista do lado da página!</p> + +<p><strong>Agora, antes de seu cérebro começar a derreter, não se preocupe!</strong> Você não precisa saber sobre a maioria deles no início da sua jornada de aprendizado. Mas há alguns que você potencialmente usará com bastante frequência que veremos aqui.</p> + +<p>Vamos digitar alguns exemplos em um console novo. Nós fornecemos um abaixo (você também pode abrir este console em uma guia ou janela separada, ou usar o console do desenvolvedor do navegador, se preferir).</p> + +<p>Nós fornecemos um abaixo (você também pode <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">abrir esse console</a> em uma aba ou janela separada, ou usar o <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console do navegador do desenvolvedor</a> se você preferir).</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>JavaScript console</title> + <style> + * { + box-sizing: border-box; + } + + html { + background-color: #0C323D; + color: #809089; + font-family: monospace; + } + + body { + max-width: 700px; + } + + p { + margin: 0; + width: 1%; + padding: 0 1%; + font-size: 16px; + line-height: 1.5; + float: left; + } + + .input p { + margin-right: 1%; + } + + .output p { + width: 100%; + } + + .input input { + width: 96%; + float: left; + border: none; + font-size: 16px; + line-height: 1.5; + font-family: monospace; + padding: 0; + background: #0C323D; + color: #809089; + } + + div { + clear: both; + } + + </style> + </head> + <body> + + + </body> + + <script> + var geval = eval; + function createInput() { + var inputDiv = document.createElement('div'); + var inputPara = document.createElement('p'); + var inputForm = document.createElement('input'); + + inputDiv.setAttribute('class', 'input'); + inputPara.textContent = '>'; + inputDiv.appendChild(inputPara); + inputDiv.appendChild(inputForm); + document.body.appendChild(inputDiv); + + inputForm.addEventListener('change', executeCode); + } + + function executeCode(e) { + try { + var result = geval(e.target.value); + } catch(e) { + var result = 'error — ' + e.message; + } + + var outputDiv = document.createElement('div'); + var outputPara = document.createElement('p'); + + outputDiv.setAttribute('class','output'); + outputPara.textContent = 'Result: ' + result; + outputDiv.appendChild(outputPara); + document.body.appendChild(outputDiv); + + e.target.disabled = true; + e.target.parentNode.style.opacity = '0.5'; + + createInput() + } + + createInput(); + + </script> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 300) }}</p> + +<h3 id="Descobrindo_o_comprimento_de_uma_string">Descobrindo o comprimento de uma string</h3> + +<p>Essa é fácil — você simplesmente usa a propriedade {{jsxref("String.prototype.length", "length")}}. Tente digitar as linhas a seguir:</p> + +<pre class="brush: js">var browserType = 'mozilla'; +browserType.length;</pre> + +<p>Isso deve retornar o número 7, porque "mozilla" tem 7 caracteres. Isso é útil por vários motivos; por exemplo, você pode querer encontrar os comprimentos de uma série de nomes para que você possa exibi-los em ordem de comprimento, ou deixar um usuário saber que um nome de usuário que ele informou em um campo de formulário é muito longo se este for maior do que um certo comprimento.</p> + +<h3 id="Recuperando_um_caractere_de_string_específico">Recuperando um caractere de string específico</h3> + +<p>Nota complementar: você pode retornar qualquer caractere dentro de uma string usando a<strong> notação colchete</strong> - isso significa que você inclui colchetes (<code>[]</code>) no final do nome da variável. Dentro dos colchetes, você inclui o número do caractere que deseja retornar, por exemplo, para recuperar a primeira letra, faça o seguinte:</p> + +<pre class="brush: js">browserType[0];</pre> + +<p>Computadores contam a partir de 0, não 1! Para recuperar o último caractere de <em>qualquer</em> string, nós podemos usar a linha a seguir, combinando essa técnica com a propriedade <code>length</code> que vimos anteriormente:</p> + +<pre class="brush: js">browserType[browserType.length-1];</pre> + +<p>O comprimento de "mozilla" é 7, mas porque a contagem começa de 0, a posição do caractere é 6, daí precisamos usar <code>length-1</code>. Você pode usar isso para, por exemplo, encontrar a primeira letra de uma série de strings e ordená-los alfabeticamente.</p> + +<h3 id="Encontrando_uma_substring_dentro_de_uma_string_e_extraindo-a">Encontrando uma substring dentro de uma string e extraindo-a</h3> + +<ol> + <li>Às vezes você quer sabe se uma string menor está presente dentro de uma maior (geralmente dizemos <em>se uma substring está presente dentro de uma string</em>). Isso pode ser feito usando o método {{jsxref ("String.prototype.indexOf ()", "indexOf ()")}}, que leva um único {{glossary ("parameter")}} - a substring que deseja procurar. Experimente isso: + + <pre class="brush: js">browserType.indexOf('zilla');</pre> + Isso nos dá o resultado 2, porque a substring "zilla" se inicia na posição 2 (0, 1, 2 — então, 3 caraceteres) dentro de "mozilla". Esse código poderia ser usado para filtrar cadeias de caracteres. Por exemplo, podemos ter uma lista de endereços da web e apenas queremos imprimir aqueles que contenham "mozilla".</li> + <li>Isso pode ser feito de outro jeito, que é possivelmente mais eficaz. Experimente isso: + <pre class="brush: js">browserType.indexOf('vanilla');</pre> + Isso deve lhe dar um resultado <code>-1</code> — isso é retornado quando a substring, neste caso 'vanilla', não é encontrada na string principal.<br> + <br> + Você pode usar isso para encontrar todas as instâncias de strings que <strong>não contém</strong> a substring 'mozilla', ou <strong>contém</strong>, se você usar o operador de negação, conforme mostrado abaixo. Você poderia fazer algo assim: + + <pre class="brush: js">if(browserType.indexOf('mozilla') !== -1) { + // faz coisas com a string +}</pre> + </li> + <li>Quando você sabe onde uma substring começa dentro de uma string e você sabe em qual caractere você deseja que ela termine, {{jsxref ("String.prototype.slice ()", "slice ()")}} pode ser usado para extrair isto. Tente o seguinte: + <pre class="brush: js">browserType.slice(0,3);</pre> + Isso retorna "moz" — o primeiro parâmetro é a posição do caractere a partir da qual será iniciada a extração, e o segundo parâmetro é a posição seguinte do último caractere a ser extraído. Então, a fatia ocorre da primeira posição, até a última posição, mas não incluindo. Você também pode dizer que o segundo parâmetro é igual ao comprimento da string que está sendo retornada.</li> +</ol> + +<p>Também, se você sabe que você deseja extrair todos os caracteres restantes em uma string após um certo caracter, você não tem que incluir o segundo parametro! Você apenas precisa incluir a posição do caracter a partir de onde você deseja extrar os caracteres restantes em uma string. Tente o seguinte: </p> + +<pre class="brush: js">browserType.slice(2);</pre> + +<p>Isso retornará "zilla" — isso é porque a posição de caracter 2 é a letra z, e porque você não incluiu o segundo parametro, a substring retornou todos os caracteres restantes na string. </p> + +<div class="note"> +<p><strong>Note</strong>: O segundo parametro do <code>slice()</code> é opcional: Se você não incluir ele, o slice finaliza no fim da string original. Existem outras opções também; estude a {{jsxref("String.prototype.slice()", "slice()")}} pagina para ver o que mais você pode descobrir.</p> +</div> + +<h3 id="Mudando_entre_maiúsculas_e_minúsculas">Mudando entre maiúsculas e minúsculas</h3> + +<p>O método string {{jsxref("String.prototype.toLowerCase()", "toLowerCase()")}} e {{jsxref("String.prototype.toUpperCase()", "toUpperCase()")}} toma a string e converte todos os caracteres para minusculo - ou maiusculo, respectivamente. Este pode ser util, por exemplo, se você quer normalizar todas as entradas de dados do usuário antes de armazenar em um banco de dados.</p> + +<p>Vamos testar inserindo as seguintes linhas para ver o que acontece:</p> + +<pre class="brush: js">var radData = 'My NaMe Is MuD'; +radData.toLowerCase(); +radData.toUpperCase();</pre> + +<h3 id="Atualizando_partes_de_uma_string">Atualizando partes de uma string</h3> + +<p>Você pode substituir uma substring dentro de uma string com uma outra substring usando o método {{jsxref("String.prototype.replace()", "replace()")}}. Este funciona muito simples em um nível básico, apesar haver algumas coisas avançadas que você pode fazer com ele, nós não iremos tão longe ainda.</p> + +<p>Ele toma dois parametros — A string que você quer substituir e a string que você quer que substitua o primeiro parametro. Tente este exemplo:</p> + +<pre class="brush: js">browserType.replace('moz','van');</pre> + +<p>Observe que para realmente obter o valor atualizado refletido na variavel <code>browserType</code> em um programa real, você teria que setar o valor da variavel para ser o resultado da operação; não apenas atualizar o valor da substring automaticamente. Assim você teria que realmente escrever isso: <code>browserType = browserType.replace('moz','van');</code></p> + +<h2 id="Exemplos_para_aprendizado_ativo">Exemplos para aprendizado ativo</h2> + +<p>Nesta seção, tentaremos escrever um código de manipulação de string. Em cada exercício abaixo, temos uma matriz de strings e um loop que processa cada valor na matriz e o exibe em uma lista com marcadores. Você não precisa entender matrizes ou loops agora - isso será explicado em artigos futuros. Tudo o que você precisa fazer em cada caso é escrever o código que produzirá as strings no formato em que as queremos.</p> + +<p>Cada exemplo vem com um botão "Reset", que você pode usar para redefinir o código original, isso se cometer um erro e não conseguir faze-lo funcionar novamente, e um botão "Show Solution" que você pode pressionar para ver aresposta em potencial se realmente estiver travado.</p> + +<h3 id="Filtrando_mensagens_de_saudação">Filtrando mensagens de saudação</h3> + +<p>No primeiro exercício, começaremos com simplicidade - temos várias mensagens de cartão, mas queremos classificá-las para listar apenas as mensagens de Natal. Queremos que você preencha um teste condicional dentro da estrutura if (...), para testar cada string e apenas imprimi-la na lista se for uma mensagem de Natal.</p> + +<ol> + <li>Primeiro pense em como você poderia testar se a mensagem em cada caso é uma mensagem de Natal. Qual string está presente em todas essas mensagens e que método você poderia usar para testar se ela está presente?</li> + <li>Em seguida, você precisará escrever um teste condicional do formulario operando2 operador operando1. A coisa à esquerda é igual à coisa à direita? Ou neste caso, o método chama à esquerda retorna o resultado à direita?</li> + <li>Dica: Nesse caso, é provavelmente mais útil testar se a chamada do método não é igual a um determinado resultado.</li> +</ol> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html"><div class="output" style="min-height: 125px;"> + +<ul> + +</ul> + +</div> + +<textarea id="code" class="playable-code" style="height: 290px;"> +var list = document.querySelector('.output ul'); +list.innerHTML = ''; +var greetings = ['Happy Birthday!', + 'Merry Christmas my love', + 'A happy Christmas to all the family', + 'You\'re all I want for Christmas', + 'Get well soon']; + +for (var i = 0; i < greetings.length; i++) { + var input = greetings[i]; + // Seu teste condicional precisa ir dentro dos parênteses + // na linha abaixo, substituindo o que está lá + if (greetings[i]) { + var result = input; + var listItem = document.createElement('li'); + listItem.textContent = result; + list.appendChild(listItem); + } +} +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + updateCode(); +}); + +solution.addEventListener('click', function() { + textarea.value = jsSolution; + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar greetings = [\'Happy Birthday!\',\n \'Merry Christmas my love\',\n \'A happy Christmas to all the family\',\n \'You\\\'re all I want for Christmas\',\n \'Get well soon\'];\n\nfor(var i = 0; i < greetings.length; i++) {\n var input = greetings[i];\n if(greetings[i].indexOf(\'Christmas\') !== -1) {\n var result = input;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n }\n}'; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', '100%', 490) }}</p> + +<h3 id="Corrigindo_a_capitalização">Corrigindo a capitalização</h3> + +<p>Neste exercício, temos os nomes das cidades no Reino Unido, mas a capitalização está toda desarrumada. Nós queremos que você as altere para que elas sejam todas minúsculas, exceto pela primeira letra maiúscula. Uma boa maneira de fazer isso é:</p> + +<ol> + <li>Converta toda a cadeia contida na variável de entrada para minúscula e armazene-a em uma nova variável.</li> + <li>Pegue a primeira letra da string nesta nova variável e armazene-a em outra variável.</li> + <li>Usando esta última variável como substring, substitua a primeira letra da string em minúsculas pela primeira letra da string em minúsculas alterada para maiúscula. Armazene o resultado desse procedimento de substituição em outra nova variável.</li> + <li>Altere o valor da variável <code>result</code> para igual ao resultado final, não a <code>input</code>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Uma dica — os parâmetros dos métodos de string não precisam ser literais de string; eles também podem ser variáveis, ou mesmo variáveis com um método sendo invocado nelas.</p> +</div> + +<div class="hidden"> +<h6 id="Playable_code_2">Playable code 2</h6> + +<pre class="brush: html"><div class="output" style="min-height: 125px;"> + +<ul> + +</ul> + +</div> + +<textarea id="code" class="playable-code" style="height: 250px;"> +var list = document.querySelector('.output ul'); +list.innerHTML = ''; +var cities = ['lonDon', 'ManCHESTer', 'BiRmiNGHAM', 'liVERpoOL']; +for(var i = 0; i < cities.length; i++) { + var input = cities[i]; + // write your code just below here + + var result = input; + var listItem = document.createElement('li'); + listItem.textContent = result; + list.appendChild(listItem); +} +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + updateCode(); +}); + +solution.addEventListener('click', function() { + textarea.value = jsSolution; + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar cities = [\'lonDon\', \'ManCHESTer\', \'BiRmiNGHAM\', \'liVERpoOL\'];\n\nfor(var i = 0; i < cities.length; i++) {\n var input = cities[i];\n var lower = input.toLowerCase();\n var firstLetter = lower.slice(0,1);\n var capitalized = lower.replace(firstLetter,firstLetter.toUpperCase());\n var result = capitalized;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n\n}'; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', '100%', 450) }}</p> + +<h3 id="Fazendo_novas_strings_a_partir_de_partes_antigas">Fazendo novas strings a partir de partes antigas</h3> + +<p>Neste último exercício, o array contém um monte de strings contendo informações sobre estações de trem no norte da Inglaterra. As strings são itens de dados que contêm o código da estação de três letras, seguido por alguns dados legíveis por máquina, seguidos por um ponto-e-vírgula, seguido pelo nome da estação legível por humanos. Por exemplo:</p> + +<pre>MAN675847583748sjt567654;Manchester Piccadilly</pre> + +<p>Queremos extrair o código e o nome da estação e juntá-los em uma string com a seguinte estrutura:</p> + +<pre>MAN: Manchester Piccadilly</pre> + +<p>Nós recomendamos que faça assim:</p> + +<ol> + <li>Extraia o código da estação de três letras e armazene-o em uma nova variável.</li> + <li>Encontre o número de índice do caractere do ponto e vírgula.</li> + <li>Extraia o nome da estação legível usando o número do índice de caracteres de ponto-e-vírgula como ponto de referência e armazene-o em uma nova variável.</li> + <li>Concatene as duas novas variáveis e uma string literal para fazer a string final.</li> + <li>Altere o valor da variável <code>result</code> para igual à string final, não a <code>input</code>.</li> +</ol> + +<div class="hidden"> +<h6 id="Playable_code_3">Playable code 3</h6> + +<pre class="brush: html"><div class="output" style="min-height: 125px;"> + +<ul> + +</ul> + +</div> + +<textarea id="code" class="playable-code" style="height: 285px;"> +var list = document.querySelector('.output ul'); +list.innerHTML = ''; +var stations = ['MAN675847583748sjt567654;Manchester Piccadilly', + 'GNF576746573fhdg4737dh4;Greenfield', + 'LIV5hg65hd737456236dch46dg4;Liverpool Lime Street', + 'SYB4f65hf75f736463;Stalybridge', + 'HUD5767ghtyfyr4536dh45dg45dg3;Huddersfield']; + +for (var i = 0; i < stations.length; i++) { + var input = stations[i]; + // write your code just below here + + var result = input; + var listItem = document.createElement('li'); + listItem.textContent = result; + list.appendChild(listItem); +} +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + updateCode(); +}); + +solution.addEventListener('click', function() { + textarea.value = jsSolution; + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar stations = [\'MAN675847583748sjt567654;Manchester Piccadilly\',\n \'GNF576746573fhdg4737dh4;Greenfield\',\n \'LIV5hg65hd737456236dch46dg4;Liverpool Lime Street\',\n \'SYB4f65hf75f736463;Stalybridge\',\n \'HUD5767ghtyfyr4536dh45dg45dg3;Huddersfield\'];\n\nfor(var i = 0; i < stations.length; i++) {\n var input = stations[i];\n var code = input.slice(0,3);\n var semiC = input.indexOf(\';\');\n var name = input.slice(semiC + 1);\n var result = code + \': \' + name;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n}'; + + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_3', '100%', 485) }}</p> + +<h2 id="Conclusão">Conclusão</h2> + +<p>Você não pode escapar do fato de que ser capaz de lidar com palavras e frases em programação é muito importante — particularmente em JavaScript, pois os sites são todos sobre comunicação com pessoas. Este artigo forneceu os fundamentos que você precisa saber sobre a manipulação de strings por enquanto. Isso deve atendê-lo bem ao abordar tópicos mais complexos no futuro. Em seguida, vamos ver o último tipo de dados importante que precisamos focar no curto prazo — arrays.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript">What is JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/A_first_splash">A first splash into JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong">What went wrong? Troubleshooting JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables">Storing the information you need — Variables</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math">Basic math in JavaScript — numbers and operators</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings">Handling text — strings in JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Useful string methods</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Silly_story_generator">Assessment: Silly story generator</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/first_steps/variáveis/index.html b/files/pt-br/learn/javascript/first_steps/variáveis/index.html new file mode 100644 index 0000000000..1afd436622 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/variáveis/index.html @@ -0,0 +1,332 @@ +--- +title: Armazenando as informações que você precisa — Variáveis +slug: Learn/JavaScript/First_steps/Variáveis +translation_of: Learn/JavaScript/First_steps/Variables +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Depois de ler os últimos artigos, você deve saber agora o que é o JavaScript, o que ele pode fazer para você, como você usa isso junto com outras tecnologias da web e as características principais de alto nível. Neste artigo, iremos ao básico, vendo como trabalhar com a maioria dos blocos de construção básicos de JavaScript - Variáveis.</p> + +<table class="learn-box"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimento básico em informática, uma compreensão básica de HTML e CSS, uma compreensão do que é o JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizar-se com o básico de variáveis em JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Ferramentas_que_você_precisa">Ferramentas que você precisa</h2> + +<p>Ao longo deste artigo, pediremos que você digite linhas de código para testar seu entendimento do conteúdo. Se você estiver utilizando um navegador em um computador, o melhor lugar para digitar seus código de exemplos é o console JavaScript do seu navegador (veja o artigo <a href="/pt-BR/docs/Learn/Common_questions/ferramentas_de_desenvolvimento_do_navegador">O que são as ferramentas de desenvolvimento do navegador</a> para mais informações sobre como acessar essa ferramenta).</p> + +<p>No entanto, nós também providenciamos um simples console JavaScript incorporado à página logo abaixo para que você inserir o código, caso não esteja usando um navegador com um console JavaScript facilmente disponível, ou se achar o console incorporado mais confortável.</p> + +<h2 id="O_que_é_uma_variável">O que é uma variável?</h2> + +<p>Uma variável é um container para um valor, como um número que podemos usar em uma operação de adição, ou uma sequência de texto que possamos usar como parte de uma oração. Mas uma coisa especial a respeito das variáveis é que seu conteúdo pode mudar. Vamos ver um exemplo simples:</p> + +<pre class="brush: html notranslate"><button>Aperte-me</button></pre> + +<pre class="brush: js notranslate">var button = document.querySelector('button'); + +button.onclick = function() { + var nome = prompt('Qual é o seu nome?'); + alert('Olá ' + nome + ', é um prazer te ver!'); +}</pre> + +<p>{{ EmbedLiveSample('O_que_é_uma_variável', '100%', 50, "", "", "hide-codepen-jsfiddle" ) }}</p> + +<p>Nesse exemplo, apertar o botão executa algumas linhas de código. A primeira linha exibe uma caixa pop-up na tela que pede ao leitor para inserir o seu nome, e então armazena o valor na variável. A segunda linha exibe uma mensagem de boas vindas que inclui seu nome, obtido do valor da variável.</p> + +<p>Para entender porque isso é útil, vamos pensar sobre como nós escreveríamos esse exemplo sem usar uma variável. Iria acabar se parecendo com algo do tipo:</p> + +<pre class="example-bad notranslate">var nome = prompt('Qual é o seu nome?'); + +if (nome === 'Adão') { + alert('Olá Adão, é um prazer te ver!'); +} else if (nome === 'Alan') { + alert('Olá Alan, é um prazer te ver!'); +} else if (nome === 'Bella') { + alert('Olá Bella, é um prazer te ver!'); +} else if (nome === 'Bianca') { + alert('Olá Bianca, é um prazer te ver!'); +} else if (nome === 'Chris') { + alert('Olá Chris, é um prazer te ver !'); +} + +// ... e assim por diante ...</pre> + +<p>Você talvez não entenda totalmente a sintaxe que estamos usando (ainda!), mas deve ter pegado a ideia — se nós não tivermos variáveis disponíveis teríamos que implementar um bloco de código gigantesco para conferir qual era o nome inserido, e então exibir a mensagem apropriada para aquele nome. Isso é obviamente muito ineficiente (o código é muito maior, mesmo para apenas quatro opções de nome), e simplesmente não funcionaria — você não poderia armazenar todas as possíveis opções de nome.</p> + +<p>Variáveis simplesmente fazem sentido, e a medida que você for aprendendo mais sobre JavaScript elas começarão a se tornar uma coisa natural.</p> + +<p>Outra coisa especial sobra as variáveis é que elas podem conter praticamente qualquer coisa — não apenas cadeias de texto e números. Variáveis também podem conter dados complexos e até mesmo funções completas para fazer coisas incríveis. Você irá aprender mais sobre isso a medida que continuarmos.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Perceba que dissemos que as variáveis contém valores. Essa é uma distinção importante a se fazer. Elas não são os valores; e sim os containers para eles. Você pode pensar nelas sendo pequenas caixas de papelão nas quais você pode guardar coisas..</p> +</div> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13506/boxes.png" style="display: block; height: 436px; margin: 0px auto; width: 1052px;"></p> + +<h2 id="Declarando_uma_variável">Declarando uma variável</h2> + +<p>Para usar uma variável primeiro tem que criá-la — mais precisamente, chamamos isso de declarar a variável. Para fazê-lo digitamos a palavra chave <code>var</code> seguido do nome que desejamos dar à variável:</p> + +<pre class="brush: js notranslate">var meuNome; +var minhaIdade;</pre> + +<p>Aqui, estamos criando duas variáveis chamadas <code>meuNome</code> e <code>minhaIdade</code>. Tente agora digitar essas linhas no console do seu navegador. Depois disso, tente criar uma variável (ou duas) com suas próprias escolhas de nomes.</p> + +<div class="note"> +<p><strong>Nota</strong>: No JavaScript, todas as intruções em código deve terminar com um ponto e vírgula (<code>;</code>) — seu código pode até funcionar sem o ponto e vírgula em linhas únicas, mas provavelmente não irá funcionar quando estiver escrevendo várias linhas de código juntas. Tente pegar o hábito de sempre incluir o ponto e vírgula.</p> +</div> + +<p>Você pode testar se os valores agora existem no ambiente de execução digitando apenas os nomes das variáveis, ex.:</p> + +<pre class="brush: js notranslate">meuNome; +minhaidade;</pre> + +<p>Elas atualmente não possuem valor; são containers vazios. Quando você insere o nome de uma variável, você deve obter em retorno ou um valor <code>undefined</code> (indefinido), ou se a variável não existir, você recebe uma mensagem de erro — tente digitar:</p> + +<pre class="brush: js notranslate">scoobyDoo;</pre> + +<div class="note"> +<p><strong>Nota</strong>: Não confunda uma variável que existe mas não tenho valor definido com uma variável que não existe — são coisas bem diferentes.</p> +</div> + +<h2 id="Inicializando_uma_variável">Inicializando uma variável</h2> + +<p>Uma vez que você declarou uma variável, você pode inicializá-la com um valor. Você faz isso digitando o nome da variável, seguido do sinal de igual (<code>=</code>) e o valor que deseja atribuir a ela. Por exemplo:</p> + +<pre class="brush: js notranslate">meuNome = 'Chris'; +minhaIdade = 37;</pre> + +<p>Tente voltar ao console agora e digitar essas linhas acima. Você deve ver o valor que atribuiu à variável retornado no console confirmando-o, em cada caso. De novo, você pode retornar os valores de suas variáveis simplesmente digitando seus nomes no console — tente isso novamente:</p> + +<pre class="brush: js notranslate">meuNome; +minhaIdade;</pre> + +<p>Você pode declarar e inicializar uma variável ao mesmo tempo, assim:</p> + +<pre class="brush: js notranslate">var meuNome = 'Chris';</pre> + +<p>Isso provavelmente é como irá fazer na maioria das vezes, já que é mais rápido do que fazer as duas ações em duas linhas separadas.</p> + +<h2 id="A_diferença_entre_var_e_let">A diferença entre var e let</h2> + +<p>Agora você pode estar pensando "por que precisamos de duas palavras-chave para definir variáveis? Por que <code>var</code> <em>e</em> <code>let</code>?".</p> + +<p>As razões são um tanto históricas. Quando o JavaScript foi criado, havia apenas <code>var</code>. Isso funciona basicamente bem na maioria dos casos, mas tem alguns problemas na maneira como funciona — seu design pode ser confuso ou totalmente irritante. Portanto, <code>let</code> foi criada nas versões modernas de JavaScript, uma nova palavra-chave para criar variáveis que funcionam de maneira um pouco diferente para <code>var</code>, corrigindo seus problemas no processo.</p> + +<p>Algumas diferenças simples são explicadas abaixo. Não abordaremos todas as diferenças agora, mas você começará a descobri-las à medida que aprender mais sobre JavaScript (se realmente quiser ler sobre elas agora, fique à vontade para conferir nossa <a href="/pt-BR/docs/Web/JavaScript/Reference/Statements/let">página de referência let</a>).</p> + +<p>Para começar, se você escrever um programa JavaScript de várias linhas que declare e inicialize uma variável, poderá realmente declarar uma variável com <code>var</code> depois de inicializá-la e ainda funcionará. Por exemplo:</p> + +<pre class="brush: js notranslate">meuNome = 'Chris'; + +function logNome() { + console.log(meuNome); +} + +logNome(); + +var meuNome;</pre> + +<div class="note"> +<p><strong>Nota</strong>: Isso não funcionará ao digitar linhas individuais em um console JavaScript, apenas ao executar várias linhas de JavaScript em um documento da web.</p> +</div> + +<p>Isso funciona por causa do <strong>hoisting</strong> — leia <a href="/pt-BR/docs/Web/JavaScript/Reference/Statements/var#var_hoisting">var hoisting</a> pra mais detalhes.</p> + +<p>Hoisting não funciona mais com <code>let</code>. Se mudássemos de <code>var</code> para <code>let</code> no exemplo acima, teríamos um erro. Isso é bom — declarar uma variável depois que você a inicializa resulta em código confuso e difícil de entender.</p> + +<p>E depois, ao usar <code>var</code>, você pode declarar a mesma variável quantas vezes quiser, mas com <code>let</code> você não consegue. Isso pode funcionar:</p> + +<pre class="brush: js notranslate">var meuNome = 'Chris'; +var meuNome = 'Bob';</pre> + +<p>Mas isso geraria um erro na segunda linha:</p> + +<pre class="brush: js notranslate">let meuNome = 'Chris'; +let meuNome = 'Bob';</pre> + +<p>Você precisaria fazer assim:</p> + +<pre class="brush: js notranslate">let meuNome = 'Chris'; +meuNome = 'Bob';</pre> + +<p>Novamente, essa é uma decisão sensata da linguagem. Não há razão para redeclarar variáveis — isso apenas torna as coisas mais confusas.</p> + +<p>Por esses motivos e mais, recomendamos que você use <code>let</code> o máximo possível em seu código, em vez de <code>var</code>. Não há motivo para usar <code>var</code>, a menos que você precise oferecer suporte para versões antigas do Internet Explorer com seu código (ele não suporta <code>let</code> até a versão 11; o navegador mais moderno do Windows, o Edge, suporta <code>let</code>).</p> + +<h2 id="Atualizando_uma_variável">Atualizando uma variável</h2> + +<p>Uma vez que uma tenha um valor atribuido, você pode atualizar esse valor simplesmente dando a ela um valor diferente. Tente inserir as seguintes linhas no seu console:</p> + +<pre class="brush: js notranslate">meuNome = 'Bob'; +minhaIdade = 40;</pre> + +<h3 id="Um_adendo_sobre_regras_de_nomeação_de_variáveis">Um adendo sobre regras de nomeação de variáveis</h3> + +<p>Você pode chamar uma variável praticamente qualquer nome que queira, mas há limitações. Geralmente você deve se limitar a utilizar somente caracteres latinos (0-9, a-z, A-Z) e o caractere underline ( _ ).</p> + +<ul> + <li>Você não deve usar outros caracteres porque eles podem causar erros ou ser difíceis de entender por uma audiência internacional.</li> + <li>Não use underline no início do nome de variáveis — isso é utilizado em certos construtores JavaScript para significar coisas específicas, então pode deixar as coisas confusas.</li> + <li>Não use número no início do nome de variáveis. Isso não é permitido e irá causar um erro.</li> + <li>Uma conveção segura e se ater é a chamada <a href="https://pt.wikipedia.org/wiki/CamelCase">"lower camel case"</a>, onde você junta várias palavras, usando minúscula para a primeira palavra inteira e, em seguita, maiusculiza a primeira letra das palavras subsequentes. Temos utilizado esse procedimento para os nomes das nossas variáveis nesse artigo até aqui.</li> + <li>Faça nomes de variáveis intuitivos, para que descrevam o dado que ela contém. Não use letras ou números únicos, ou frases muito longas.</li> + <li>As variáveis diferenciam letras maiúsculas e minúsculas — então <code>minhaidade</code> é uma variável diferente de <code>minhaIdade</code>.</li> + <li>Um último ponto — você também precisa evitar utilizar palavras reservadas pelo JavaScript como nome para suas variáveis — com isso, queremos dizer as palavras que fazem parte da sintaxe do JavaScript! Então você não pode usar palavras como <code>var</code>, <code>function</code>, <code>let</code> e <code>for</code> como nome de variáveis. Os navegadores vão reconhecê-las como itens de código diferentes e, portanto, você terá erros.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Você pode encontrar uma lista bem completa de palavras reservadas para evitar em <a href="/pt-BR/docs/Web/JavaScript/Reference/Lexical_grammar#Palavras-chave">Gramática léxica — Palavras-chave</a>.</p> +</div> + +<p>Exemplos de bons nomes:</p> + +<pre class="example-good notranslate">idade +minhaIdade +inicio +corInicial +valorFinalDeSaida +audio1 +audio2</pre> + +<p>Exemplos ruins de nomes:</p> + +<pre class="example-bad notranslate">1 +a +_12 +minhaidade +MINHAIDADE +var +Document +skjfndskjfnbdskjfb +esseeumnomedevariavelbemlongoeestupido +</pre> + +<p>Tente criar mais algumas variáveis agora, com a orientação acima em mente.</p> + +<h2 id="Tipos_de_variáveis">Tipos de variáveis</h2> + +<p>Existem alguns diferentes tipos de dados que podemos armazenar em variáveis. Nessa seção iremos descrevê-los brevemente, e então em artigos futuros você aprenderá sobre eles em mais detalhes.</p> + +<p>Até agora nós vimos os dois primeiros, mas há outros.</p> + +<h3 id="Números">Números</h3> + +<p>Você pode armazenar números em variáveis, tanto números inteiros, como por exemplo 30 (também chamados de <em>integers</em>) como números decimais, por exemplo 2.456 (também chamados de <em>floats</em> ou <em>floating point numbers</em>). Você não precisa declarar tipos de variáveis no JavaScript, diferentemente de outras linguagens de programação. Quando você atribui a uma variável o valor em número, você não inclui as aspas:</p> + +<pre class="brush: js notranslate">var minhaIdade = 17;</pre> + +<h3 id="Strings_cadeias_de_texto"><em>Strings</em> (cadeias de texto)</h3> + +<p><em>Strings</em> são sequências de texto. Quando você dá a uma variável um valor em texto (<em>string</em>), você precisa envolver o texto em aspas simples ou duplas; caso contrário, o JavaScript vai tentar interpretá-lo como sendo outro nome de variável.</p> + +<pre class="brush: js notranslate">var despedidaGolfinho = 'Até logo e obrigado por todos os peixes!';</pre> + +<h3 id="Booleans_boleanos"><em>Booleans</em> (boleanos)</h3> + +<p><em>Booleans</em> são valores verdadeiro/falso (<em>true/false</em>) — eles podem ter dois valores, <code>true</code> (verdadeiro) ou <code>false</code> (falso). São geralmente usados para verificar uma condição, que em seguida o código é executado apopriadamente. Por exemplo, um caso simples seria:</p> + +<pre class="brush: js notranslate">var estouVivo = true;</pre> + +<p>Enquanto na realidade seria utlizado mais da seguinte forma:</p> + +<pre class="brush: js notranslate">var teste = 6 < 3;</pre> + +<p>Esse exemplo está usando o operador "menor que" (<code><</code>) para testar se 6 é menor que 3. Como você pode esperar, irá retornar <code>false</code> (falso), porque 6 não é menor que 3! Você aprenderá mais sobre tais operadores mais tarde no curso.</p> + +<h3 id="Arrays"><em>Arrays</em></h3> + +<p>Um array é um único objeto que contém valores múltiplos inseridos entre colchetes e separados por vírgulas. Tente inserir as seguintes linhas de código no seu console:</p> + +<pre class="brush: js notranslate">var meuNomeArray = ['Chris', 'Bob', 'Jim']; +var meuNumeroArray = [10,15,40];</pre> + +<p>Uma vez que esses arrays estejam definidos, você pode acessar cada um de seus valores através de sua localização dentro do array. Tente essas linhas:</p> + +<pre class="brush: js notranslate">meuNomeArray[0]; // deve retornar 'Chris' +meuNumeroArray[2]; // deve retornar 40</pre> + +<p>Os colchetes especificam um valor do índice correspondente à posição do valor que você deseja retornado. Você talvez tenha notado que os arrays em JavaScript são indexados a partir do zero: o primeiro elemento está na posíção 0 do índice.</p> + +<p>Você aprenderá mais sobre arrays em um artigo futuro.</p> + +<h3 id="Objetos">Objetos</h3> + +<p>Em programação, um objeto é uma estrutura de código que representa um objeto da vida real. Você pode ter um simples objeto que representa um estacionamento de carro contendo informações sobre sobre sua largura e comprimento, ou você poderia ter um objeto que representa uma pessoa, e contém dados sobre seu nome, altura, peso, que idioma ela fala, como dizer olá a ela, e mais.</p> + +<p>Tente inserir a seguinte linha em seu console:</p> + +<pre class="brush: js notranslate">var cachorro = { nome : 'Totó', raca : 'Dálmata' };</pre> + +<p>Para obeter a informação armazenada no objeto, você pode usar a seguinte sintaxe:</p> + +<pre class="brush: js notranslate">cachorro.nome</pre> + +<p>Nós não iremos ver mais sobre objetos por agora — você pode aprender mais sobre eles em um artigo futuro.</p> + +<h2 id="Digitação_permissiva">Digitação permissiva</h2> + +<p>JavaScript é uma "dynamically typed language", o que significa que, diferente de outras linguagens, você não precisa especificar que tipo de dados uma variável irá conter (ex.: números, cadeias de texto, arrays, etc).</p> + +<p>Por exemplo, se você declarar uma variável e dar a ela um valor encapsulado em aspas, o navegador irá tratar a variável como sendo uma <em>string</em> (cadeia de texto):</p> + +<pre class="brush: js notranslate">var minhaString = 'Olá';</pre> + +<p>Irá continuar sendo uma <em>string</em>, mesmo que dentro das apas contenha um número, então seja cuidadoso:</p> + +<pre class="brush: js notranslate">var meuNumero = '500'; // opa, isso continua sendo uma string +typeof(meuNumero); +meuNumero = 500; // bem melhor — agora isso é um número +typeof(meuNumero);</pre> + +<p>Tente inserir as quatro linhas acima em seu console uma por uma, e veja quais são os resultados. Você notará que estamos usando uma função especial chamada <code>typeof()</code> — ela irá retornar o tipo de dado da variável que você passar. Da primeira vez que for executada, deve retornar <code>string</code>, como naquele ponto a variável <code>meuNumero</code> contém uma <em>string</em>, <code>'500'</code>. Dê uma olhada e veja o que é retornado da segunda vez que você a utilizar.</p> + +<h2 id="Constants_em_JavaScript">Constants em JavaScript</h2> + +<p>Muitas linguagens de programação têm o conceito de <em>constant</em> — um valor que uma vez declarado não pode ser alterado. Há muitas razões pelas quais você deseja fazer isso, desde segurança (se um script de terceiros alterou esses valores, poderia causar problemas) até a depuração e a compreensão do código (é mais difícil alterar acidentalmente valores que não devem ser alterados e bagunçar as coisas).</p> + +<p>Nos primeiros dias do JavaScript, não existiam <em>constants</em>. No JavaScript moderno, temos a palavra-chave <code>const</code>, que nos permite armazenar valores que nunca podem ser alterados:</p> + +<pre class="brush: js notranslate">const diasNaSemana = 7<span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-number">; +const horasNoDia = 24;</span></span></span></span></pre> + +<p><span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-number"><code>const</code> funciona exatamente da mesma maneira que <code>let</code>, exceto que você não pode atribuir um novo valor a <code>const</code>. No exemplo a seguir, a segunda linha geraria um erro:</span></span></span></span></p> + +<pre class="brush: js notranslate">const diasNaSemana = 7<span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-number">; +</span></span></span></span>diasNaSemana<span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-number"> = 8;</span></span></span></span></pre> + +<h2 id="Teste_suas_habilidades!">Teste suas habilidades!</h2> + +<p>Você chegou ao final deste artigo, mas consegue se lembrar das informações mais importantes? Você pode encontrar alguns testes adicionais para verificar se você reteve essas informações antes de prosseguir — veja <a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Teste_suas_habilidades:_variaveis">Teste suas habilidades: variáveis</a>.</p> + +<h2 id="Sumário">Sumário</h2> + +<p>Por agora você deve saber razoavelmente sobre variáveis JavaScript e como criá-las. No próximo artigo Vamos focar nos números em mais detalhes, vendo como fazer matemática básica no JavaScript.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Maths", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="https://wiki.developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/O_que_e_JavaScript">O que é JavaScript?</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/A_first_splash">Um primeiro mergulho no JavaScript</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/What_went_wrong">O que deu errado? Resolvendo problemas no JavaScript</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Vari%C3%A1veis">Armazenando as informações que você precisa — Variáveis</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Matematica">Matemática básica no JavaScript — números e operadores</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Strings">Trabalhando com textos — strings em JavaScript</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos úteis de string</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Gerador_de_historias_bobas">Avaliação: Gerador de histórias bobas</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/first_steps/what_went_wrong/index.html b/files/pt-br/learn/javascript/first_steps/what_went_wrong/index.html new file mode 100644 index 0000000000..ee121e8773 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/what_went_wrong/index.html @@ -0,0 +1,245 @@ +--- +title: O que deu errado? Resolvendo problemas no JavaScript +slug: Learn/JavaScript/First_steps/What_went_wrong +translation_of: Learn/JavaScript/First_steps/What_went_wrong +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Quando você construiu o jogo "Adivinhe o número" no artigo anterior, você talvez tenha descoberto que ele não funcionou. Não tema — este artigo tem como objetivo impedir que você arranque os cabelos por causa desses problemas, fornecendo-lhe algumas dicas simples de como encontrar e corrigir erros nos programas JavaScript.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requesitos:</th> + <td> + <p>Conhecimentos básicos de informática, uma compreensão básica de HTML e CSS, uma compreensão do que é JavaScript.</p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ganhar habilidade e confiança para começar a resolver problemas simples em seu próprio código.</td> + </tr> + </tbody> +</table> + +<h2 id="Tipos_de_erros">Tipos de erros</h2> + +<p>De um modo geral, quando você faz algo errado no código, existem dois tipos principais de erros que você encontrará:</p> + +<ul> + <li><strong>Erros de sintaxe:</strong> são erros de ortografia em seu código que realmente fazem com que o programa não seja executado, ou pare de trabalhar parcialmente - você geralmente receberá algumas mensagens de erro também. Estes geralmente são adequados para consertar, desde que você esteja familiarizado com as ferramentas certas e saiba o que as mensagens de erro significam!</li> + <li><strong>Erros lógicos: </strong>são erros onde a sintaxe está realmente correta, mas o código não é o que você pretendia, o que significa que o programa é executado com sucesso, mas dá resultados incorretos. Muitas vezes, eles são mais difíceis de consertar do que erros de sintaxe, pois geralmente não há uma mensagem de erro resultante para direcioná-lo para a origem do erro.</li> +</ul> + +<p>Ok, então não é assim tão simples - há alguns outros diferenciadores à medida que você aprofunda. Mas as classificações acima serão bem úteis nesta fase inicial da sua carreira. Examinaremos esses dois tipos a seguir.</p> + +<h2 id="Um_exemplo_errôneo">Um exemplo errôneo</h2> + +<p>Para começar, voltemos ao nosso jogo de adivinhação - porém desta vez estaremos explorando uma versão que tem alguns erros inseridos propositalmente. Vá até o Github e faça uma cópia local de <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/troubleshooting/jogo-numero-erros.html">jogo-numero-erros.html</a> (<a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/troubleshooting/jogo-numero-erros.html">veja-o em execução aqui</a>).</p> + +<ol> + <li>Para começar, abra a cópia local dentro do seu editor de texto favorito, e em seu navegador.</li> + <li>Tente jogar o jogo - você notará que, quando você pressiona o botão "Enviar palpite", ele não funciona!</li> +</ol> + +<div class="note"> +<p><strong>Nota: </strong>Talvez você tenha sua própria versão de exemplo do jogo que não funciona, e pode querer consertá-la! Nós ainda gostaríamos que você trabalhasse no artigo com a nossa versão, para que possa aprender as técnicas que estamos ensinando aqui. Daí então você pode voltar e tentar consertar seu exemplo.</p> +</div> + +<p>Neste ponto, vamos consultar o console do desenvolvedor para ver se identificamos qualquer erro de sintaxe, e então tentar consertá-lo. Você irá aprender como, logo abaixo.</p> + +<h2 id="Consertando_erros_de_sintaxe">Consertando erros de sintaxe</h2> + +<p>Anteriormente no curso, nós fizemos você digitar alguns comandos simples de JavaScript no <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console JavaScript</a> (se você não se lembra como, abra o link anterior). O que é ainda mais útil é o fato do console lhe mostrar mensagens de erro sempre que existir algo errado na sintaxe dentro do JavaScript enviado ao motor de JavaScript do navegador. Agora vamos à caça.</p> + +<ol> + <li>Vá até a aba onde você tem aberto o arquivo <code>jogo-numero-erros.html</code> e abra o console JavaScript. Você deverá ver uma mensagem de erro sendo exibida:<br> + <img alt="" src="https://mdn.mozillademos.org/files/15590/nao-e-uma-funcao.png"></li> + <li>Esse é um erro bem fácil de identifcar, e o navegador lhe fornece várias informações úteis para lhe ajudar (a captura de tela acima foi feita no Firefox, mas os outros navegadores oferecem informações similares). Da esquerda para a direita, nós temos: + <ul> + <li>Um "x" laranja para indicar que esse é um erro.</li> + <li>Uma mensagem de erro para indicar o que está errado: "TypeError: envioPalpite.addeventListener is not a function"</li> + <li>Um link "Learn More" que encaminha à uma página no MDN docs explicando o que esse erro significa em uma quantidade enorme de detalhes.</li> + <li>O nome do arquivo JavaScript, que direciona à aba Debugger das ferramentas de desenvolvimento. Se você clicar nesse link, verá a linha exata onde o erro está destatacada.</li> + <li>O número da linha onde o erro se encontra, e o número do caractere na linha onde o erro é encontrado primeiro. Neste caso nós temos, linha 86, caractere número 3.</li> + </ul> + </li> + <li>Se olharmos para a linha 86 em nosso nosso código de código, vamos encontrar a seguinte linha: + <pre class="brush: js">envioPalpite.addeventListener('click', conferir Palpite);</pre> + </li> + <li>O erro diz o seguinte "envioPalpite.addeventListener is not a function", que significa envioPalpite.addeventListener não é uma funçao. Então provavelmente digitamos algo errado. Se você não estiver certo da digitação correta de parte da sintaxe, é uma boa ideia procurar a funcionalidade no MDN docs. A melhor forma de fazer isso atualmente é pesquisar por "mdn <em>nome-da-funcionalidade</em>" em seu mecanismo de buscas favorito. Aqui está um atalho para te salvar algum tempo nesse caso: <code><a href="/pt-BR/docs/Web/API/Element/addEventListener">addEventListener()</a></code>.</li> + <li>Então, olhando nessa essa página, o erro parece ser termos digitado o nome da função errado! Lembre-se de que o JavaScript diferencia letras maiúsculas de minúsculas, então qualquer diferença na digitação ou no uso de letras maiúsculas irá causar um erro. Alterar <code>addeventListener</code> para <code>addEventListener</code> deverá corrigir esse erro. Faça essa alteração no código do seu arquivo.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Veja nossa página de referência <a href="/pt-BR/docs/Web/JavaScript/Reference/Errors/Not_a_function">TypeError: "x" is not a function</a> para mais detalhes sobre esse erro.</p> +</div> + +<h3 id="Erros_de_sintaxe_-_segundo_round">Erros de sintaxe - segundo round</h3> + +<ol> + <li>Salve o arquivo e atualize a aba do navegador, e você poderá ver que o erro foi corrigido.</li> + <li>Agora se você tentar enviar um palpite e pressionar o botão !Enviar palpite" você verá... outro erro!<br> + <img alt="" src="https://mdn.mozillademos.org/files/15591/variavel-e-nula.png"></li> + <li>Dessa vez o erro informado é "TypeError: baixoOuAlto is null", na linha 78. + <div class="note"><strong>Nota</strong>: <code><a href="/en-US/docs/Glossary/Null">Null</a></code> é um valor especial que significa "nada", ou "sem valor". Então <code>baixoOuAlto</code> foi declarado e inicializado, mas não com algum valor significativo — não possui nenhum caractere ou valor.</div> + + <div class="note"><strong>Nota</strong>: Esse erro não apareceu assim que a página foi carregada porque esse erro ocorreu dentro de uma função (dentro do bloco <code>conferirPalpite() { ... }</code> ). Como você irá aprender com mais detalhes no nosso artigo de funções mais tarde, o código localizado dentro de funções roda em um escopo separado do código presente fora das funções. Nesse caso, o código não estava rodando e o erro não estava aparecendo até a função <code>conferirPalpite()</code> ser executada na linha 86.</div> + </li> + <li>Dê uma olhada na linha 78, e você verá o seguinte código: + <pre class="brush: js">baixoOuAlto.textContent = 'Seu palpite foi muito alto!';</pre> + </li> + <li>Essa linha está tentando definir a propriedade <code>textContent</code> (conteúdo de texto) da variável <code>baixoOuAlto</code> como uma sequência de texto, mas isso não está funcionando porque <code>baixoOuAlto</code> não contém o que deveria conter. Vamos ver o porquê — tente localizar outras instâncias de <code>baixoOuAlto</code> no código. A instância que aparece primeiro no código JavaScript é na linha 48: + <pre class="brush: js">var baixoOuAlto = document.querySelector('baixoOuAlto');</pre> + </li> + <li>Nesse ponto estamos tentando fazer com que a variável contenha uma referência a um elemento no documento HTML. Vamos conferir se o valor é <code>null</code> (nulo) depois que essa linha é executada. Adicione o seguinte código na linha 49: + <pre class="brush: js">console.log(baixoOuAlto);</pre> + + <div class="note"> + <p><strong>Nota</strong>: <code><a href="/en-US/docs/Web/API/Console/log">console.log()</a></code> é uma função de debugging (correção de erros) realmente útil que exibe um valor na tela do console. Então ela irá imprimir o valor da variável <code>baixoOuAlto</code> na tela do console assim que tentarmos defini-la na linha 48.</p> + </div> + </li> + <li>Salve o arquivo e o atualize no navegador, e você deverá ver agora o resultado do <code>console.log()</code> na tela do seu console.<br> + <img alt="" src="https://mdn.mozillademos.org/files/15592/console-log-saida.png"><br> + Pois bem, nesse ponto o valor de <code>baixoOuAlto</code> e <code>null</code>, então definitivamente há um problema com a linha 48.</li> + <li>Vamos pensar em qual poderia ser o problema. A linha 48 está usando um método <code><a href="/en-US/docs/Web/API/Document/querySelector">document.querySelector()</a></code> para pegar a referência do elemento selecionado com um seletor CSS selector (<em>CSS selector</em>). Olhando mais acima no nosso código, podemos encontrar o parágrafo em questão: + <pre class="brush: js"><p class="baixoOuAlto"></p></pre> + </li> + <li>Então nós precisamos de um seletor de classe aqui, que começa com um ponto (.), mas o seletor passado pelo método <code>querySelector()</code> na linha 48 não tem o ponto. Esse pode ser o problema! Tente mudar <code>baixoOuAlto</code> para <code>.baixoOuAlto</code> na linha 48.</li> + <li>Tente salvar o arquivo e atualizá-lo no navegador de novo, e a sua declaração <code>console.log()</code> deverá retornar o elemento <code><p></code> que queremos. Ufa! Outro erro resolvido! Você pode deletar a linha do seu <code>console.log()</code> agora, ou mantê-la para referência posterior — a escolha é sua.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Veja nossa página de referência <a href="/pt-BR/docs/Web/JavaScript/Reference/Errors/Unexpected_type">TypeError: "x" is (not) "y"</a> para mais detalhes sobre esse erro.</p> +</div> + +<h3 id="Erros_de_sintaxe_-_terceiro_round">Erros de sintaxe - terceiro round</h3> + +<ol> + <li>Agora se você tentar jogar novamente, você deve ter mais sucesso — o jogo deve continuar normalmente, até você terminar, ou adivinhando o número, ou ficando sem mais chances.</li> + <li>Nesse ponto, o jogo falha mais uma vez, e o mesmo erro do início é exibido — "TypeError: botaoReinicio.addeventListener is not a function"! No entanto, dessa vez é listado vindo da linha 94.</li> + <li>Olhando a linha 94, é fácil de ver que nós cometemos o mesmo erro novamente. Só precisamos alterar mais uma vez <code>addeventListener</code> para <code>addEventListener</code>. Faça isso.</li> +</ol> + +<h2 id="Um_erro_de_lógica">Um erro de lógica</h2> + +<p>Nesse ponto, o jogo deve rodar normalmente, porém depois de jogá-lo algumas vezes você irá notar que o número "aleatório" que você tem que adivinhar é sempre igual a 1. Definitivamente não é como queremos que o jogo funcione!</p> + +<p>Há sem dúvida um problema na lógica do jogo em algum lugar — o jogo não está retornando nenhum erro;simplesmente não está funcionando corretamente.</p> + +<ol> + <li>Procure pela variável <code>numeroAleatorio</code>, e as linhas onde o número aleatório é definido primeiro. A instância que armazena o número aleatório que queremos adivinhar no começo do jogo deve estar na linha 44 ou próximo a ela: + + <pre class="brush: js">var numeroAleatorio = Math.floor(Math.random()) + 1;</pre> + </li> + <li>E a linha que gera o número aleatório antes de cada jogo subsequente está na linha 113, ou próximo a ela: + <pre class="brush: js">numeroAleatorio = Math.floor(Math.random()) + 1;</pre> + </li> + <li>Para checar se essas linhas são mesmo o problema, vamos recorrer ao nosso amigo <code>console.log()</code> de novo — insira a seguinte linha diretamente abaixo de cada uma das duas linhas: + <pre class="brush: js">console.log(numeroAleatorio);</pre> + </li> + <li>Salve o arquivo e atualize o navegador, então jogue algumas vezes — você verá que o <code>numeroAleatorio</code> é igual a 1 cada vez em que é exibido no console.</li> +</ol> + +<h3 id="Trabalhando_através_da_lógica">Trabalhando através da lógica</h3> + +<p>Para consertar isso, vamos considerar como essa linha está trabalhando. Primeiro, nós invocamos <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random">Math.random()</a></code>, que gera um número decimal aleatório entre 0 e 1, ex. 0.5675493843.</p> + +<pre class="brush: js">Math.random()</pre> + +<p>Em seguida, passamos o resultado invocando <code>Math.random()</code> através de <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor">Math.floor()</a></code>, que arredonda o número passado para o menor número inteiro mais próximo. E então adicionamos 1 ao resultado:</p> + +<pre>Math.floor(Math.random()) + 1</pre> + +<p>Arredondando um número decimal aleatório entre 0 e 1 para baixo irá sempre retornar 0, então adicionando 1 a ele sempre retornará 1. Precisamos multiplicar o número aleatório por 100 antes de o arredondarmos para baixo. O código seguinte nos daria um número aleatório entre 0 and 99:</p> + +<pre class="brush: js">Math.floor(Math.random()*100);</pre> + +<p>Por isso, queremos adicionar 1, para nos dar um número aleatório entre 1 e 100:</p> + +<pre class="brush: js">Math.floor(Math.random()*100) + 1;</pre> + +<p>Tente atualizar as duas linhas dessa forma, então salve e atualize o navegador — o jogo deve agora funcionar como nós queremos que funcione!</p> + +<h2 id="Outros_erros_comuns">Outros erros comuns</h2> + +<p>Existem outros erros comuns com os quais você irá esbarrar em seu código. Essa seção destaca a maioria deles.</p> + +<h3 id="SyntaxError_missing_before_statement"><em>SyntaxError: missing ; before statement</em></h3> + +<p>Erro de sintaxe: faltando ";" antes da declaração. Esse erro geralmente significa que você deixou de inserir um ponto e vírgula ao final de uma de suas linhas de código, mas algumas vezes pode ser mais crítico. Por exemplo, se mudarmos essa linha (número 58) dentro da função <code>conferirPalpite()</code>:</p> + +<pre class="brush: js">var palpiteUsuario = Number(campoPalpite.value);</pre> + +<p>para</p> + +<pre class="brush: js">var palpiteUsuario === Number(campoPalpite.value);</pre> + +<p>Exibe esse erro porque pensa que você está fazendo algo diferente. Você deve se certificar de não misturar o operador de atribuição (<code>=</code>) — que configura uma variável para ser igual a determinado valor — com o operador de igualdade restrita (<code>===</code>), que testa se um valor é exatamente igual a outro, e retorna um resultado <code>true</code>/<code>false</code> (verdadeiro ou falso).</p> + +<div class="note"> +<p><strong>Nota</strong>: Veja nossa página de referência <a href="/pt-BR/docs/Web/JavaScript/Reference/Errors/Missing_semicolon_before_statement">SyntaxError: missing ; before statement</a> para mais detalhes sobre esse erro.</p> +</div> + +<h3 id="O_programa_sempre_diz_que_você_ganhou_independentemente_do_palpite_que_insira">O programa sempre diz que você ganhou, independentemente do palpite que insira</h3> + +<p>Isso pode ser outro sintoma de confusão entre o operador de atribuição e o operador de igualdade restrita. Por exemplo, se nós quiséssemos essa linha dentro de <code>conferirPalpite()</code>:</p> + +<pre class="brush: js">if (palpiteUsuario === numeroAleatorio) {</pre> + +<p>para</p> + +<pre class="brush: js">if (palpiteUsuario = numeroAleatorio) {</pre> + +<p>o teste retornaria sempre <code>true</code> (verdadeiro), causando o programa a reportar que o jogo foi vencido. Tome cuidado!</p> + +<h3 id="SyntaxError_missing_after_argument_list"><em>SyntaxError: missing ) after argument list</em></h3> + +<p>Erro de sintaxe: faltando ")" depois de listar uma declaração. Esse é bem simples — geralmente significa que deixamos de fechar o parênteses no final ao invocar uma função/método.</p> + +<div class="note"> +<p><strong>Nota</strong>: Veja nossa página de referência <a href="/en-US/docs/Web/JavaScript/Reference/Errors/Missing_parenthesis_after_argument_list">SyntaxError: missing ) after argument list</a> para mais detalhes sobre o erro.</p> +</div> + +<h3 id="SyntaxError_missing_after_property_id"><em>SyntaxError: missing : after property id</em></h3> + +<p>Erro de sintaxe: faltando ":" depois da propriedade id. Esse erro geralmente se relaciona à formação incorreta de um objeto de JavaScript, mas nesse caso o obtivemos alterando:</p> + +<pre class="brush: js">function conferirPalpite() {</pre> + +<p>para</p> + +<pre class="brush: js">function conferirPalpite( {</pre> + +<p>Isso levou o navegador a pensar que estávamos tentando passar todo o conteúdo da função como se fosse um argumento dessa função. Seja cuidadoso com esses parênteses!</p> + +<h3 id="SyntaxError_missing_after_function_body"><em>SyntaxError: missing } after function body</em></h3> + +<p>Erro de sintaxe: faltando "}" depois do corpo da função. Isso é fácil — geralmente significa que você deixou de colocar uma das chaves de uma função ou de uma estrutura condicional. Nós obtemos esse erro deletando uma das chaves de fechamento próximas ao final da função <code>conferirPalpite()</code>.</p> + +<h3 id="SyntaxError_expected_expression_got_string_ou_SyntaxError_unterminated_string_literal"><em>SyntaxError: expected expression, got 'string' </em>ou <em>SyntaxError: unterminated string literal</em></h3> + +<p>Erro de sintaxe: esperado uma expressão, obtido uma 'string' e Erro de sintaxe: string literal não terminada. Esses erros geralmente significam que você deixou de colocar aspas no início ou no final da declaração de uma cadeia de texto. No primeiro erro acima, '<em>string'</em> seria substituído pelo(s) caractere(s) encontrado(s) pelo navegador ao invés da aspa no início de uma cadeia de texto. O segundo erro quer dizer que a cadeia de texto não foi finalizada com o caractere de aspa.</p> + +<p>Para todos esses erros, pense em como nós abordamos os exemplos em que olhamos no passo a passo. Quando um erro surge, olha o número da linha que é informado, vá até essa linha e veja se consegue localizar o que há de errado. Mantenha em mente que o erro não estará necessariamente nessa linha, e também que o erro pode não ter sido causado exatamente pelo mesmo problema que citamos acima!</p> + +<div class="note"> +<p><strong>Nota</strong>: Veja nossas páginas de referência <a href="/pt-BR/docs/Web/JavaScript/Reference/Errors/Unexpected_token">SyntaxError: Unexpected token</a> e <a href="/pt-BR/docs/Web/JavaScript/Reference/Errors/Unterminated_string_literal">SyntaxError: unterminated string literal</a> para mais detalhes sobre esses erros.</p> +</div> + +<h2 id="Sumário">Sumário</h2> + +<p>Então aqui temos, o básico de como resolver erros em programas simples de JavaScript. Não será sempre tão fácil de solucionar o que está errado em seu código, mas pelo menos isso irá te poupar algumas horas de sono e lhe permitir progredir um pouco mais rápido quando as coisas não saírem certas no início da sua jornada de aprendizado.</p> + +<h2 id="Veja_também">Veja também</h2> + +<div> +<ul> + <li>Há muitos outros tipos de erros que não listamos aqui; estamos compilando uma referência que explica o que eles significam em detalhes — veja a <a href="/pt-BR/docs/Web/JavaScript/Reference/Errors">referência de erros do JavaScript</a>.</li> + <li>Se você se deparar com qualquer erro em seu código que não tenha certeza de como resolver mesmo depois de ler este artigo, você pode pedir ajuda! Pergunte na <a class="external external-icon" href="https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294">Área de Discussão e Aprendizagem</a>, ou no canal IRC <a href="irc://irc.mozilla.org/mdn">#mdn</a> em <a class="external external-icon" href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Nos diga quel é o seu erro, e nós iremos tentar te ajudar. Uma amostra do seu código também seria útil.</li> +</ul> +</div> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}</p> diff --git a/files/pt-br/learn/server-side/django/admin_site/index.html b/files/pt-br/learn/server-side/django/admin_site/index.html new file mode 100644 index 0000000000..28b83e9d78 --- /dev/null +++ b/files/pt-br/learn/server-side/django/admin_site/index.html @@ -0,0 +1,364 @@ +--- +title: 'Tutorial Django Parte 4: Django admin site' +slug: Learn/Server-side/Django/Admin_site +tags: + - Aprender + - Artigo + - Iniciante + - Python + - Tutorial + - django + - django_admin + - lado servidor (server-side) +translation_of: Learn/Server-side/Django/Admin_site +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Models", "Learn/Server-side/Django/Home_page", "Learn/Server-side/Django")}}</div> + +<p class="summary">Agora que criamos modelos para o site da <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Tutorial_website_biblioteca_local">LocalLibrary</a>, usaremos o site do Django Admin para adicionar alguns dados de livros "reais". Primeiro, mostraremos como registrar os modelos no site de administração, depois mostraremos como fazer login e criar alguns dados. No final do artigo, mostraremos algumas maneiras de melhorar ainda mais a apresentação do site Admin.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Primeiro complete: <a href="/en-US/docs/Learn/Server-side/Django/Models">Tutorial Django Parte 3: Usando modelos</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Para entender os benefícios e limitações do site de administração do Django, use-o para criar alguns registros para nossos modelos.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_Geral">Visão Geral</h2> + +<p>O aplicativo de administração do Django pode usar seus modelos para criar automaticamente uma área de site que você possa usar para criar, visualizar, atualizar e excluir registros. Isso pode poupar muito tempo durante o desenvolvimento, tornando muito fácil testar seus modelos e ter uma ideia de se você tem os dados corretos. O aplicativo administrativo também pode ser útil para gerenciar dados em produção, dependendo do tipo de site. O projeto Django o recomenda apenas para gerenciamento interno de dados (ou seja, apenas para uso por administradores ou pessoas internas à sua organização), pois a abordagem centrada no modelo não é necessariamente a melhor interface possível para todos os usuários e expõe muitos detalhes desnecessários sobre os modelos.</p> + +<p>Toda a configuração necessária para incluir o aplicativo admin em seu site foi feita automaticamente quando você criou o <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/skeleton_website">esqueleto do projeto</a> (para obter informações sobre as dependências reais necessárias, consulte a <a href="https://docs.djangoproject.com/pt-br/2.1/ref/contrib/admin/">documentação do Django aqui</a>). Como resultado, tudo o que você precisa fazer para adicionar seus modelos ao aplicativo administrativo é registrá-los. No final deste artigo, forneceremos uma breve demonstração de como você pode configurar ainda mais a área de administração para exibir melhor nossos dados de modelo.</p> + +<p>Depois de registrar os modelos, mostraremos como criar um novo "superusuário", acessar o site e criar alguns livros, autores, instâncias de livros e gêneros. Isso será útil para testar as visualizações e os modelos que começaremos a criar no próximo tutorial.</p> + +<h2 id="Registrando_modelos">Registrando modelos</h2> + +<p>Primeiro, abra o admin.py no aplicativo de catálogo (/locallibrary/catalog/admin.py). Atualmente parece com isso - note que ele já importa <code>django.contrib.admin</code>:</p> + +<pre class="brush: python notranslate">from django.contrib import admin + +# Register your models here. +</pre> + +<p>Registre os modelos copiando o seguinte texto na parte inferior do arquivo. Este código simplesmente importa os modelos e, em seguida, chama <code>admin.site.register</code> para registrar cada um deles.</p> + +<pre class="brush: python notranslate">from catalog.models import Author, Genre, Book, BookInstance + +admin.site.register(Book) +admin.site.register(Author) +admin.site.register(Genre) +admin.site.register(BookInstance) +</pre> + +<div class="note">Nota: Se você aceitou o desafio de criar um modelo para representar a linguagem natural de um livro (<a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Models">consulte o artigo do tutorial de modelos</a>), importe-o e registre-o também!</div> + +<p>Essa é a maneira mais simples de registrar um modelo ou modelos no site. O site de administração é altamente personalizável e falaremos mais sobre as outras maneiras de registrar seus modelos mais abaixo.</p> + +<h2 id="Criando_um_super_usuário">Criando um super usuário</h2> + +<p>Para fazer login no site de administração, precisamos de uma conta de usuário com o status da equipe ativado. Para visualizar e criar registros, também precisamos que esse usuário tenha permissões para gerenciar todos os nossos objetos. Você pode criar uma conta "superusuário" que tenha acesso total ao site e todas as permissões necessárias usando <strong>manage.py</strong>.</p> + +<p>Chame o seguinte comando, no mesmo diretório que manage.py, para criar o superusuário. Você será solicitado a digitar um nome de usuário, endereço de e-mail e senha forte.</p> + +<pre class="brush: bash notranslate">python3 manage.py createsuperuser +</pre> + +<p>Quando esse comando for concluído, um novo superusuário será adicionado ao banco de dados. Agora reinicie o servidor de desenvolvimento para que possamos testar o login:</p> + +<pre class="brush: bash notranslate">python3 manage.py runserver + +</pre> + +<h2 id="Fazendo_o_login_e_usando_o_site">Fazendo o login e usando o site</h2> + +<p>Para fazer login no site, abra o URL /<em>admin</em> (e.g. <a href="http://127.0.0.1:8000/admin/">http://127.0.0.1:8000/admin</a>) e insira suas novas credenciais de usuário e senha de superusuário (você será redirecionado para a página de login e, em seguida, de volta para o URL /<em>admin </em>depois de inserir seus detalhes).</p> + +<p>Esta parte do site exibe todos os nossos modelos, agrupados por aplicativo instalado. Você pode clicar no nome de um modelo para ir a uma tela que lista todos os seus registros associados e clicar nos registros para editá-los. Você também pode clicar diretamente no link Adicionar ao lado de cada modelo para começar a criar um registro desse tipo.</p> + +<p><img alt="Admin Site - Home page" src="https://mdn.mozillademos.org/files/13975/admin_home.png" style="display: block; height: 634px; margin: 0px auto; width: 998px;"></p> + +<p>Clique no link Adicionar à direita de Books para criar um novo livro (isso exibirá um diálogo muito parecido com o abaixo). Observe como os títulos de cada campo, o tipo de widget usado e o <code>help_text</code> (se houver) correspondem aos valores especificados no modelo.</p> + +<p>Digite valores para os campos. Você pode criar novos autores ou gêneros pressionando o botão + ao lado dos respectivos campos (ou selecione os valores existentes nas listas, se você já os criou). Quando estiver pronto, você pode pressionar<strong> SALVAR, Salvar</strong> <strong>e adicionar </strong>outro ou S<strong>alvar e continuar editando</strong> para salvar o registro.</p> + +<p><img alt="Admin Site - Book Add" src="https://mdn.mozillademos.org/files/13979/admin_book_add.png" style="border-style: solid; border-width: 1px; display: block; height: 780px; margin: 0px auto; width: 841px;"></p> + +<div class="note"> +<p>Observação: neste ponto, gostaríamos que você passasse algum tempo adicionando alguns livros, autores e gêneros (por exemplo, Fantasia) à sua inscrição. Certifique-se de que cada autor e gênero inclua alguns livros diferentes (isso tornará suas visualizações de lista e detalhes mais interessantes quando forem implementadas posteriormente na série de artigos).</p> +</div> + +<p>Quando terminar de adicionar livros, clique no link <strong>Home</strong> no marcador superior para ser levado de volta à página principal do administrador. Então clique no link <strong>Books </strong> para exibir a lista atual de livros (ou em um dos outros links para ver outras listas de modelos). Agora que você adicionou alguns livros, a lista pode ser semelhante à captura de tela abaixo. O título de cada livro é exibido; este é o valor retornado no modelo do livro pelo método <code>__str__()</code> que especificamos no último artigo.</p> + +<p><img alt="Admin Site - List of book objects" src="https://mdn.mozillademos.org/files/13935/admin_book_list.png" style="border-style: solid; border-width: 1px; display: block; height: 407px; margin: 0px auto; width: 1000px;"></p> + +<p>Nessa lista, você pode excluir livros marcando a caixa de seleção ao lado do livro que não deseja, selecionando a ação excluir ... na lista suspensa Ação e pressionando o botão Ir. Você também pode adicionar novos livros pressionando o botão <strong>ADD BOOK</strong>. </p> + +<p>Você pode editar um livro selecionando seu nome no link. A página de edição de um livro, mostrada abaixo, é quase idêntica à página "Adicionar". As principais diferenças são o título da página (Change book) e a adição de botões <strong>Delete</strong>, <strong>HISTORY</strong> e <strong>VIEW ON SITE</strong> (este último botão aparece porque definimos o método <code>get_absolute_url()</code> em nosso modelo).</p> + +<p><img alt="Admin Site - Book Edit" src="https://mdn.mozillademos.org/files/13977/admin_book_modify.png" style="border-style: solid; border-width: 1px; display: block; height: 780px; margin: 0px auto; width: 841px;"></p> + +<p>Agora navegue de volta para o <strong>Home</strong> page (usando o link Home, a trilha de navegação) e, em seguida, <strong>Author</strong> e listas de <strong>Genre</strong> — você já deve ter criado a partir de quando adicionou os novos livros, mas fique à vontade para adicionar um pouco mais.</p> + +<p>O que você não terá é qualquer instância do livro, porque elas não são criadas a partir de livros (embora você possa criar <code>Book</code> a partir de <code>BookInstance</code> — esta é a natureza da <code>ForeignKey</code> field). Navegue de volta para a<em> Página inicial</em> e pressione o botão <em>Adicionar</em> associado para exibir a tela <em>Adicionar instância</em> do livro abaixo. Observe o ID grande e globalmente exclusivo, que pode ser usado para identificar separadamente uma única cópia de um livro na biblioteca.</p> + +<p><img alt="Admin Site - BookInstance Add" src="https://mdn.mozillademos.org/files/13981/admin_bookinstance_add.png" style="border-style: solid; border-width: 1px; display: block; height: 514px; margin: 0px auto; width: 863px;"></p> + +<p>Crie vários desses registros para cada um de seus livros. Defina o status como <em>Disponível</em> para pelo menos alguns registros e <em>Em empréstimo</em> para outros. Se o status <strong>não </strong>for <em>Disponível</em>, defina também uma <em>data de vencimento</em> futura.</p> + +<p>É isso aí! Agora você aprendeu como configurar e usar o site de administração. Você também criou registros para <code>Book</code>, <code>BookInstance</code>, <code>Genre</code>, e <code>Author</code> que poderemos usar assim que criarmos nossas próprias visualizações e modelos.</p> + +<h2 id="Configuração_Avançada">Configuração Avançada</h2> + +<p>O Django faz um bom trabalho ao criar um site de administração básico usando as informações dos modelos registrados:</p> + +<ul> + <li>Cada modelo possui uma lista de registros individuais, identificados pela string criada com o método <code>__str__()</code> do modelo, e vinculado a visualizações de views/forms para edição. Por padrão, essa exibição tem um menu de ação na parte superior que você pode usar para executar operações de exclusão em massa nos registros.</li> + <li>Os formulários de registro de detalhes do modelo para edição e adição de registros contêm todos os campos do modelo, dispostos verticalmente em sua ordem de declaração. </li> +</ul> + +<p>Você pode personalizar ainda mais a interface para torná-la ainda mais fácil de usar. Algumas das coisas que você pode fazer são:</p> + +<ul> + <li>List views: + <ul> + <li>Adicionar adicional fields/information exibido para cada registro.</li> + <li>Adicione filtros para selecionar quais registros são listados, com base na data ou em algum outro valor de seleção (e.g. Book loan status).</li> + <li>Adicione opções adicionais ao menu de ações nas exibições de lista e escolha onde esse menu é exibido no formulário.</li> + </ul> + </li> + <li>Detail views + <ul> + <li>Escolha quais campos exibir (ou excluir), junto com sua ordem, agrupamento, se eles são editáveis, o widget usado, a orientação etc.</li> + <li>Adicione campos relacionados a um registro para permitir a edição imediata (por exemplo, adicione a capacidade de adicionar e editar registros de livros enquanto cria o registro de autor).</li> + </ul> + </li> +</ul> + +<p>In this section we're going to look at a few changes that will improve the interface for our <em>LocalLibrary</em>, including adding more information to <code>Book</code> and <code>Author</code> model lists, and improving the layout of their edit views. We won't change the <code>Language</code> and <code>Genre</code> model presentation because they only have one field each, so there is no real benefit in doing so!</p> + +<p>You can find a complete reference of all the admin site customisation choices in <a href="https://docs.djangoproject.com/en/2.0/ref/contrib/admin/">The Django Admin site</a> (Django Docs).</p> + +<h3 id="Registrando_uma_classe_ModelAdmin">Registrando uma classe ModelAdmin</h3> + +<p>Para alterar como um modelo é exibido na interface de administração, você define uma classe ModelAdmin (que descreve o layout) e registra-o no modelo.</p> + +<p>Vamos começar com o <code>Author</code> model. Abra <strong>admin.py</strong> no aplicativo de catálogo (/locallibrary/catalog/admin.py). Comente o seu registro original (prefixo com um #) para o <code>Author</code> model:</p> + +<pre class="brush: js notranslate"># admin.site.register(Author)</pre> + +<p>Agora adicione um novo <code>AuthorAdmin</code> e registre como mostrado abaixo.</p> + +<pre class="brush: python notranslate"># Define the admin class +class AuthorAdmin(admin.ModelAdmin): + pass + +# Register the admin class with the associated model +admin.site.register(Author, AuthorAdmin) +</pre> + +<p>Agora vamos adicionar as classes <code>ModelAdmin</code> para <code>Book</code>, e <code>BookInstance</code>. Precisamos novamente comentar os registros originais:</p> + +<pre class="brush: js notranslate"># admin.site.register(Book) +# admin.site.register(BookInstance)</pre> + +<p>Agora, para criar e registrar os novos modelos; para o propósito desta demonstração, vamos usar o <code>@register</code> decorador para registrar os modelos (isso faz exatamente a mesma coisa que <code>admin.site.register()</code> sintaxe):</p> + +<pre class="brush: python notranslate"># Register the Admin classes for Book using the decorator +@admin.register(Book) +class BookAdmin(admin.ModelAdmin): + pass + +# Register the Admin classes for BookInstance using the decorator +@admin.register(BookInstance) +class BookInstanceAdmin(admin.ModelAdmin): + pass +</pre> + +<p>Atualmente todas as nossas classes administrativas estão vazias (veja <code>pass</code>) então o comportamento do administrador não será alterado! Agora podemos estendê-los para definir nosso comportamento administrativo específico do modelo.</p> + +<h3 id="Configure_list_views">Configure list views</h3> + +<p>A LocalLibrary atualmente lista todos os autores usando o nome do objeto gerado a partir do método <code>__str__()</code> do modelo. Isso é bom quando você tem apenas alguns autores, mas quando você tem muitos, você pode acabar tendo duplicatas. Para diferenciá-los, ou apenas porque você quer mostrar informações mais interessantes sobre cada autor, você pode usar <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display">list_display</a> para adicionar campos adicionais à vista.</p> + +<p>Substitua seu<code>AuthorAdmin</code> class com o código abaixo. Os nomes de campo a serem exibidos na lista são declarados em uma <em>tupla </em>na ordem requerida, conforme mostrado (esses são os mesmos nomes especificados em seu modelo original).</p> + +<pre class="brush: python notranslate">class AuthorAdmin(admin.ModelAdmin): + list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death') +</pre> + +<p>Agora navegue até a lista de autores em seu site. Os campos acima devem agora ser exibidos, assim:</p> + +<p><img alt="Admin Site - Improved Author List" src="https://mdn.mozillademos.org/files/14023/admin_improved_author_list.png" style="border-style: solid; border-width: 1px; display: block; height: 302px; margin: 0px auto; width: 941px;"></p> + +<p>Para o nosso <code>Book</code> model nós vamos adicionalmente exibir o <code>author</code> e <code>genre</code>. O <code>author</code> é uma variável <code>ForeignKey</code> (um-para-um) relacionamento, e assim será representado pelo valor <code>__str__()</code> para o registro associado. Substitua o <code>BookAdmin</code> class com a versão abaixo.</p> + +<pre class="brush: python notranslate">class BookAdmin(admin.ModelAdmin): + list_display = ('title', 'author', 'display_genre') +</pre> + +<p>Infelizmente não podemos especificar diretamente a variável <font face="Consolas, Liberation Mono, Courier, monospace">genre </font>na <code>list_display</code> porque é um <code>ManyToManyField</code>(O Django evita isso porque há um grande "custo" de acesso ao banco de dados ao fazer isso). Em vez disso, vamos definir uma função <code>display_genre</code> para obter as informações como uma string (esta é a função que chamamos acima; vamos defini-lo abaixo).</p> + +<div class="note"> +<p>Nota: Obtendo o <code>genre</code> pode não ser uma boa ideia aqui, por causa do "custo" da operação do banco de dados. Estamos mostrando como as funções de chamada em seus modelos podem ser muito úteis por outros motivos - por exemplo, para adicionar um link <em>Apagar </em>ao lado de cada item da lista.</p> +</div> + +<p>Adicione o seguinte código ao seu <code>Book</code> model (<strong>models.py</strong>). Isso cria uma string a partir dos três primeiros valores da variavel <code>genre</code> (se existirem) e cria um <code>short_description</code> que pode ser usado no site administrativo para esse método.</p> + +<pre class="brush: python notranslate"> def display_genre(self): + """Create a string for the Genre. This is required to display genre in Admin.""" + return ', '.join(genre.name for genre in self.genre.all()[:3]) + + display_genre.short_description = 'Genre' +</pre> + +<p>Depois de salvar o modelo e o administrador atualizado, abra o site e vá para a página da lista Livros; você deve ver uma lista de livros como a abaixo:</p> + +<p><img alt="Admin Site - Improved Book List" src="https://mdn.mozillademos.org/files/14025/admin_improved_book_list.png" style="border-style: solid; border-width: 1px; display: block; height: 337px; margin: 0px auto; width: 947px;"></p> + +<p>O <code>Genre</code> model (e a <code>Language</code> model, se você definiu um) ambos têm um único campo, portanto, não faz sentido criar um modelo adicional para exibir campos adicionais.</p> + +<div class="note"> +<p>Nota: Vale a pena atualizar o<code>BookInstance</code> model list para mostrar pelo menos o status e a data de retorno esperada. Nós adicionamos isso como um desafio no final deste artigo!</p> +</div> + +<h3 id="Adicionando_list_filters">Adicionando list filters</h3> + +<p>Uma vez que você tenha muitos itens em uma lista, pode ser útil filtrar quais itens são exibidos. Isso é feito listando os campos no atributo <code>list_filter</code>. Substitua sua atual <code style="font-style: normal; font-weight: normal;">BookInstanceAdmin</code> class com o fragmento de código abaixo.</p> + +<pre class="brush: python notranslate">class BookInstanceAdmin(admin.ModelAdmin): +<strong> list_filter = ('status', 'due_back')</strong> +</pre> + +<p>A visualização de lista agora incluirá uma caixa de filtro à direita. Observe como você pode escolher datas e status para filtrar os valores:</p> + +<p><img alt="Admin Site - BookInstance List Filters" src="https://mdn.mozillademos.org/files/14037/admin_improved_bookinstance_list_filters.png" style="height: 528px; width: 960px;"></p> + +<h3 id="Organizando_o_layout_da_detail_view">Organizando o layout da detail view</h3> + +<p>Por padrão, as exibições detalhadas exibem todos os campos verticalmente, em sua ordem de declaração no modelo. Você pode alterar a ordem da declaração, quais campos são exibidos (ou excluídos), se as seções são usadas para organizar as informações, se os campos são exibidos horizontalmente ou verticalmente e até mesmo quais widgets de edição são usados nos formulários admin.</p> + +<div class="note"> +<p>Nota: Os modelos <em>LocalLibrary </em>são relativamente simples, portanto não é necessário alterar o layout; No entanto, faremos algumas alterações, só para mostrar como.</p> +</div> + +<h4 id="Controlando_quais_campos_são_exibidos">Controlando quais campos são exibidos</h4> + +<p>Atualize seu <code>AuthorAdmin</code> class para adicionar a linha <code>fields</code>, como mostrado abaixo (em negrito):</p> + +<pre class="brush: python notranslate">class AuthorAdmin(admin.ModelAdmin): + list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death') +<strong> fields = ['first_name', 'last_name', ('date_of_birth', 'date_of_death')]</strong> +</pre> + +<p>O atributo <code>fields</code> lista apenas os campos que devem ser exibidos no formulário, em ordem. Os campos são exibidos verticalmente por padrão, mas serão exibidos horizontalmente se você agrupá-los posteriormente em uma tupla (conforme mostrado nos campos "data" acima).</p> + +<p>No seu site, acesse a visualização de detalhes do autor. Agora, ele deve aparecer como mostrado abaixo:</p> + +<p><img alt="Admin Site - Improved Author Detail" src="https://mdn.mozillademos.org/files/14027/admin_improved_author_detail.png" style="border-style: solid; border-width: 1px; display: block; height: 282px; margin: 0px auto; width: 928px;"></p> + +<div class="note"> +<p>Nota: você também pode usar o atributo <code>exclude</code> para declarar uma lista de atributos a serem excluídos do formulário (todos os outros atributos no modelo serão exibidos).</p> +</div> + +<h4 id="Seccionando_a_detail_view">Seccionando a detail view</h4> + +<p>Você pode adicionar "seções" para agrupar informações de modelo relacionadas dentro do formulário detalhado, usando o atributo <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets">fieldsets</a>.</p> + +<p>Na <code>BookInstance</code> model temos informações relacionadas ao que o livro é (i.e. <code>name</code>, <code>imprint</code>, e <code>id</code>) e quando estará disponível (<code>status</code>, <code>due_back</code>). Podemos adicionar estes em diferentes seções, adicionando o texto em negrito para o nosso <code>BookInstanceAdmin</code> class. </p> + +<pre class="brush: python notranslate">@admin.register(BookInstance) +class BookInstanceAdmin(admin.ModelAdmin): + list_filter = ('status', 'due_back') + +<strong> fieldsets = ( + (None, { + 'fields': ('book', 'imprint', 'id') + }), + ('Availability', { + 'fields': ('status', 'due_back') + }), + )</strong></pre> + +<p>Cada seção tem seu próprio título (ou <code>None</code>,se você não quiser um título) e uma tupla associada de campos em um dicionário - o formato é complicado de descrever, mas bastante fácil de entender se você olhar o fragmento de código imediatamente acima.</p> + +<p>Agora, navegue até uma visualização de instância do livro em seu website; o formulário deve aparecer como mostrado abaixo:</p> + +<p><img alt="Admin Site - Improved BookInstance Detail with sections" src="https://mdn.mozillademos.org/files/14029/admin_improved_bookinstance_detail_sections.png" style="border-style: solid; border-width: 1px; display: block; height: 580px; margin: 0px auto; width: 947px;"></p> + +<h3 id="Edição_inline_de_registros_associados">Edição inline de registros associados</h3> + +<p>Às vezes, pode fazer sentido adicionar registros associados ao mesmo tempo. Por exemplo, pode fazer sentido ter as informações do livro e as informações sobre as cópias específicas que você tem na mesma página de detalhes.</p> + +<p>Você pode fazer isso declarando <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.inlines">inlines</a>, do tipo <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.TabularInline">TabularInline</a> (horizonal layout) or <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.StackedInline">StackedInline</a> (layout vertical, assim como o layout do modelo padrão). Você pode adicionar ao <code>BookInstance</code> informações inline para o nosso <code>Book</code> detalhe, adicionando as linhas abaixo em negrito perto do seu <code>BookAdmin</code>:</p> + +<pre class="brush: python notranslate"><strong>class BooksInstanceInline(admin.TabularInline): + model = BookInstance</strong> + +@admin.register(Book) +class BookAdmin(admin.ModelAdmin): + list_display = ('title', 'author', 'display_genre') +<strong> inlines = [BooksInstanceInline]</strong> +</pre> + +<p>Agora navegue até uma view pala um <code>Book</code> no seu site - na parte inferior, você verá as instâncias do livro relacionadas a este livro (imediatamente abaixo dos campos de gênero do livro):</p> + +<p><img alt="Admin Site - Book with Inlines" src="https://mdn.mozillademos.org/files/14033/admin_improved_book_detail_inlines.png" style="border-style: solid; border-width: 1px; display: block; height: 889px; margin: 0px auto; width: 937px;"></p> + +<p>Nesse caso, tudo o que fizemos foi declarar nossa classe inline tabular, que apenas adiciona todos os campos do modelo embutido. Você pode especificar todos os tipos de informações adicionais para o layout, incluindo os campos a serem exibidos, sua ordem, se eles são somente leitura ou não, etc. (veja <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.TabularInline">TabularInline</a> para maiores informações).</p> + +<div class="note"> +<p>Nota: Existem alguns limites dolorosos nesta funcionalidade! Na captura de tela acima, temos três instâncias de livros existentes, seguidas de três espaços reservados para novas instâncias de livros (que são muito semelhantes!). Seria melhor não ter instâncias do livro reserva por padrão e apenas adicioná-las com o link <strong>Add another Book instance</strong> , ou poder listar apenas <code>BookInstance</code>s como links não legíveis daqui. A primeira opção pode ser feita configurando atributo <code>extra</code> para 0 no <code>BooksInstanceInline</code> model, tente você mesmo.</p> +</div> + +<h2 id="Desafie-se">Desafie-se</h2> + +<p>Aprendemos muito nesta seção, então agora é hora de você tentar algumas coisas.</p> + +<ol> + <li>Para a <em>listview</em> <code>BookInstance</code>, adicione o código para exibir o livro, o status, a data de devolução e o id (em vez do texto padrão <code>__str__()</code>).</li> + <li>Adicione uma listagem <em>inline</em> de itens <code>Book</code> para a lista detalhada de <code>Author</code> usando a mesma abordagem que fizemos para <code>Book</code>/<code>BookInstance</code>.</li> +</ol> + +<ul> +</ul> + +<h2 id="Resumo">Resumo</h2> + +<p>É isso aí! Agora você aprendeu como configurar o site de administração na sua forma simples e aprimorada, como criar um superusuário, como navegar no site de administração e visualizar, excluir e atualizar registros. Ao longo do caminho você criou um monte de Livros, Instâncias de livros, Gêneros e Autores que poderemos listar e exibir assim que criarmos nossas próprias <em>views</em> e <em>templates</em>.</p> + +<h2 id="Leitura_adicional">Leitura adicional</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.0/intro/tutorial02/#introducing-the-django-admin">Escrevendo seu primeiro app Django, parte 2: Apresentando o Django Admin</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.0/ref/contrib/admin/">O Django Admin site</a> (Django Docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Models", "Learn/Server-side/Django/Home_page", "Learn/Server-side/Django")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: Website de uma biblioteca local</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Tutorial Django Parte 2: Criando o escopo do website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Models">Django Parte 3: Utilizando models</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Admin_site">Django Parte 4: Django admin site</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Home_page">Django Parte 5: Criando nossa página principal</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Generic_views">Django Parte 6: Lista genérica e detail views</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Sessions">Django Parte 7: Framework de Sessões</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Authentication">Django Parte 8: Autenticação de Usuário e permissões</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Forms">Django Parte 9: Trabalhando com formulários</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Testing">Django Parte 10: Testando uma aplicação web Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial Django Parte 11: Implantando Django em produção</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/web_application_security">Segurança de aplicações Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/ambiente_de_desenvolvimento/index.html b/files/pt-br/learn/server-side/django/ambiente_de_desenvolvimento/index.html new file mode 100644 index 0000000000..101d1a15ad --- /dev/null +++ b/files/pt-br/learn/server-side/django/ambiente_de_desenvolvimento/index.html @@ -0,0 +1,431 @@ +--- +title: Configurando um ambiente de desenvolvimento Django +slug: Learn/Server-side/Django/ambiente_de_desenvolvimento +tags: + - Ambiente de desenvolvimento + - Aprender + - Iniciante + - Instalação + - Introdução + - Python + - django +translation_of: Learn/Server-side/Django/development_environment +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Introduction", "Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django")}}</div> + +<p>Agora que você sabe para que serve o Django, nós iremos te mostrar como instalar, configurar e testar um ambiente de desenvolvimento no Windows, Linux (Ubuntu), e macOS - seja qual for o sistema operacional (SO) que você usar, este artigo deve fornecê-lo o suficiente para conseguir começar a desenvolver aplicativos Django.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Saber como usar um teminal / linha de comando. Saber instalar softwares em seu sistema operacional.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ter uma ambiente de desenvolvimento Django (2.0) operando em seu computador.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_geral_do_ambiente_de_desenvolvimento_Django">Visão geral do ambiente de desenvolvimento Django</h2> + +<p>Django facilita muito a configuração em seu computador para iniciar logo o desenvolvimento de aplicações web. Essa seção explica o que você ganha com o ambiente de desenvolvimento e fornece um plano geral de algumas opções de instalação e configuração. O resto do artigo explica o método <em>recomendado</em> de instalar o ambiente Django no Ubuntu, macOS e Windows e como testar.</p> + +<h3 id="O_que_é_o_ambiente_de_desenvolvimento_Django">O que é o ambiente de desenvolvimento Django?</h3> + +<p>O ambiente de desenvolvimento é uma instalação do Django em seu computador local para que você use-o para desenvolver e testar apps Django antes de implementá-los em um ambiente de produção</p> + +<p>A principal ferramenta que Django fornece é um conjunto de scripts Python para criar e trabalhar com projetos Django, junto com um simples<em> webserver de desenvolvimento</em> que você pode usar para testar localmente (i.e. no seu computador, não em um web server externo) aplicações web Django no seu navegador.</p> + +<p>Existem outras ferramentas secundárias que fazem parte do ambiente de desenvolvimento que não cobriremos aqui. Isso inclui coisas como um <a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Available_text_editors">editor de texto</a> ou IDE para edição de código, e uma ferramenta pra gerenciamento do controle de origem de códigos (como o <a href="https://git-scm.com/">Git</a>) para administrar com segurança as diferentes versões de seu sistema. Nós estamos assumindo que você já tem um editor de texto instalado.</p> + +<h3 id="Quais_são_as_opções_de_instalação_do_Django">Quais são as opções de instalação do Django?</h3> + +<p>Django é extremamente flexível em termos de como e onde ele pode ser instalado e configurado. Django pode:</p> + +<ul> + <li>Ser instalado em diferentes sistemas operacionais.</li> + <li>Ser instalado pelo código-fonte, pelo Python Package Index (PyPi) e, em muitos casos, pelo aplicativo gerenciador de pacotes do computador host.</li> + <li>Ser configurado para uso de um dos vários bancos de dados, que também podem ser instalados e configurados separadamente.</li> + <li>Operar no ambiente principal do sistema Python ou em ambientes virtuais Python, separadamente.</li> +</ul> + +<p>Cada opção requer leves diferenças de configuração e instalação. As subseções abaixo explicam algumas de suas escolhas. No resto do artigo nós iremos mostrar como instalar o Django em um pequeno número de sistemas operacionais. No resto do módulo, assumiremos que você tenha instalado o Django em sua máquina.</p> + +<div class="note"> +<p><strong>Nota</strong>: Outras possíveis opções de instalação são cobertas pela documentação oficial do Django. Nós linkamos os <a href="#Veja_também" id="See_also">documents adequados abaixo</a>.</p> +</div> + +<h4 id="Quais_sistemas_operacionais_suportam_Django">Quais sistemas operacionais suportam Django?</h4> + +<p>Aplicações web Django podem rodar em quase todas as maquinas que suportam a linguagem de programação Python 3. Windows, macOS, Linux/Unix e Solaris são alguns desses SO's. A maioria dos computadores atuais devem ter o desempenho necessário para operar Django.</p> + +<p>Neste artigo, iremos fornecer instruções para Windows, macOS a Linux/Unix.</p> + +<h4 id="Qual_versão_de_Python_deve_ser_usada">Qual versão de Python deve ser usada?</h4> + +<p>Nós recomendamos que use a mais recente versão disponível — no momento que escrevo é Python 3.7.1.</p> + +<p>Se necessário, versões a partir de Python 3.5 podem ser usadas (o suporte para Python 3.5 irá acabar em versões futuras).</p> + +<div class="note"> +<p><strong>Nota</strong>: Python 2.7 não pode ser usado com Django 2.1 (A série Django 1.11.x é a última que suporta Python 2.7).</p> +</div> + +<h4 id="Onde_posso_baixar_o_Django">Onde posso baixar o Django?</h4> + +<p>Existem três lugares para fazer o download do Django:</p> + +<ul> + <li>Python Package Repository (PyPi), usando o comando <em>pip</em>. Esta é a melhor forma de conseguir a última versão estável do Django.</li> + <li>A partir de uma versão do gerenciador de pacotes de seu computador. Distribuições de Django que são empacotadas com o sistema operacional oferecem uma "instalação familiar". Contudo, note que a versão disponível pode ser um pouco antiga, e que pode ser instalada apenas dentro do sistema ambiente do Python (podendo ser algo que você não queira).</li> + <li>Instalar pelo código-fonte. Você pode pegar a última versão acessível do código do Django e instalar no seu computador. Não é recomendado aos iniciantes, mas é necessário quando você se sentir pronto para contribuir com o Django.</li> +</ul> + +<p>Este artigo mostra a instalação pelo Pypi, pois queremos a última versão estável do Django.</p> + +<h4 id="Qual_banco_de_dados">Qual banco de dados?</h4> + +<p>Django suporta (principalmente) quatro bancos de dados (PostgreSQL, MySQL, Oracle, e SQLite ), contudo, existem bibliotecas community que fornecem níveis variados de suporte para outros populares bancos de dados SQL e NoSQL. Nós recomendamos que você use o mesmo banco de dados tanto para produção quanto para desenvolvimento (embora o Django abstraia muitas das diferenças dos bancos de dados usando seu Object-Relational Mapper (ORM), ainda há <a href="https://docs.djangoproject.com/en/2.1/ref/databases/">problemas em potencial</a> que é melhor evitar).</p> + +<p>Neste artigo (e na maior parte deste módulo) nós usaremos o banco de Dados <em>SQL</em><em>ite</em>, que armazena dados em um arquivo. SQLite é destinado para uso sendo um banco de dados leve e que não consegue suportar uma demanda muito alta. Entretanto, uma excelente opção para aplicações de que focam em leitura de dados.</p> + +<div class="note"> +<p><strong>Nota:</strong> Django é configurado por padrão a usar SQLite ao iniciar seu projeto usando as ferramentas padrão (django-admin). É uma ótima escolha quando você está começando, porque não requer configurações adicionais ou instalações.</p> +</div> + +<h4 id="Instalar_em_todo_o_sistema_ou_em_um_ambiente_virtual_Python">Instalar em todo o sistema ou em um ambiente virtual Python?</h4> + +<p>Quando você instala Python 3 você pega um único ambiente global que é compartilhado por todo o código Python 3. Enquanto você pode instalar qualquer pacote Python que quiser no ambiente, você pode instalar apenas uma versão particular de cada pacote por vez.</p> + +<div class="note"> +<p><strong>Nota</strong>: Aplicações Python instaladas no ambiente global têm forte potêncial de entrar em conflito entre si (i.e. se elas dependem de versões diferentes do mesmo pacote).</p> +</div> + +<p>Se você instalar Django no ambiente padrão/global você só será capaz de ter uma versão do Django em seu computador. Isto pode ser um problema se você quer criar novos websites (usando a versão mais recente do Django) enquanto ainda realiza manutenção nos websites que dependem das versões antigas.</p> + +<p>Pensando nisso, desenvolvedores experientes de Python/Django normalmente executam apps Python dentro de um <em>ambiente virtual Python </em>independente. Isso permite usar diferentes ambientes Django em um único computador. A própria equipe de desenvolvedores Django recomenda o uso de ambientes virtuais Python!</p> + +<p>Esse módulo assume que você instalou o Django em um ambiente virtual, nós iremos mostrá-lo como fazer isso logo abaixo.</p> + +<h2 id="Instalando_Python_3">Instalando Python 3</h2> + +<p>Você deve ter Python instalado em seu sistema operacional para usar Django. Se você estiver usando <em>Python 3</em>, também precisará da ferramenta <a href="https://pypi.python.org/pypi">Python Package Index</a> — <em>pip3 </em>— que é usada para administrar (instalar, editar, remover) pacotes/bibliotecas Python usadas por Django e seus outros aplicativos Python.</p> + +<p>Essa parte explica brevemente como você pode checar quais versões de Python estão disponíveis e instalar novas versões se necessário (em Ubuntu 18.04, macOS e Windows 10).</p> + +<div class="note"> +<p><strong>Nota</strong>: Dependendo da sua plataforma, você também pode instalar Python/pip3 no seu sistema operacional através de seu próprio gerenciador de pacotes ou por outros mecanismos. Para a maioria das plataformas, você pode baixar os arquivos necessários para instalação em <a href="https://www.python.org/downloads/">https://www.python.org/downloads/</a> e instalá-los usando o método específico da plataforma em questão.</p> +</div> + +<h3 id="Ubuntu_18.04">Ubuntu 18.04</h3> + +<p>Ubuntu Linux 18.04 LTS inclui Python 3.6.6 por padrão. Você pode confirmar isso executando o seguinte comando no Terminal:</p> + +<pre class="brush: bash notranslate"><span style="line-height: 1.5;">python3 -V + Python 3.6.6</span></pre> + +<p>Contudo, o Python Package Index, que você precisará para instalar pacotes para Python 3 (incluindo Django), <strong>não</strong> está disponível por padrão. Você pode instalar pip3 pelo Terminal usando:</p> + +<pre class="brush: bash notranslate">sudo apt install python3-pip +</pre> + +<h3 id="macOS">macOS</h3> + +<p>macOS "El Capitan" e outras versões mais recentes não incluem Python 3. Você pode confirmar isto executando os comandos abaixo no Terminal:</p> + +<pre class="brush: bash notranslate"><span style="line-height: 1.5;">python3 -V + </span>-bash: python3: command not found</pre> + +<p>Você pode instalar Python 3 (com a ferramenta pip3) facilmente em <a href="https://www.python.org/">python.org</a>:</p> + +<ol> + <li>Baixe o instalador exigido: + <ol> + <li>Acesse <a href="https://www.python.org/downloads/">https://www.python.org/downloads/</a></li> + <li>Selecione o botão <strong>Download Python 3.7.1</strong> (o número exato da versão menor pode diferir).</li> + </ol> + </li> + <li>Localize o arquivo usando <em>o Finder</em>, e clique duplo no arquivo do pacote. Siga os passos da instalação dos prompts.</li> +</ol> + +<p>Agora você pode confirmar se tudo deu certo checando o<em> Python 3 </em>como mostrado abaixo:</p> + +<pre class="brush: bash notranslate"><span style="line-height: 1.5;">python3 -V + Python 3.7.1</span> +</pre> + +<p>Você pode checar se<em> pip3</em> está instalado listando todos os pacotes disponíveis.</p> + +<pre class="brush: bash notranslate">pip3 list</pre> + +<h3 id="Windows_10">Windows 10</h3> + +<p>Windows não inclui Python por padrão, mas você pode instalá-lo facilmente (com a ferramenta<em> pip3</em>) em <a href="https://www.python.org/">python.org</a>:</p> + +<ol> + <li>Baixe o instalador exigido: + <ol> + <li>Acesse <a href="https://www.python.org/downloads/">https://www.python.org/downloads/</a></li> + <li>Selecione o botão <strong>Download Python 3.7.1</strong> (o número exato da versão menor pode diferir).</li> + </ol> + </li> + <li>Instale Python com um clique duplo no arquivo baixado e siga a instalação dos prompts.</li> + <li>Tenha certeza que a caixa "Add Python to PATH" está checada.</li> +</ol> + +<p>Você pode verificar se o Python 3 foi instalado colocando o seguinte texto no Prompt de Comando</p> + +<pre class="brush: bash notranslate"><span style="line-height: 1.5;">py -3 -V + Python 3.7.1</span> +</pre> + +<p>O instalador do Windows incorpora<em> pip3</em> (o administrador de pacotes Python) por padrão. Você pode facilmente listar os pacotes instalados com o comando abaixo:</p> + +<pre class="brush: bash notranslate"><span style="line-height: 1.5;">pip3 list</span> +</pre> + +<div class="note"> +<p><strong>Nota</strong>: O instalador deve ter configurado tudo que você precisa antes para esse comando funcionar. Se for exibida uma mensagem que Python não encontrou, você pode ter esquecido de adicioná-lo ao PATH do Sistema. Você pode fazer isso exexutando o instalador novamente, selecionando "Modify", e checando a caixa chamada " Add Python to environment variables " na segunda tela.</p> +</div> + +<h2 id="Usando_Django_em_um_ambiente_virtual_Python">Usando Django em um ambiente virtual Python</h2> + +<p>As bibliotecas que nós iremos usar para criar nossos ambientes virtuais são <a href="https://virtualenvwrapper.readthedocs.io/en/latest/index.html">virtualenvwrapper</a> (Linux e macOS) e <a href="https://pypi.python.org/pypi/virtualenvwrapper-win">virtualenvwrapper-win</a> (Windows), sendo que ambas usam a ferramenta <a href="https://developer.mozilla.org/en-US/docs/Python/Virtualenv">virtualenv</a>. as bibliotecas criam uma interface consistente para manusear interfaces em todas plataformas;</p> + +<h3 id="Instalando_o_software_de_ambiente_virtual">Instalando o software de ambiente virtual</h3> + +<h4 id="Instalação_do_ambiente_virtual_no_Ubuntu">Instalação do ambiente virtual no Ubuntu</h4> + +<p>Após instalar Python e pip, você pode instalar<em> virtualenvwrapper</em> (que inclui<em>virtualenv</em>). O guia oficial para a instalação pode ser encontrado <a href="http://virtualenvwrapper.readthedocs.io/en/latest/install.html">aqui</a>, ou siga as instruções abaixo.</p> + +<p>Instale a ferramenta usando<em> pip3</em>:</p> + +<pre class="brush: bash notranslate"><code>sudo pip3 install virtualenvwrapper</code></pre> + +<p>Em seguida, adicione as linhas abaixo no fim de seu arquivo shell startup (este é um arquivo oculto nomeado <strong>.bashrc </strong>em seu diretório home). Isto coloca a localização de onde seus ambientes virtuais deveriam estar, a localização dos diretórios para desevolvimento de projetos e a localização do script instalado com o pacote.</p> + +<pre class="brush: bash notranslate"><code>export WORKON_HOME=$HOME/.virtualenvs +export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 +export VIRTUALENVWRAPPER_VIRTUALENV_ARGS=' -p /usr/bin/python3 ' +export PROJECT_HOME=$HOME/Devel +source /usr/local/bin/virtualenvwrapper.sh</code> +</pre> + +<div class="note"> +<p><strong>Note</strong>: As variáveis <code>VIRTUALENVWRAPPER_PYTHON</code> e <code>VIRTUALENVWRAPPER_VIRTUALENV_ARGS </code>apontam para a localização em uma instalação normal de Python 3, e <code>source /usr/local/bin/virtualenvwrapper.sh</code> aponta para a localização normal do script <code>virtualenvwrapper.sh</code> Se<em> virtualenv</em> não funciona quando você testa, uma coisa a se verificar é se o Python e o script estão na localização esperada (e então alterar o arquivo de startup com os caminhos corretos).<br> + <br> + Você pode encontrar a localização correta no seu sistema usando os comandos <code>which virtualenvwrapper.sh</code> e <code>which python3</code>.</p> +</div> + +<p>Recarregue o arquivo de startup executando o seguinte comando no Terminal:</p> + +<pre class="brush: bash notranslate"><code>source ~/.bashrc</code></pre> + +<p>Após executar o comando, você deveria ver scripts como esses:</p> + +<pre class="brush: bash notranslate"><code>virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/premkproject +virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/postmkproject +... +virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/preactivate +virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/postactivate +virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/get_env_details</code> +</pre> + +<p>Agora você pode criar um novo ambiente virtual com o comando <code>mkvirtualenv</code>.</p> + +<h4 id="Instalação_do_ambiente_virtual_no_macOS">Instalação do ambiente virtual no macOS</h4> + +<p>Instalar<em> virtualenvwrapper</em> no macOS é quase a mesma coisa que instalar no Ubuntu (novamente, você pode seguir as instruções do <a href="http://virtualenvwrapper.readthedocs.io/en/latest/install.html">guia oficial de instalação </a>ou as instruções abaixo).</p> + +<p>Instale<em> virtualenvwrapper</em> (e<em> virtualenv</em>) usando<em> pip</em> como abaixo.</p> + +<pre class="brush: bash notranslate"><code>sudo pip3 install virtualenvwrapper</code></pre> + +<p>Então adicione as seguintes linhas no arquivo de startup do seu shell.</p> + +<pre class="brush: bash notranslate"><code>export WORKON_HOME=$HOME/.virtualenvs +export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 +export PROJECT_HOME=$HOME/Devel +source /usr/local/bin/virtualenvwrapper.sh</code></pre> + +<div class="note"> +<p><strong>Note</strong>: A variável <code>VIRTUALENVWRAPPER_PYTHON</code> aponta para uma localização em uma instalação normal de Python 3, e <code>source /usr/local/bin/virtualenvwrapper.sh</code> aponta para a localização comum do script <code>virtualenvwrapper.sh</code>. Se <em>virtualenv</em> não funciona quando você testa, uma coisa a se verificar é se o Python e o script estão na localização esperada (e então alterar o arquivo de startup com os caminhos corretos).</p> + +<p>Por exemplo, uma instalação teste no macOS termina com as seguintes linhas no arquivo de startup:</p> + +<pre class="brush: bash notranslate">export WORKON_HOME=$HOME/.virtualenvs +export VIRTUALENVWRAPPER_PYTHON=/Library/Frameworks/Python.framework/Versions/3.7/bin/python3 +export PROJECT_HOME=$HOME/Devel +source /Library/Frameworks/Python.framework/Versions/3.7/bin/virtualenvwrapper.sh</pre> + +<p>Você pode encontrar a localização correta no seu sistema usando os comandos <code>which virtualenvwrapper.sh</code> e <code>which python3</code>.</p> +</div> + +<p>São as mesmas linhas digitadas no Ubuntu, mas o arquivo de startup é diferente nomeado como <strong>.bash_profile</strong>, oculto no seu diretório home.</p> + +<div class="note"> +<p><strong>Nota</strong>: Se você não acha o arquivo <strong>.bash_profile</strong> pelo finder, você pode abir pelo terminal usando o <em>nano</em>.</p> + +<p>Os comandos são como esses:</p> + +<pre class="notranslate"><code>cd ~ # Navigate to my home directory +ls -la #List the content of the directory. YOu should see .bash_profile +nano .bash_profile # Open the file in the nano text editor, within the terminal +# Scroll to the end of the file, and copy in the lines above +# Use Ctrl+X to exit nano, Choose Y to save the file.</code> +</pre> +</div> + +<p>Atualize o arquivo de startup fazendo o seguinte chamado no terminal:</p> + +<pre class="brush: bash notranslate"><code>source ~/.bash_profile</code></pre> + +<p>Com isso, você deveria ver alguns scripts na tela do terminal sendo executados (os mesmos scripts da instalação no Ubuntu). Agora você está apto a criar um novo ambiente virtual pelo comando <code>mkvirtualenv</code>.</p> + +<h4 id="Instalação_do_ambiente_virtual_no_Windows_10">Instalação do ambiente virtual no Windows 10</h4> + +<p>Instalar <a href="https://pypi.python.org/pypi/virtualenvwrapper-win">virtualenvwrapper-win</a> é ainda mais simples que instalar <em>virtualenvwrapper</em>, porque você não precisa configurar onde a ferramenta armazena as informações do ambiente virtual (pois é um valor padrão). Tudo que você precisa fazer é rodar o seguinte comando no Prompt de Comando.</p> + +<pre class="notranslate"><code>pip3 install virtualenvwrapper-win</code></pre> + +<p>Agora você pode criar um novo ambiente virtual com o comando <code>mkvirtualenv</code>.</p> + +<h3 id="Criando_um_ambiente_virtual">Criando um ambiente virtual</h3> + +<p>Uma vez que você tenha instalado <em>virtualenvwrapper</em> ou <em>virtualenvwrapper-win</em>, trabalhar com ambientes virtuais é bem parecido em todas as plataformas.</p> + +<p>Agora você pode criar um novo ambiente virtual com o comando <code>mkvirtualenv</code>. Ao executar esse comando, você verá o ambiente sendo configurado (o que você verá varia um pouco em cada plataforma). Quando o comando encerrar a configuração, o ambiente virtual estará ativo — você pode ver isso porque no topo do prompt (aquela barra de título do programa) estará escrito o nome do ambiente entre colchetes (abaixo nós mostramos como é a criação do ambiente no Ubuntu, mas o comando é igual para o Windows/macOS).</p> + +<pre class="notranslate"><code>$ mkvirtualenv my_django_environment + +Running virtualenv with interpreter /usr/bin/python3 +... +virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/t_env7/bin/get_env_details +(my_django_environment) ubuntu@ubuntu:~$</code> +</pre> + +<p>Agora que você está em um ambiente virtual, você pode instalar Django e iniciar o desenvolvimento.</p> + +<div class="note"> +<p><strong>Nota</strong>: De agora em diante, esse artigo (na verdade todo o módulo) está supondo que todos os comando serão executados em um ambiente virtual Python como o que configuramos acima.</p> +</div> + +<h3 id="Usando_um_ambiente_virtual">Usando um ambiente virtual</h3> + +<p>Existem apenas alguns poucos comandos que você deveria conhecer (há mais comandos que você pode encontrar na documentação da ferramenta, porém, os comandos abaixo serão os que você usará regularmente):</p> + +<ul> + <li><code>deactivate</code> — Encerra o ambiente virtual Python corrente.</li> + <li><code>workon</code> — Lista ambientes virtuais disponíveis.</li> + <li><code>workon name_of_environment</code> — Ativa o ambiente virtual Python especificado.</li> + <li><code>rmvirtualenv name_of_environment</code> — Remove o ambiente especificado.</li> +</ul> + +<h2 id="Instalando_o_Django">Instalando o Django</h2> + +<p>Após criar um ambiente virtual e usado o comando <code>workon</code> para ativá-lo, você pode usar <em>pip3 </em>para instalar o Django. </p> + +<pre class="brush: bash notranslate">pip3 install django +</pre> + +<p>Você pode testar a instalação do Django executando o seguinte comando (isso apenas testa se o Python pode achar o módulo Django):</p> + +<pre class="brush: bash notranslate"># Linux/macOS +python3 -m django --version + 2.1.5 + +# Windows +py -3 -m django --version + 2.1.5 +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Se o comando Windows acima não mostrar um módulo django, tente:</p> + +<pre class="brush: bash notranslate">py -m django --version</pre> + +<p>No Windows, os scripts <em>Python 3</em> são iniciados prefixando o comando com <code>py -3</code>, embora isso possa variar de acordo com sua instalação. Tente omitir o modificador <code>-3</code> se você encontrar algum problema com os comandos. No Linux/macOS, o comando é <code>python3</code>.</p> +</div> + +<div class="warning"> +<p><strong>Importante</strong>: O resto deste <strong>módulo </strong>usa o comando <em>Linux</em> para chamar o Python 3 (<code>python3</code>). Se você está usando o Windows, substitua o prefixo por: <code>py -3</code></p> +</div> + +<h2 id="Testando_sua_instalação">Testando sua instalação</h2> + +<p>O teste acima funciona, mas não é muito divertido. Um teste mais interessante é criar o esqueleto de um projeto e vê-lo funcionando. Para fazer isso, para isso navegue em seu prompt de comando/terminal até o diretório que quer armazenar seus aplicativos Django. Crie uma pasta para seu site e navegue nela.</p> + +<pre class="brush: bash notranslate">mkdir django_test +cd django_test +</pre> + +<p>Agora você pode criar um novo site chamado "<em>mytestsite</em>" usando a ferramenta <strong>django-admin</strong>. Após criar o site você pode navegar dentro da pasta onde encontrará o script principal para gerenciar projetos, nomeado <strong>manage.py</strong>.</p> + +<pre class="brush: bash notranslate">django-admin startproject mytestsite +cd mytestsite</pre> + +<p>Nós podemos rodar o <em>web server de desenvolvimento</em> dentro dessa pasta usando o <strong>manage.py</strong> e o comando <code>runserver</code>, como mostrado.</p> + +<pre class="brush: bash notranslate">$ python3 manage.py runserver +Performing system checks... + +System check identified no issues (0 silenced). + +You have 15 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. +Run 'python manage.py migrate' to apply them. + +December 16, 2018 - 07:06:30 +Django version 2.1.5, using settings 'mytestsite.settings' +Starting development server at http://127.0.0.1:8000/ +Quit the server with CONTROL-C. +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Acima foi mostrado o comando em Linux/macOS. Você já pode ignorar o aviso sobre "15 unapplied migration(s)"!</p> +</div> + +<p>Uma vez que o servidor está operando, você pode acessar o site colocando a seguinte URL no seu navegador local:<code>http://127.0.0.1:8000/</code>. Você deveria ver um site como esse:<br> + <img alt="Django Skeleton App Homepage - Django 2.0" src="https://mdn.mozillademos.org/files/16288/Django_Skeleton_Website_Homepage_2_1.png" style="height: 714px; width: 806px;"></p> + +<ul> +</ul> + +<h2 id="Resumo">Resumo</h2> + +<p>Agora você tem um ambiente de desenvolvimento em Django funcionando em seu computador.</p> + +<p>Na seção <em>Testando sua instalação </em>você viu brevemente como criar um website Django usando <code>django-admin startproject</code>, e executá-lo em seu navegador usando um web server de desenvolvimento (<code>python3 manage.py runserver</code>). No próximo artigo nós iremos expandir esse processo, construindo uma aplicação web simples, mas completa.</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.1/intro/install/">Guia de Instalação Rápida</a> (documentação Django)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/install/">Como instalar Django — Guia completo</a> (documentação Django) - inclui informações para remover o Django</li> + <li><a href="https://docs.djangoproject.com/en/2.1/howto/windows/">Como instalar Django no Windows</a> (documentação Django)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Introduction", "Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: Website de uma Biblioteca Local</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/skeleton_website">Tutorial Django Parte 2: Criando a base do website</a></li> + <li><a href="https://developer.mozilla.org/pt-br/docs/Learn/Server-side/Django/Models">Tutorial Django Parte 3: Utilizando models</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Admin_site">Tutorial Django Parte 4: Django admin site</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Home_page">Tutorial Django Parte 5: Criando nossa página principal</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Generic_views">Tutorial Django Parte 6: Lista genérica e detail views</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Sessions">Tutorial Django Parte 7: Framework de Sessões</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Authentication">Django Tutorial Part 8: Autenticação de Usuário e permissões</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Forms">Tutorial Django Parte 9: Trabalhando com formulários</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Testing">Tutorial Django Parte 10: Testando uma aplicação web Django</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Deployment">Tutorial Django Parte 11: Implantando Django em produção</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/web_application_security">Segurança de aplicações web Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/authentication/index.html b/files/pt-br/learn/server-side/django/authentication/index.html new file mode 100644 index 0000000000..77535ae7ba --- /dev/null +++ b/files/pt-br/learn/server-side/django/authentication/index.html @@ -0,0 +1,692 @@ +--- +title: 'Tutorial Django Parte 8: Autenticação de usuário e permissões' +slug: Learn/Server-side/Django/Authentication +translation_of: Learn/Server-side/Django/Authentication +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Sessions", "Learn/Server-side/Django/Forms", "Learn/Server-side/Django")}}</div> + +<p class="summary">Neste tutorial, mostraremos como permitir que os usuários efetuem login no seu site com suas próprias contas e como controlar o que eles podem fazer e ver com base em se eles estão ou não conectados e em suas permissões. Como parte desta demonstração, estenderemos o <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a> website, adicionando páginas de login e logout e páginas específicas do usuário e da equipe para visualizar os livros emprestados.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conclua todos os tópicos do tutorial anterior, incluindo <a href="/en-US/docs/Learn/Server-side/Django/Sessions">Django Tutorial Part 7: Sessions framework</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Para entender como configurar e usar a autenticação e permissões de usuário.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_global">Visão global</h2> + +<p>O Django fornece um sistema de autenticação e autorização ("permissão"), construído sobre a estrutura da sessão discutida no <a href="/en-US/docs/Learn/Server-side/Django/Sessions">tutorial anterior</a>, que permite verificar as credenciais do usuário e definir quais ações cada usuário tem permissão para executar. A estrutura inclui modelos internos para <code>Users</code> e <code>Groups</code> (uma maneira genérica de aplicar permissões a mais de um usuário por vez), permissões/sinalizadores que designam se um usuário pode executar uma tarefa, formulários e exibições para efetuar logon em usuários e exibir ferramentas para restringir o conteúdo.</p> + +<div class="note"> +<p><strong>Nota</strong>: De acordo com o Django, o sistema de autenticação pretende ser muito genérico e, portanto, não fornece alguns recursos fornecidos em outros sistemas de autenticação na web. Soluções para alguns problemas comuns estão disponíveis como pacotes de terceiros. Por exemplo, limitação de tentativas de login e autenticação contra terceiros (por exemplo, OAuth).</p> +</div> + +<p>Neste tutorial, mostraremos como habilitar a autenticação do usuário no diretório <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a> website, crie suas próprias páginas de logon e logout, adicione permissões aos seus modelos e controle o acesso às páginas. Usaremos a autenticação/permissões para exibir listas de livros que foram emprestados para usuários e bibliotecários.</p> + +<p>O sistema de autenticação é muito flexível e você pode criar seus URLs, formulários, visualizações e modelos a partir do zero, se quiser, apenas chamando a API fornecida para efetuar login no usuário. No entanto, neste artigo, vamos usar as visualizações e formulários de autenticação "stock" do Django para nossas páginas de logon e logout. Ainda precisamos criar alguns modelos, mas isso é bem fácil.</p> + +<p>Também mostraremos como criar permissões e verificar o status e as permissões de login nas visualizações e nos modelos.</p> + +<h2 id="Ativando_a_autenticação">Ativando a autenticação</h2> + +<p>A autenticação foi ativada automaticamente quando <a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">criamos o esqueleto do site</a> (no tutorial 2), para que você não precise fazer mais nada neste momento.</p> + +<div class="note"> +<p><strong>Nota</strong>: A configuração necessária foi feita para nós quando criamos o aplicativo usando o comando <code>django-admin startproject</code>. As tabelas de banco de dados para usuários e permissões de modelo foram criadas quando chamamos pela primeira vez <code>python manage.py migrate</code>.</p> +</div> + +<p>A configuração está definida nas seções <code>INSTALLED_APPS</code> e <code>MIDDLEWARE</code> no settings.py (<strong>locallibrary/locallibrary/settings.py</strong>), como mostrado abaixo:</p> + +<pre class="brush: python notranslate">INSTALLED_APPS = [ + ... +<strong> 'django.contrib.auth', </strong>#Core authentication framework and its default models. +<strong> 'django.contrib.contenttypes', #</strong>Django content type system (allows permissions to be associated with models). + .... + +MIDDLEWARE = [ + ... +<strong> 'django.contrib.sessions.middleware.SessionMiddleware',</strong> #Manages sessions across requests + ... +<strong> 'django.contrib.auth.middleware.AuthenticationMiddleware',</strong> #Associates users with requests using sessions. + .... +</pre> + +<h2 id="Criando_usuários_e_grupos">Criando usuários e grupos</h2> + +<p>Você já criou seu primeiro usuário quando olhamos para o <a href="/en-US/docs/Learn/Server-side/Django/Admin_site">site Django admin</a> no tutorial 4 (este era um superusuário, criado com o comando <code>python manage.py createsuperuser)</code>. Nosso superusuário já está autenticado e tem todas as permissões, portanto, precisamos criar um usuário de teste para representar um usuário normal do site. Usaremos o site de administração para criar nossos grupos de bibliotecas de locais e logins de sites, pois é uma das maneiras mais rápidas de fazer isso.</p> + +<div class="note"> +<p><strong>Nota</strong>: Você também pode criar usuários programaticamente, conforme mostrado abaixo. Você precisaria fazer isso, por exemplo, se desenvolvesse uma interface para permitir que os usuários criassem seus próprios logins (você não deve conceder aos usuários acesso ao site de administração).</p> + +<pre class="brush: python notranslate">from django.contrib.auth.models import User + +# Create user and save to the database +user = User.objects.create_user('myusername', 'myemail@crazymail.com', 'mypassword') + +# Update fields and then save again +user.first_name = 'John' +user.last_name = 'Citizen' +user.save() +</pre> +</div> + +<p>Abaixo, primeiro criaremos um grupo e depois um usuário. Embora ainda não tenhamos permissões para adicionar aos membros da nossa biblioteca, se precisarmos mais tarde, será muito mais fácil adicioná-los uma vez ao grupo do que individualmente a cada membro.</p> + +<p>Inicie o servidor de desenvolvimento e navegue até o site de administração em seu navegador da web local (<a href="http://127.0.0.1:8000/admin/">http://127.0.0.1:8000/admin/</a>). Entre no site usando as credenciais da sua conta de superusuário. O nível superior do site Admin exibe todos os seus modelos, classificados por "aplicativo Django". Na seção <strong>Autenticação e Autorização</strong>, você pode clicar nos links <strong>Usuários </strong>ou <strong>Grupos </strong>para ver seus registros existentes.</p> + +<p><img alt="Admin site - add groups or users" src="https://mdn.mozillademos.org/files/14091/admin_authentication_add.png" style="border-style: solid; border-width: 1px; display: block; height: 364px; margin: 0px auto; width: 661px;"></p> + +<p>Primeiro vamos criar um novo grupo para os membros da nossa biblioteca.</p> + +<ol> + <li>Clique no botão <strong>Adicionar</strong> (ao lado de Grupo) para criar um novo grupo; digite o <strong>Nome</strong> "Library Members" para o grupo.<img alt="Admin site - add group" src="https://mdn.mozillademos.org/files/14093/admin_authentication_add_group.png" style="border-style: solid; border-width: 1px; display: block; height: 561px; margin: 0px auto; width: 800px;"></li> + <li>Não precisamos de permissões para o grupo, então pressione <strong>SALVAR </strong>(você será direcionado para uma lista de grupos).</li> +</ol> + +<p>Agora vamos criar um usuário:</p> + +<ol> + <li>Volte para a página inicial do site de administração</li> + <li>Clique no botão <strong>Adicionar </strong>ao lado de <em>Usuários </em>para abrir a caixa de diálogo <em>Adicionar usuário</em>.<img alt="Admin site - add user pt1" src="https://mdn.mozillademos.org/files/14095/admin_authentication_add_user_prt1.png" style="border-style: solid; border-width: 1px; display: block; height: 409px; margin: 0px auto; width: 800px;"></li> + <li>Digite um nome de <strong>usuário </strong>e uma <strong>senha/confirmação de senha</strong> adequados para o usuário de teste</li> + <li>Pressione <strong>SALVAR </strong>para criar o usuário.<br> + <br> + O site de administração criará o novo usuário e levará você imediatamente para uma tela Alterar usuário, na qual é possível alterar seu <strong>nome de usuário</strong> e adicionar informações aos campos opcionais do modelo de usuário. Esses campos incluem o nome, o sobrenome, o endereço de email e o status e as permissões do usuário (somente o sinalizador <strong>Ativo </strong>deve ser definido). Mais abaixo, você pode especificar os grupos e permissões do usuário e ver datas importantes relacionadas ao usuário (por exemplo, a data de ingresso e a última data de login).<img alt="Admin site - add user pt2" src="https://mdn.mozillademos.org/files/14097/admin_authentication_add_user_prt2.png" style="border-style: solid; border-width: 1px; display: block; height: 635px; margin: 0px auto; width: 800px;"></li> + <li>Na seção <em>Grupos</em>, selecione grupo de <strong>Library Members</strong> na lista de <em>Grupos disponíveis</em> e pressione a <strong>seta para a direita</strong> entre as caixas para movê-lo para a caixa <em>Grupos escolhidos</em>.<img alt="Admin site - add user to group" src="https://mdn.mozillademos.org/files/14099/admin_authentication_user_add_group.png" style="border-style: solid; border-width: 1px; display: block; height: 414px; margin: 0px auto; width: 933px;"></li> + <li>Não precisamos fazer mais nada aqui; basta selecionar <strong>SALVAR </strong>novamente, para ir para a lista de usuários.</li> +</ol> + +<p>É isso aí! Agora você tem uma conta de "membro normal da biblioteca" que poderá usar nos testes (depois de implementarmos as páginas para permitir o login).</p> + +<div class="note"> +<p><strong>Nota</strong>: Você deve tentar criar outro usuário membro da biblioteca. Além disso, crie um grupo para bibliotecários e adicione um usuário a ele também!</p> +</div> + +<h2 id="Configurando_suas_views_de_autenticação">Configurando suas views de autenticação</h2> + +<p>O Django fornece quase tudo que você precisa para criar páginas de autenticação para lidar com o login, logout e gerenciamento de senhas "out of the box". Isso inclui um mapeador de URL, visualizações e formulários, mas não inclui os modelos - precisamos criar os nossos!</p> + +<p>Nesta seção, mostramos como integrar o sistema padrão no site <em>LocalLibrary </em>e criar os modelos. Vamos colocá-los nos principais URLs do projeto.</p> + +<div class="note"> +<p><strong>Nota</strong>: Você não precisa usar nenhum desses códigos, mas é provável que queira, porque isso facilita muito as coisas. Você quase certamente precisará alterar o código de manipulação de formulários se alterar seu modelo de usuário (um tópico avançado!), Mas, mesmo assim, ainda poderá usar as funções padrão das views.</p> +</div> + +<div class="note"> +<p><strong>Nota: </strong>Nesse caso, poderíamos colocar razoavelmente as páginas de autenticação, incluindo os URLs e modelos, dentro do nosso aplicativo de catálogo. No entanto, se tivéssemos vários aplicativos, seria melhor separar esse comportamento de login compartilhado e disponibilizá-lo em todo o site, e é isso que mostramos aqui!</p> +</div> + +<h3 id="URLs_do_Projeto">URLs do Projeto</h3> + +<p>Adicione o seguinte à parte inferior do arquivo urls.py do projeto (<strong>locallibrary/locallibrary/urls.py</strong>):</p> + +<pre class="brush: python notranslate">#Add Django site authentication urls (for login, logout, password management) +urlpatterns += [ + path('accounts/', include('django.contrib.auth.urls')), +] +</pre> + +<p>Navegue até URL <a href="http://127.0.0.1:8000/accounts/">http://127.0.0.1:8000/accounts/</a> (observe a barra à direita!) e o Django mostrará um erro que não foi possível encontrar esse URL e listará todos os URLs que ele tentou. A partir disso, você pode ver os URLs que funcionarão, por exemplo:</p> + +<div class="note"> +<p><strong>Nota: </strong>O uso do método acima adiciona os seguintes URLs com nomes entre colchetes, que podem ser usados para reverter os mapeamentos de URL. Você não precisa implementar mais nada - o mapeamento de URL acima mapeia automaticamente os URLs mencionados abaixo.</p> + +<pre class="brush: python notranslate">accounts/ login/ [name='login'] +accounts/ logout/ [name='logout'] +accounts/ password_change/ [name='password_change'] +accounts/ password_change/done/ [name='password_change_done'] +accounts/ password_reset/ [name='password_reset'] +accounts/ password_reset/done/ [name='password_reset_done'] +accounts/ reset/<uidb64>/<token>/ [name='password_reset_confirm'] +accounts/ reset/done/ [name='password_reset_complete']</pre> +</div> + +<p>Agora tente navegar para o URL de login (<a href="http://127.0.0.1:8000/accounts/login/">http://127.0.0.1:8000/accounts/login/</a>). Isso falhará novamente, mas com um erro informando que estamos perdendo o modelo necessário (<strong>registration/login.html</strong>) no caminho de pesquisa do modelo. Você verá as seguintes linhas listadas na seção amarela na parte superior:</p> + +<pre class="brush: python notranslate">Exception Type: TemplateDoesNotExist +Exception Value: <strong>registration/login.html</strong></pre> + +<p>A próxima etapa é criar um diretório de registro no caminho de pesquisa e adicionar o arquivo <strong>login.html</strong>.</p> + +<h3 id="Diretório_de_Templates">Diretório de Templates</h3> + +<p>Os URLs (e implicitamente, visualizações) que acabamos de adicionar esperam encontrar seus modelos associados em um diretório <strong>/registration/</strong> em algum lugar no caminho de pesquisa de modelos.</p> + +<p>Neste site, colocaremos nossas páginas HTML no diretório <strong>templates/registration/</strong>. Esse diretório deve estar no diretório raiz do projeto, ou seja, o mesmo diretório que a pasta <strong>catalog</strong> e <strong>locallibrary</strong>. Por favor, crie essas pastas agora.</p> + +<div class="note"> +<p><strong>Nota:</strong> Sua estrutura de pastas agora deve se parecer como abaixo:<br> + locallibrary (Django project folder)<br> + |_catalog<br> + |_locallibrary<br> + |_templates <strong>(new)</strong><br> + |_registration</p> +</div> + +<p>Para tornar esses diretórios visíveis para o carregador de modelos (ou seja, para colocar esse diretório no caminho de pesquisa de modelos), abra as configurações do projeto (<strong>/locallibrary/locallibrary/settings.py</strong>) e atualize o seção <code>TEMPLATES</code> linha <code>'DIRS'</code> como mostrado abaixo.</p> + +<pre class="brush: python notranslate">TEMPLATES = [ + { + ... +<strong> 'DIRS': [os.path.join(BASE_DIR, 'templates')],</strong> + 'APP_DIRS': True, + ... +</pre> + +<h3 id="Template_de_login">Template de login</h3> + +<div class="warning"> +<p><strong>Importante</strong>: Os modelos de autenticação fornecidos neste artigo são uma versão muito básica/ligeiramente modificada dos modelos de login de demonstração do Django. Pode ser necessário personalizá-los para seu próprio uso!</p> +</div> + +<p>Crie um novo arquivo HTML chamado <strong>/locallibrary/templates/registration/login.html</strong> e forneça o seguinte conteúdo:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + + {% if form.errors %} + <p>Your username and password didn't match. Please try again.</p> + {% endif %} + + {% if next %} + {% if user.is_authenticated %} + <p>Your account doesn't have access to this page. To proceed, + please login with an account that has access.</p> + {% else %} + <p>Please login to see this page.</p> + {% endif %} + {% endif %} + + <form method="post" action="{% url 'login' %}"> + {% csrf_token %} + <table> + <tr> + <td>\{{ form.username.label_tag }}</td> + <td>\{{ form.username }}</td> + </tr> + <tr> + <td>\{{ form.password.label_tag }}</td> + <td>\{{ form.password }}</td> + </tr> + </table> + <input type="submit" value="login" /> + <input type="hidden" name="next" value="\{{ next }}" /> + </form> + + {# Assumes you setup the password_reset view in your URLconf #} + <p><a href="{% url 'password_reset' %}">Lost password?</a></p> + +{% endblock %}</pre> + +<p id="sect1">Este modelo compartilha algumas semelhanças com as que já vimos antes - estende nosso modelo base e substitui o bloco <code>content</code>. O restante do código é um código de manipulação de formulário bastante padrão, que discutiremos em um tutorial posterior. Por enquanto, tudo o que você precisa saber é que isso exibirá um formulário no qual é possível inserir seu nome de usuário e senha e que, se você inserir valores inválidos, será solicitado que você digite os valores corretos quando a página for atualizada.</p> + +<p>Navegue de volta para a página de login (<a href="http://127.0.0.1:8000/accounts/login/">http://127.0.0.1:8000/accounts/login/</a>). Depois de salvar seu modelo, você verá algo assim:</p> + +<p><img alt="Library login page v1" src="https://mdn.mozillademos.org/files/14101/library_login.png" style="border-style: solid; border-width: 1px; display: block; height: 173px; margin: 0px auto; width: 441px;"></p> + +<p>Se você fizer login usando credenciais válidas, será redirecionado para outra página (por padrão, isso será <a href="http://127.0.0.1:8000/accounts/profile/">http://127.0.0.1:8000/accounts/profile/</a>). O problema é que, por padrão, o Django espera que, ao fazer o login, você deseje ser levado para uma página de perfil, o que pode ou não ser o caso. Como você ainda não definiu esta página, receberá outro erro!</p> + +<p>Abra as configurações do projeto (<strong>/locallibrary/locallibrary/settings.py</strong>) e adicione o texto abaixo na parte inferior. Agora, quando você faz login, deve ser redirecionado para a página inicial do site por padrão.</p> + +<pre class="brush: python notranslate"># Redirect to home URL after login (Default redirects to /accounts/profile/) +LOGIN_REDIRECT_URL = '/' +</pre> + +<h3 id="Template_de_logout">Template de logout</h3> + +<p>Se você navegar para o URL de logout (<a href="http://127.0.0.1:8000/accounts/logout/">http://127.0.0.1:8000/accounts/logout/</a>) você verá um comportamento estranho - seu usuário será desconectado com certeza, mas será direcionado para a pagina de logout do <strong>Admin</strong>. Não é isso que você deseja, apenas porque o link de login nessa página o leva para a tela de login do administrador (e está disponível apenas para usuários que têm a permissão <code>is_staff</code>).</p> + +<p>Crie e abra /<strong>locallibrary/templates/registration/logged_out.html</strong>. Copie o texto abaixo:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + <p>Logged out!</p> + <a href="{% url 'login'%}">Click here to login again.</a> +{% endblock %}</pre> + +<p>Este modelo é muito simples. Ele apenas exibe uma mensagem informando que você foi desconectado e fornece um link que você pode pressionar para voltar à tela de login. Se você acessar o URL de logoff novamente, deverá ver esta página:</p> + +<p><img alt="Library logout page v1" src="https://mdn.mozillademos.org/files/14103/library_logout.png" style="border-style: solid; border-width: 1px; display: block; height: 169px; margin: 0px auto; width: 385px;"></p> + +<h3 id="Templates_para_reset_de_password">Templates para reset de password</h3> + +<p>O sistema de redefinição de senha padrão usa o email para enviar ao usuário um link de redefinição. Você precisa criar formulários para obter o endereço de email do usuário, enviar o email, permitir que ele insira uma nova senha e anotar quando todo o processo está completo.</p> + +<p>Os seguintes modelos podem ser usados como ponto de partida.</p> + +<h4 id="Formulário_para_reset_de_password">Formulário para reset de password</h4> + +<p>Este é o formulário usado para obter o endereço de email do usuário (para enviar o email de redefinição de senha). Crie <strong>/locallibrary/templates/registration/password_reset_form.html</strong> e forneça o seguinte conteúdo:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + <form action="" method="post"> + {% csrf_token %} + {% if form.email.errors %} + \{{ form.email.errors }} + {% endif %} + <p>\{{ form.email }}</p> + <input type="submit" class="btn btn-default btn-lg" value="Reset password"> + </form> +{% endblock %} +</pre> + +<h4 id="Password_reset_done">Password reset done</h4> + +<p>Este formulário é exibido após a coleta do seu endereço de email. Crie <strong>/locallibrary/templates/registration/password_reset_done.html</strong>, e forneça o seguinte conteúdo:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + <p>We've emailed you instructions for setting your password. If they haven't arrived in a few minutes, check your spam folder.</p> +{% endblock %} +</pre> + +<h4 id="Password_reset_email">Password reset email</h4> + +<p>Este modelo fornece o texto do email em HTML que contém o link de redefinição que enviaremos aos usuários. Crie<strong> /locallibrary/templates/registration/password_reset_email.html</strong> e forneça o seguinte conteúdo:</p> + +<pre class="brush: html notranslate">Someone asked for password reset for email \{{ email }}. Follow the link below: +\{{ protocol}}://\{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %} +</pre> + +<h4 id="Password_reset_confirm">Password reset confirm</h4> + +<p>É nesta página que você digita sua nova senha depois de clicar no link no e-mail de redefinição de senha. Crie <strong>/locallibrary/templates/registration/password_reset_confirm.html</strong> e forneça o seguinte conteúdo:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + {% if validlink %} + <p>Please enter (and confirm) your new password.</p> + <form action="" method="post"> + {% csrf_token %} + <table> + <tr> + <td>\{{ form.new_password1.errors }} + <label for="id_new_password1">New password:</label></td> + <td>\{{ form.new_password1 }}</td> + </tr> + <tr> + <td>\{{ form.new_password2.errors }} + <label for="id_new_password2">Confirm password:</label></td> + <td>\{{ form.new_password2 }}</td> + </tr> + <tr> + <td></td> + <td><input type="submit" value="Change my password" /></td> + </tr> + </table> + </form> + {% else %} + <h1>Password reset failed</h1> + <p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p> + {% endif %} +{% endblock %} +</pre> + +<h4 id="Password_reset_complete">Password reset complete</h4> + +<p>Este é o último modelo de redefinição de senha, exibido para notificá-lo quando a redefinição de senha for bem-sucedida. Crie <strong>/locallibrary/templates/registration/password_reset_complete.html</strong> e forneça o seguinte conteúdo:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + <h1>The password has been changed!</h1> + <p><a href="{% url 'login' %}">log in again?</a></p> +{% endblock %}</pre> + +<h3 id="Testando_as_novas_páginas_de_autenticação">Testando as novas páginas de autenticação</h3> + +<p>Agora que você adicionou a configuração da URL e criou todos esses modelos, as páginas de autenticação agora devem funcionar!</p> + +<p>Você pode testar as novas páginas de autenticação tentando fazer login e sair da sua conta de superusuário usando estes URLs:</p> + +<ul> + <li><a href="http://127.0.0.1:8000/accounts/login/">http://127.0.0.1:8000/accounts/login/</a></li> + <li><a href="http://127.0.0.1:8000/accounts/logout/">http://127.0.0.1:8000/accounts/logout/</a></li> +</ul> + +<p>Você poderá testar a funcionalidade de redefinição de senha no link na página de login. <strong>Esteja ciente de que o Django enviará apenas emails de redefinição para endereços (usuários) que já estão armazenados em seu banco de dados!</strong></p> + +<div class="note"> +<p><strong>Nota</strong>: O sistema de redefinição de senha exige que seu site suporte e-mail, que está além do escopo deste artigo, portanto esta parte ainda não funcionará. Para permitir o teste, coloque a seguinte linha no final do seu arquivo settings.py. Isso registra todos os emails enviados ao console (para que você possa copiar o link de redefinição de senha do console).</p> + +<pre class="brush: python notranslate">EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +</pre> + +<p>Para mais informações, veja <a href="https://docs.djangoproject.com/en/2.1/topics/email/">Sending email</a> (Django docs).</p> +</div> + +<h2 id="Testando_contra_usuários_autenticados">Testando contra usuários autenticados</h2> + +<p>Esta seção analisa o que podemos fazer para controlar seletivamente o conteúdo que o usuário vê, com base em se está logado ou não.</p> + +<h3 id="Testando_nos_templates">Testando nos templates</h3> + +<p>Você pode obter informações sobre o usuário conectado no momento em modelos com a variável de template <code>\{{ user }}</code> (isso é adicionado ao contexto do template por padrão quando você configura o projeto como fizemos em nosso esqueleto).</p> + +<p>Normalmente você primeiro testará contra a variável de template <code>\{{ user.is_authenticated }}</code> para determinar se o usuário está qualificado para ver conteúdo específico. Para demonstrar isso, em seguida, atualizaremos nossa barra lateral para exibir um link "Login" se o usuário estiver desconectado e um link "Logout" se estiverem conectados.</p> + +<p>Abra o template base (<strong>/locallibrary/catalog/templates/base_generic.html</strong>) e copie o texto a seguir no bloco <code>sidebar</code>, imediatamente antes da template tag <code>endblock</code>.</p> + +<pre class="brush: html notranslate"> <ul class="sidebar-nav"> + + ... + + <strong>{% if user.is_authenticated %}</strong> + <li>User: <strong>\{{ user.get_username }}</strong></li> + <li><a href="{% url 'logout'%}?next=\{{request.path}}">Logout</a></li> + <strong>{% else %}</strong> + <li><a href="{% url 'login'%}?next=\{{request.path}}">Login</a></li> + <strong>{% endif %} </strong> + </ul></pre> + +<p>Como você pode ver, usamos template tags <code>if</code>-<code>else</code>-<code>endif</code> para exibir condicionalmente o texto com base em <code>\{{ user.is_authenticated }}</code> ser verdadeiro. Se o usuário estiver autenticado, sabemos que temos um usuário válido, por isso chamamos <code>\{{ user.get_username }}</code><strong> </strong>para exibir o nome deles.</p> + +<p>Criamos os URLs dos links de logon e logout usando a template tag <code>url</code> e os nomes das respectivas configurações de URL. Observe também como anexamos <code>?next=\{{request.path}}</code> no final dos URLs. O que isso faz é adicionar um parâmetro de URL a seguir, contendo o endereço (URL) da página atual, ao final do URL vinculado. Após o usuário ter efetuado login/logout com sucesso, as visualizações usarão este valor "<code>next</code>" para redirecionar o usuário de volta à página em que ele clicou pela primeira vez no link de logon/logout.</p> + +<div class="note"> +<p><strong>Nota</strong>: Experimente! Se você estiver na página inicial e clicar em Login/Logout na barra lateral, depois que a operação for concluída, você deverá voltar à mesma página.</p> +</div> + +<h3 id="Testando_nas_views">Testando nas views</h3> + +<p>Se você estiver usando views baseadas em funções, a maneira mais fácil de restringir o acesso a suas funções é aplicando o decorator <code>login_required</code> à sua função view, como mostrado abaixo. Se o usuário estiver logado, seu código de exibição será executado normalmente. Se o usuário não estiver conectado, isso será redirecionado para o URL de login definido nas configurações do projeto.(<code>settings.LOGIN_URL</code>), passando o caminho absoluto atual como o <code>next</code> no parametro da URL. Se o usuário conseguir fazer login, ele retornará a esta página, mas desta vez autenticado.</p> + +<pre class="brush: python notranslate">from django.contrib.auth.decorators import login_required + +@login_required +def my_view(request): + ...</pre> + +<div class="note"> +<p><strong>Nota:</strong> Você pode fazer o mesmo tipo de coisa manualmente testando em<code>request.user.is_authenticated</code>, mas o decorator é muito mais conveniente!</p> +</div> + +<p>Da mesma forma, a maneira mais fácil de restringir o acesso a usuários logados em suas visualizações baseadas em classe é derivar de <code>LoginRequiredMixin</code>. Você precisa declarar esse mixin primeiro na lista de superclasses, antes da classe de visualização principal.</p> + +<pre class="brush: python notranslate">from django.contrib.auth.mixins import LoginRequiredMixin + +class MyView(LoginRequiredMixin, View): + ...</pre> + +<p>Isso tem exatamente o mesmo comportamento de redirecionamento que o decorator <code>login_required</code>. Você também pode especificar um local alternativo para redirecionar o usuário se ele não estiver autenticado (<code>login_url</code>), e um nome de parâmetro de URL em vez de "<code>next</code>" para inserir o caminho absoluto atual (<code>redirect_field_name</code>).</p> + +<pre class="brush: python notranslate">class MyView(LoginRequiredMixin, View): + login_url = '/login/' + redirect_field_name = 'redirect_to' +</pre> + +<p>Para detalhes adicionais, consulte o <a href="https://docs.djangoproject.com/en/2.1/topics/auth/default/#limiting-access-to-logged-in-users">Django docs here</a>.</p> + +<h2 id="Exemplo_-_listando_os_livros_do_usuário_atual">Exemplo - listando os livros do usuário atual</h2> + +<p>Agora que sabemos como restringir uma página a um usuário específico, vamos criar uma visualização dos livros que o usuário atual emprestou.</p> + +<p>Infelizmente, ainda não temos como os usuários emprestarem livros! Portanto, antes que possamos criar a lista de livros, primeiro estenderemos o modelo <code>BookInstance</code> para suportar o conceito de empréstimo e usar o aplicativo Django Admin para emprestar vários livros ao nosso usuário de teste.</p> + +<h3 id="Models">Models</h3> + +<p>Primeiro, teremos que possibilitar que os usuários tenham um <code>BookInstance</code> emprestado (já temos um <code>status</code> e uma data <code>due_back</code>, mas ainda não temos nenhuma associação entre esse modelo e um usuário. Vamos criar um usando um campo <code>ForeignKey</code> (one-to-many). Também precisamos de um mecanismo fácil para testar se um livro emprestado está vencido.</p> + +<p>Abra <strong>catalog/models.py</strong>, e importe o model <code>User</code> de <code>django.contrib.auth.models</code> (adicione isso logo abaixo da linha de importação anterior na parte superior do arquivo, para <code>User</code> estar disponível para o código subsequente que faz uso dele):</p> + +<pre class="brush: python notranslate">from django.contrib.auth.models import User +</pre> + +<p>Em seguida, adicione o campo <code>borrower</code> para o modelo <code>BookInstance</code>:</p> + +<pre class="brush: python notranslate">borrower = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) +</pre> + +<p>Enquanto estamos aqui, vamos adicionar uma propriedade que podemos chamar de nossos modelos para saber se uma instância específica de um livro está atrasada. Embora possamos calcular isso no próprio modelo, usando uma <a href="https://docs.python.org/3/library/functions.html#property">property</a> como mostrado abaixo será muito mais eficiente.</p> + +<p>Adicione isso em algum lugar perto da parte superior do arquivo:</p> + +<pre class="brush: python notranslate">from datetime import date</pre> + +<p class="brush: python">Agora adicione a seguinte definição de propriedade a classe <code>BookInstance</code>:</p> + +<pre class="brush: python notranslate">@property +def is_overdue(self): + if self.due_back and date.today() > self.due_back: + return True + return False</pre> + +<div class="note"> +<p><strong>Nota</strong>: Primeiro, verificamos se <code>due_back</code> está vazio antes de fazer uma comparação. Um campo <code>due_back</code> vazio faria com que o Django gerasse um erro em vez de mostrar a página: valores vazios não são comparáveis. Isso não é algo que gostaríamos que nossos usuários experimentassem!</p> +</div> + +<p>Agora que atualizamos nossos modelos, precisaremos fazer novas migrações no projeto e aplicá-las:</p> + +<pre class="brush: bash notranslate">python3 manage.py makemigrations +python3 manage.py migrate +</pre> + +<h3 id="Admin">Admin</h3> + +<p>Agora abra <strong>catalog/admin.py</strong>, e adicione o campo <code>borrower</code> para a classe <code>BookInstanceAdmin</code> em ambos os <code>list_display</code> e o <code>fieldsets</code> como mostrado abaixo. Isso tornará o campo visível na seção Admin, permitindo atribuir um <code>User</code> para um <code>BookInstance</code> quando necessário.</p> + +<pre class="brush: python notranslate">@admin.register(BookInstance) +class BookInstanceAdmin(admin.ModelAdmin): + list_display = ('book', 'status'<strong>, 'borrower'</strong>, 'due_back', 'id') + list_filter = ('status', 'due_back') + + fieldsets = ( + (None, { + 'fields': ('book','imprint', 'id') + }), + ('Availability', { + 'fields': ('status', 'due_back'<strong>,'borrower'</strong>) + }), + )</pre> + +<h3 id="Emprestando_alguns_livros">Emprestando alguns livros</h3> + +<p>Agora que é possível emprestar livros para um usuário específico, vá e empreste vários <code>BookInstance</code>. Defina o campo <code>borrowed</code> para o usuário de teste, faça o <code>status</code> "On loan", e defina datas de vencimento no futuro e no passado.</p> + +<div class="note"> +<p><strong>Nota</strong>: Não detalharemos o processo, pois você já sabe como usar o site Admin!</p> +</div> + +<h3 id="Na_view_loan">Na view loan</h3> + +<p>Agora, adicionaremos uma view para obter a lista de todos os livros que foram emprestados ao usuário atual. Usaremos a mesma view de lista genérica baseada em classe com a qual estamos familiarizados, mas desta vez também importaremos e derivaremos de <code>LoginRequiredMixin</code>, para que apenas um usuário conectado possa chamar essa visualização. Também optaremos por declarar um <code>template_name</code>, em vez de usar o padrão, pois podemos ter algumas listas diferentes de registros BookInstance, com diferentes visualizações e modelos.</p> + +<p>Adicione o seguinte a <strong>catalog/views.py</strong>:</p> + +<pre class="brush: python notranslate">from django.contrib.auth.mixins import LoginRequiredMixin + +class LoanedBooksByUserListView(LoginRequiredMixin,generic.ListView): + """Generic class-based view listing books on loan to current user.""" + model = BookInstance + template_name ='catalog/bookinstance_list_borrowed_user.html' + paginate_by = 10 + + def get_queryset(self): + return BookInstance.objects.filter(borrower=self.request.user).filter(status__exact='o').order_by('due_back')</pre> + +<p>Para restringir nossa consulta apenas ao objeto <code>BookInstance</code> para o usuário atual, reimplementamos <code>get_queryset()</code> como mostrado abaixo. Observe que "o" is the stored code for "on loan" (emprestado) e nós pedimos pela data <code>due_back</code> para que os itens mais antigos sejam exibidos primeiro.</p> + +<h3 id="URL_conf_para_livros_on_loan_emprestado">URL conf para livros on loan (emprestado)</h3> + +<p>Agora abra <strong>/catalog/urls.py</strong> e adicione um <code>path()</code> apontando para a visualização acima (você pode copiar o texto abaixo no final do arquivo).</p> + +<pre class="brush: python notranslate">urlpatterns += [ + path('mybooks/', views.LoanedBooksByUserListView.as_view(), name='my-borrowed'), +]</pre> + +<h3 id="Template_para_livros_on_loan_emprestado">Template para livros on loan (emprestado)</h3> + +<p>Agora, tudo o que precisamos fazer para esta página é adicionar um modelo. Primeiro, crie o arquivo de modelo <strong>/catalog/templates/catalog/bookinstance_list_borrowed_user.html</strong> e forneça o seguinte conteúdo:</p> + +<pre class="brush: python notranslate">{% extends "base_generic.html" %} + +{% block content %} + <h1>Borrowed books</h1> + + {% if bookinstance_list %} + <ul> + + {% for bookinst in bookinstance_list %} + <li class="{% if bookinst.is_overdue %}text-danger{% endif %}"> + <a href="{% url 'book-detail' bookinst.book.pk %}">\{{bookinst.book.title}}</a> (\{{ bookinst.due_back }}) + </li> + {% endfor %} + </ul> + + {% else %} + <p>There are no books borrowed.</p> + {% endif %} +{% endblock %}</pre> + +<p>Este modelo é muito semelhante ao que criamos anteriormente para os objetos <code>Book</code> e <code>Author</code>. A única coisa "nova" aqui é que verificamos o método que adicionamos no modelo <code>(bookinst.is_overdue</code>) e use-o para alterar a cor dos itens em atraso.</p> + +<p>Quando o servidor de desenvolvimento estiver em execução, agora você poderá visualizar a lista de um usuário conectado no seu navegador em <a href="http://127.0.0.1:8000/catalog/mybooks/">http://127.0.0.1:8000/catalog/mybooks/</a>. Experimente isso com o usuário conectado e desconectado (no segundo caso, você deve ser redirecionado para a página de login).</p> + +<h3 id="Adicione_a_lista_à_barra_lateral">Adicione a lista à barra lateral</h3> + +<p>O último passo é adicionar um link para esta nova página na barra lateral. Colocaremos isso na mesma seção em que exibimos outras informações para o usuário conectado.</p> + +<p>Abra o template base (<strong>/locallibrary/catalog/templates/base_generic.html</strong>) e adicione a linha em negrito à barra lateral, como mostrado.</p> + +<pre class="brush: python notranslate"> <ul class="sidebar-nav"> + {% if user.is_authenticated %} + <li>User: \{{ user.get_username }}</li> +<strong> <li><a href="{% url 'my-borrowed' %}">My Borrowed</a></li></strong> + <li><a href="{% url 'logout'%}?next=\{{request.path}}">Logout</a></li> + {% else %} + <li><a href="{% url 'login'%}?next=\{{request.path}}">Login</a></li> + {% endif %} + </ul> +</pre> + +<h3 id="Com_o_que_se_parece">Com o que se parece?</h3> + +<p>Quando qualquer usuário estiver conectado, ele verá o link <em>My Borrowed</em> na barra lateral e a lista de livros exibida abaixo (o primeiro livro não tem data de vencimento, que é um bug que esperamos corrigir em um tutorial posterior!) .</p> + +<p><img alt="Library - borrowed books by user" src="https://mdn.mozillademos.org/files/14105/library_borrowed_by_user.png" style="border-style: solid; border-width: 1px; display: block; height: 215px; margin: 0px auto; width: 530px;"></p> + +<h2 id="Permissões">Permissões</h2> + +<p>As permissões são associadas aos modelos e definem as operações que podem ser executadas em uma instância de modelo por um usuário que possui a permissão. Por padrão, o Django automaticamente fornece permissões de adição, alteração e exclusão para todos os modelos, o que permite que usuários com permissões executem as ações associadas através do site de administração. Você pode definir suas próprias permissões para modelos e concedê-las a usuários específicos. Você também pode alterar as permissões associadas a diferentes instâncias do mesmo modelo.</p> + +<p>Testar permissões nas views e templates é muito semelhante ao teste no status de autenticação (e, na verdade, testar uma permissão também testa a autenticação).</p> + +<h3 id="Models_2">Models</h3> + +<p>A definição de permissões é feita na seção "<code>class Meta</code>" do modelo, usando o campo <code>permissions</code>. Você pode especificar quantas permissões você precisar em uma tupla, cada permissão sendo definida em uma tupla aninhada que contém o nome da permissão e o valor de exibição da permissão. Por exemplo, podemos definir uma permissão para permitir que um usuário marque que um livro foi retornado como mostrado:</p> + +<pre class="brush: python notranslate">class BookInstance(models.Model): + ... + class Meta: + ... +<strong> permissions = (("can_mark_returned", "Set book as returned"),) </strong> </pre> + +<p>Poderíamos então atribuir a permissão a um grupo "Librarian" no site do administrador.</p> + +<p>Abra <strong>catalog/models.py</strong>, e adicione a permissão como mostrado acima. Você ira precisar atualizar seus <em>migrations</em> (execute <code>python3 manage.py makemigrations</code> e <code>python3 manage.py migrate</code>) para atualizar o banco de dados apropriadamente.</p> + +<h3 id="Templates">Templates</h3> + +<p>As permissões do usuário atual são armazenadas em uma variável de modelo chamada <code>\{{ perms }}</code>. Você pode verificar se o usuário atual tem uma permissão específica usando o nome da variável específica no "aplicativo" associado ao Django — e.g. <code>\{{ perms.catalog.can_mark_returned }}</code> será <code>True</code> se o usuário tiver essa permissão, caso contrário, <code>False</code>. Normalmente testamos a permissão usando a template tag <code>{% if %}</code> como mostrado:</p> + +<pre class="brush: python notranslate">{% if perms.catalog.can_mark_returned %} + <!-- We can mark a BookInstance as returned. --> + <!-- Perhaps add code to link to a "book return" view here. --> +{% endif %} +</pre> + +<h3 id="Views">Views</h3> + +<p>As permissões podem ser testadas na exibição de funções usando o decorator <code>permission_required</code> ou em uma view baseada em classe usando o <code>PermissionRequiredMixin</code>. O padrão e o comportamento são os mesmos da autenticação de login, embora, é claro, você possa razoavelmente precisar adicionar várias permissões.</p> + +<p>Função view decorator:</p> + +<pre class="brush: python notranslate">from django.contrib.auth.decorators import permission_required + +@permission_required('catalog.can_mark_returned') +@permission_required('catalog.can_edit') +def my_view(request): + ...</pre> + +<p>Um permission-required mixin para class-based views.</p> + +<pre class="brush: python notranslate">from django.contrib.auth.mixins import PermissionRequiredMixin + +class MyView(PermissionRequiredMixin, View): + permission_required = 'catalog.can_mark_returned' + # Or multiple permissions + permission_required = ('catalog.can_mark_returned', 'catalog.can_edit') + # Note that 'catalog.can_edit' is just an example + # the catalog application doesn't have such permission!</pre> + +<h3 id="Exemplo">Exemplo</h3> + +<p>Não atualizaremos a <em>LocalLibrary </em>aqui; talvez no próximo tutorial!</p> + +<h2 id="Desafie-se">Desafie-se</h2> + +<p>No início deste artigo, mostramos como criar uma página para o usuário atual, listando os livros emprestados. O desafio agora é criar uma página semelhante que seja visível apenas para bibliotecários, que exiba <em>todos </em>os livros que foram emprestados e que inclua o nome de cada mutuário.</p> + +<p>Você deve seguir o mesmo padrão da outra view. A principal diferença é que você precisará restringir a visualização apenas a bibliotecários. Você pode fazer isso com base no fato de o usuário ser um membro da equipe (decorator da função: <code>staff_member_required</code>, variável do template: <code>user.is_staff</code>) mas recomendamos que você use a permissão <code>can_mark_returned</code> e <code>PermissionRequiredMixin</code>, conforme descrito na seção anterior.</p> + +<div class="warning"> +<p><strong>Importante</strong>: Lembre-se de não usar seu superusuário para testes baseados em permissões (as verificações de permissão sempre retornam verdadeiras para os superusuários, mesmo que uma permissão ainda não tenha sido definida!). Em vez disso, crie um usuário bibliotecário e adicione o recurso necessário.</p> +</div> + +<p>Quando terminar, sua página será semelhante à captura de tela abaixo.</p> + +<p><img alt="All borrowed books, restricted to librarian" src="https://mdn.mozillademos.org/files/14115/library_borrowed_all.png" style="border-style: solid; border-width: 1px; display: block; height: 283px; margin: 0px auto; width: 500px;"></p> + +<ul> +</ul> + +<h2 id="Resumo">Resumo</h2> + +<p>Excelente trabalho — Você criou um site no qual os membros da biblioteca podem fazer login e ver seu próprio conteúdo e que os bibliotecários (com as permissões corretas) podem usar para visualizar todos os livros emprestados e seus devedores. No momento, ainda estamos apenas visualizando conteúdo, mas os mesmos princípios e técnicas são usadas quando você deseja começar a modificar e adicionar dados.</p> + +<p>Em nosso próximo artigo, veremos como você pode usar os formulários Django para coletar entradas do usuário, e então começar a modificar alguns dos nossos dados armazenados.</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/auth/">Autenticação de usuário no Django</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/auth/default//">Usando o sistema (default) de Autenticação do Django</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/class-based-views/intro/#decorating-class-based-views">Introdução a views baseadas em classe > Decorating class-based views</a> (Django docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Sessions", "Learn/Server-side/Django/Forms", "Learn/Server-side/Django")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: Website de uma Biblioteca Local</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/skeleton_website">Tutorial Django Parte 2: Criando a base do website</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Models">Tutorial Django Parte 3: Usando models</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Admin_site">Tutorial Django Parte 4: Django admin site</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Home_page">Tutorial Django Parte 5: Criando nossa página principal</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Generic_views">Tutorial Django Parte 6: Lista genérica e detail views</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Sessions">Tutorial Django Parte 7: Framework de Sessões</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Authentication">Tutorial Django Parte 8: Autenticação de Usuário e permissões</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Forms">Tutorial Django Parte 9: Trabalhando com formulários</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Testing">Tutorial Django Parte 10: Testando uma aplicação web Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Deployment">Tutorial Django Parte 11: Implantando Django em produção</a></li> + <li><a rel="nofollow" title="A página ainda não foi criada.">Segurança de aplicações web Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/forms/index.html b/files/pt-br/learn/server-side/django/forms/index.html new file mode 100644 index 0000000000..dda15b7657 --- /dev/null +++ b/files/pt-br/learn/server-side/django/forms/index.html @@ -0,0 +1,679 @@ +--- +title: 'Tutorial Django Parte 9: Trabalhando com formulários' +slug: Learn/Server-side/Django/Forms +translation_of: Learn/Server-side/Django/Forms +--- +<div> {{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/authentication_and_sessions", "Learn/Server-side/Django/Testing", "Learn/Server-side/Django")}}</div> + +<p class="summary">Neste tutorial, vamos te mostrar como trabalhar com formulários HTML no Django e, em particular, a maneira mais fácil de programar formulários para criar, alterar e excluir instâncias de modelos. Como parte desta demonstração, vamos estender o site da <a href="/pt-BR/docs/Learn/Server-side/Django/Tutorial_website_biblioteca_local">BibliotecaLocal</a> para que bibliotecários possam renovar reservas e criar, alterar e excluir autores usando nossos próprios formulários em vez do "admin" do Django.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Completar todos os tópicos anteriores deste tutorial, incluindo <a href="/en-US/docs/Learn/Server-side/Django/authentication_and_sessions">Django Tutorial Parte 8: Autenticação e Permissões de Usuário</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Entender como programar formulários para obter informações dos usuários e atualizar a base de dados. Entender como as <em>views</em> genéricas de edição de formulários baseadas em classes podem simplificar a criação de formulários para trabalhar com um único <em>model</em>.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Visão_Geral">Visão Geral</h2> + +<p>Um <a href="/pt-BR/docs/Web/Guide/HTML/Forms">Formulário HTML</a> é um grupo de um ou mais campos/<em>widgets</em> em uma página web, que podem ser utilizados para coletar informações dos usuários para submetê-las a um servidor. Formulários são um mecanismo flexível para coletar input de usuário porque há <em>widgets</em> adequados para entrada de variados tipos de dados, incluindo caixas de texto, caixas de seleção, botões radiais, seletores de data etc. Formulários são também um meio relativamente seguro de compartilhar dados com o servidor, pois nos permitem enviar dados em requisições <code>POST</code> com proteção contra ataques maliciosos <strong>CSRF</strong> (<em><strong>Cross-Site Request Forgery</strong></em> - em inglês, falsificação de solicitação entre sites).</p> + +<p>Apesar de ainda não termos criado formulários até o momento neste tutorial, já os encontramos na página do Django Admin — por exemplo, a captura de tela abaixo mostra um formulário para editar um dos nossos modelos de <a href="/pt-br/docs/Learn/Server-side/Django/Models">Livros</a>, incluindo algumas listas de seleção e editores de texto.</p> + +<p><img alt="Admin Site - Book Add" src="https://mdn.mozillademos.org/files/13979/admin_book_add.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>Trabalhar com formulários pode ser complicado! Desenvolvedores precisam escrever HTML para o formulário, validar e limpar dados submetidos ao servidor (e possivelmente também ao navegador), programar mensagens de erro no formulário para informar o usuário de quaisquer preenchimentos inválidos, lidar com os dados quando enviados com sucesso e, finalmente, mostrar ao usuário algum indicativo de sucesso. Os <em>Django Forms </em>adiantam boa parte desses passos disponibilizando uma estrutura que permite a você definir formulários e seus campos programaticamente, e então utilizar esses objetos tanto para gerar o código HTML do formulário como para cuidar de boa parte da validação e interação de usuário.</p> + +<p>Neste tutorial, vamos te mostrar alguns dos métodos para se criar e trabalhar com formulários e, em particular, como as <em>views</em> genéricas de edição de formulários podem reduzir significativamente o seu trabalho ao criar formulários para manipular seus <em>models</em>. Ao longo do caminho, vamos estender nossa aplicação <em>LocalLibrary </em>adicionando um formulário que permita que bibliotecários renovem locações de livros, e vamos construir páginas para criar, alterar e excluir livros e autores (reproduzindo uma versão básica do formulário exibido acima para alterar livros).</p> + +<h2 id="Formulários_HTML">Formulários HTML</h2> + +<p>Antes de mais nada, um breve resumo de <a href="/pt-br/docs/Learn/HTML/Forms">Formulários HTML</a>. Considere um formulário HTML simples, com um único campo de texto para entrada do nome de uma "equipe", e sua respectiva legenda:</p> + +<p><img alt="Simple name field example in HTML form" src="https://mdn.mozillademos.org/files/14117/form_example_name_field.png" style="border-style: solid; border-width: 1px; display: block; height: 44px; margin: 0px auto; width: 399px;"></p> + +<p>O formulário é definido no HTML como uma coleção de elementos dentro das tags <code><form>...</form></code>, contendo ao menos um elemento <code>input</code> do tipo <code>type="submit"</code>.</p> + +<pre class="brush: html"><form action="/team_name_url/" method="post"> + <label for="team_name">Enter name: </label> + <input id="team_name" type="text" name="name_field" value="Default name for team."> + <input type="submit" value="OK"> +</form></pre> + +<p>Apesar de aqui nós termos um único para inserir o nome da equipe, um formulário pode ter qualquer quantidade de outros elementos de entrada e suas respectivas legendas. O atributo <code>type</code> de um campo define que tipo de widget será exibido. O <code>name</code> e o <code>id</code> de cada campo são utilizados para identificá-lo no JavaScript/CSS/HTML, enquanto <code>value</code> define o valor preenchido inicialmente no campo quando ele é exibido pela primeira vez. A legenda da equipe é especificada usando a tag <code>label</code> (veja "Enter name" na imagem acima), com um atributo <code>for</code> contendo o valor de <code>id</code> do <code>input</code> a ele associado.</p> + +<p>A entrada <code>submit</code> será exibida como um botão (por padrão) que pode ser pressionado pelo usuário para enviar ao servidor os dados preenchidos em todos os outros elementos de entrada naquele formulário (neste caso, apenas <code>team_name</code>). Os atributos do formulário definem o método HTTP (<code>method</code>) utilizado para enviar os dados e o destino para esses dados no servidor (<code>action</code>):</p> + +<ul> + <li><code>action</code>: O recurso/URL para onde os dados devem ser enviados para processamento quando o formulário é enviado. Se isso não estiver configurado (ou configurado para uma string vazia), o formulário será enviado de volta para URL da página atual.</li> + <li><code>method</code>: O método HTTP method utilizado para enviar os dados: <em>post</em> or <em>get</em>. + <ul> + <li>O método <code>POST</code> deve sempre ser utilizado se os dados forem resultar em uma alteração no banco de dados do servidor, pois é mais resistente a ataques de falsificação de solicitação entre sites.</li> + <li>O método <code>GET</code> deve ser utilizado somente para formulários que não alteram dados de usuário (um formulário de busca, por exemplo). Ele é recomendado para quando você quiser poder favoritar ou compartilhar a URL.</li> + </ul> + </li> +</ul> + +<p>O papel do servidor é primeiramente carregar o estado inicial do formulário — seja contendo campos em branco ou preenchidos com valores iniciais. Após o usuário clicar no botão de envio, o servidor receberá do navegador os dados do formulário preenchido e deverá validar as informações. Se o formulário contiver dados inválidos, o servidor deverá exibir o formulário novamente, desta vez já com os valores enviados pelo usuário nos campos preenchidos corretamente, mais uma mensagem descrevendo o problema encontrado em cada campo considerado inválido. Uma vez que o servidor receber uma requisição do formulário com todos os dados válidos, poderá exercer a ação apropriada (por exemplo, salvar os dados, retornar o resultado de uma busca, subir um arquivo etc) e então notificar o usuário.</p> + +<p>Como você pode imaginar, as ações de criar o HTML, validar os dados recebidos, re-exibir os dados enviados com mensagens de erro se necessário e realizar a operação desejada com os dados válidos podem todas tomar bastante tempo e esforço. O Django torna tudo isso muito mais fácil, adiantando parte do "trabalho braçal" e código repetitivo!</p> + +<h2 id="Processo_de_manipulação_de_formulários_Django">Processo de manipulação de formulários Django</h2> + +<p>O tratamento de formulários do Django usa todas as mesmas técnicas que aprendemos nos tutoriais anteriores (para exibir informações sobre nossos modelos): a view recebe uma solicitação, executa todas as ações necessárias, incluindo a leitura de dados dos modelos, gera e retorna uma página HTML ( de um modelo, no qual passamos um <em>contexto </em>que contém os dados a serem exibidos). O que torna as coisas mais complicadas é que o servidor também precisa processar dados fornecidos pelo usuário e exibir novamente a página se houver algum erro.</p> + +<p>Um fluxograma do processo de como o Django lida com solicitações de formulário é mostrado abaixo, começando com uma solicitação para uma página contendo um formulário (mostrado em verde).</p> + +<p><img alt="Updated form handling process doc." src="https://mdn.mozillademos.org/files/14205/Form%20Handling%20-%20Standard.png" style="display: block; height: 569px; margin: 0px auto; width: 800px;"></p> + +<p>Com base no diagrama acima, as principais coisas que o manuseio de formulários do Django faz são:</p> + +<ol> + <li>Exiba o formulário padrão na primeira vez em que for solicitado pelo usuário + <ul> + <li>O formulário pode conter campos em branco (por exemplo, se você estiver criando um novo registro) ou pode ser preenchido previamente com valores iniciais (por exemplo, se você estiver alterando um registro ou tiver valores iniciais padrão úteis).</li> + <li>O formulário é referido como <em>unbound</em> neste momento, porque não está associado a nenhum dado inserido pelo usuário (embora possa ter valores iniciais).</li> + </ul> + </li> + <li>Receba dados de uma solicitação de envio e vincule-os ao formulário. + <ul> + <li>Vincular dados ao formulário significa que os dados inseridos pelo usuário e quaisquer erros estão disponíveis quando precisamos exibir novamente o formulário.</li> + </ul> + </li> + <li>Limpe e valide os dados. + <ul> + <li>A limpeza dos dados executa a higienização da entrada (por exemplo, removendo caracteres inválidos que podem ser usados para enviar conteúdo malicioso ao servidor) e os converte em tipos consistentes de Python.</li> + <li>A validação verifica se os valores são apropriados para o campo (por exemplo, estão no período certo, não são muito curtos ou muito longos etc.)</li> + </ul> + </li> + <li>Se algum dado for inválido, exiba novamente o formulário, desta vez com valores preenchidos pelo usuário e mensagens de erro para os campos problemáticos.</li> + <li>Se todos os dados forem válidos, execute as ações necessárias (por exemplo, salve os dados, envie e envie por e-mail, retorne o resultado de uma pesquisa, faça o upload de um arquivo etc.)</li> + <li>Quando todas as ações estiverem concluídas, redirecione o usuário para outra página.</li> +</ol> + +<p>O Django fornece várias ferramentas e abordagens para ajudá-lo nas tarefas detalhadas acima. O mais fundamental é a classe <code>Form</code>, o que simplifica a geração de HTML de formulário e a limpeza/validação de dados. Na próxima seção, descreveremos como os formulários funcionam usando o exemplo prático de uma página para permitir que os bibliotecários renovem os livros.</p> + +<div class="note"> +<p><strong>Nota:</strong> Entendendo como <code>Form</code> é usado para ajudá-lo quando discutirmos as classes de estrutura de formulário mais "de alto nível" do Django.</p> +</div> + +<h2 id="Renew-book_form_usando_uma_function_view">Renew-book form usando uma function view</h2> + +<p>Em seguida, adicionaremos uma página para permitir que os bibliotecários renovem os livros emprestados. Para fazer isso, criaremos um formulário que permita aos usuários inserir um valor de data. Preencheremos o campo com um valor inicial três semanas a partir da data atual (o período normal de empréstimo) e adicionaremos alguma validação para garantir que o bibliotecário não possa inserir uma data no passado ou uma data muito distante no futuro. Quando uma data válida for inserida, nós a escreveremos no registro atual no campo <code>BookInstance.due_back</code>.</p> + +<p>O exemplo usará uma function-based view e uma classe <code>Form</code>. As seções a seguir explicam como os formulários funcionam e as alterações que você precisa fazer em nosso projeto <em>LocalLibrary</em>.</p> + +<h3 id="Form">Form</h3> + +<p>A classe <code>Form</code> é o coração do sistema de manipulação de formulários do Django. Ele especifica os campos no formulário, seu layout, exibe widgets, rótulos, valores iniciais, valores válidos e (uma vez validadas) as mensagens de erro associadas a campos inválidos. A classe também fornece métodos para renderizar-se em modelos usando formatos predefinidos (tabelas, listas etc.) ou para obter o valor de qualquer elemento (habilitando a renderização manual refinada).</p> + +<h4 id="Declarando_um_Form">Declarando um Form</h4> + +<p>A sintaxe da declaração para um <code>Form</code> é muito semelhante ao da declaração de um <code>Model</code>, e compartilha os mesmos tipos de campo (e alguns parâmetros semelhantes). Isso faz sentido porque, em ambos os casos, precisamos garantir que cada campo lide com os tipos corretos de dados, seja restrito a dados válidos e tenha uma descrição para exibição/documentação.</p> + +<p>Os dados do formulário são armazenados no arquivo forms.py de um aplicativo, dentro do diretório do aplicativo. Crie e abra o arquivo <strong>locallibrary/catalog/forms.py</strong>. Para criar um <code>Form</code>, nós importamos a biblioteca <code>forms</code>, deriva da classe <code>Form</code>, e declarar os campos do formulário. Uma classe de formulário muito básica para nosso formulário de renovação de livros da biblioteca é mostrada abaixo - adicione-a ao seu novo arquivo:</p> + +<pre class="brush: python">from django import forms + +class RenewBookForm(forms.Form): + renewal_date = forms.DateField(help_text="Enter a date between now and 4 weeks (default 3).") +</pre> + +<h4 id="Campos_do_Form">Campos do Form</h4> + +<p>Nesse caso, temos um único <code><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#datefield">DateField</a></code> para inserir a data de renovação que será renderizada em HTML com um valor em branco, o valor padrão da label "<em>Renewal date:</em>", e algum texto de ajuda: "<em>Enter a date between now and 4 weeks (default 3 weeks).</em>" Como nenhum dos outros argumentos opcionais é especificado, o campo aceita datas usando o <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#django.forms.DateField.input_formats">input_formats</a>: YYYY-MM-DD (2016-11-06), MM/DD/YYYY (02/26/2016), MM/DD/YY (10/25/16), e será renderizado usando o padrão <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#widget">widget</a>: <a href="https://docs.djangoproject.com/en/2.1/ref/forms/widgets/#django.forms.DateInput">DateInput</a>.</p> + +<p>Existem muitos outros tipos de campos de formulário que você reconhecerá amplamente por sua semelhança com as classes de campo de modelo equivalentes: <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#booleanfield"><code>BooleanField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#charfield"><code>CharField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#choicefield"><code>ChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#typedchoicefield"><code>TypedChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#datefield"><code>DateField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#datetimefield"><code>DateTimeField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#decimalfield"><code>DecimalField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#durationfield"><code>DurationField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#emailfield"><code>EmailField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#filefield"><code>FileField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#filepathfield"><code>FilePathField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#floatfield"><code>FloatField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#imagefield"><code>ImageField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#integerfield"><code>IntegerField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#genericipaddressfield"><code>GenericIPAddressField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#multiplechoicefield"><code>MultipleChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#typedmultiplechoicefield"><code>TypedMultipleChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#nullbooleanfield"><code>NullBooleanField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#regexfield"><code>RegexField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#slugfield"><code>SlugField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#timefield"><code>TimeField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#urlfield"><code>URLField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#uuidfield"><code>UUIDField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#combofield"><code>ComboField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#multivaluefield"><code>MultiValueField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#splitdatetimefield"><code>SplitDateTimeField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#modelmultiplechoicefield"><code>ModelMultipleChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#modelchoicefield"><code>ModelChoiceField</code></a>.</p> + +<p>Os argumentos comuns à maioria dos campos estão listados abaixo (estes têm valores padrão sensíveis):</p> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#required">required</a>: Se <code>True</code>, o campo não pode ser deixado em branco ou receber um valor <code>None</code>. Os campos são obrigatórios por padrão, então você deve definir <code>required=False</code> para permitir valores em branco no formulário.</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#label">label</a>: O label a ser usado ao renderizar o campo em HTML. Se um <a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#label">label</a> não for especificado, o Django criará um a partir do nome do campo colocando em maiúscula a primeira letra e substituindo sublinhados por espaços (e.g. <em>Renewal date</em>).</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#label-suffix">label_suffix</a>: Por padrão, dois pontos são exibidos após o rótulo (e.g. Renewal date<strong>:</strong>). Esse argumento permite especificar um sufixo diferente contendo outros caractere(s).</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#initial">initial</a>: O valor inicial para o campo quando o formulário é exibido.</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#widget">widget</a>: O widget de exibição a ser usado.</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#help-text">help_text</a> (como visto no exemplo acima): Texto adicional que pode ser exibido em formulários para explicar como usar o campo.</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#error-messages">error_messages</a>: Uma lista de mensagens de erro para o campo. Você pode substituí-los por suas próprias mensagens, se necessário.</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#validators">validators</a>: Uma lista de funções que serão chamadas no campo quando validadas.</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#localize">localize</a>:Permite a localização da entrada de dados do formulário (consulte o link para obter mais informações).</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/#disabled">disabled</a>: O campo é exibido, mas seu valor não pode ser editado se este for <code>True</code>. O padrão é <code>False</code>.</li> +</ul> + +<h4 id="Validação">Validação</h4> + +<p>O Django fornece vários locais onde você pode validar seus dados. A maneira mais fácil de validar um único campo é substituir o método <code>clean_<strong><fieldname></strong>()</code> para o campo que você deseja verificar. Por exemplo, podemos validar esse valor inserido <code>renewal_date</code> daqui a quatro semanas, implementando <code>clean_<strong>renewal_date</strong>()</code> como mostrado abaixo.</p> + +<p>Atualize seu arquivo forms.py para ficar assim:</p> + +<pre class="brush: python"><strong>import datetime</strong> + +from django import forms +<strong>from django.core.exceptions import ValidationError +from django.utils.translation import ugettext_lazy as _ +</strong> +class RenewBookForm(forms.Form): + renewal_date = forms.DateField(help_text="Enter a date between now and 4 weeks (default 3).") + +<strong> def clean_renewal_date(self): + data = self.cleaned_data['renewal_date'] + + # Check if a date is not in the past. + if data < datetime.date.today(): + raise ValidationError(_('Invalid date - renewal in past')) + + # Check if a date is in the allowed range (+4 weeks from today). + if data > datetime.date.today() + datetime.timedelta(weeks=4): + raise ValidationError(_('Invalid date - renewal more than 4 weeks ahead')) + + # Remember to always return the cleaned data. + return data</strong></pre> + +<p>Há duas coisas importantes a serem observados. A primeira é que temos nossos dados usando <code>self.cleaned_data['renewal_date']</code> e que nós retornaremos esses dados ou não podemos alterá-lo no final da função. Este passo nos leva a dados "limpos" e higienizados de potencialmente inseguro usando os validadores de entrada padrão e convertidos para o tipo padrão correto para os dados (neste caso, um objeto Python <code>datetime.datetime</code>).</p> + +<p>O segundo ponto é que, se um valor cai fora da nossa gama que levanta um <code>ValidationError</code>, especificando o texto de erro que deseja exibir no formulário se um valor inválido for inserido. Os exemplos acima também envolvem este texto em um dos <a href="https://docs.djangoproject.com/en/2.1/topics/i18n/translation/">Django's translation functions</a> <code>ugettext_lazy()</code> (importado como <code>_()</code>), que é uma boa prática se você quiser traduzir o seu site mais tarde.</p> + +<div class="note"> +<p><strong>Nota:</strong> Existem muitos outros exemplos e métodos para validar os forms <a href="https://docs.djangoproject.com/en/2.1/ref/forms/validation/">Form e field validation</a> (Django docs). Por exemplo, nos casos em que você tem vários campos que dependem uns dos outros, você pode substituir a função <a href="https://docs.djangoproject.com/en/2.1/ref/forms/api/#django.forms.Form.clean">Form.clean()</a> e novamente levantar uma <code>ValidationError</code>.</p> +</div> + +<p>Isso é tudo que necessitamos para o form neste exemplo?</p> + +<h3 id="Configuração_da_URL">Configuração da URL</h3> + +<p>Antes de criar nossa view, vamos adicionar a configuração da URL para a pagina <em>renew-books</em>. Copie a seguinte configuração para o final do aquivo <strong>locallibrary/catalog/urls.py</strong>.</p> + +<pre class="brush: python">urlpatterns += [ + path('book/<uuid:pk>/renew/', views.renew_book_librarian, name='renew-book-librarian'), +]</pre> + +<p>A configuração da URL irá redirecionar as URLs com o formato <strong>/catalog/book/<em><bookinstance id></em>/renew/</strong> para a função chamada <code>renew_book_librarian()</code> em <strong>views.py</strong>, e enviar o id <code>BookInstance</code> como parâmetro nomeado <code>pk</code>. O padrão corresponde apenas se <code>pk</code> estiver com a formatação <code>uuid</code> correta.</p> + +<div class="note"> +<p><strong>Nota</strong>: Podemos citar nos nossos dados capturados na URL "<code>pk</code>" qualquer coisa que quisermos, porque nós temos o controle completo sobra a função view (nós não estamos usando uma view detail genérica, onde se espera os parâmetros com um certo nome). Contudo, a abreviação <code>pk</code> para "chave primária", é uma convenção razoável para uso!</p> +</div> + +<h3 id="View">View</h3> + +<p>Como discutido no <a href="#django_form_handling_process">processo de manipulação de formulários Django </a>acima, a view renderizará o formulário padrão chamado pela primeira vez e então retorná-lo com mensagens de erro se os dados forem inválidos, ou processar os dados e redirecioná-lo para uma nova página se os dados forem válidos.A fim de executar essas ações diferentes, a view deve ser capas de saber se está sendo chamada pela primeira vez para renderizar o form padrão ou um subsequente para a validação dos dados.</p> + +<p>Para forms que usam uma solicitação <code>POST</code> para enviar informações para o servidor, o padrão mais comum para a view é testar se o tipo de solicitação é <code>POST</code> (<code>if request.method == 'POST':</code>) para identificar requisições válidas de formulário e <code>GET</code> (usando uma condição <code>else</code>) para identificar a requisição de criação do form inicial. Se você deseja enviar seus dados usando uma reuquisição <code>GET</code> uma abordagem típica para identificar se é a primeira ou subsequente requisição é ler os dados do formulário (por exemplo, ler um valor oculto no form).</p> + +<p>O processo de renovação de livros será gravado em nosso banco de dados, portanto, por convenção, usamos a abordagem de requisição <code>POST</code>. O fragmento de código abaixo mostra o padrão (bem padrão) para esse tipo de exibição de função.</p> + +<pre class="brush: python">import datetime + +from django.shortcuts import render, get_object_or_404 +from django.http import HttpResponseRedirect +from django.urls import reverse + +from catalog.forms import RenewBookForm + +def renew_book_librarian(request, pk): + book_instance = get_object_or_404(BookInstance, pk=pk) + + # If this is a POST request then process the Form data +<strong> if request.method == 'POST':</strong> + + # Create a form instance and populate it with data from the request (binding): + form = RenewBookForm(request.POST) + + # Check if the form is valid: + <strong>if form.is_valid():</strong> + # process the data in form.cleaned_data as required (here we just write it to the model due_back field) + book_instance.due_back = form.cleaned_data['renewal_date'] + book_instance.save() + + # redirect to a new URL: + return HttpResponseRedirect(reverse('all-borrowed') ) + + # If this is a GET (or any other method) create the default form. +<strong> else:</strong> + proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3) + form = RenewBookForm(initial={'renewal_date': proposed_renewal_date}) + + context = { + 'form': form, + 'book_instance': book_instance, + } + + return render(request, 'catalog/book_renew_librarian.html', context)</pre> + +<p>Primeiro, importamos nosso formulário (<code>RenewBookForm</code>) e outros objetos/métodos úteis usados no corpo da função <em>view</em>:</p> + +<ul> + <li><code><a href="https://docs.djangoproject.com/en/2.1/topics/http/shortcuts/#get-object-or-404">get_object_or_404()</a></code>: Retorna um objeto especificado de um modelo com base em seu valor de chave primária, e gera uma exceção <code>Http404</code> (não encontrada) se o registro não existir. </li> + <li><code><a href="https://docs.djangoproject.com/en/2.1/ref/request-response/#django.http.HttpResponseRedirect">HttpResponseRedirect</a></code>: Isso cria um redirecionamento para uma URL especificada (código de status HTTP 302). </li> + <li><code><a href="https://docs.djangoproject.com/en/2.1/ref/urlresolvers/#django.urls.reverse">reverse()</a></code>: Isso gera uma URL a partir de uma configuração de nome de URL e um conjunto de argumentos. É o equivalente em Python da tag <code>url</code> que usamos em nossos <em>templates</em>.</li> + <li><code><a href="https://docs.python.org/3/library/datetime.html">datetime</a></code>: Uma biblioteca Python para a manipulação de dadas e tempo.</li> +</ul> + +<p>Na <em>view</em>, primeiro usamos o argumento <code>pk</code> em <code>get_object_or_404()</code> para obter o <code>BookInstance</code> atual (se isso não existir, a <em>view</em> será imediatamente encerrada e a página exibirá um erro "não encontrada"). Se essa não for uma solicitação <code>POST</code> (manipulada pela cláusula <code>else</code>) criamos o formulário padrão passando o valor <code>initial</code> para o campo <code>renewal_date</code> (como mostrado abaixo em negrito, isso é, 3 semanas a partir da data atual). </p> + +<pre class="brush: python"> book_instance = get_object_or_404(BookInstance, pk=pk) + + # If this is a GET (or any other method) create the default form + else: + proposed_renewal_date = datetime.date.today() + datetime.timedelta(<strong>weeks=3</strong>) + <strong>form = RenewBookForm(initial={'renewal_date': proposed_renewal_date})</strong> + + context = { + 'form': form, + 'book_instance': book_instance, + } + + return render(request, 'catalog/book_renew_librarian.html', context)</pre> + +<p>Depois de criar o <em>form</em>, chamamos <code>render()</code> para criar a página HTML, especificando o <em>template</em> e o <em>context</em> que contém o nosso <em>form</em>. Nesse caso, o <em>context</em> também contem nosso <code>BookInstance</code>, que usaremos no <em>template</em> para fornecer informações sobre o livro que estamos renovando.</p> + +<p>No entenato, se essa for uma solicitação <code>POST</code> , criamos nosso objeto <code>form</code> e prenchemos com dados da requisição. Esse processo é chamado <em>"binding"</em> e permite validar o formulário. Em seguida, verificamos se o formulário é válido, que executa todo o código de validação em todos os campos — incluindo o código genérico para verificar se nosso campo de data é realmente uma data válida e a função específica <code>clean_renewal_date()</code> do nosso formulário para verificar se a data está na faixa certa. </p> + +<pre class="brush: python"> book_instance = get_object_or_404(BookInstance, pk=pk) + + # If this is a POST request then process the Form data + if request.method == 'POST': + + # Create a form instance and populate it with data from the request (binding): +<strong> form = RenewBookForm(request.POST)</strong> + + # Check if the form is valid: + if form.is_valid(): + # process the data in form.cleaned_data as required (here we just write it to the model due_back field) + book_instance.due_back = form.cleaned_data['renewal_date'] + book_instance.save() + + # redirect to a new URL: + return HttpResponseRedirect(reverse('all-borrowed') ) + + context = { + 'form': form, + 'book_instance': book_instance, + } + + return render(request, 'catalog/book_renew_librarian.html', context)</pre> + +<p>Se o formulário não é válido, chamamos <code>render()</code> novamente, mas dessa vez o valor passado de <em>form</em> no <em>context</em> incluirá mensagens de erro. </p> + +<p>Se o formulário é válido, então podemos começar a utilizar os dados, acessando-o por meio do atributo<code>form.cleaned_data</code> (Ex. <code>data = form.cleaned_data['renewal_date']</code>). Aqui, apenas salvamos os dados no atributo <code>due_back</code> do objeto <code>BookInstance</code> associado.</p> + +<div class="warning"> +<p><strong>Importante</strong>: Embora você também possa acessar os dados do formulário diretamente por meio do <em>request</em> (por exemplo, <code>request.POST['renewal_date']</code> ou <code>request.GET['renewal_date']</code> se utilizando requisição GET), isso NÃO é recomendado. O dado limpo é "higienizado", validado, e convertido em tipo compatível com Python.</p> +</div> + +<p>A estapa final da manipulação de formulário na parte da <em>view</em> é redirecionar para outra página, geralmente uma página de "êxito". Nesse caso, usamos <code>HttpResponseRedirect</code> e <code>reverse()</code> para redirecionar para a <em>view </em>chamada <code>'all-borrowed'</code> (isso foi criado como desafio em <a href="/en-US/docs/Learn/Server-side/Django/authentication_and_sessions#Challenge_yourself">Tutorial Django Parte 8: Autenticação de usuário e permissões</a>). Se você não criou está página considere redirecionar para a página principal na URL '/').</p> + +<p>Isso é tudo que é necessário para a manipulação do formulario, mas ainda precisamo restringir o acesso a <em>view</em> aos bibliotecários. Provavelmente devemos criar uma nova permissão em <code>BookInstance</code> ("<code>can_renew</code>"), mas, para simplificar as coisa aqui, apenas usamos o <em>decorator </em>da função<em>, </em><code>@permission_required</code> com nossa permissão existente <code>can_mark_returned</code>.</p> + +<p>A <em>view</em> final, é portanto, como mostrado abaixo. Por favor, copie isso na parte inferior de <strong>locallibrary/catalog/views.py</strong>.</p> + +<pre><strong>import datetime + +from django.contrib.auth.decorators import permission_required</strong> +from django.shortcuts import get_object_or_404 +from django.http import HttpResponseRedirect +from django.urls import reverse + +from catalog.forms import RenewBookForm + +<strong>@permission_required('catalog.can_mark_returned')</strong> +def renew_book_librarian(request, pk): + """View function for renewing a specific BookInstance by librarian.""" + book_instance = get_object_or_404(BookInstance, pk=pk) + + # If this is a POST request then process the Form data + if request.method == 'POST': + + # Create a form instance and populate it with data from the request (binding): + form = RenewBookForm(request.POST) + + # Check if the form is valid: + if form.is_valid(): + # process the data in form.cleaned_data as required (here we just write it to the model due_back field) + book_instance.due_back = form.cleaned_data['renewal_date'] + book_instance.save() + + # redirect to a new URL: + return HttpResponseRedirect(reverse('all-borrowed') ) + + # If this is a GET (or any other method) create the default form. + else: + proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3) + form = RenewBookForm(initial={'renewal_date': proposed_renewal_date}) + + context = { + 'form': form, + 'book_instance': book_instance, + } + + return render(request, 'catalog/book_renew_librarian.html', context) +</pre> + +<h3 id="O_template">O <em>template</em></h3> + +<p>Crie o <em>template</em> mencionado na <em>view</em> (<strong>/catalog/templates/catalog/book_renew_librarian.html</strong>) e copie o código abaixo nele:</p> + +<pre class="brush: html">{% extends "base_generic.html" %} + +{% block content %} + <h1>Renew: \{{ book_instance.book.title }}</h1> + <p>Borrower: \{{ book_instance.borrower }}</p> + <p{% if book_instance.is_overdue %} class="text-danger"{% endif %}>Due date: \{{ book_instance.due_back }}</p> + +<strong> <form action="" method="post"> + {% csrf_token %} + <table> + \{{ form.as_table }} + </table> + <input type="submit" value="Submit"> + </form></strong> +{% endblock %}</pre> + +<p>A maior parte disso será totalmente familiar dos tutoriais anteriores. Estendemos o <em>template</em> base e então redefinimos o bloco <em>content</em>. Somos capazes de referenciar <code>\{{ book_instance }}</code> (e suas variáveis) porque foi passado no objeto <em>context</em> na função <code>render()</code>, e nós as usamos para listar o título do livro, tomador do empréstimo, e a data de devolução original.</p> + +<p>O código do formulário é relativamente simples. Primeiro, declaramos a tag <code>form</code>, especificando onde o formulário deve ser submetido (<code>action</code>) e o <code>method</code> para submeter os dados (nesse caso, um "HTTP POST") — se você lembrar da visão geral de <a href="#HTML_forms">Formulários HTML</a> na parte superior da página, uma <code>action</code> vazia, como mostrada, significa que os dados do formulário serão postados de volta para a URL atual da página (que é o que queremos!). Dentro das tags, definimos a entrada <code>submit</code>, que um usuário pode apertar para submeter os dados. O <code>{% csrf_token %}</code> adicionado apenas dentro das tags do formulário é parte da proteção de falsificação ente sites (cross-site forgery protection) do Django.</p> + +<div class="note"> +<p><strong>Nota:</strong> Adicione o <code>{% csrf_token %}</code> para todos os <em>templates </em>Django que você cria que utiliza <code>POST</code> para submeter dados. Isso reduzirá a chance de que os formulários sejam invadidos por usuários maliciosos.</p> +</div> + +<p>Tudo que resta é a variável <code>\{{ form }}</code> do <em>template</em>, que passamos para o <em>template</em> no dicionário <em>context</em>. Talvez, sem supresa, quando usado como mostrado, isto fornece a renderização padrão de todos os campos do formulário, incluindo seus <em>labels</em>, <em>widgets</em> e texto de ajuda — a renderização é como mostrado abaixo:</p> + +<pre class="brush: html"><tr> + <th><label for="id_renewal_date">Renewal date:</label></th> + <td> + <input id="id_renewal_date" name="renewal_date" type="text" value="2016-11-08" required> + <br> + <span class="helptext">Enter date between now and 4 weeks (default 3 weeks).</span> + </td> +</tr> +</pre> + +<div class="note"> +<p><strong>Nota:</strong> Talvez não seja óbvio porque temos apenas um campo, mas, por padrão, todo campo é definido em sua própria linha de tabela. Essa mesma renderização é fornecida se você referenciar a váriavel de <em>template</em> <code>\{{ form.as_table }}</code>.</p> +</div> + +<p>Se você fosse inserir uama data inválida, você também obteria uma lista dos erros renderizados na página (mostrado em negrito abaixo).</p> + +<pre class="brush: html"><tr> + <th><label for="id_renewal_date">Renewal date:</label></th> + <td> +<strong> <ul class="errorlist"> + <li>Invalid date - renewal in past</li> + </ul></strong> + <input id="id_renewal_date" name="renewal_date" type="text" value="2015-11-08" required> + <br> + <span class="helptext">Enter date between now and 4 weeks (default 3 weeks).</span> + </td> +</tr></pre> + +<h4 id="Outras_maneiras_de_usar_variável_de_formulário_de_template">Outras maneiras de usar variável de formulário de <em>template</em></h4> + +<p>Usando <code>\{{ form.as_table }}</code> como mostrado acima, cada campo é renderizado como uma linha da tabela. Você também pode renderizar cada campo como um item da lista (usando <code>\{{ form.as_ul }}</code> ) como um parágrafo (usando <code>\{{ form.as_p }}</code>).</p> + +<p>Também é possível ter controle completo sobre a renderização de cada parte do formulário, indexando suas propriedades usando notação de ponto. Assim, por exemplo, podemos acessar vários itens separados pelo nosso campo <code>renewal_date</code>:</p> + +<ul> + <li><code>\{{ form.renewal_date }}:</code> O campo todo.</li> + <li><code>\{{ form.renewal_date.errors }}</code>: A lista de erros.</li> + <li><code>\{{ form.renewal_date.id_for_label }}</code>: O id do <em>label</em>.</li> + <li><code>\{{ form.renewal_date.help_text }}</code>: O texto de ajuda do campo.</li> +</ul> + +<p>Para mais exemplos de como renderizar formulários manualmente em <em>templates </em>e fazer loop nos campos de <em>templates</em>, veja <a href="https://docs.djangoproject.com/en/2.1/topics/forms/#rendering-fields-manually">Trabalhando com formulários > Renderizando campos manualmente</a> (Django docs).</p> + +<h3 id="Testando_a_página">Testando a página</h3> + +<p>Se você aceitou o "desafio" em <a href="/en-US/docs/Learn/Server-side/Django/authentication_and_sessions#Challenge_yourself">Tutorial Django Parte 8: Autenticação de usuário e permissões</a> você terá uma lista de todos os livros emprestados na biblioteca, que é visível apenas aos funcionários da biblioteca. Podemos adicionar um <em>link</em> para nossa página de renovação ao lado de cada item, usando o código de modelo abaixo.</p> + +<pre class="brush: html">{% if perms.catalog.can_mark_returned %}- <a href="{% url 'renew-book-librarian' bookinst.id %}">Renew</a> {% endif %}</pre> + +<div class="note"> +<p><strong>Nota</strong>: Lembre que seu login de teste precisará ter a permissão "<code>catalog.can_mark_returned</code>" para acessar a página de renovação de livro (talvez use sua conta de superusuário).</p> +</div> + +<p>Você pode, alternativamente, construir manualmente uma URL de teste como esta — <a href="http://127.0.0.1:8000/catalog/book/<bookinstance id>/renew/">http://127.0.0.1:8000/catalog/book/<em><bookinstance_id></em>/renew/</a> (um id válido de <em>bookinstance</em> pode ser obtido navegando para a página de detalhes de um livro em sua biblioteca, e copiando o campo<code>id</code>).</p> + +<h3 id="Com_o_que_se_parece">Com o que se parece?</h3> + +<p>Se você tiver sucesso, o formulário padrão será semelhante a este:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14209/forms_example_renew_default.png" style="border-style: solid; border-width: 1px; display: block; height: 292px; margin: 0px auto; width: 680px;"></p> + +<p>O formulário com um valor inválido inserido terá a seguinte aparência:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14211/forms_example_renew_invalid.png" style="border-style: solid; border-width: 1px; display: block; height: 290px; margin: 0px auto; width: 658px;"></p> + +<p>A lista de todos os livros com o link de renovação será assim:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14207/forms_example_renew_allbooks.png" style="border-style: solid; border-width: 1px; display: block; height: 256px; margin: 0px auto; width: 613px;"></p> + +<h2 id="ModelForms">ModelForms</h2> + +<p>Criar uma classe<code>Form</code> usando a abordagem descrita acima é muito flexível, permitindo criar qualquer tipo de página de formulário que você desejar e associá-la a qualquer modelo ou modelos.</p> + +<p>Contudo, se você só precisa de um formulário para mapear os campos de um único modelo, então seu modelo já definirá a maioria das informações que vocÊ precisa em seu formulário: campos, rótulos, texto de ajuda, etc. Em vez de recriar as definições do modelo em seu formulário, é mais fácil usar a classe auxiliar <a href="https://docs.djangoproject.com/en/2.1/topics/forms/modelforms/">ModelForm</a> para criar o formulário a partir do seu modelo. Esse <code>ModelForm</code> pode ser usado em suas <em>views</em> exatamente da mesma maneira como um <code>Form</code> comum.</p> + +<p>Uma <code>ModelForm</code> contém o mesmo campo que nossa <code>RenewBookForm</code> original, como mostrado abaixo. Tudo que você precisa fazer para criar o formulário é adicionar <code>class Meta</code> com o <code>model</code> (<code>BookInstance</code>) associado e uma lista dos <code>fields</code> do modelo a serem incluídos no formulário (você pode incluir todos os campos usando <code>fields = '__all__'</code>, ou pode usar <code>exclude</code> (em vez de <code>fields</code>) para especificar os campos do modelo a não incluir).</p> + +<pre class="brush: python">from django.forms import ModelForm + +from catalog.models import BookInstance + +class RenewBookModelForm(ModelForm): +<strong> class Meta: + model = BookInstance + fields = ['due_back']</strong> +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Isso pode não parecer muito mais simples do que apenas usar um <code>Form</code> (e não é nesse caso, porque temos apenas um campo). No entanto, se você tiver muitos campos, isso pode reduzir a quantidade de código significativamente!</p> +</div> + +<p>O restante das informações vem das definições de campo do modelo (ex. rótulos, <em>widgets</em>, texdo de ajuda, mensagens de erro). Se isso não for suficiente, então podemos substituí-los em nossa <code>class Meta</code>, especificando um dicionário contendo o campo para mudar e seu novo valor. Por exemplo, neste formulário podemos querer um rótulo para nosso campo de "<em>Renewal date</em>" (em vez do padrão baseado no padrão com base no nome do campo: <em>Due Back</em>), e também queremos que nosso campo de ajuda seja específico para esse caso de uso. A <code>Meta</code> abaixo mostra como substituir esses campos, e você pode definir <code>widgets</code> and <code>error_messages</code> da mesma forma, se os padrões não forem suficientes.</p> + +<pre class="brush: python">class Meta: + model = BookInstance + fields = ['due_back'] +<strong> labels = {'due_back': _('New renewal date')} + help_texts = {'due_back</strong><strong>': _('Enter a date between now and 4 weeks (default 3).')} </strong> +</pre> + +<p>Para adicionar validação você pode usar a mesma abordagem como uma <code>Form</code> normal — você define uma função chamada <code>clean_<em>field_name</em>()</code> e <em>raise</em> a exceção <code>ValidationError</code> para valores inválidos. A única diferença em relação ao nosso <em>form </em>original é que o campo do modelo é chamdo <code>due_back</code> e não "<code>renewal_date</code>". Essa mudança é necessária pois o campo correspondente em <code>BookInstance</code> é chamado <code>due_back</code>. </p> + +<pre class="brush: python">from django.forms import ModelForm + +from catalog.models import BookInstance + +class RenewBookModelForm(ModelForm): +<strong> def clean_due_back(self): + data = self.cleaned_data['due_back</strong><strong>'] + + # Check if a date is not in the past. + if data < datetime.date.today(): + raise ValidationError(_('Invalid date - renewal in past')) + + <strong># Check if a date is in the allowed range (+4 weeks from today).</strong> + if data > datetime.date.today() + datetime.timedelta(weeks=4): + raise ValidationError(_('Invalid date - renewal more than 4 weeks ahead')) + + # Remember to always return the cleaned data. + return data +</strong> + class Meta: + model = BookInstance + fields = ['due_back'] + labels = {'due_back': _('Renewal date')} + help_texts = {'due_back': _('Enter a date between now and 4 weeks (default 3).')} +</pre> + +<p>A classe <code>RenewBookModelForm</code> acima agora é funcionalmente equivalente a nossa original <code>RenewBookForm</code>. Você poderia importar e usar onde quer que você use <code>RenewBookForm</code> desde que você também atualize o nome da variável do formulário correspondente de <code>renewal_date</code> para <code>due_back</code> como na segunda declaração do formulário: <code>RenewBookModelForm(initial={'due_back': proposed_renewal_date}</code>.</p> + +<h2 id="Views_genéricas_de_edição">Views genéricas de edição</h2> + +<p>O algoritmo de manipulação de formulários que usamos em nosso exemplo de função <em>view</em> acima, representa um padrão extremamente comum nas <em>views</em> de edição de formulário. Django abstrai grande parte desse "<em>boilerplate</em>" (trabalho repetitivo) para você, criando <a href="https://docs.djangoproject.com/en/2.1/ref/class-based-views/generic-editing/">views genéricas de edição</a> para views de criação, edição e exclusão baseadas em modelos. Não apenas lidam com o comportamento de visualização, mas também criam automaticamente para você a classe de formulário (uma <code>ModelForm</code>) a partir do modelo.</p> + +<div class="note"> +<p><strong>Nota: </strong>Além das <em>views</em> de edição descritas aqui, há também uma classe <a href="https://docs.djangoproject.com/en/2.1/ref/class-based-views/generic-editing/#formview">FormView</a>, que fica em algum lugar entre nossa função <em>view</em> e outra <em>view</em> genérica em termos de "flexibilidade" vs "esforço de codificação". Usando <code>FormView</code>, você ainda precisa criar seu <code>Form</code>, mas não precisa implementar todos os padrões de manipulação de formulário. Em vez disso, você tem apenas que fornecer uma implementação da função que será chamada assim que o envio for válido.</p> +</div> + +<p>Nessa seção vamos usar <em>views</em> genericas de edição para criar páginas para adicionar funcionalidades para criar, editar e excluir registros de <code>Author</code> da nossa biblioteca — fornecendo efetivamente uma reimplementação básica de parte do site <em>Admin</em> (isso poderá ser útil se você precisa oferecer funcionalidades de administrador de uma maneira mais flexível que possa ser fornecida pelo dite <em>Admin</em>).</p> + +<h3 id="Views"><em>Views</em></h3> + +<p>Abra o arquivo das <em>views</em> (<strong>locallibrary/catalog/views.py</strong>) e acrescente o seguinte bloco de código na parte inferior:</p> + +<pre class="brush: python">from django.views.generic.edit import CreateView, UpdateView, DeleteView +from django.urls import reverse_lazy + +from catalog.models import Author + +class AuthorCreate(CreateView): + model = Author + fields = '__all__' + initial = {'date_of_death': '05/01/2018'} + +class AuthorUpdate(UpdateView): + model = Author + fields = ['first_name', 'last_name', 'date_of_birth', 'date_of_death'] + +class AuthorDelete(DeleteView): + model = Author + success_url = reverse_lazy('authors')</pre> + +<p>Como você pode ver, para criar, atualizar e excluir as <em>views</em>, você precisa derivar de <code>CreateView</code>, <code>UpdateView</code>, e <code>DeleteView</code> (respectivamente) e então definir o modelo associado.</p> + +<p>Para os casos "criar" e "atualizar" você também precisa especificar os campos para mostrar no formulário (usando a mesma sintaxe que para <code>ModelForm</code>). Nesse caso, nós mostramos ambas as sintaxes para mostrar todos (<em>"all"</em>) campos e como você pode listar eles individualmente. Você também pode especificar valores iniciais para cada campo usando um dicionário com pares nome_campo/valor (aqui, arbitrariamente, definimos a data de morte para fins de demonstração — talvez você queira remover isso!). Por padrão, essas <em>views</em> irão redirecionar, se houver sucesso, para uma página mostrando o item do modelo recentemente criado/editado, que no nosso caso será a página de visualização de detalhes do autor que criamos em um tutorial anterior. Você pode especificar ums local de redirecionamento alternativo, declarando explicitamente o parâmetro <code>success_url</code> (como feito na classe <code>AuthorDelete</code>).</p> + +<p>A classe <code>AuthorDelete</code> não precisa mostrar nenhum dos campos, então eles não precisam ser especificados. No entanto, você precisa especificar a <code>success_url</code>, porque não há um valor padrão óbvio para o Django usar. Nesse caso, usamos a função <code><a href="https://docs.djangoproject.com/en/2.1/ref/urlresolvers/#reverse-lazy">reverse_lazy()</a></code> para redirecioanr para nossa lista de autores depois que um autor é excluido — <code>reverse_lazy()</code> é uma versão executada "preguiçosamente" de <code>reverse()</code>, usada aqui porque estamos fornecendo uma URL para um atributo baseado em classe de <em>view</em>.</p> + +<h3 id="Templates"><em>Templates</em></h3> + +<p>As <em>views</em> "<em>create</em>" e "<em>update</em>" usam o mesmo <em>template</em> por padrão, que serão nomeadas seguindo o modelo: <em>model_name</em><strong>_form.html</strong> (você pode mudar o sufixo para algo diferente de <strong>_form</strong> usando o campo <code>template_name_suffix</code> em sua <em>view</em>, ex. <code>template_name_suffix = '_other_suffix'</code>)</p> + +<p>Crie o arquivo de <em>template </em><strong>locallibrary/catalog/templates/catalog/author_form.html</strong> e copie o texto abaixo.</p> + +<pre class="brush: html">{% extends "base_generic.html" %} + +{% block content %} + <form action="" method="post"> + {% csrf_token %} + <table> + \{{ form.as_table }} + </table> + <input type="submit" value="Submit"> + </form> +{% endblock %}</pre> + +<p>Isso é semelhante aos nossos formulários anteriores e renderiza os campos usando uma tabela. Note também como novamente declaramos o <code>{% csrf_token %}</code> para garantir que nossos formulários são resistentes a ataques CSRF.</p> + +<p>A <em>view</em> "delete" espera encontrar um <em>template</em> nomeado com o formato <em>model_name</em><strong>_confirm_delete.html</strong> (novamente, você pode mudar o sufixo usando <code>template_name_suffix</code> em sua <em>view</em>). Crie o arquivo de <em>template</em> <strong>locallibrary/catalog/templates/catalog/author_confirm_delete</strong><strong>.html</strong> e copie o texto abaixo.</p> + +<pre class="brush: html">{% extends "base_generic.html" %} + +{% block content %} + +<h1>Delete Author</h1> + +<p>Are you sure you want to delete the author: \{{ author }}?</p> + +<form action="" method="POST"> + {% csrf_token %} + <input type="submit" value="Yes, delete."> +</form> + +{% endblock %} +</pre> + +<h3 id="URL_configurations">URL configurations</h3> + +<p>Abra seu arquivo de configuração de URL (<strong>locallibrary/catalog/urls.py</strong>) e adicione a seguinte configuração no final do arquivo:</p> + +<pre class="brush: python">urlpatterns += [ + path('author/create/', views.AuthorCreate.as_view(), name='author_create'), + path('author/<int:pk>/update/', views.AuthorUpdate.as_view(), name='author_update'), + path('author/<int:pk>/delete/', views.AuthorDelete.as_view(), name='author_delete'), +]</pre> + +<p>Não há nada particularmente novo aqui! Você pode ver que as <em>views</em> são classes, e portanto devem ser chamadas via <code>.as_view()</code>, e você deve poder reconhecer os padrões URL em cada caso. Devemos usar <code>pk</code> como o nome para nosso valor capturado de chave primária (<em>primary key</em>), como esse é o nome do parâmetro esperado pelas classes <em>view</em>.</p> + +<p>As páginas de criação, atualização e remoção de autor agora estão prontas para teste (neste caso, não nos incomodaremos em conectá-las a barra lateral do site, embora você possa fazer se desejar).</p> + +<div class="note"> +<p><strong>Nota</strong>: Usuários observadores devem ter notado que não fizemos nada para previnir que usuários não autorizadosde acessem as páginas! Deixamos isso como um exercício para você (dica: você pode usar <code>PermissionRequiredMixin</code> e criar uma nova permissão ou reutilizar nossa permissão <code>can_mark_returned</code>).</p> +</div> + +<h3 id="Testando_a_página_2">Testando a página</h3> + +<p>Primeiro, efetue login no site com uma conta que possua as permissões que você decidiu que são necessárias para acessar a página de edição de autor.</p> + +<p>Então navegue para a página de criação de autor: <a href="http://127.0.0.1:8000/catalog/author/create/">http://127.0.0.1:8000/catalog/author/create/</a>, que deve parecer como a captura de tela abaixo.</p> + +<p><img alt="Form Example: Create Author" src="https://mdn.mozillademos.org/files/14223/forms_example_create_author.png" style="border-style: solid; border-width: 1px; display: block; height: 184px; margin: 0px auto; width: 645px;"></p> + +<p>Entre com valores para os campos e então pressione <strong>Submit</strong> para dalvar o registro de autor. Você agora deve ser direcionado para uma visualização detalhada para o seu novo autor, com uma URL de algo como <em>http://127.0.0.1:8000/catalog/author/10</em>.</p> + +<p>Você pode testar edição de registros enexando <em>/update/</em> ao final da URL da página de detalhe (ex. <em>http://127.0.0.1:8000/catalog/author/10/update/</em>) — não mostramos uma captura de tela, porque se parace com a página de criação</p> + +<p>Finalmente, podemos excluir a página anexando <em>delete</em> ao final da URL da visualização detalhada do autor (ex. <em>http://127.0.0.1:8000/catalog/author/10/delete/</em>). Django deve exibir a página de exclusão mostrada abaixo. Pressione <strong>Yes, delete.</strong> para remover o registro e ser levado para a lista de todos os autores.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14221/forms_example_delete_author.png" style="border-style: solid; border-width: 1px; display: block; height: 194px; margin: 0px auto; width: 561px;"></p> + +<h2 id="Desafie-se">Desafie-se</h2> + +<p>Crie alguns <em>forms</em> para criar, editar e excluir registros de <code>Book</code>. Você pode utilizar exatamente a mesma estrutura que a de <code>Authors</code>. Se seu <em>template</em> <strong>book_form.html</strong> é apenas uma cópia renomeada de <strong>author_form.html</strong> , então a nova página "criar livro" será semelhante a captura de tela abaixo:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14225/forms_example_create_book.png" style="border-style: solid; border-width: 1px; display: block; height: 521px; margin: 0px auto; width: 595px;"></p> + +<ul> +</ul> + +<h2 id="Resumo">Resumo</h2> + +<p>Criar e manipular formulários pode ser um processo complicado! Django torna muito mais fácil fornecendo mecanismos programáticos para declarar, renderizar e validar formulários. Além disso, Django fornece <em>views</em> genéricas de edição de formulário, isso pode fazes quase todo trabalho para definir páginas que podem criar, editar e excluir registros associados com uma única instância de <em>model.</em></p> + +<p>Há muito mais que pode ser feito com formulários (confira abaixo nossa lista Veja também), mas agora você deve entender como adicionar formulários básicos e o código de manipulação de formulários para seus próprios websites.</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/forms/">Trabalhando com formulários</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/intro/tutorial04/#write-a-simple-form">Escrevendo seu primeiro <em>app</em> Django, parte 4 > Escrevendo um formulário simples</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/api/">A API <em>Forms</em></a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/fields/">Form fields</a> (Django docs) </li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/forms/validation/">Formulários e validação de campos</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/class-based-views/generic-editing/">Manipulação de formulários com <em>views</em> baseadas em classe</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/forms/modelforms/">Criando formulários com <em>models</em></a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/class-based-views/generic-editing/">Views genéricas de edição</a> (Django docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/authentication_and_sessions", "Learn/Server-side/Django/Testing", "Learn/Server-side/Django")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: </a><a rel="nofollow" title="A página ainda não foi criada.">Website de uma Biblioteca Local</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Django Parte 2: </a><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/skeleton_website">Criando a base do website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Models">Django Parte 3: Usando <em>models</em></a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Admin_site">Django Parte 4: Django admin site</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Home_page">Django Parte 5: Criando nossa página principal</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Generic_views">Django Parte 6: </a><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Generic_views">Lista genérica e <em>detail views</em></a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Sessions">Django Parte 7: </a><a rel="nofollow" title="A página ainda não foi criada.">Framework de Sessões</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Authentication">Django Parte 8: </a><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Authentication">Autenticação de Usuário e permissões</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Forms">Django Parte 9: </a><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Forms">Trabalhando com formulários</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Testing">Django Parte 10: </a><a rel="nofollow" title="A página ainda não foi criada.">Testando uma aplicação web Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Deployment">Django Parte 11: </a><a rel="nofollow" title="A página ainda não foi criada.">Implantando Django em produção</a></li> + <li><a rel="nofollow" title="A página ainda não foi criada.">Segurança de aplicações web Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/generic_views/index.html b/files/pt-br/learn/server-side/django/generic_views/index.html new file mode 100644 index 0000000000..f5a176b192 --- /dev/null +++ b/files/pt-br/learn/server-side/django/generic_views/index.html @@ -0,0 +1,617 @@ +--- +title: 'Tutorial Django Parte 6: Lista genérica e detail views' +slug: Learn/Server-side/Django/Generic_views +translation_of: Learn/Server-side/Django/Generic_views +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Home_page", "Learn/Server-side/Django/Sessions", "Learn/Server-side/Django")}}</div> + +<p class="summary">Este tutorial estende nosso website <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a>, adicionando páginas de lista e detalhes para livros e autores. Aqui, aprenderemos sobre visualizações genéricas baseadas em classe e mostraremos como elas podem reduzir a quantidade de código que você precisa escrever para casos de uso comuns. Também abordaremos o tratamento de URLs em mais detalhes, mostrando como executar a correspondência básica de padrões.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conclua todos os tópicos do tutorial anterior, incluindo <a href="/pt-br/docs/Learn/Server-side/Django/Home_page">Django Tutorial Part 5: Creating our home page</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Para entender onde e como usar modos de exibição genéricos baseados em classe e como extrair padrões de URLs e passar as informações para modos de exibição.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_global">Visão global</h2> + +<p>Neste tutorial, vamos concluir a primeira versão do website <a href="https://developer.mozilla.org/pt-br/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a> adicionando páginas de lista e detalhes de livros e autores (ou, para ser mais preciso, mostraremos como implementar as páginas do livro e você mesmo irá criar as páginas dos autores!)</p> + +<p>O processo é semelhante à criação da página index, que mostramos no tutorial anterior. Ainda precisamos criar mapas de URL, views e templates. A principal diferença é que, para as páginas de detalhes, teremos o desafio adicional de extrair informações de padrões no URL e passá-las para a visualização. Para essas páginas, demonstraremos um tipo de exibição completamente diferente: lista genérica baseada em classe e exibições detalhadas. Isso pode reduzir significativamente a quantidade de código de visualização necessária, facilitando a gravação e a manutenção.</p> + +<p>A parte final do tutorial demonstrará como paginar seus dados ao usar visualizações de lista genéricas baseadas em classe.</p> + +<h2 id="Book_list_page">Book list page</h2> + +<p>A página da lista de livros exibirá uma lista de todos os registros de livros disponíveis na página, acessados usando o URL: <code>catalog/books/</code>. A página exibirá um título e um autor para cada registro, com o título sendo um hiperlink para a página de detalhes do livro associada. A página terá a mesma estrutura e navegação que todas as outras páginas do site e, portanto, podemos estender o modelo base (<strong>base_generic.html</strong>) que criamos no tutorial anterior.</p> + +<h3 id="URL_mapping">URL mapping</h3> + +<p>Abra <strong>/catalog/urls.py</strong> e copie na linha mostrada em negrito abaixo. Quanto à página index, a função <code>path()</code> define um padrão para corresponder ao URL (<strong>'books/'</strong>), a função view que será chamado se o URL corresponder (<code>views.BookListView.as_view()</code>), e um nome para esse mapeamento específico.</p> + +<pre class="brush: python notranslate">urlpatterns = [ + path('', views.index, name='index'), +<strong> </strong>path<strong>('books/', views.BookListView.as_view(), name='books'),</strong> +]</pre> + +<p>Conforme discutido no tutorial anterior, o URL já deve ter correspondencia <code>/catalog</code>, então a visualização será realmente chamada para o URL: <code>/catalog/books/</code>.</p> + +<p>A função view tem um formato diferente do que antes - é porque essa view será realmente implementada como uma classe. Herdaremos de uma função view genérica existente que já faz a maior parte do que queremos que essa função view faça, em vez de escrever a nossa a partir do zero.</p> + +<p>Para as class-based views do Django, acessamos uma função de visualização apropriada chamando o método de classe <code>as_view()</code>. Isso faz todo o trabalho de criar uma instância da classe e garantir que os métodos do manipulador certo sejam chamados para solicitações HTTP recebidas.</p> + +<h3 id="View_class-based">View (class-based)</h3> + +<p>Poderíamos escrever com facilidade a view da lista de livros como uma função regular (assim como a view index anterior), que consultaria todos os livros no banco de dados e depois chamaria <code>render()</code> para passar a lista para um modelo especificado. No entanto, usaremos uma view de lista genérica class-based (<code>ListView</code>) — uma classe que herda de uma view existente. Como a view genérica já implementa a maioria das funcionalidades necessárias e segue as práticas recomendadas do Django, poderemos criar uma exibição de lista mais robusta com menos código, menos repetições e, finalmente, menos manutenção.</p> + +<p>Abra <strong>catalog/views.py</strong>, e copie o seguinte código na parte inferior do arquivo:</p> + +<pre class="brush: python notranslate">from django.views import generic + +class BookListView(generic.ListView): + model = Book</pre> + +<p>É isso aí! A view genérica consultará o banco de dados para obter todos os registros para o modelo especificado (<code>Book</code>) em seguida, renderize um template localizado em <strong>/locallibrary/catalog/templates/catalog/book_list.html</strong> (que criaremos abaixo). Dentro do template, você pode acessar a lista de livros com a variável de template denominada <code>object_list</code> OU <code>book_list</code> (i.e. genericamente "<code><em>the_model_name</em>_list</code>").</p> + +<div class="note"> +<p><strong>Nota</strong>: Esse caminho estranho para a localização do template não é um erro de impressão - as visualizações genéricas procuram modelos em <code>/<em>application_name</em>/<em>the_model_name</em>_list.html</code> (<code>catalog/book_list.html</code> nesse caso) dentro do aplicativo <code>/<em>application_name</em>/templates/</code> diretório (<code>/catalog/templates/)</code>.</p> +</div> + +<p>Você pode adicionar atributos para alterar o comportamento padrão acima. Por exemplo, você pode especificar outro arquivo do template se precisar ter várias visualizações que usem esse mesmo modelo ou se desejar usar um nome de variável de template diferente se <code>book_list</code> não é intuitivo para o seu caso de uso de template específico. Possivelmente, a variação mais útil é alterar/filtrar o subconjunto de resultados retornados - portanto, em vez de listar todos os livros, você pode listar os cinco principais livros que foram lidos por outros usuários.</p> + +<pre class="brush: python notranslate">class BookListView(generic.ListView): + model = Book + context_object_name = 'my_book_list' # your own name for the list as a template variable + queryset = Book.objects.filter(title__icontains='war')[:5] # Get 5 books containing the title war + template_name = 'books/my_arbitrary_template_name_list.html' # Specify your own template name/location</pre> + +<h4 id="Substituindo_métodos_em_class-based_views">Substituindo métodos em class-based views</h4> + +<p>Embora não precisemos fazer isso aqui, você também pode substituir alguns dos métodos da classe.</p> + +<p>Por exemplo, podemos substituir o método <code>get_queryset()</code> para alterar a lista de registros retornados. Isso é mais flexível do que apenas definir o atributo <code>queryset</code> como fizemos no fragmento de código anterior (embora não haja nenhum benefício real neste caso):</p> + +<pre class="brush: python notranslate">class BookListView(generic.ListView): + model = Book + + def get_queryset(self): + return Book.objects.filter(title__icontains='war')[:5] # Get 5 books containing the title war +</pre> + +<p>Também podemos substituir <code>get_context_data()</code> para passar variáveis de contexto adicionais para o template (por exemplo, a lista de livros é passada por padrão). O fragmento abaixo mostra como adicionar uma variável chamada "<code>some_data</code>" para o contexto (estaria disponível como uma variável de template).</p> + +<pre class="brush: python notranslate">class BookListView(generic.ListView): + model = Book + + def get_context_data(self, **kwargs): + # Call the base implementation first to get the context + context = super(BookListView, self).get_context_data(**kwargs) + # Create any data and add it to the context + context['some_data'] = 'This is just some data' + return context</pre> + +<p>Ao fazer isso, é importante seguir o padrão usado acima:</p> + +<ul> + <li>Primeiro obtenha o contexto existente da nossa superclasse.</li> + <li>Em seguida, adicione as novas informações de contexto.</li> + <li>Em seguida, retorne o novo contexto (atualizado).</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Confira <a href="https://docs.djangoproject.com/pt-br/2.1/topics/class-based-views/generic-display/">Built-in class-based generic views</a> (Django docs) para muitos mais exemplos do que você pode fazer.</p> +</div> + +<h3 id="Criando_o_template_List_View">Criando o template List View</h3> + +<p>Crie o arquivo HTML <strong>/locallibrary/catalog/templates/catalog/book_list.html</strong> e copie o texto abaixo. Como discutido acima, este é o arquivo de template padrão esperado pela list view genérica da class-based view (para um modelo chamado <code>Book</code> em um aplicativo chamado <code>catalog</code>).</p> + +<p>Os templates para visualizações genéricas são como qualquer outro template (<em>embora</em>, é claro, o contexto/informações passadas para o template possam ser diferentes). Assim como em nosso template <em>index</em>, estendemos nosso template base na primeira linha e substituímos o bloco denominado <code>content</code>.</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + <h1>Book List</h1> + <strong>{% if book_list %}</strong> + <ul> + {% for book in book_list %} + <li> + <a href="\{{ book.get_absolute_url }}">\{{ book.title }}</a> (\{{book.author}}) + </li> + {% endfor %} + </ul> + <strong>{% else %}</strong> + <p>There are no books in the library.</p> + <strong>{% endif %} </strong> +{% endblock %}</pre> + +<p>A view passa o contexto (lista de livros), por padrão, um <code>object_list</code> e <code>book_list</code> aliases; qualquer um funcionará.</p> + +<h4 id="Execução_conditional">Execução conditional</h4> + +<p>Nós usamos o <code><a href="https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#if">if</a></code>, <code>else</code>, e <code>endif</code> template tags para verificar se o <code>book_list</code> foi definido e não está vazio. E se <code>book_list</code> está vazio, então a cláusula <code>else</code> exibe o texto explicando que não há livros para listar. E se <code>book_list</code> não estiver vazio, percorreremos a lista de livros.</p> + +<pre class="brush: html notranslate"><strong>{% if book_list %}</strong> + <!-- code here to list the books --> +<strong>{% else %}</strong> + <p>There are no books in the library.</p> +<strong>{% endif %}</strong> +</pre> + +<p>A condição acima verifica apenas um caso, mas você pode testar em condições adicionais usando a template tag <code>elif</code> (e.g. <code>{% elif var2 %}</code>). Para obter mais informações sobre operadores condicionais, consulte: <a href="https://docs.djangoproject.com/pt-br/2.1/ref/templates/builtins/#if">if</a>, <a href="https://docs.djangoproject.com/pt-br/2.1/ref/templates/builtins/#ifequal-and-ifnotequal">ifequal/ifnotequal</a>, e <a href="https://docs.djangoproject.com/pt-br/2.1/ref/templates/builtins/#ifchanged">ifchanged</a> em <a href="https://docs.djangoproject.com/pt-br/2.1/ref/templates/builtins">Built-in template tags and filters</a> (Django Docs).</p> + +<h4 id="For_loops">For loops</h4> + +<p>O template usa as template tags <a href="https://docs.djangoproject.com/pt-br/2.1/ref/templates/builtins/#for">for</a> e <code>endfor</code> para percorrer a lista de livros, como mostrado abaixo. Cada iteração preenche a variável de template <code>book</code> com informações para o item da lista atual.</p> + +<pre class="brush: html notranslate">{% for <strong>book</strong> in book_list %} + <li> <!-- code here get information from each <strong>book</strong> item --> </li> +{% endfor %} +</pre> + +<p>Embora não seja usado aqui, dentro do loop, o Django também criará outras variáveis que você pode usar para rastrear a iteração. Por exemplo, você pode testar a variável <code>forloop.last</code> para executar o processamento condicional na última vez em que o loop é executado.</p> + +<h4 id="Acessando_variáveis">Acessando variáveis</h4> + +<p>O código dentro do loop cria um item de lista para cada livro que mostra o título (como um link para a exibição de detalhes ainda a ser criada) e o autor.</p> + +<pre class="brush: html notranslate"><a href="\{{ book.get_absolute_url }}">\{{ book.title }}</a> (\{{book.author}}) +</pre> + +<p>Acessamos os <em>campos </em>do registro de livro associado usando a "notação de ponto" (e.g. <code>book.title</code> e <code>book.author</code>), onde o texto após o item <code>book</code> é o nome do campo (conforme definido no modelo).</p> + +<p>Também podemos chamar <em>funções </em>no modelo de dentro do nosso template - nesse caso, chamamos <code>Book.get_absolute_url()</code> para obter um URL que você pode usar para exibir o registro de detalhe associado. Isso funciona desde que a função não tenha argumentos (não há como passar argumentos!)</p> + +<div class="note"> +<p><strong>Nota</strong>: Temos que ter um pouco de cuidado com os "efeitos colaterais" ao chamar funções em templates. Aqui apenas exibimos um URL, mas uma função pode fazer praticamente qualquer coisa - não queremos excluir nosso banco de dados (por exemplo) apenas renderizando nosso template!</p> +</div> + +<h4 id="Atualize_o_template_base">Atualize o template base</h4> + +<p>Abra o template base (<strong>/locallibrary/catalog/templates/<em>base_generic.html</em></strong>) e insira <strong>{% url 'books' %} </strong>no link da URL para <strong>All books</strong>,como mostrado abaixo. Isso habilitará o link em todas as páginas (podemos colocá-lo em prática agora que criamos o mapeador de URL "books").</p> + +<pre class="brush: python notranslate"><li><a href="{% url 'index' %}">Home</a></li> +<strong><li><a href="{% url 'books' %}">All books</a></li></strong> +<li><a href="">All authors</a></li></pre> + +<h3 id="Com_o_que_se_parece">Com o que se parece?</h3> + +<p>Ainda não será possível criar a lista de livros, porque ainda falta uma dependência - o mapa de URL para as páginas de detalhes do livro, necessário para criar hiperlinks para livros individuais. Mostraremos as visualizações de lista e de detalhes após a próxima seção.</p> + +<h2 id="Pagina_Book_detail">Pagina Book detail</h2> + +<p>A página book detail exibirá informações sobre um livro específico, acessado usando o URL <code>catalog/book/<em><id></em></code> (onde <code><em><id></em></code> é a chave primária do livro). Além dos campos no model <code>Book</code> (author, summary, ISBN, language, e genre), também listaremos os detalhes das cópias disponíveis (<code>BookInstances</code>) incluindo o status, data prevista de retorno, impressão e ID. Isso permitirá que nossos leitores não apenas saibam sobre o livro, mas também confirmem se/quando ele está disponível.</p> + +<h3 id="URL_mapping_2">URL mapping</h3> + +<p>Abra <strong>/catalog/urls.py</strong> e adicione a URL '<strong>book-detail</strong>' mostrado em negrito abaixo. Esta função <code>path()</code> define um padrão, exibição de detalhes genérica associada à classe associada e um nome.</p> + +<pre class="brush: python notranslate">urlpatterns = [ + path('', views.index, name='index'), + path('books/', views.BookListView.as_view(), name='books'), +<strong> path('book/<int:pk>', views.BookDetailView.as_view(), name='book-detail'),</strong> +]</pre> + +<p>Para o path <em>book-detail</em> o padrão de URL usa uma sintaxe especial para capturar o ID específico do livro que queremos ver. A sintaxe é muito simples: colchetes angulares definem a parte da URL a ser capturada, incluindo o nome da variável que a view pode usar para acessar os dados capturados. Por exemplo, <strong><something></strong> , capturará o padrão marcado e passará o valor para a visualização como uma variável "alguma coisa". Opcionalmente, você pode preceder o nome da variável com um <a href="https://docs.djangoproject.com/pt-br/2.1/topics/http/urls/#path-converters">converter specification</a> que define o tipo de dados (int, str, slug, uuid, path).</p> + +<p>Neste caso, usamos <code>'<int:pk>'</code><strong> </strong>para capturar o ID do livro, que deve ser uma sequência especialmente formatada e passá-la para a view como um parâmetro chamado <code>pk</code> (abreviatura de primary key). Esta é a id que está sendo usado para armazenar o livro exclusivamente no banco de dados, conforme definido no Book Model.</p> + +<div class="note"> +<p><strong>Nota</strong>: Como discutido anteriormente, nosso URL correspondente é realmente <code>catalog/book/<digits></code> (porque estamos no aplicativo de <strong>catalog</strong>, <code>/catalog/</code> é assumido).</p> +</div> + +<div class="warning"> +<p><strong>Importante</strong>: A view de detalhes genérica class-based <em>espera </em>receber um parâmetro chamado <strong>pk</strong>. Se você estiver escrevendo sua própria função view, poderá usar o nome de qualquer parâmetro que desejar, ou mesmo transmitir as informações em um argumento sem nome.</p> +</div> + +<h4 id="Correspondência_avançada_de_caminhosiniciador_de_expressão_regular">Correspondência avançada de caminhos/iniciador de expressão regular</h4> + +<div class="note"> +<p><strong>Nota</strong>: Você não precisará desta seção para concluir o tutorial! Nós fornecemos isso porque conhecer essa opção provavelmente será útil no seu futuro centrado no Django.</p> +</div> + +<p>The pattern matching provided by <code>path()</code> is simple and useful for the (very common) cases where you just want to capture <em>any</em> string or integer. If you need more refined filtering (for example, to filter only strings that have a certain number of characters) then you can use the <a href="https://docs.djangoproject.com/en/2.1/ref/urls/#django.urls.re_path">re_path()</a> method.</p> + +<p>This method is used just like <code>path()</code> except that it allows you to specify a pattern using a <a href="https://docs.python.org/3/library/re.html">Regular expression</a>. For example, the previous path could have been written as shown below:</p> + +<pre class="brush: python notranslate"><strong>re_path(r'^book/(?P<pk>\d+)$', views.BookDetailView.as_view(), name='book-detail'),</strong> +</pre> + +<p><em>Regular expressions</em> are an incredibly powerful pattern mapping tool. They are, frankly, quite unintuitive and scary for beginners. Below is a very short primer!</p> + +<p>The first thing to know is that regular expressions should usually be declared using the raw string literal syntax (i.e. they are enclosed as shown: <strong>r'<your regular expression text goes here>'</strong>).</p> + +<p>The main parts of the syntax you will need to know for declaring the pattern matches are:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Symbol</th> + <th scope="col">Meaning</th> + </tr> + </thead> + <tbody> + <tr> + <td>^</td> + <td>Match the beginning of the text</td> + </tr> + <tr> + <td>$</td> + <td>Match the end of the text</td> + </tr> + <tr> + <td>\d</td> + <td>Match a digit (0, 1, 2, ... 9)</td> + </tr> + <tr> + <td>\w</td> + <td>Match a word character, e.g. any upper- or lower-case character in the alphabet, digit or the underscore character (_)</td> + </tr> + <tr> + <td>+</td> + <td>Match one or more of the preceding character. For example, to match one or more digits you would use <code>\d+</code>. To match one or more "a" characters, you could use <code>a+</code></td> + </tr> + <tr> + <td>*</td> + <td>Match zero or more of the preceding character. For example, to match nothing or a word you could use <code>\w*</code></td> + </tr> + <tr> + <td>( )</td> + <td>Capture the part of the pattern inside the brackets. Any captured values will be passed to the view as unnamed parameters (if multiple patterns are captured, the associated parameters will be supplied in the order that the captures were declared).</td> + </tr> + <tr> + <td>(?P<<em>name</em>>...)</td> + <td>Capture the pattern (indicated by ...) as a named variable (in this case "name"). The captured values are passed to the view with the name specified. Your view must therefore declare an argument with the same name!</td> + </tr> + <tr> + <td>[ ]</td> + <td>Match against one character in the set. For example, [abc] will match on 'a' or 'b' or 'c'. [-\w] will match on the '-' character or any word character.</td> + </tr> + </tbody> +</table> + +<p>Most other characters can be taken literally!</p> + +<p>Let's consider a few real examples of patterns:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Pattern</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><strong>r'^book/(?P<pk>\d+)$'</strong></td> + <td> + <p>This is the RE used in our URL mapper. It matches a string that has <code>book/</code> at the start of the line (<strong>^book/</strong>), then has one or more digits (<code>\d+</code>), and then ends (with no non-digit characters before the end of line marker).</p> + + <p>It also captures all the digits <strong>(?P<pk>\d+)</strong> and passes them to the view in a parameter named 'pk'. <strong>The captured values are always passed as a string!</strong></p> + + <p>For example, this would match <code>book/1234</code> , and send a variable <code>pk='1234'</code> to the view.</p> + </td> + </tr> + <tr> + <td><strong>r'^book/(\d+)$'</strong></td> + <td>This matches the same URLs as the preceding case. The captured information would be sent as an unnamed argument to the view.</td> + </tr> + <tr> + <td><strong>r'^book/(?P<stub>[-\w]+)$'</strong></td> + <td> + <p>This matches a string that has <code>book/</code> at the start of the line (<strong>^book/</strong>), then has one or more characters that are <em>either</em> a '-' or a word character (<strong>[-\w]+</strong>), and then ends. It also captures this set of characters and passes them to the view in a parameter named 'stub'.</p> + + <p>This is a fairly typical pattern for a "stub". Stubs are URL-friendly word-based primary keys for data. You might use a stub if you wanted your book URL to be more informative. For example <code>/catalog/book/the-secret-garden</code> rather than <code>/catalog/book/33</code>.</p> + </td> + </tr> + </tbody> +</table> + +<p>You can capture multiple patterns in the one match, and hence encode lots of different information in a URL.</p> + +<div class="note"> +<p><strong>Nota</strong>: Como desafio, considere como você pode codificar um URL para listar todos os livros lançados em um determinado ano, mês, dia e o RE que poderia ser usado para correspondê-lo.</p> +</div> + +<h4 id="Passando_opções_adicionais_em_seus_mapas_de_URL">Passando opções adicionais em seus mapas de URL</h4> + +<p>Um recurso que não usamos aqui, mas que você pode achar valioso, é que você pode declarar e passar <a href="https://docs.djangoproject.com/pt-br/2.1/topics/http/urls/#views-extra-options">opções adicionais</a> para a view. As opções são declaradas como um dicionário que você passa como o terceiro argumento sem nome para a função <code>path()</code>. Essa abordagem pode ser útil se você desejar usar a mesma visualização para vários recursos e transmitir dados para configurar seu comportamento em cada caso (abaixo, fornecemos um modelo diferente em cada caso).</p> + +<pre class="brush: python notranslate">path('url/', views.my_reused_view, <strong>{'my_template_name': 'some_path'}</strong>, name='aurl'), +path('anotherurl/', views.my_reused_view, <strong>{'my_template_name': 'another_path'}</strong>, name='anotherurl'), +</pre> + +<div class="note"> +<p><strong>Nota:</strong> As opções extras e os padrões capturados nomeados são passados para a view como argumentos <em>nomeados</em>. Se você usar o <strong>mesmo nome</strong> para um padrão capturado e uma opção extra, somente o valor do padrão capturado será enviado para a visualização (o valor especificado na opção adicional será descartado).</p> +</div> + +<h3 id="View_class-based_2">View (class-based)</h3> + +<p>Abra <strong>catalog/views.py</strong>, e copie o seguinte código na parte inferior do arquivo:</p> + +<pre class="brush: python notranslate">class BookDetailView(generic.DetailView): + model = Book</pre> + +<p>É isso aí! Tudo o que você precisa fazer agora é criar um modelo chamado <strong>/locallibrary/catalog/templates/catalog/book_detail.html</strong>, e a visualização passará as informações do banco de dados para o registro <code>Book</code> extraído pelo mapeador de URL. Dentro do modelo, você pode acessar a lista de livros com a variável de modelo denominada <code>object</code> ou <code>book</code> (i.e. genericamente "<code><em>the_model_name</em></code>").</p> + +<p>Se necessário, você pode alterar o template usado e o nome do objeto de contexto usado para referenciar o livro no template. Você também pode substituir métodos para, por exemplo, adicionar informações adicionais ao contexto.</p> + +<h4 id="O_que_acontece_se_o_registro_não_existir">O que acontece se o registro não existir?</h4> + +<p>Se um registro solicitado não existir, a view de detalhes genérica class-based levantará uma exceção <code>Http404</code> para você automaticamente — em produção, isso exibirá automaticamente uma página apropriada de "resource not found", que você pode personalizar se desejar.</p> + +<p>Apenas para lhe dar uma idéia de como isso funciona, o fragmento de código abaixo demonstra como você implementaria a exibição baseada em classe como uma função se você não estivesse usando a view de detalhe genérica class-based.</p> + +<pre class="brush: python notranslate">def book_detail_view(request, primary_key): + try: + book = Book.objects.get(pk=primary_key) + except Book.DoesNotExist: + raise Http404('Book does not exist') + + return render(request, 'catalog/book_detail.html', context={'book': book}) +</pre> + +<p>A view tenta primeiro obter o registro de livro específico do modelo. Se isso falhar, a view deve gerar uma exceção <code>Http404</code> para indicar que o livro "não foi encontrado". A etapa final é, como sempre, chamar <code>render()</code> com o nome do template e os dados do livro no parâmetro <code>context</code> (como um dicionário).</p> + +<p>Como alternativa, podemos usar a função <code>get_object_or_404()</code> como um atalho para levantar uma exceção <code>Http404</code> se o registro não for encontrado.</p> + +<pre class="brush: python notranslate">from django.shortcuts import get_object_or_404 + +def book_detail_view(request, primary_key): + book = get_object_or_404(Book, pk=primary_key) + return render(request, 'catalog/book_detail.html', context={'book': book})</pre> + +<h3 id="Criando_o_template_Detail_View">Criando o template Detail View</h3> + +<p>Crie o arquivo HTML <strong>/locallibrary/catalog/templates/catalog/book_detail.html</strong> e forneça o conteúdo abaixo. Conforme discutido acima, este é o nome do arquivo de template padrão esperado pela view de <em>detalhes </em>genérica class-based (para um modelo chamado <code>Book</code> no aplicativo chamado <code>catalog</code>).</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + <h1>Title: \{{ book.title }}</h1> + + <p><strong>Author:</strong> <a href="">\{{ book.author }}</a></p> <!-- author detail link not yet defined --> + <p><strong>Summary:</strong> \{{ book.summary }}</p> + <p><strong>ISBN:</strong> \{{ book.isbn }}</p> + <p><strong>Language:</strong> \{{ book.language }}</p> + <p><strong>Genre:</strong> {% for genre in book.genre.all %} \{{ genre }}{% if not forloop.last %}, {% endif %}{% endfor %}</p> + + <div style="margin-left:20px;margin-top:20px"> + <h4>Copies</h4> + + {% for copy in book.bookinstance_set.all %} + <hr> + <p class="{% if copy.status == 'a' %}text-success{% elif copy.status == 'm' %}text-danger{% else %}text-warning{% endif %}">\{{ copy.get_status_display }}</p> + {% if copy.status != 'a' %} + <p><strong>Due to be returned:</strong> \{{copy.due_back}}</p> + {% endif %} + <p><strong>Imprint:</strong> \{{copy.imprint}}</p> + <p class="text-muted"><strong>Id:</strong> \{{copy.id}}</p> + {% endfor %} + </div> +{% endblock %}</pre> + +<ul> +</ul> + +<div class="note"> +<p>O link do autor no template acima tem um URL vazio porque ainda não criamos uma página de detalhes do autor. Uma vez que isso exista, você deve atualizar o URL assim:</p> + +<pre class="notranslate"><a href="<strong>{% url 'author-detail' book.author.pk %}</strong>">\{{ book.author }}</a> +</pre> +</div> + +<p>Embora um pouco maior, quase tudo neste template foi descrito anteriormente:</p> + +<ul> + <li>Estendemos nosso modelo básico e substituímos o bloco "content".</li> + <li>Usamos o processamento condicional para determinar se deve ou não exibir conteúdo específico.</li> + <li>Usamos <code>for</code> loops para percorrer as listas de objetos.</li> + <li>Acessamos os campos de contexto usando a notação de ponto (porque usamos a exibição genérica detalhada, o contexto é chamado <code>book</code>; também poderíamos usar "<code>object</code>")</li> +</ul> + +<p>A única coisa interessante que não vimos antes é a função <code>book.bookinstance_set.all()</code>. Este método é "automagicamente" construído pelo Django para retornar o conjunto de registros <code>BookInstance</code> associados com um <code>Book</code> em particular.</p> + +<pre class="brush: python notranslate">{% for copy in book.bookinstance_set.all %} + <!-- code to iterate across each copy/instance of a book --> +{% endfor %}</pre> + +<p>Este método é necessário porque você declara um campo <code>ForeignKey</code> (um-para-muitos) somente no lado "um" do relacionamento. Como você não faz nada para declarar o relacionamento nos outros modelos ("muitos"), ele não possui nenhum campo para obter o conjunto de registros associados. Para superar esse problema, o Django constrói uma função "pesquisa reversa" chamada de forma apropriada, que você pode usar. O nome da função é construído com letras minúsculas no nome do modelo em que o <code>ForeignKey</code> foi declarado, seguido por <code>_set</code> (i.e. então a função criada em <code>Book</code> é <code>bookinstance_set()</code>).</p> + +<div class="note"> +<p><strong>Nota</strong>: Aqui usamos <code>all()</code> para obter todos os registros (o padrão). Enquanto você pode usar o método <code>filter()</code> para obter um subconjunto de registros no código, não é possível fazer isso diretamente nos modelos, porque não é possível especificar argumentos para funções.</p> + +<p>Observe também que, se você não definir um pedido (na sua class-based view ou modelo), também verá erros do servidor de desenvolvimento como este:</p> + +<pre class="notranslate">[29/May/2017 18:37:53] "GET /catalog/books/?page=1 HTTP/1.1" 200 1637 +/foo/local_library/venv/lib/python3.5/site-packages/django/views/generic/list.py:99: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: <QuerySet [<Author: Ortiz, David>, <Author: H. McRaven, William>, <Author: Leigh, Melinda>]> + allow_empty_first_page=allow_empty_first_page, **kwargs) +</pre> + +<p>Isso acontece porque o <a href="https://docs.djangoproject.com/pt-br/2.1/topics/pagination/#paginator-objects">objeto paginator</a> espera ver algum ORDER BY sendo executado no seu banco de dados subjacente. Sem ele, não é possível garantir que os registros que estão sendo retornados estejam na ordem certa!<strong> </strong></p> + +<p>Este tutorial não atingiu a <strong>Paginação </strong>(ainda, mas em breve), mas como você não pode usar <code>sort_by()</code> e passar um parâmetro (o mesmo com <code>filter()</code> descrito acima), você terá que escolher entre três opções:</p> + +<ol> + <li>Adicione um <code>ordering</code> dentro de uma declaração <code>class Meta</code> no seu model.</li> + <li>Adicione um atributo <code>queryset</code> na sua class-based view, especificando um <code>order_by()</code>.</li> + <li>Adicione um método <code>get_queryset</code> à sua class-based view personalisada e também especifique o <code>order_by()</code>.</li> +</ol> + +<p>Se você decidir ir com uma <code>class Meta</code> no model <code>Author</code> (provavelmente não tão flexível quanto personalizar o class-based view, mas fácil o suficiente), você terminará com algo assim:</p> + +<pre class="notranslate">class Author(models.Model): + first_name = models.CharField(max_length=100) + last_name = models.CharField(max_length=100) + date_of_birth = models.DateField(null=True, blank=True) + date_of_death = models.DateField('Died', null=True, blank=True) + + def get_absolute_url(self): + return reverse('author-detail', args=[str(self.id)]) + + def __str__(self): + return f'{self.last_name}, {self.first_name}' + +<strong> class Meta: + ordering = ['last_name']</strong></pre> + +<p>Obviamente, o campo não precisa ser <code>last_name</code>: poderia ser qualquer outro.</p> + +<p>E por último, mas não menos importante, você deve classificar por um atributo/coluna que realmente tenha um índice (exclusivo ou não) em seu banco de dados para evitar problemas de desempenho. Obviamente, isso não será necessário aqui (e provavelmente estamos nos adiantando muito) com tão poucos livros (e usuários!), Mas é algo a ser lembrado em projetos futuros.</p> +</div> + +<h2 id="Com_o_que_se_parece_agora">Com o que se parece agora?</h2> + +<p>Nesse ponto, deveríamos ter criado tudo o necessário para exibir a lista de livros e as páginas de detalhes do livro. Execute o servidor (<code>python3 manage.py runserver</code>) e abra no seu navegador <a href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a>.</p> + +<div class="warning"> +<p><strong>Aviso:</strong> Não clique em nenhum autor ou link de detalhes do autor ainda - você os criará no desafio!</p> +</div> + +<p>Clique no link <strong>All books</strong> para exibir a lista de livros.</p> + +<p><img alt="Book List Page" src="https://mdn.mozillademos.org/files/14049/book_list_page_no_pagination.png" style="border-style: solid; border-width: 1px; display: block; height: 216px; margin: 0px auto; width: 823px;"></p> + +<p>Em seguida, clique no link de um dos seus livros. Se tudo estiver configurado corretamente, você deverá ver algo como a seguinte captura de tela.</p> + +<p><img alt="Book Detail Page" src="https://mdn.mozillademos.org/files/14051/book_detail_page_no_pagination.png" style="border-style: solid; border-width: 1px; display: block; height: 783px; margin: 0px auto; width: 926px;"></p> + +<h2 id="Paginação">Paginação</h2> + +<p>Se você tiver apenas alguns registros, nossa página da lista de livros ficará bem. No entanto, à medida que você entra nas dezenas ou centenas de registros, a página levará progressivamente mais tempo para carregar (e terá muito conteúdo para navegar com sensatez). A solução para esse problema é adicionar paginação às exibições de lista, reduzindo o número de itens exibidos em cada página.</p> + +<p>O Django possui excelente suporte embutido para paginação. Melhor ainda, isso é incorporado às exibições de lista genéricas baseadas em classes, para que você não precise fazer muito para habilitá-lo!</p> + +<h3 id="Views">Views</h3> + +<p>Abra <strong>catalog/views.py</strong>, e adicionea linha <code>paginate_by</code> mostrado em negrito abaixo.</p> + +<pre class="brush: python notranslate">class BookListView(generic.ListView): + model = Book + <strong>paginate_by = 10</strong></pre> + +<p>Com essa adição, assim que você tiver mais de 10 registros, a visualização começará a paginar os dados que envia para o modelo. As diferentes páginas são acessadas usando os parâmetros GET - para acessar a página 2, você usaria o URL: <code>/catalog/books/<strong>?page=2</strong></code>.</p> + +<h3 id="Templates">Templates</h3> + +<p>Agora que os dados estão paginados, precisamos adicionar suporte ao modelo para rolar pelo conjunto de resultados. Como podemos fazer isso em todas as visualizações de lista, faremos isso de uma maneira que possa ser adicionada ao modelo base. </p> + +<p>Abra <strong>/locallibrary/catalog/templates/<em>base_generic.html</em></strong> e copie no seguinte bloco de paginação, abaixo do nosso bloco de conteúdo (destacado abaixo em negrito). O código primeiro verifica se a paginação está ativada na página atual. Nesse caso, adiciona os links seguintes e anteriores, conforme apropriado (e o número da página atual).</p> + +<pre class="brush: python notranslate">{% block content %}{% endblock %} + +<strong> {% block pagination %} + {% if is_paginated %} + <div class="pagination"> + <span class="page-links"> + {% if page_obj.has_previous %} + <a href="\{{ request.path }}?page=\{{ page_obj.previous_page_number }}">previous</a> + {% endif %} + <span class="page-current"> + Page \{{ page_obj.number }} of \{{ page_obj.paginator.num_pages }}. + </span> + {% if page_obj.has_next %} + <a href="\{{ request.path }}?page=\{{ page_obj.next_page_number }}">next</a> + {% endif %} + </span> + </div> + {% endif %} + {% endblock %} </strong></pre> + +<p>O <code>page_obj</code> é um objeto de <a href="https://docs.djangoproject.com/pt-br/2.1/topics/pagination/#paginator-objects">Paginator</a> que existirá se a paginação estiver sendo usada na página atual. Permite obter todas as informações sobre a página atual, as páginas anteriores, quantas páginas existem, etc.</p> + +<p>Usamos <code>\{{ request.path }}</code> para obter o URL da página atual para criar os links de paginação. Isso é útil porque é independente do objeto que estamos paginando.</p> + +<p>É isso aí!</p> + +<h3 id="Com_o_que_se_parece_agora_2">Com o que se parece agora?</h3> + +<p>A captura de tela abaixo mostra a aparência da paginação - se você não inseriu mais de 10 títulos no banco de dados, pode testá-lo com mais facilidade, abaixando o número especificado na linha <code>paginate_by</code> no seu arquivo <strong>catalog/views.py</strong>. Para obter o resultado abaixo, alteramos para <code>paginate_by = 2</code>.</p> + +<p>Os links de paginação são exibidos na parte inferior, com os links seguinte/anterior, dependendo da página em que você está.</p> + +<p><img alt="Book List Page - paginated" src="https://mdn.mozillademos.org/files/14057/book_list_paginated.png" style="border-style: solid; border-width: 1px; display: block; height: 216px; margin: 0px auto; width: 924px;"></p> + +<h2 id="Challenge_yourself">Challenge yourself</h2> + +<p>The challenge in this article is to create the author detail and list views required to complete the project. These should be made available at the following URLs:</p> + +<ul> + <li><code>catalog/authors/</code> — The list of all authors.</li> + <li><code>catalog/author/<em><id></em></code><em> </em>— The detail view for the specific author with a primary key field named <em><code><id></code></em></li> +</ul> + +<p>The code required for the URL mappers and the views should be virtually identical to the <code>Book</code> list and detail views we created above. The templates will be different but will share similar behaviour.</p> + +<div class="note"> +<p><strong>Note</strong>:</p> + +<ul> + <li>Once you've created the URL mapper for the author list page you will also need to update the <strong>All authors</strong> link in the base template. Follow the <a href="#Update_the_base_template">same process</a> as we did when we updated the <strong>All books</strong> link.</li> + <li>Once you've created the URL mapper for the author detail page, you should also update the <a href="#Creating_the_Detail_View_template">book detail view template</a> (<strong>/locallibrary/catalog/templates/catalog/book_detail.html</strong>) so that the author link points to your new author detail page (rather than being an empty URL). The line will change to add the template tag shown in bold below. + <pre class="brush: html notranslate"><p><strong>Author:</strong> <a href="<strong>{% url 'author-detail' book.author.pk %}</strong>">\{{ book.author }}</a></p> +</pre> + </li> +</ul> +</div> + +<p>When you are finished, your pages should look something like the screenshots below.</p> + +<p><img alt="Author List Page" src="https://mdn.mozillademos.org/files/14053/author_list_page_no_pagination.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<ul> +</ul> + +<p><img alt="Author Detail Page" src="https://mdn.mozillademos.org/files/14055/author_detail_page_no_pagination.png" style="border-style: solid; border-width: 1px; display: block; height: 358px; margin: 0px auto; width: 825px;"></p> + +<ul> +</ul> + +<h2 id="Summary">Summary</h2> + +<p>Congratulations, our basic library functionality is now complete! </p> + +<p>In this article, we've learned how to use the generic class-based list and detail views and used them to create pages to view our books and authors. Along the way we've learned about pattern matching with regular expressions, and how you can pass data from URLs to your views. We've also learned a few more tricks for using templates. Last of all we've shown how to paginate list views so that our lists are manageable even when we have many records.</p> + +<p>In our next articles, we'll extend this library to support user accounts, and thereby demonstrate user authentication, permissons, sessions, and forms.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/class-based-views/generic-display/">Built-in class-based generic views</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/class-based-views/generic-display/">Generic display views</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/class-based-views/intro/">Introduction to class-based views</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/templates/builtins">Built-in template tags and filters</a> (Django docs).</li> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/pagination/">Pagination</a> (Django docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Home_page", "Learn/Server-side/Django/Sessions", "Learn/Server-side/Django")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: Website de uma Biblioteca Local</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/skeleton_website">Tutorial Django Parte 2: Criando a base do website</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Models">Tutorial Django Parte 3: Usando models</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Admin_site">Tutorial Django Parte 4: Django admin site</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Home_page">Tutorial Django Parte 5: Criando nossa página principal</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Generic_views">Tutorial Django Parte 6: Lista genérica e detail views</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Sessions">Tutorial Django Parte 7: Framework de Sessões</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Authentication">Tutorial Django Parte 8: Autenticação de Usuário e permissões</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Forms">Tutorial Django Parte 9: Trabalhando com formulários</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Testing">Tutorial Django Parte 10: Testando uma aplicação web Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Deployment">Tutorial Django Parte 11: Implantando Django em produção</a></li> + <li><a rel="nofollow" title="A página ainda não foi criada.">Segurança de aplicações web Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/home_page/index.html b/files/pt-br/learn/server-side/django/home_page/index.html new file mode 100644 index 0000000000..3c7783c352 --- /dev/null +++ b/files/pt-br/learn/server-side/django/home_page/index.html @@ -0,0 +1,420 @@ +--- +title: 'Django Tutorial Parte 5: Criando nossa home page' +slug: Learn/Server-side/Django/Home_page +tags: + - Aprender + - Artigo + - Codificação + - Iniciante + - Tutorial + - django + - django templates + - django views + - lado servidor (server-side) +translation_of: Learn/Server-side/Django/Home_page +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django")}}</div> + +<p class="summary">Agora estamos prontos para adicionar o código que exibe nossa primeira página completa - uma home page do site <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a>. A página inicial mostrará o número de registros que temos para cada tipo de modelo e fornecerá links de navegação na barra lateral para nossas outras páginas. Ao longo do caminho, obteremos experiência prática ao escrever mapas e visualizações básicos de URL, obter registros do banco de dados e usar modelos.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Leia a <a href="/en-US/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a>. Conclua os tópicos do tutorial anterior (incluindo <a href="/en-US/docs/Learn/Server-side/Django/Admin_site">Django Tutorial Part 4: Django admin site</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a criar mapas e visualizações de URL simples (onde nenhum dado é codificado no URL), obtenha dados de modelos e crie modelos.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_Global">Visão Global</h2> + +<p>Depois de definirmos nossos modelos e criarmos alguns registros iniciais da biblioteca para trabalhar, é hora de escrever o código que apresenta essas informações aos usuários. A primeira coisa que precisamos fazer é determinar quais informações queremos exibir em nossas páginas e definir os URLs a serem usados para retornar esses recursos. Em seguida, criaremos um mapeador de URLs, visualizações e modelos para exibir as páginas.</p> + +<p>O diagrama a seguir descreve o fluxo de dados principal e os componentes necessários ao manipular solicitações e respostas HTTP. Como já implementamos o modelo, os principais componentes que criaremos são:</p> + +<ul> + <li>Mapeadores de URL para encaminhar os URLs suportados (e qualquer informação codificada nos URLs) para as funções de exibição apropriadas.</li> + <li>View functions para obter os dados solicitados dos modelos, crie páginas HTML que exibem os dados e retorne as páginas ao usuário para visualização no navegador.</li> + <li>Templates para usar ao renderizar dados nas visualizações.</li> +</ul> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13931/basic-django.png" style="display: block; margin: 0px auto;"></p> + +<p>Como você verá na próxima seção, temos 5 páginas para exibir, o que é muita informação para documentar em um único artigo. Portanto, este artigo se concentrará em como implementar a página inicial e abordaremos as outras páginas em um artigo subsequente. Isso deve fornecer uma boa compreensão completa de como os mapeadores, visualizações e modelos de URL funcionam na prática.</p> + +<h2 id="Definindo_os_URLs_do_recurso">Definindo os URLs do recurso</h2> + +<p>Como esta versão do <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary </a>é essencialmente somente leitura para usuários finais, precisamos fornecer uma página de destino para o site (uma página inicial) e páginas que exibam visualizações de lista e detalhes de livros e autores.</p> + +<p>As URLs que iremos precisar na nossa página são:</p> + +<ul> + <li><code>catalog/</code> — A página inicial (index).</li> + <li><code>catalog/books/</code> — Uma lista de todos os livros.</li> + <li><code>catalog/authors/</code> — Uma lista de todos os autores.</li> + <li><code>catalog/book/<em><id></em></code> — A exibição de detalhes de um livro específico, com uma chave primária de campo <code><em><id></em></code> (o padrão). Por exemplo, o URL do terceiro livro adicionado à lista será <code>/catalog/book/3</code>.</li> + <li><code>catalog/author/<em><id></em></code><em> </em>— A exibição de detalhes para o autor específico com um campo de chave primária de <em><code><id>. </code></em>Por exemplo, o URL do 11º autor adicionado à lista será <code>/catalog/author/11</code>.</li> +</ul> + +<p>Os três primeiros URLs retornarão a página de índice, a lista de livros e a lista de autores. Esses URLs não codificam nenhuma informação adicional e as consultas que buscam dados no banco de dados sempre serão as mesmas. No entanto, os resultados retornados pelas consultas dependerão do conteúdo do banco de dados.</p> + +<p>Por outro lado, os dois URLs finais exibirão informações detalhadas sobre um livro ou autor específico. Esses URLs codificam a identidade do item a ser exibido (representado por <code><em><id></em></code> acima). O mapeador de URLs extrairá as informações codificadas e as passará para a visualização, e a visualização determinará dinamicamente quais informações serão obtidas do banco de dados. Ao codificar as informações no URL, usaremos um único conjunto de mapeamento de URL, uma visualização e um modelo para lidar com todos os livros (ou autores). </p> + +<div class="note"> +<p><strong>Nota</strong>: Com o Django, você pode construir suas URLs da maneira que desejar - você pode codificar informações no corpo da URL, como mostrado acima, ou incluir <code>GET</code> parâmetros no URL, por exemplo <code>/book/?id=6</code>. Qualquer que seja a abordagem usada, os URLs devem ser mantidos limpos, lógicos e legíveis, conforme <a href="https://www.w3.org/Provider/Style/URI">recomendado pelo W3C</a>.<br> + A documentação do Django recomenda informações de codificação no corpo da URL para obter um melhor design da URL.</p> +</div> + +<p>Conforme mencionado na visão geral, o restante deste artigo descreve como construir a página index.</p> + +<h2 id="Criando_a_página_index">Criando a página index</h2> + +<p>A primeira página que criaremos é a página index (<code>catalog/</code>). A pagina index incluirá algum HTML estático, juntamente com "contagens" geradas de diferentes registros no banco de dados. Para fazer isso funcionar, criaremos um mapeamento de URL, uma visualização e um modelo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Vale a pena prestar um pouco de atenção extra nesta seção. A maioria das informações também se aplica às outras páginas que criaremos.</p> +</div> + +<h3 id="Mapeamento_de_URL">Mapeamento de URL</h3> + +<p>Quando criamos o <a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">esqueleto do website</a>, atualizamos o arquivo <strong>locallibrary/urls.py</strong> para garantir que sempre que um URL que comece com <code>catalog/</code> é recebido, o módulo URLConf <code>catalog.urls</code> processará a substring restante.</p> + +<p>O seguinte snippet de código de <strong>locallibrary/urls.py </strong>inclui o modulo <code>catalog.urls</code>:</p> + +<pre class="notranslate">urlpatterns += [ + path('catalog/', include('catalog.urls')), +] +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Sempre que o Django encontra a função de importação <code><a href="https://docs.djangoproject.com/en/2.1/ref/urls/#django.urls.include" title="django.conf.urls.include">django.urls.include()</a></code>, divide a string da URL no caractere final designado e envia a subsequência restante para o módulo URLconf incluído para processamento adicional.</p> +</div> + +<p>Também criamos um arquivo de espaço reservado para o modulo <em>URLConf</em>, chamado <strong>/catalog/urls.py</strong>. Adicione as seguintes linhas a esse arquivo: </p> + +<pre class="brush: python notranslate">urlpatterns = [ +<strong> path('', views.index, name='index'),</strong> +]</pre> + +<p>A função <code>path()</code> define o seguinte:</p> + +<ul> + <li>Um padrão de URL, que é uma sequência vazia: <code>''</code>. Discutiremos detalhadamente os padrões de URL ao trabalhar em outras visualizações.</li> + <li>A view function that will be called if the URL pattern is detected: <code>views.index</code>, which is the function named <code>index()</code> in the <strong>views.py </strong>file. </li> +</ul> + +<p>A função <code>path()</code> também especifica um parâmetro de nome, que é um identificador exclusivo para esse mapeamento de URL específico. Você pode usar o nome para "reverter" o mapeador, ou seja, para criar dinamicamente um URL que aponte para o recurso que o mapeador foi projetado para manipular. Por exemplo, podemos usar o parâmetro name para vincular à nossa home page a partir de qualquer outra página adicionando o seguinte link em um modelo:</p> + +<pre class="brush: html notranslate"><a href="<strong>{% url 'index' %}</strong>">Home</a>.</pre> + +<div class="note"> +<p><strong>Nota</strong>: Podemos codificar o link como em <code><a href="<strong>/catalog/</strong>">Home</a></code>), mas se alterarmos o padrão da nossa página inicial, por exemplo, para <code>/catalog/index</code>) os modelos não serão mais vinculados corretamente. Usar um mapeamento de URL invertido é muito mais flexível e robusto.</p> +</div> + +<h3 id="View_function-based">View (function-based)</h3> + +<p>Uma view é uma função que processa uma solicitação HTTP, busca os dados necessários no banco de dados, renderiza os dados em uma página HTML usando um modelo HTML e, em seguida, retorna o HTML gerado em uma resposta HTTP para exibir a página ao usuário. A visualização do índice segue esse modelo - ele busca informações sobre o número de <code>Book</code>, <code>BookInstance</code>, disponibilidade de <code>BookInstance</code> e registros de <code>Author</code> que temos no banco de dados e passa essas informações para um modelo para exibição.</p> + +<p>Abra <strong>catalog/views.py</strong> e observe que o arquivo já importa o <a href="https://docs.djangoproject.com/en/2.1/topics/http/shortcuts/#django.shortcuts.render">render()</a> da função shortcuts para gerar arquivo HTML usando um modelo e dados: </p> + +<pre class="brush: python notranslate">from django.shortcuts import render + +# Create your views here. +</pre> + +<p>Cole as seguintes linhas na parte inferior do arquivo:</p> + +<pre class="brush: python notranslate">from catalog.models import Book, Author, BookInstance, Genre + +def index(request): + """View function for home page of site.""" + + # Generate counts of some of the main objects + num_books = Book.objects.all().count() + num_instances = BookInstance.objects.all().count() + + # Available books (status = 'a') + num_instances_available = BookInstance.objects.filter(status__exact='a').count() + + # The 'all()' is implied by default. + num_authors = Author.objects.count() + + context = { + 'num_books': num_books, + 'num_instances': num_instances, + 'num_instances_available': num_instances_available, + 'num_authors': num_authors, + } + + # Render the HTML template index.html with the data in the context variable + return render(request, 'index.html', context=context)</pre> + +<p>A primeira linha importa as classes de models que usaremos para acessar dados em todas as nossas visualizações.</p> + +<p>A primeira parte da função view busca o número de registros usando o atributo <code>objects.all()</code> nas classes de modelo. Também recebe uma lista de objetos de <code>BookInstance</code> que possuem um valor de 'a' (Disponibilidade) no campo status. Você pode encontrar mais informações sobre como acessar os dados do modelo em nosso tutorial anterior <a href="/en-US/docs/Learn/Server-side/Django/Models#Searching_for_records">Django Tutorial Part 3: Using models > Searching for records</a>.</p> + +<p>No final da função view chamamos a função <code>render()</code> para criar uma página HTML e retornar a página como resposta. essa função de atalho envolve várias outras funções para simplificar um caso de uso muito comum. A função <code>render()</code> aceita os seguintes parâmetros:</p> + +<ul> + <li>o objeto <code>request</code> original, que é um <code>HttpRequest</code>.</li> + <li>um modelo HTML com espaços reservados para os dados.</li> + <li>uma variável <code>context</code>, que é um dicionário Python, contendo os dados a serem inseridos nos espaços reservados. </li> +</ul> + +<p>Falaremos mais sobre modelos e variáveis <code>context</code> na próxima seção. Vamos criar nosso template para que possamos exibir algo para o usuário!</p> + +<h3 id="Template">Template</h3> + +<p>Um template é um arquivo de texto que define a estrutura ou o layout de um arquivo (como uma página HTML), usa espaços reservados para representar o conteúdo real.</p> + +<p>Django irá procurar automaticamente templates na pasta chamada '<strong>templates</strong>' em sua aplicação. Por exemplo, na exibição de index que acabamos de adicionar, a função <code>render()</code> espera encontrar o arquivo <em><strong>index.html</strong> em</em><em> </em><strong>/locallibrary/catalog/templates/</strong> e gera um erro se o arquivo não estiver presente.</p> + +<p>Você pode verificar isso salvando as alterações anteriores e acessando <code>127.0.0.1:8000</code> no seu navegador - ele exibirá uma mensagem de erro bastante intuitiva: "<code>TemplateDoesNotExist at /catalog/</code>", e outros detalhes.</p> + +<div class="note"> +<p><strong>Nota</strong>: Com base no arquivo de configurações do seu projeto, o Django procurará templates em vários locais, pesquisando nos aplicativos instalados por padrão. Você pode descobrir mais sobre como o Django encontra templates e quais formatos ele suporta no <a href="https://docs.djangoproject.com/en/2.1/topics/templates/">the Templates section of the Django documentation</a>.</p> +</div> + +<h4 id="Estendendo_templates">Estendendo templates</h4> + +<p>O index template precisará de marcação HTML padrão para head e a body, juntamente com as seções de navegação para criar um link para as outras páginas do site (que ainda não criamos) e para as seções que exibem dados introdutórios de texto e livro.</p> + +<p>Grande parte da estrutura HTML e de navegação será a mesma em todas as páginas do nosso site. Em vez de duplicar o código padrão em todas as páginas, você pode usar a linguagem de modelagem do Django para declarar um modelo base e depois estendê-lo para substituir apenas os bits que são diferentes para cada página específica.</p> + +<p>O seguinte snippet de código é um template base de amostra de um arquivo <strong>base_generic.html</strong>. Em breve, criaremos o modelo para a LocalLibrary. O exemplo abaixo inclui HTML comum com seções para um título, uma barra lateral e o conteúdo principal marcado com as template tags de nome <code>block</code> e <code>endblock</code>, mostrado em negrito. Você pode deixar os blocos vazios ou incluir o conteúdo padrão a ser usado ao renderizar páginas derivadas do modelo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Template <em>tags</em> são funções que você pode usar em um modelo para percorrer as listas, executar operações condicionais com base no valor de uma variável e assim por diante. Além das template tags, a sintaxe template permite que você faça referência a variáveis que são passadas para a template a partir da view e use filtros de template para formatar variáveis (por exemplo, para converter uma sequência em minúscula).</p> +</div> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html lang="en"> +<head> + <strong>{% block title %}</strong><title>Local Library</title><strong>{% endblock %}</strong> +</head> +<body> + <strong>{% block sidebar %}</strong><!-- insert default navigation text for every page --><strong>{% endblock %}</strong> + <strong>{% block content %}</strong><!-- default content text (typically empty) --><strong>{% endblock %}</strong> +</body> +</html> +</pre> + +<p>Ao definir um template para uma visualização específica, primeiro especificamos o template base usando a template tag <code>extends</code> — veja o exemplo de código abaixo. Em seguida, declaramos quais seções do template queremos substituir (se houver), usando seções <code>block</code>/<code>endblock</code> como no template base. </p> + +<p>Por exemplo, o trecho de código abaixo mostra como usar a template tag <code>extends</code> e substituir o block <code>content</code>. O HTML gerado incluirá o código e a estrutura definidos no template base, incluindo o conteúdo padrão que você definiu no block <code>title</code>, mas o novo block <code>content</code> no lugar do padrão.</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + <h1>Local Library Home</h1> + <p>Welcome to LocalLibrary, a website developed by <em>Mozilla Developer Network</em>!</p> +{% endblock %}</pre> + +<h4 id="O_template_base_LocalLibrary">O template base LocalLibrary</h4> + +<p>Usaremos o seguinte snippet de código como modelo básico para o site <em>LocalLibrary</em>. Como você pode ver, ele contém algum código HTML e define blocos para <code>title</code>, <code>sidebar</code>, e <code>content</code>. Temos um título padrão e uma barra lateral padrão com links para listas de todos os livros e autores, ambos colocados em blocos para serem facilmente alterados no futuro.</p> + +<div class="note"> +<p><strong>Nota</strong>: Também introduzimos duas template tags adicionais: <code>url</code> e <code>load static</code>. Essas tags serão explicadas nas próximas seções.</p> +</div> + +<p>Crie um novo arquivo <strong><em>base_generic.html </em></strong>em <strong>/locallibrary/catalog/templates/</strong> e cole o seguinte código no arquivo:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html lang="en"> +<head> + {% block title %}<title>Local Library</title>{% endblock %} + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> + <!-- Add additional CSS in static file --> + {% load static %} + <link rel="stylesheet" href="{% static 'css/styles.css' %}"> +</head> +<body> + <div class="container-fluid"> + <div class="row"> + <div class="col-sm-2"> + {% block sidebar %} + <ul class="sidebar-nav"> + <li><a href="{% url 'index' %}">Home</a></li> + <li><a href="">All books</a></li> + <li><a href="">All authors</a></li> + </ul> + {% endblock %} + </div> + <div class="col-sm-10 ">{% block content %}{% endblock %}</div> + </div> + </div> +</body> +</html></pre> + +<p>O template inclui CSS de <a href="http://getbootstrap.com/">Bootstrap</a> para melhorar o layout e a apresentação da página HTML. O uso do Bootstrap (ou outra estrutura da Web do lado do cliente) é uma maneira rápida de criar uma página atraente que é exibida bem em diferentes tamanhos de tela.</p> + +<p>O template base também faz referência a um arquivo css local (<strong>styles.css</strong>) que fornece estilo adicional. Criar um arquivo <strong>styles.css </strong>em<strong> </strong><strong>/locallibrary/catalog/static/css/</strong> e cole o seguinte código no arquivo:</p> + +<pre class="brush: css notranslate">.sidebar-nav { + margin-top: 20px; + padding: 0; + list-style: none; +}</pre> + +<h4 id="O_template_index">O template index</h4> + +<p>Crie um novo arquivo HTML <strong><em>index.html </em></strong>em <strong>/locallibrary/catalog/templates/</strong> e cole o seguinte código no arquivo Esse código estende nosso modelo base na primeira linha e substitui o padrão block <code>content</code> para o template. </p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + <h1>Local Library Home</h1> + <p>Welcome to LocalLibrary, a website developed by <em>Mozilla Developer Network</em>!</p> + <h2>Dynamic content</h2> + <p>The library has the following record counts:</p> + <ul> + <li><strong>Books:</strong> <strong>\{{ num_books }}</strong></li> + <li><strong>Copies:</strong> <strong>\{{ num_instances }}</strong></li> + <li><strong>Copies available:</strong> <strong>\{{ num_instances_available }}</strong></li> + <li><strong>Authors:</strong> <strong>\{{ num_authors }}</strong></li> + </ul> +{% endblock %}</pre> + +<p>Na seção <em>Dynamic content</em>, declaramos espaços reservados (<em>variáveis de template</em>) para as informações da exibição que queremos incluir. As variáveis são colocadas entre chaves (guiador), como mostrado em negrito no exemplo de código. </p> + +<div class="note"> +<p><strong>Nota:</strong> Você pode reconhecer facilmente variáveis de template e template tags (funções) - as variáveis são colocadas entre chaves (<code>\{{ num_books }}</code>), e as tags são colocadas em chaves simples com sinais de porcentagem (<code>{% extends "base_generic.html" %}</code>).</p> +</div> + +<p>O importante a ser observado aqui é que as variáveis são nomeadas com as <em>chaves</em> que passamos para o dicionário <code>context</code> na função <code>render()</code> da nossa view (veja a amostra abaixo). As variáveis serão substituídas pelos <em>valores </em>associados quando o modelo for renderizado.</p> + +<pre class="brush: python notranslate">context = { + '<strong>num_books</strong>': num_books, + '<strong>num_instances</strong>': num_instances, + '<strong>num_instances_available</strong>': num_instances_available, + '<strong>num_authors</strong>': num_authors, +} + +return render(request, 'index.html', context=context)</pre> + +<h4 id="Referenciando_arquivos_estáticos_nos_templates">Referenciando arquivos estáticos nos templates</h4> + +<p>É provável que seu projeto use recursos estáticos, incluindo JavaScript, CSS e imagens. Como a localização desses arquivos pode não ser conhecida (ou pode mudar), o Django permite que você especifique a localização em seus modelos em relação a configuração global <code>STATIC_URL</code>. O site padrão do esqueleto define o valor de <code>STATIC_URL</code> para '<code>/static/</code>', mas você pode optar por hospedá-los em uma rede de entrega de conteúdo ou em outro local.</p> + +<p>Dentro do template que você chama primeiro na template tag <code>load</code> especificando "static" para adicionar a biblioteca de modelos, conforme mostrado no exemplo de código abaixo. Você pode então usar a template tag <code>static</code> e especifique o URL relativo ao arquivo necessário.</p> + +<pre class="brush: html notranslate"><!-- Add additional CSS in static file --> +{% load static %} +<link rel="stylesheet" href="{% static 'css/styles.css' %}"></pre> + +<p>Você pode adicionar uma imagem à página de maneira semelhante, por exemplo:</p> + +<pre class="brush: html notranslate">{% load static %} +<img src="{% static 'catalog/images/local_library_model_uml.png' %}" alt="UML diagram" style="width:555px;height:540px;"> +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Os exemplos acima especificam onde os arquivos estão localizados, mas o Django não os serve por padrão. Configuramos o servidor da web de desenvolvimento para exibir arquivos modificando o mapeador de URL global (<strong>/locallibrary/locallibrary/urls.py</strong>) quando <a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">criamos o esqueleto do website</a>, mas ainda precisamos ativar a veiculação de arquivos na produção. Veremos isso mais tarde.</p> +</div> + +<p>Para obter mais informações sobre como <a href="https://docs.djangoproject.com/en/2.1/howto/static-files/">Trabalhar com arquivos estaticos</a>, consulte Gerenciando arquivos estáticos na documentação do Django.</p> + +<h4 id="Vinculando_as_URLs">Vinculando as URLs</h4> + +<p>O template base abaixo introduziu a template tag <code>url</code>.</p> + +<pre class="brush: python notranslate"><li><a href="{% url 'index' %}">Home</a></li> +</pre> + +<p>Essa tag aceita o nome de uma função <code>path()</code> chamado em <strong>urls.py</strong> e os valores para quaisquer argumentos que a view associada receberá dessa função e retorna um URL que você pode usar para vincular ao recurso.</p> + +<h4 id="Configurando_onde_encontrar_os_templates">Configurando onde encontrar os templates</h4> + +<p>Você precisa dizer ao Django para procurar seus templates na pasta de templates. Para fazer isso, adicione o diretório de templates ao objeto TEMPLATES editando o arquivo <strong>settings.py</strong>, como mostrado em negrito, no seguinte exemplo de código:</p> + +<pre class="brush: python notranslate">TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ +<strong> os.path.join(BASE_DIR, 'templates'), +</strong> ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +]</pre> + +<h2 id="Com_o_que_se_parece">Com o que se parece?</h2> + +<p>Neste ponto, criamos todos os recursos necessários para exibir a página index. Execute o servidor (<code>python3 manage.py runserver</code>) e abra <a href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a> no seu navegador. Se tudo estiver configurado corretamente, seu site deverá ter a seguinte captura de tela.</p> + +<p><img alt="Index page for LocalLibrary website" src="https://mdn.mozillademos.org/files/14045/index_page_ok.png" style="border-style: solid; border-width: 1px; display: block; height: 356px; margin: 0px auto; width: 874px;"></p> + +<div class="note"> +<p><strong>Nota:</strong> Os links <strong>All books</strong> e <strong>All authors</strong> ainda não funcionarão porque os caminhos, visualizações e modelos para essas páginas não estão definidos. Acabamos de inserir espaços reservados para esses links no template <code>base_generic.html</code>.</p> +</div> + +<h2 id="Desafie-se">Desafie-se</h2> + +<p>Temos duas tarefas para testar a sua familiaridade com as consultas de modelos, views e templates</p> + +<ol> + <li>O modelo de <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Home_page#The_LocalLibrary_base_template">base</a> da BibliotecaLocal inclui um bloco de <code>título</code>. Substitua este bloco no modelo de índice e crie um novo título para a página.</li> + <li> + <div class="note"> + <p><strong>Dica: </strong>A seção<a href="#Extending_templates"> Extendendo Templates</a> explica como criar blocos e extender um bloco em outro template.</p> + </div> + </li> + <li>Modifique a <a href="#View_(function-based)">view</a> para gerar contagens para gêneros e livros que contenham uma palavra específica (case insensitive), e passe o resultado para o <code>contexto.</code> <span class="tlid-translation translation" lang="pt"><span title="">Isso é feito de maneira semelhante à criação e uso de <code>num_books</code> e <code>num_instances_available</code>.</span> <span title="">Em seguida, atualize o template do index para incluir essas variáveis.</span></span></li> +</ol> + +<ul> +</ul> + +<h2 id="Resumo">Resumo</h2> + +<p>Acabamos de criar a página inicial do nosso site - uma página HTML que exibe uma série de registros do banco de dados e links para outras páginas ainda a serem criadas. Ao longo do caminho, aprendemos informações fundamentais sobre mapeadores de url, views, consulta do banco de dados com modelos, passagem de informações para um modelo a partir de uma view e criação e extensão de templates.</p> + +<p>No próximo artigo, continuaremos sobre esse conhecimento para criar as quatro páginas restantes de nosso site.</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/pt-br/3.1/intro/tutorial03/">Escrevendo sua primeira aplicação Django, parte 3: View e Templates</a> (documentação do Django)</li> + <li><a href="https://docs.djangoproject.com/pt-br/3.1/topics/http/urls/">Despachante de URL</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/pt-br/3.1/topics/http/views/">Funções das Views </a> (DJango docs)</li> + <li><a href="https://docs.djangoproject.com/pt-br/3.1/topics/templates/">Templates</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/howto/static-files/">Gerenciando arquivos estáticos</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/http/shortcuts/#django.shortcuts.render">Funções de atalho do Django</a> (Django docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django")}}</p> + +<h2 id="Nesse_Módulo">Nesse Módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: Website de uma Biblioteca Local</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/skeleton_website">Tutorial Django Parte 2: Criando a base do website</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Models">Tutorial Django Parte 3: Utilizando models</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Admin_site">Tutorial Django Parte 4: Django admin site</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Home_page">Tutorial Django Parte 5: Criando nossa página principal</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Generic_views">Tutorial Django Parte 6: Lista genérica e detail views</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Sessions">Tutorial Django Parte 7: Sessões de Framework </a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Forms">Tutorial Django Parte 9: Trabalhando com formulários</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Testing">Tutorial Django Parte 10: Testando uma aplicação web Django</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial Django Parte 11: Implantando Django em produção</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/web_application_security">Segurança de aplicações web Django</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/hospedagem/index.html b/files/pt-br/learn/server-side/django/hospedagem/index.html new file mode 100644 index 0000000000..baa2217b71 --- /dev/null +++ b/files/pt-br/learn/server-side/django/hospedagem/index.html @@ -0,0 +1,692 @@ +--- +title: 'Tutorial Django Parte 11: Hospedando Django para produção' +slug: Learn/Server-side/Django/Hospedagem +tags: + - Codificação de Scripts + - Deploy do django + - Fazendo deploy + - Iniciante + - django + - servidor web +translation_of: Learn/Server-side/Django/Deployment +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Testing", "Learn/Server-side/Django/web_application_security", "Learn/Server-side/Django")}}</div> + +<p class="summary">Agora que criou (e testou) um fantástico website de Biblioteca Local, vai querer instalá-lo em um servidor web público para que possa ser acessado pelo pessoal da biblioteca e membros através da Internet. Este artigo fornece uma visão geral de como poderá encontrar um servidor de hospedagem para instalar o seu web site, e o que precisa fazer para ter o seu site web pronto para produção.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td> + <p>Completar todos os tópicos do tutorial anterior, incluindo o <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Testing">Tutorial Django Parte 10: Testando uma aplicação web Django.</a></p> + </td> + </tr> + <tr> + <th scope="row">Objectivo:</th> + <td>Para saber onde e como se pode hospedar uma aplicação Django na produção.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_geral">Visão geral</h2> + +<p>Uma vez terminado o seu website (ou terminado "o suficiente" para iniciar testes públicos) vai precisar publicá-lo em um host mais público e acessível do que o seu computador de desenvolvimento pessoal.</p> + +<p>Até agora tem trabalhado em um ambiente de desenvolvimento, utilizando o servidor web de desenvolvimento Django para compartilhar o seu site com o navegador/rede local, e executando o seu site com configurações de desenvolvimento (inseguras) que expõem debug e outras informações privadas. Antes de poder hospedar um website externamente, vai precisar fazer primeiro:</p> + +<ul> + <li>Faça algumas alterações nas configurações do seu projeto.</li> + <li>Escolher um ambiente para hospedar a aplicação Django.</li> + <li>Escolher um ambiente para hospedar qualquer arquivo estático.</li> + <li>Configurar uma infraestrutura de nível de produção para servir seu website.</li> +</ul> + +<p>Este tutorial fornece algumas orientações sobre suas opções para escolher um site de hospedagem, uma breve visão geral do que você precisa fazer para deixar seu aplicativo Django pronto para produção e um exemplo prático de como instalar o site Biblioteca Local no serviço de hospedagem em nuvem do <a href="https://www.heroku.com/">Heroku.</a></p> + +<h2 id="O_que_é_um_ambiente_de_produção">O que é um ambiente de produção?</h2> + +<p>O ambiente de produção é o ambiente fornecido pelo computador/servidor onde você executará seu site para consumo externo. O ambiente inclui:</p> + +<ul> + <li>Hardware de computador no qual o website é executado.</li> + <li>Sistema operacional (por exemplo, Linux, Windows).</li> + <li>Linguagem de programação de tempo de execução e bibliotecas de estrutura sobre as quais seu site é escrito.</li> + <li>Servidor da Web usado para servir páginas e outros conteúdos (por exemplo, Nginx, Apache).</li> + <li>Servidor de aplicativos que passa solicitações "dinâmicas" entre seu site Django e o servidor web.</li> + <li>Bancos de dados dos quais seu site depende.</li> +</ul> + +<div class="note"> +<p><strong>Nota: </strong>Dependendo de como sua produção está configurada, você também pode ter um proxy reverso, load balancer(balanceador de carga), etc.</p> +</div> + +<p>O computador/servidor pode estar localizado em suas instalações e conectado à Internet por um link rápido, mas é muito mais comum usar um computador hospedado "na nuvem". O que isso realmente significa é que seu código é executado em algum computador remoto (ou possivelmente em um computador "virtual") no(s) centro(s) de dados da empresa de hospedagem. O servidor remoto geralmente oferece algum nível garantido de recursos de computação (por exemplo, CPU, RAM, memória de armazenamento, etc.) e conectividade com a Internet por um determinado preço.</p> + +<p>Esse tipo de hardware de computação/rede acessível remotamente é conhecido como <em>Infraestrutura como Serviço</em> (IaaS). Muitos fornecedores de IaaS fornecem opções para pré-instalar um sistema operacional específico, no qual você deve instalar os outros componentes de seu ambiente de produção. Outros fornecedores permitem que você selecione ambientes com mais recursos, talvez incluindo uma configuração completa de Django e servidor web.</p> + +<div class="note"> +<p><strong>Nota:</strong> Ambientes pré-construídos podem tornar a configuração do seu site muito fácil porque reduzem a configuração, mas as opções disponíveis podem limitar você a um servidor desconhecido (ou outros componentes) e podem ser baseadas em uma versão mais antiga do sistema operacional. Freqüentemente, é melhor instalar você mesmo os componentes, para obter os que deseja e, quando precisar atualizar partes do sistema, tenha uma ideia de por onde começar!</p> +</div> + +<p>Outros provedores de hospedagem oferecem suporte a Django como parte de uma oferta de <em>Plataforma como Serviço</em> (PaaS). Nesse tipo de hospedagem, você não precisa se preocupar com a maior parte do seu ambiente de produção (servidor da web, servidor de aplicativos, balanceadores de carga), pois a plataforma host cuida disso para você (junto com a maior parte do que você precisa fazer para para dimensionar seu aplicativo). Isso torna a implantação muito fácil, porque você só precisa se concentrar em seu aplicativo da web e não em toda a outra infraestrutura de servidor.</p> + +<p>Alguns desenvolvedores escolherão a maior flexibilidade fornecida por IaaS em vez de PaaS, enquanto outros apreciarão a sobrecarga de manutenção reduzida e escalonamento mais fácil de PaaS. Quando você está começando, configurar seu site em um sistema PaaS é muito mais fácil e é isso que faremos neste tutorial.</p> + +<div class="note"> +<p><strong>Dica:</strong> Se você escolher um provedor de hospedagem compatível com Python / Django, ele deve fornecer instruções sobre como configurar um site Django usando diferentes configurações de servidor da web, servidor de aplicativos, proxy reverso, etc (isso não será relevante se você escolher um PaaS ) Por exemplo, existem muitos guias passo a passo para várias configurações nos <a href="https://www.digitalocean.com/community/tutorials?q=django">documentos da comunidade Digital Ocean Django.</a></p> +</div> + +<h2 id="Escolhendo_um_provedor_de_hospedagem">Escolhendo um provedor de hospedagem</h2> + +<p>Existem mais de 100 provedores de hospedagem que são conhecidos por oferecer suporte ativo ou funcionar bem com o Django (você pode encontrar uma lista bastante exaustiva em <a href="https://djangofriendly.com/index.html">Djangofriendly hosts</a>). Esses fornecedores oferecem diferentes tipos de ambientes (IaaS, PaaS) e diferentes níveis de recursos de computação e rede a preços diferentes.</p> + +<p>Algumas coisas a serem consideradas ao escolher um host:</p> + +<ul> + <li>O quão ocupado seu site provavelmente estará e o custo dos dados e recursos de computação necessários para atender a essa demanda.</li> + <li>Nível de suporte para escalonamento horizontal (adicionando mais máquinas) e verticalmente (atualizando para máquinas mais potentes) e os custos de fazê-lo.</li> + <li>Onde o fornecedor possui centros de dados e, portanto, onde o acesso provavelmente será mais rápido.</li> + <li>O histórico de tempo de atividade e desempenho do tempo de inatividade do host.</li> + <li>Ferramentas fornecidas para gerenciar o site - são fáceis de usar e seguras (por exemplo, SFTP x FTP).</li> + <li>Estruturas integradas para monitorar seu servidor.</li> + <li>Limitações conhecidas. Alguns hosts bloqueiam deliberadamente certos serviços (por exemplo, e-mail). Outros oferecem apenas um certo número de horas de "tempo de vida" em algumas faixas de preço ou oferecem apenas uma pequena quantidade de armazenamento.</li> + <li>Benefícios adicionais. Alguns provedores oferecem nomes de domínio gratuitos e suporte para certificados SSL que, de outra forma, você teria que pagar.</li> + <li>Se o nível "gratuito" com o qual você está contando expira com o tempo e se o custo de migrar para um nível mais caro significa que você teria ficado melhor usando algum outro serviço em primeiro lugar!</li> +</ul> + +<p>A boa notícia quando você está começando é que existem alguns sites que fornecem ambientes de computação de "avaliação", "desenvolvedor" ou "amador" de graça. Esses são sempre ambientes com recursos limitados / restritos e você precisa estar ciente de que eles podem expirar após um período introdutório. No entanto, eles são ótimos para testar sites de baixo tráfego em um ambiente real e podem fornecer uma migração fácil para pagar por mais recursos quando seu site ficar mais ocupado. As escolhas populares nesta categoria incluem <a href="https://www.heroku.com/">Heroku</a>, <a href="https://www.pythonanywhere.com/">Python Anywhere</a>, <a href="https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/billing-free-tier.html">Amazon Web Services</a>, <a href="https://azure.microsoft.com/en-us/pricing/details/app-service/windows/">Microsoft Azure</a>, etc.</p> + +<p>Muitos provedores também têm uma camada "básica" que fornece níveis mais úteis de capacidade de computação e menos limitações. <a href="https://www.digitalocean.com/">Digital Ocean</a> e <a href="https://www.pythonanywhere.com/">Python Anywhere</a> são exemplos de provedores de hospedagem populares que oferecem uma camada de computação básica relativamente barata (na faixa de US$5 a US$10 por mês).</p> + +<div class="note"> +<p><strong>Nota: </strong>Lembre-se de que o preço não é o único critério de seleção. Se o seu site for bem-sucedido, pode ser que a escalabilidade seja a consideração mais importante.</p> +</div> + +<h2 id="Preparando_seu_site_para_publicação">Preparando seu site para publicação</h2> + +<p>O <a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Server-side/Django/skeleton_website">esqueleto do site do Django</a> criado usando as ferramentas django-admin e manage.py é configurado para tornar o desenvolvimento mais fácil. Muitas das configurações do projeto Django (especificadas em settings.py) devem ser diferentes para produção, por motivos de segurança ou desempenho.</p> + +<div class="note"> +<p><strong>Dica:</strong> É comum ter um arquivo <strong>settings.py</strong> separado para produção e importar configurações confidenciais de um arquivo separado ou de uma variável de ambiente. Este arquivo deve ser protegido, mesmo se o resto do código-fonte estiver disponível em um repositório público.</p> +</div> + +<p>As configurações críticas que você deve verificar são:</p> + +<ul> + <li><code>DEBUG</code>. Isso deve ser definido como <code>False</code> em produção (<code>DEBUG = False</code>). Isso impede que o rastreamento de depuração sensível/confidencial e as informações variáveis sejam exibidas.</li> + <li><code>SECRET_KEY</code>. Este é um grande valor aleatório usado para proteção contra CSRF etc. É importante que a chave usada na produção não esteja no controle de origem ou acessível fora do servidor de produção. Os documentos do Django sugerem que isso pode ser melhor carregado de uma variável de ambiente ou lido de um arquivo somente servidor. + <pre class="brush: python notranslate"># Read SECRET_KEY from an environment variable +import os +SECRET_KEY = os.environ['SECRET_KEY'] + +# OR + +# Read secret key from a file +with open('/etc/secret_key.txt') as f: + SECRET_KEY = f.read().strip()</pre> + </li> +</ul> + +<p>Vamos mudar o aplicativo LocalLibrary para que possamos ler nosso <code>SECRET_KEY</code> e <code>DEBUG</code> variáveis de variáveis de ambiente se forem definidas, mas caso contrário, use os valores padrão no arquivo de configuração.</p> + +<p>Abra <strong>/locallibrary/settings.py</strong>, desative o original <code>SECRET_KEY</code>configuração e adicione as novas linhas conforme mostrado abaixo em <strong>negrito</strong>. Durante o desenvolvimento, nenhuma variável de ambiente será especificada para a chave, então o valor padrão será usado (não importa qual chave você usa aqui, ou se a chave "vaza", porque você não a usará na produção).</p> + +<pre class="brush: python notranslate"># SECURITY WARNING: keep the secret key used in production secret! +# SECRET_KEY = 'cg#p$g+j9tax!#a3cup@1$8obt2_+&k3q+pmu)5%asj6yjpkag' +<strong>import os</strong> +<strong>SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'cg#p$g+j9tax!#a3cup@1$8obt2_+&k3q+pmu)5%asj6yjpkag')</strong> +</pre> + +<p>Em seguida, comente o existente <code>DEBUG</code> configuração e adicione a nova linha mostrada abaixo.</p> + +<pre class="brush: python notranslate"># SECURITY WARNING: don't run with debug turned on in production! +# DEBUG = True +<strong>DEBUG = os.environ.get('DJANGO_DEBUG', '') != 'False'</strong> +</pre> + +<p>O valor do <code>DEBUG</code> será <code>True</code> por padrão, mas será apenas <code>False</code> se o valor do <code>DJANGO_DEBUG</code> variável de ambiente é definida para <code>False</code>. Observe que as variáveis de ambiente são strings e não tipos Python. Portanto, precisamos comparar strings. A única maneira de definir o <code>DEBUG</code> variável para <code>False</code> é realmente configurá-lo para a string <code>False</code></p> + +<p>Você pode definir a variável de ambiente como False, emitindo o seguinte comando:</p> + +<pre class="brush: bash notranslate">export DJANGO_DEBUG=False</pre> + +<p>Uma lista de verificação completa das configurações que você pode querer mudar é fornecida na <a href="https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/">Lista de verificação de implantação</a> (documentos do Django). Você também pode listar vários deles usando o comando de terminal abaixo:</p> + +<pre class="brush: python notranslate">python3 manage.py check --deploy +</pre> + +<h2 id="Exemplo_Instalando_LocalLibrary_no_Heroku">Exemplo: Instalando LocalLibrary no Heroku</h2> + +<p>Esta seção fornece uma demonstração prática de como instalar a LocalLibrary na nuvem <a href="https://www.heroku.com/">Heroku PaaS.</a></p> + +<h3 id="Por_que_Heroku">Por que Heroku?</h3> + +<p>Heroku é um dos mais antigos e populares serviços de PaaS baseados em nuvem. Originalmente, ele suportava apenas aplicativos Ruby, mas agora pode ser usado para hospedar aplicativos de muitos ambientes de programação, incluindo Django!</p> + +<p>Estamos optando por usar o Heroku por vários motivos:</p> + +<ul> + <li>O Heroku tem um <a href="https://www.heroku.com/pricing">nível gratuito</a> que é realmente gratuito (embora com algumas limitações).</li> + <li>Como PaaS, o Heroku cuida de grande parte da infraestrutura web para nós. Isso torna muito mais fácil começar, porque você não se preocupa com servidores, balanceadores de carga, proxies reversos ou qualquer outra infraestrutura web que o Heroku fornece para nós nos bastidores.</li> + <li>Embora tenha algumas limitações, elas não afetarão este aplicativo específico. Por exemplo: + <ul> + <li>O Heroku fornece apenas armazenamento de curta duração, portanto, os arquivos carregados pelo usuário não podem ser armazenados com segurança no próprio Heroku.</li> + <li>O nível gratuito suspenderá um aplicativo da web inativo se não houver solicitações dentro de um período de meia hora. O site pode levar vários segundos para responder quando for ativado.</li> + <li>O nível gratuito limita o tempo de execução do seu site a uma determinada quantidade de horas todos os meses (sem incluir o tempo em que o site fica "adormecido"). Isso é bom para um site de baixo uso/demonstração, mas não será adequado se 100% de tempo de atividade for necessário.</li> + <li>Outras limitações estão listadas em <a href="https://devcenter.heroku.com/articles/limits">Limites</a> (documentos do Heroku).</li> + </ul> + </li> + <li>Na maioria das vezes, ele simplesmente funciona e, se você acabar adorando, dimensionar seu aplicativo é muito fácil.</li> +</ul> + +<p>Embora o Heroku seja perfeito para hospedar esta demonstração, pode não ser perfeito para o seu site real. O Heroku torna as coisas fáceis de configurar e escalar, ao custo de ser menos flexível e potencialmente muito mais caro depois que você sai do nível gratuito.</p> + +<h3 id="How_does_Heroku_work">How does Heroku work?</h3> + +<p>Heroku runs Django websites within one or more "<a href="https://devcenter.heroku.com/articles/dynos">Dynos</a>", which are isolated, virtualized Unix containers that provide the environment required to run an application. The dynos are completely isolated and have an <em>ephemeral</em> file system (a short-lived file system that is cleaned/emptied every time the dyno restarts). The only thing that dynos share by default are application <a href="https://devcenter.heroku.com/articles/config-vars">configuration variables</a>. Heroku internally uses a load balancer to distribute web traffic to all "web" dynos. Since nothing is shared between them, Heroku can scale an app horizontally simply by adding more dynos (though of course you may also need to scale your database to accept additional connections).</p> + +<p>Because the file system is ephemeral you can't install services required by your application directly (e.g. databases, queues, caching systems, storage, email services, etc). Instead Heroku web applications use backing services provided as independent "add-ons" by Heroku or 3rd parties. Once attached to your web application, the dynos access the services using information contained in application configuration variables.</p> + +<p>In order to execute your application Heroku needs to be able to set up the appropriate environment and dependencies, and also understand how it is launched. For Django apps we provide this information in a number of text files:</p> + +<ul> + <li><strong>runtime.txt</strong>:<strong> </strong>the programming language and version to use.</li> + <li><strong>requirements.txt</strong>: the Python component dependencies, including Django.</li> + <li><strong>Procfile</strong>: A list of processes to be executed to start the web application. For Django this will usually be the Gunicorn web application server (with a <code>.wsgi</code> script).</li> + <li><strong>wsgi.py</strong>: <a href="http://wsgi.readthedocs.io/en/latest/what.html">WSGI</a> configuration to call our Django application in the Heroku environment.</li> +</ul> + +<p>Developers interact with Heroku using a special client app/terminal, which is much like a Unix Bash shell. This allows you to upload code that is stored in a git repository, inspect the running processes, see logs, set configuration variables and much more!</p> + +<p>In order to get our application to work on Heroku we'll need to put our Django web application into a git repository, add the files above, integrate with a database add-on, and make changes to properly handle static files.</p> + +<p>Once we've done all that we can set up a Heroku account, get the Heroku client, and use it to install our website.</p> + +<div class="note"> +<p><strong>Note:</strong> The instructions below reflect how to work with Heroku at time of writing. If Heroku significantly change their processes, you may wish to instead check their setup documents: <a href="https://devcenter.heroku.com/articles/getting-started-with-python#introduction">Getting Started on Heroku with Django</a>.</p> +</div> + +<p>That's all the overview you need in order to get started (see <a href="https://devcenter.heroku.com/articles/how-heroku-works">How Heroku works</a> for a more comprehensive guide).</p> + +<h3 id="Creating_an_application_repository_in_Github">Creating an application repository in Github</h3> + +<p>Heroku is closely integrated with the <strong>git</strong> source code version control system, using it to upload/synchronise any changes you make to the live system. It does this by adding a new heroku "remote" repository named <em>heroku</em> pointing to a repository for your source on the Heroku cloud. During development you use git to store changes on your "master" repository. When you want to deploy your site, you sync your changes to the Heroku repository.</p> + +<div class="note"> +<p><strong>Note:</strong> If you're used to following good software development practices you are probably already using git or some other SCM system. If you already have a git repository, then you can skip this step.</p> +</div> + +<p>There are a lot of ways to work with git, but one of the easiest is to first set up an account on <a href="https://github.com/">Github</a>, create the repository there, and then sync to it locally:</p> + +<ol> + <li>Visit <a href="https://github.com/">https://github.com/</a> and create an account.</li> + <li>Once you are logged in, click the <strong>+</strong> link in the top toolbar and select <strong>New repository</strong>.</li> + <li>Fill in all the fields on this form. While these are not compulsory, they are strongly recommended. + <ul> + <li>Enter a new repository name (e.g. <em>django_local_library</em>), and description (e.g. "Local Library website written in Django".</li> + <li>Choose <strong>Python</strong> in the <em>Add .gitignore</em> selection list.</li> + <li>Choose your preferred license in the <em>Add license</em> selection list.</li> + <li>Check <strong>Initialize this repository with a README</strong>.</li> + </ul> + </li> + <li>Press <strong>Create repository</strong>.</li> + <li>Click the green "<strong>Clone or download</strong>" button on your new repo page.</li> + <li>Copy the URL value from the text field inside the dialog box that appears (it should be something like: <strong>https://github.com/<em><your_git_user_id></em>/django_local_library.git</strong>).</li> +</ol> + +<p>Now that the repository ("repo") is created we are going to want to clone it on our local computer:</p> + +<ol> + <li>Install <em>git</em> for your local computer (you can find versions for different platforms <a href="https://git-scm.com/downloads">here</a>).</li> + <li>Open a command prompt/terminal and clone your repository using the URL you copied above: + <pre class="brush: bash notranslate">git clone https://github.com/<strong><em><your_git_user_id></em></strong>/django_local_library.git +</pre> + This will create the repository in a new folder in the current working directory.</li> + <li>Navigate into the new repo. + <pre class="brush: bash notranslate">cd django_local_library</pre> + </li> +</ol> + +<p>The final steps are to copy your application into this local project directory and then add (or "push", in git lingo) the local repository to your remote Github repository:</p> + +<ol> + <li>Copy your Django application into this folder (all the files at the same level as <strong>manage.py</strong> and below, <strong>not</strong> their containing locallibrary folder).</li> + <li>Open the <strong>.gitignore</strong> file, copy the following lines into the bottom of it, and then save (this file is used to identify files that should not be uploaded to git by default). + <pre class="notranslate"># Text backup files +*.bak + +# Database +*.sqlite3</pre> + </li> + <li>Open a command prompt/terminal and use the <code>add</code> command to add all files to git. This adds the files which aren't ignored by the <strong>.gitignore</strong> file to the "staging area". + <pre class="brush: bash notranslate">git add -A +</pre> + </li> + <li>Use the <code>status</code> command to check that all files you are about to <code>commit</code> are correct (you want to include source files, not binaries, temporary files etc.). It should look a bit like the listing below. + <pre class="notranslate">> git status +On branch master +Your branch is up-to-date with 'origin/master'. +Changes to be committed: + (use "git reset HEAD <file>..." to unstage) + + modified: .gitignore + new file: catalog/__init__.py + ... + new file: catalog/migrations/0001_initial.py + ... + new file: templates/registration/password_reset_form.html</pre> + </li> + <li>When you're satisfied, <code>commit</code> the files to your local repository. This is essentially equivalent to signing off on the changes and making them an official part of the local repository. + <pre class="brush: bash notranslate">git commit -m "First version of application moved into github"</pre> + </li> + <li>At this point, the remote repository has not been changed. Synchronise (<code>push</code>) your local repository to the remote Github repository using the following command: + <pre class="notranslate">git push origin master</pre> + </li> +</ol> + +<p>When this operation completes, you should be able to go back to the page on Github where you created your repo, refresh the page, and see that your whole application has now been uploaded. You can continue to update your repository as files change using this add/commit/push cycle.</p> + +<div class="note"> +<p><strong>Tip:</strong> This is a good point to make a backup of your "vanilla" project — while some of the changes we're going to be making in the following sections might be useful for deployment on any platform (or development) others might not.</p> + +<p>The <em>best</em> way to do this is to use <em>git</em> to manage your revisions. With <em>git</em> you can not only go back to a particular old version, but you can maintain this in a separate "branch" from your production changes and cherry-pick any changes to move between production and development branches. <a href="https://help.github.com/articles/good-resources-for-learning-git-and-github/">Learning Git</a> is well worth the effort, but is beyond the scope of this topic.</p> + +<p>The <em>easiest</em> way to do this is to just copy your files into another location. Use whichever approach best matches your knowledge of git!</p> +</div> + +<h3 id="Update_the_app_for_Heroku">Update the app for Heroku</h3> + +<p>This section explains the changes you'll need to make to our <em>LocalLibrary</em> application to get it to work on Heroku. While Heroku's <a href="https://devcenter.heroku.com/articles/getting-started-with-python#introduction">Getting Started on Heroku with Django</a> instructions assume you will use the Heroku client to also run your local development environment, our changes are compatible with the existing Django development server and the workflows we've already learned.</p> + +<h4 id="Procfile">Procfile</h4> + +<p>Create the file <code>Procfile</code> (no extension) in the root of your GitHub repository to declare the application's process types and entry points. Copy the following text into it:</p> + +<pre class="notranslate">web: gunicorn locallibrary.wsgi --log-file -</pre> + +<p>The "<code>web:</code>" tells Heroku that this is a web dyno and can be sent HTTP traffic. The process to start in this dyno is <em>gunicorn</em>, which is a popular web application server that Heroku recommends. We start Gunicorn using the configuration information in the module <code>locallibrary.wsgi</code> (created with our application skeleton: <strong>/locallibrary/wsgi.py</strong>).</p> + +<h4 id="Gunicorn">Gunicorn</h4> + +<p><a href="http://gunicorn.org/">Gunicorn</a> is the recommended HTTP server for use with Django on Heroku (as referenced in the Procfile above). It is a pure-Python HTTP server for WSGI applications that can run multiple Python concurrent processes within a single dyno (see <a href="https://devcenter.heroku.com/articles/python-gunicorn">Deploying Python applications with Gunicorn</a> for more information).</p> + +<p>While we won't need <em>Gunicorn</em> to serve our LocalLibrary application during development, we'll install it so that it becomes part of our <a href="#requirements">requirements</a> for Heroku to set up on the remote server.</p> + +<p>Install <em>Gunicorn</em> locally on the command line using <em>pip</em> (which we installed when <a href="/en-US/docs/Learn/Server-side/Django/development_environment">setting up the development environment</a>):</p> + +<div class="blockIndicator note"> +<p>Note: Make sure that you're in your Python virtual environment (use the <code>workon [name-of-virtual-environment]</code> command) before you install <em>Gunicorn</em> and further modules with <em>pip</em>, or you might experience problems with importing these modules in your <strong>/locallibrary/settings.py</strong> file in the later sections. </p> +</div> + +<pre class="brush: bash notranslate">pip3 install gunicorn +</pre> + +<h4 id="Database_configuration">Database configuration</h4> + +<p>We can't use the default SQLite database on Heroku because it is file-based, and it would be deleted from the <em>ephemeral</em> file system every time the application restarts (typically once a day, and every time the application or its configuration variables are changed).</p> + +<p>The Heroku mechanism for handling this situation is to use a <a href="https://elements.heroku.com/addons#data-stores">database add-on</a> and configure the web application using information from an environment <a href="https://devcenter.heroku.com/articles/config-vars">configuration variable</a>, set by the add-on. There are quite a lot of database options, but we'll use the <a href="https://devcenter.heroku.com/articles/heroku-postgres-plans#plan-tiers">hobby tier</a> of the <em>Heroku postgres</em> database as this is free, supported by Django, and automatically added to our new Heroku apps when using the free hobby dyno plan tier.</p> + +<p>The database connection information is supplied to the web dyno using a configuration variable named <code>DATABASE_URL</code>. Rather than hard-coding this information into Django, Heroku recommends that developers use the <a href="https://warehouse.python.org/project/dj-database-url/">dj-database-url</a> package to parse the <code>DATABASE_URL</code> environment variable and automatically convert it to Django’s desired configuration format. In addition to installing the <em>dj-database-url</em> package we'll also need to install <a href="http://initd.org/psycopg/">psycopg2</a>, as Django needs this to interact with Postgres databases.</p> + +<h5 id="dj-database-url_Django_database_configuration_from_environment_variable">dj-database-url (Django database configuration from environment variable)</h5> + +<p>Install <em>dj-database-url</em> locally so that it becomes part of our <a href="#requirements">requirements</a> for Heroku to set up on the remote server:</p> + +<pre class="notranslate">$ pip3 install dj-database-url +</pre> + +<h5 id="settings.py">settings.py</h5> + +<p>Open <strong>/locallibrary/settings.py</strong> and copy the following configuration into the bottom of the file:</p> + +<pre class="notranslate"># Heroku: Update database configuration from $DATABASE_URL. +import dj_database_url +db_from_env = dj_database_url.config(conn_max_age=500) +DATABASES['default'].update(db_from_env)</pre> + +<div class="note"> +<p><strong>Note:</strong></p> + +<ul> + <li>We'll still be using SQLite during development because the <code>DATABASE_URL</code> environment variable will not be set on our development computer.</li> + <li>The value <code>conn_max_age=500</code> makes the connection persistent, which is far more efficient than recreating the connection on every request cycle. However, this is optional and can be removed if needed.</li> +</ul> +</div> + +<h5 id="psycopg2_Python_Postgres_database_support">psycopg2 (Python Postgres database support)</h5> + +<p>Django needs <em>psycopg2</em> to work with Postgres databases and you will need to add this to the <a href="#requirements">requirements.txt</a> for Heroku to set this up on the remote server (as discussed in the requirements section below).</p> + +<p>Django will use our SQLite database locally by default, because the <code>DATABASE_URL</code> environment variable isn't set in our local environment. If you want to switch to Postgres completely and use our Heroku free tier database for both development and production then you can. For example, to install psycopg2 and its dependencies locally on a Debian-flavoured Linux system you would use the following Bash/terminal commands:</p> + +<pre class="brush: bash notranslate"><code>sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib</code> +pip3 install psycopg2-binary +</pre> + +<p>Installation instructions for the other platforms can be found on the <a href="http://initd.org/psycopg/docs/install.html">psycopg2 website here</a>.</p> + +<p>However, you don't need to do this — you don't need PostgreSQL active on the local computer, as long as you give it to Heroku as a requirement, in <code>requirements.txt</code> (see below).</p> + +<h4 id="Serving_static_files_in_production">Serving static files in production</h4> + +<p>During development we used Django and the Django development web server to serve our static files (CSS, JavaScript, etc.). In a production environment we instead typically serve static files from a content delivery network (CDN) or the web server.</p> + +<div class="note"> +<p><strong>Note:</strong> Serving static files via Django/web application is inefficient because the requests have to pass through unnecessary additional code (Django) rather than being handled directly by the web server or a completely separate CDN. While this doesn't matter for local use during development, it would have a significant performance impact if we were to use the same approach in production. </p> +</div> + +<p>To make it easy to host static files separately from the Django web application, Django provides the <em>collectstatic</em> tool to collect these files for deployment (there is a settings variable that defines where the files should be collected when <em>collectstatic</em> is run). Django templates refer to the hosting location of the static files relative to a settings variable (<code>STATIC_URL</code>), so that this can be changed if the static files are moved to another host/server.</p> + +<p>The relevant setting variables are:</p> + +<ul> + <li><code>STATIC_URL</code>: This is the base URL location from which static files will be served, for example on a CDN. This is used for the static template variable that is accessed in our base template (see <a href="/en-US/docs/Learn/Server-side/Django/Home_page">Django Tutorial Part 5: Creating our home page</a>).</li> + <li><code>STATIC_ROOT</code>: This is the absolute path to a directory where Django's "collectstatic" tool will gather any static files referenced in our templates. Once collected, these can then be uploaded as a group to wherever the files are to be hosted.</li> + <li><code>STATICFILES_DIRS</code>: This lists additional directories that Django's collectstatic tool should search for static files.</li> +</ul> + +<h5 id="settings.py_2">settings.py</h5> + +<p>Open <strong>/locallibrary/settings.py</strong> and copy the following configuration into the bottom of the file. The <code>BASE_DIR</code> should already have been defined in your file (the <code>STATIC_URL</code> may already have been defined within the file when it was created. While it will cause no harm, you might as well delete the duplicate previous reference).</p> + +<pre class="notranslate"># Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/2.1/howto/static-files/ + +# The absolute path to the directory where collectstatic will collect static files for deployment. +STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') + +# The URL to use when referring to static files (where they will be served from) +STATIC_URL = '/static/' +</pre> + +<p>We'll actually do the file serving using a library called <a href="https://warehouse.python.org/project/whitenoise/">WhiteNoise</a>, which we install and configure in the next section.</p> + +<p>For more information, see <a href="https://devcenter.heroku.com/articles/django-assets">Django and Static Assets</a> (Heroku docs).</p> + +<h4 id="Whitenoise">Whitenoise</h4> + +<p>There are many ways to serve static files in production (we saw the relevant Django settings in the previous sections). Heroku recommends using the <a href="https://warehouse.python.org/project/whitenoise/">WhiteNoise</a> project for serving of static assets directly from Gunicorn in production.</p> + +<div class="note"> +<p><strong>Note: </strong>Heroku automatically calls <em>collectstatic</em> and prepares your static files for use by WhiteNoise after it uploads your application. Check out <a href="https://warehouse.python.org/project/whitenoise/">WhiteNoise</a> documentation for an explanation of how it works and why the implementation is a relatively efficient method for serving these files.</p> +</div> + +<p>The steps to set up <em>WhiteNoise</em> to use with the project are <a href="http://whitenoise.evans.io/en/stable/django.html">given here</a> (and reproduced below):</p> + +<h5 id="WhiteNoise">WhiteNoise</h5> + +<p>Install whitenoise locally using the following command:</p> + +<pre class="notranslate">$ pip3 install whitenoise +</pre> + +<h5 id="settings.py_3">settings.py</h5> + +<p>To install <em>WhiteNoise</em> into your Django application, open <strong>/locallibrary/settings.py</strong>, find the <code>MIDDLEWARE</code> setting and add the <code>WhiteNoiseMiddleware</code> near the top of the list, just below the <code>SecurityMiddleware</code>:</p> + +<pre class="notranslate">MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + <strong>'whitenoise.middleware.WhiteNoiseMiddleware',</strong> + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] +</pre> + +<p>Optionally, you can reduce the size of the static files when they are served (this is more efficient). Just add the following to the bottom of <strong>/locallibrary/settings.py</strong>:</p> + +<pre class="notranslate"># Simplified static file serving. +# https://warehouse.python.org/project/whitenoise/ +STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' +</pre> + +<h4 id="Requirements">Requirements</h4> + +<p>The Python requirements of your web application must be stored in a file <strong>requirements.txt</strong> in the root of your repository. Heroku will then install these automatically when it rebuilds your environment. You can create this file using <em>pip</em> on the command line (run the following in the repo root):</p> + +<pre class="brush: bash notranslate">pip3 freeze > requirements.txt</pre> + +<p>After installing all the different dependencies above, your <strong>requirements.txt</strong> file should have <em>at least</em> these items listed (though the version numbers may be different). Please delete any other dependencies not listed below, unless you've explicitly added them for this application.</p> + +<pre class="notranslate">dj-database-url==0.5.0 +Django==2.1.5 +gunicorn==19.9.0 +<strong>psycopg2-binary==2.7.7</strong> +whitenoise==4.1.2 +</pre> + +<div class="note"> +<p>Make sure that a <strong>psycopg2</strong> line like the one above is present! Even if you didn't install this locally then you should still add it to <strong>requirements.txt</strong>.</p> +</div> + +<h4 id="Runtime">Runtime</h4> + +<p>The <strong>runtime.txt</strong> file, if defined, tells Heroku which programming language to use. Create the file in the root of the repo and add the following text:</p> + +<pre class="notranslate">python-3.7.0</pre> + +<div class="note"> +<p><strong>Note:</strong> Heroku only supports a small number of <a href="https://devcenter.heroku.com/articles/python-support#supported-python-runtimes">Python runtimes</a> (at time of writing, this includes the one above). Heroku will use a supported runtime irrespective of the value specified in this file.</p> +</div> + +<h4 id="Re-test_and_save_changes_to_Github">Re-test and save changes to Github</h4> + +<p>Before we proceed, lets test the site again locally and make sure it wasn't broken by any of our changes above. Run the development web server as usual and then check the site still works as you expect on your browser.</p> + +<pre class="brush: bash notranslate">python3 manage.py runserver</pre> + +<p>Next, lets <code>push</code> our changes to Github. In the terminal (after having navigated to our local repository), enter the following commands:</p> + +<pre class="brush: python notranslate">git add -A +git commit -m "Added files and changes required for deployment to heroku" +git push origin master +</pre> + +<p>We should now be ready to start deploying LocalLibrary on Heroku.</p> + +<h3 id="Get_a_Heroku_account">Get a Heroku account</h3> + +<p>To start using Heroku you will first need to create an account:</p> + +<ul> + <li>Go to <a href="https://www.heroku.com/">www.heroku.com</a> and click the <strong>SIGN UP FOR FREE</strong> button.</li> + <li>Enter your details and then press <strong>CREATE FREE ACCOUNT</strong>. You'll be asked to check your account for a sign-up email.</li> + <li>Click the account activation link in the signup email. You'll be taken back to your account on the web browser.</li> + <li>Enter your password and click <strong>SET PASSWORD AND LOGIN</strong>.</li> + <li>You'll then be logged in and taken to the Heroku dashboard: <a href="https://dashboard.heroku.com/apps">https://dashboard.heroku.com/apps</a>.</li> +</ul> + +<h3 id="Install_the_client">Install the client</h3> + +<p>Download and install the Heroku client by following the <a href="https://devcenter.heroku.com/articles/getting-started-with-python#set-up">instructions on Heroku here</a>.</p> + +<p>After the client is installed you will be able run commands. For example to get help on the client:</p> + +<pre class="brush: bash notranslate">heroku help +</pre> + +<h3 id="Create_and_upload_the_website">Create and upload the website</h3> + +<p>To create the app we run the "create" command in the root directory of our repository. This creates a git remote ("pointer to a remote repository") named <em>heroku</em> in our local git environment.</p> + +<pre class="brush: bash notranslate">heroku create</pre> + +<div class="note"> +<p><strong>Note:</strong> You can name the remote if you like by specifying a value after "create". If you don't then you'll get a random name. The name is used in the default URL.</p> +</div> + +<p>We can then push our app to the Heroku repository as shown below. This will upload the app, package it in a dyno, run collectstatic, and start the site.</p> + +<pre class="brush: bash notranslate">git push heroku master</pre> + +<p>If we're lucky, the app is now "running" on the site, but it won't be working properly because we haven't set up the database tables for use by our application. To do this we need to use the <code>heroku run</code> command and start a "<a href="https://devcenter.heroku.com/articles/deploying-python#one-off-dynos">one off dyno</a>" to perform a migrate operation. Enter the following command in your terminal:</p> + +<pre class="brush: bash notranslate">heroku run python manage.py migrate</pre> + +<p>We're also going to need to be able to add books and authors, so lets also create our administration superuser, again using a one-off dyno:</p> + +<pre class="brush: bash notranslate">heroku run python manage.py createsuperuser</pre> + +<p>Once this is complete, we can look at the site. It should work, although it won't have any books in it yet. To open your browser to the new website, use the command:</p> + +<pre class="brush: bash notranslate">heroku open</pre> + +<p>Create some books in the admin site, and check out whether the site is behaving as you expect.</p> + +<h3 id="Managing_addons">Managing addons</h3> + +<p>You can check out the add-ons to your app using the <code>heroku addons</code> command. This will list all addons, and their price tier and state.</p> + +<pre class="brush: bash notranslate">> heroku addons + +Add-on Plan Price State +───────────────────────────────────────── ───────── ───── ─────── +heroku-postgresql (postgresql-flat-26536) hobby-dev free created + └─ as DATABASE</pre> + +<p>Here we see that we have just one add-on, the postgres SQL database. This is free, and was created automatically when we created the app. You can open a web page to examine the database add-on (or any other add-on) in more detail using the following command:</p> + +<pre class="brush: bash notranslate">heroku addons:open heroku-postgresql +</pre> + +<p>Other commands allow you to create, destroy, upgrade and downgrade addons (using a similar syntax to opening). For more information see <a href="https://devcenter.heroku.com/articles/managing-add-ons">Managing Add-ons</a> (Heroku docs).</p> + +<h3 id="Setting_configuration_variables">Setting configuration variables</h3> + +<p>You can check out the configuration variables for the site using the <code>heroku config</code> command. Below you can see that we have just one variable, the <code>DATABASE_URL</code> used to configure our database.</p> + +<pre class="brush: bash notranslate">> heroku config + +=== locallibrary Config Vars +DATABASE_URL: postgres://uzfnbcyxidzgrl:j2jkUFDF6OGGqxkgg7Hk3ilbZI@ec2-54-243-201-144.compute-1.amazonaws.com:5432/dbftm4qgh3kda3</pre> + +<p>If you recall from the section on <a href="#Getting_your_website_ready_to_publish">getting the website ready to publish</a>, we have to set environment variables for <code>DJANGO_SECRET_KEY</code> and <code>DJANGO_DEBUG</code>. Let's do this now.</p> + +<div class="note"> +<p><strong>Note:</strong> The secret key needs to be really secret! One way to generate a new key is to use the <a href="https://www.miniwebtool.com/django-secret-key-generator/">Django Secret Key Generator</a>.</p> +</div> + +<p>We set <code>DJANGO_SECRET_KEY</code> using the <code>config:set</code> command (as shown below). Remember to use your own secret key!</p> + +<pre class="brush: bash notranslate">> heroku config:set DJANGO_SECRET_KEY='eu09(ilk6@4sfdofb=b_2ht@vad*$ehh9-)3u_83+y%(+phh&=' + +Setting DJANGO_SECRET_KEY and restarting locallibrary... done, v7 +DJANGO_SECRET_KEY: eu09(ilk6@4sfdofb=b_2ht@vad*$ehh9-)3u_83+y%(+phh +</pre> + +<p>We similarly set <code>DJANGO_DEBUG</code>:</p> + +<pre class="brush: bash notranslate">> heroku config:set <code>DJANGO_DEBUG= + +Setting DJANGO_DEBUG and restarting locallibrary... done, v8</code></pre> + +<p>If you visit the site now you'll get a "Bad request" error, because the <a href="https://docs.djangoproject.com/en/2.1/ref/settings/#allowed-hosts">ALLOWED_HOSTS</a> setting is <em>required</em> if you have <code>DEBUG=False</code> (as a security measure). Open <strong>/locallibrary/settings.py</strong> and change the <code>ALLOWED_HOSTS</code> setting to include your base app url (e.g. 'locallibrary1234.herokuapp.com') and the URL you normally use on your local development server.</p> + +<pre class="brush: python notranslate">ALLOWED_HOSTS = ['<your app URL without the https:// prefix>.herokuapp.com','127.0.0.1'] +# For example: +# ALLOWED_HOSTS = ['fathomless-scrubland-30645.herokuapp.com', '127.0.0.1'] +</pre> + +<p>Then save your settings and commit them to your Github repo and to Heroku:</p> + +<pre class="brush: bash notranslate">git add -A +git commit -m 'Update ALLOWED_HOSTS with site and development server URL' +git push origin master +git push heroku master</pre> + +<div class="note"> +<p>After the site update to Heroku completes, enter a URL that does not exist (e.g. <strong>/catalog/doesnotexist/</strong>). Previously this would have displayed a detailed debug page, but now you should just see a simple "Not Found" page.</p> +</div> + +<h3 id="Debugging">Debugging</h3> + +<p>The Heroku client provides a few tools for debugging:</p> + +<pre class="brush: bash notranslate"># Show current logs +heroku logs + +# Show current logs and keep updating with any new results +heroku logs --tail + +# Add additional logging for collectstatic (this tool is run automatically during a build) +heroku config:set DEBUG_COLLECTSTATIC=1 + +# Display dyno status +heroku ps +</pre> + +<p>If you need more information than these can provide you will need to start looking into <a href="https://docs.djangoproject.com/en/2.1/topics/logging/">Django Logging</a>.</p> + +<ul> +</ul> + +<h2 id="Summary">Summary</h2> + +<p>That's the end of this tutorial on setting up Django apps in production, and also the series of tutorials on working with Django. We hope you've found them useful. You can check out a fully worked-through version of the <a href="https://github.com/mdn/django-locallibrary-tutorial">source code on Github here</a>.<br> + <br> + The next step is to read our last few articles, and then complete the assessment task.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.1/howto/deployment/">Deploying Django</a> (Django docs) + + <ul> + <li><a href="https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/">Deployment checklist</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/howto/static-files/deployment/">Deploying static files</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/">How to deploy with WSGI</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/modwsgi/">How to use Django with Apache and mod_wsgi</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/gunicorn/">How to use Django with Gunicorn</a> (Django docs)</li> + </ul> + </li> + <li>Heroku + <ul> + <li><a href="https://devcenter.heroku.com/articles/django-app-configuration">Configuring Django apps for Heroku</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/getting-started-with-python#introduction">Getting Started on Heroku with Django</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/django-assets">Django and Static Assets</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/python-concurrency-and-database-connections">Concurrency and Database Connections in Django</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/how-heroku-works">How Heroku works</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/dynos">Dynos and the Dyno Manager</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/config-vars">Configuration and Config Vars</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/limits">Limits</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/python-gunicorn">Deploying Python applications with Gunicorn</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/deploying-python">Deploying Python and Django apps on Heroku</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/search?q=django">Other Heroku Django docs</a></li> + </ul> + </li> + <li>Digital Ocean + <ul> + <li><a href="https://www.digitalocean.com/community/tutorials/how-to-serve-django-applications-with-uwsgi-and-nginx-on-ubuntu-16-04">How To Serve Django Applications with uWSGI and Nginx on Ubuntu 16.04</a></li> + <li><a href="https://www.digitalocean.com/community/tutorials?q=django">Other Digital Ocean Django community docs</a></li> + </ul> + </li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Testing", "Learn/Server-side/Django/web_application_security", "Learn/Server-side/Django")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Django/Introduction">Django introduction</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/development_environment">Setting up a Django development environment</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Django Tutorial: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Django Tutorial Part 2: Creating a skeleton website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Models">Django Tutorial Part 3: Using models</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Admin_site">Django Tutorial Part 4: Django admin site</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Home_page">Django Tutorial Part 5: Creating our home page</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Generic_views">Django Tutorial Part 6: Generic list and detail views</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Sessions">Django Tutorial Part 7: Sessions framework</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Authentication">Django Tutorial Part 8: User authentication and permissions</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Forms">Django Tutorial Part 9: Working with forms</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Testing">Django Tutorial Part 10: Testing a Django web application</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Django Tutorial Part 11: Deploying Django to production</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/web_application_security">Django web application security</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/index.html b/files/pt-br/learn/server-side/django/index.html new file mode 100644 index 0000000000..58d0f08a16 --- /dev/null +++ b/files/pt-br/learn/server-side/django/index.html @@ -0,0 +1,75 @@ +--- +title: Django Web Framework (Python) +slug: Learn/Server-side/Django +tags: + - Aprender + - CodingScripting + - Desenvolvimento Web + - Iniciante + - Introdução + - Python + - django + - framework +translation_of: Learn/Server-side/Django +--- +<div>{{LearnSidebar}}</div> + +<p>Django é um framework de web server-side extremamente popular e repleto de características, escrito em Python. O módulo mostra por que o Django é um dos frameworks web mais populares, como configurar um ambiente de desenvolvimento e como começar a usa-lo para criar seus próprios aplicativos da Web.</p> + +<h2 id="Pré-requisitos">Pré-requisitos</h2> + +<p>Antes de iniciar este módulo você não precisa ter nenhum conhecimento de Django. Você precisará entender o que programação server-side e web frameworks são, idealmente lendo os tópicos em nosso módulo <a href="/pt-BR/docs/Learn/Server-side/First_steps">Server-side programação de website primeiros passos</a>.</p> + +<p>Um conhecimento geral de conceitos de programação e Python é recomendado, mas não essenciais para entendimento dos conceitos principais.</p> + +<div class="note"> +<p><strong>Nota</strong>: O Python é uma das linguagens de programação mais fáceis para os iniciantes lerem e entenderem. Dito isto, se você quiser entender melhor este módulo, então existem inúmeros livros e tutoriais gratuitos disponíveis pela Internet (programadores iniciantes podem querer ver a página <a href="https://wiki.python.org/moin/BeginnersGuide/NonProgrammers">Python for não programadores</a> no wiki do python.org)</p> +</div> + +<h2 id="Como_começar">Como começar?</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Introdu%C3%A7%C3%A3o">Introdução ao Django</a></dt> + <dd> + <p>Neste primeiro artigo sobre Django vamos responder a questão “O que é Django?” e mostrar um resumo sobre o que faz esse web framework ser especial. Nós vamos resumir os recursos principais, <span lang="pt-PT">i</span><span lang="pt-PT">ncluindo algumas das funcionalidades avançadas que não teremos tempo de detalhar neste módulo. Também mostraremos alguns dos principais blocos de construção de um aplicativo Django, para que você tenha uma idéia do que ele pode fazer antes de continuar e configurá-lo e começar a </span><span lang="pt-PT">se divertir</span><span lang="pt-PT">.</span></p> + </dd> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></dt> + <dd>Agora que você sabe para quê o Django serve, iremos mostrar-lhe como configurar e testar um ambiente de desenvolvimento Django no Windows, Linux (Ubuntu) e Mac OS X - ou qualquer outro sistema operacional que você esteja usando, esse artigo deve ajudá-lo no que precisa para começar a desenvolver aplicações no Django.</dd> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: Website de uma Biblioteca Local</a></dt> + <dd>O primeiro artigo em nossa série de tutoria prática explica o que você irá aprender, e provê uma visão geral do site de exemplo "biblioteca geral" que estaremos trabalhando e evoluindo nos artigos subsequentes.</dd> +</dl> + +<dl> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/skeleton_website">Tutorial Django Parte 2: Criando a base do website</a></dt> + <dd>Esse artigo mostra como você pode criar um projeto de site "esqueleto" como base, o qual poderá ser preenchido com configurações, urls, models, views e templates de um site específico.</dd> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/Models">Tutorial Django Parte 3: Utilizando models</a></dt> + <dd>Este artigo mostra como definir modelos para o site<em> </em><em>BibliotecaLocal</em> - os modelos representam <span id="result_box" lang="pt"><span>as estruturas de dados em que queremos armazenar os dados do aplicativo</span></span>, além de permitirem o Django armazenar dados em banco de dados pela gente (e modificá-los depois). Ele explica o que é um modelo, como declará-lo, e alguns dos principais tipos de campos. Além de brevemente apresentar algumas das principais maneiras de acessar os dados de um modelo.</dd> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/Admin_site">Tutorial Django Parte 4: Django admin site</a></dt> + <dd>Agora que nós criamos os modelos para o site <em>BibliotecaLocal, </em>iremos usar o site Django Admin para adicionar alguns dados "reais" de livros. Primeiros mostraremos como registrar os modelos com o site admin, e então veremos como fazer login e criar alguns dados. Ao final iremos mostrar algumas maneiras de aprimorar ainda mais a apresentação do site de administração.</dd> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/Home_page">Tutorial Django Parte 5: Criando nossa página principal</a></dt> + <dd>Agora estamos prontos para adicionar o código para exibir nossa primeira página inteira - uma home page para a BibliotecaLocal que mostra quantos registros temos de cada tipo de modelo e fornece links de navegação da barra lateral para nossas outras páginas. Ao longo do caminho, obteremos experiência prática ao escrever mapas e visualizações de URLs básicos, obtendo registros do banco de dados e usando modelos.</dd> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/Generic_views">Tutorial Django Parte 6: Lista genérica e detail views</a></dt> + <dd>Este tutorial estende nosso website <em>BibliotecaLocal</em> adicionando páginas de listagem e de detalhes, para livros e autores. Aqui nós vamos aprender sobre visualizações genéricas baseadas em classes e mostrar como elas podem reduzir a quantidade de código que você tem que escrever para casos comuns. Nós também entraremos na manipulação de URL em maiores detalhes, mostrando como realizar correspondências de padrões básicas.</dd> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/Sessions">Tutorial Django Parte 7: Framework de Sessões</a></dt> + <dd>Este tutorial estende nosso site <em>BibliotecaLocal</em>, adicionando um contador de visitas baseado em sessão à home page. Esse é um exemplo relativamente simples, mas mostra como você pode usar a estrutura da sessão para prover um comportamento persistente para usuários anônimos em seus próprios sites.</dd> + <dt><a href="/pt-br/docs/Learn/Server-side/Django/Authentication">Django Tutorial Part 8: Autenticação de Usuário e permissões</a></dt> + <dd>Neste tutorial, mostraremos como permitir que os usuários façam login em seu site com suas próprias contas e como controlar o que podem fazer e ver com base no fato de estarem ou não logados e de suas permissões. Como parte dessa demonstração, ampliaremos o site da LocalLibrary, adicionando páginas de login e logout e páginas específicas de usuários e funcionários para a visualização de livros que foram emprestados.</dd> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/Forms">Tutorial Django Parte 9: Trabalhando com formulários</a></dt> + <dd>Neste tutorial iremos mostrar como trabalhar com <a href="/en-US/docs/Web/Guide/HTML/Forms">HTML Forms</a> no Django, e em particular a maneira mais fácil para escrever formulários para criar, atualizar e excluir instâncias do modelo. Como parte desta demonstração ampliaremos o website <em>BibliotecaLocal</em> para que bibliotecários possam renovar livros, e criar, atualizar e excluir autores usando usindo nossos próprios formulários (em vez de usar o aplicativo administrativo).</dd> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/Testing">Tutorial Django Parte 10: Testando uma aplicação web Django</a></dt> + <dd>Conforme os sites crescem, tornam-se mais difíceis de testar manualmente - não apenas há mais para testar, mas à medida que as interações entre os componentes se tornam mais complexas, uma pequena alteração em uma área pode exigir muitos testes adicionais para verificar seu impacto em outras áreas. Uma forma de mitigar esses problemas é escrever testes automatizados, que podem ser executados de maneira fácil e confiável sempre que você fizer uma alteração. Este tutorial mostra como automatizar <em>o teste de unidade</em> do seu site usando a estrutura de teste do Django.</dd> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/Deployment">Tutorial Django Parte 11: Implantando Django em produção</a></dt> + <dd>Agora você criou (e testou) um site da LocalLibrary incrível, você vai querer instalá-lo em um servidor web público para que ele possa ser acessado pela equipe da biblioteca e membros pela Internet. Este artigo fornece uma visão geral de como você pode encontrar um host para implantar seu site e o que você precisa fazer para preparar seu site para a produção.</dd> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/web_application_security">Segurança de aplicações web Django</a></dt> + <dd>Proteger os dados do usuário é uma parte essencial do design de qualquer site. Anteriormente, explicamos algumas das ameaças de segurança mais comuns no artigo <a href="https://developer.mozilla.org/en-US/docs/Web/Security">Web security</a> - este artigo fornece uma demonstração prática de como as proteções internas do Django lidam com essas ameaças.</dd> + <dt></dt> +</dl> + +<h2 id="Assessments">Assessments</h2> + +<p>A avaliação a seguir testará sua compreensão de como criar um site usando o Django, conforme descrito nos guias listados acima.</p> + +<dl> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></dt> + <dd>Nesta avaliação, você usará alguns dos conhecimentos que aprendeu neste módulo para criar seu próprio blog.</dd> +</dl> diff --git a/files/pt-br/learn/server-side/django/introdução/index.html b/files/pt-br/learn/server-side/django/introdução/index.html new file mode 100644 index 0000000000..9258d18dc6 --- /dev/null +++ b/files/pt-br/learn/server-side/django/introdução/index.html @@ -0,0 +1,346 @@ +--- +title: Introdução ao Django +slug: Learn/Server-side/Django/Introdução +tags: + - Aprender + - Codificação + - Iniciante + - Introdução + - Programação do lado do servidor + - Python + - django +translation_of: Learn/Server-side/Django/Introduction +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django")}}</div> + +<p class="summary">Neste primeiro artigo do Django, respondemos a pergunta "O que é o Django?" e daremos uma visão geral do que torna este framework web especial. Vamos descrever os principais recursos, incluindo algumas das funcionalidades avançadas que não teremos tempo para abordar detalhadamente neste módulo. Também mostraremos alguns dos principais blocos de construção de um aplicativo Django (embora neste momento você ainda não tenha um ambiente de desenvolvimento para testá-lo).</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td> + <p><span id="result_box" lang="pt"><span>Conhecimentos básicos em computação.</span> <span>Um entendimento geral de <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps">programação de websites do lado do servidor</a> e, em particular, a mecânica de <a href="/pt-BR/docs/">interações cliente-servidor em websites</a>.</span></span></p> + </td> + </tr> + <tr> + <th scope="row">Objetivos:</th> + <td>Ganhar familiaridade com o que é o Django, quais funcionalidades ele fornece e os principais blocos de construção de uma aplicação django.</td> + </tr> + </tbody> +</table> + +<h2 id="O_que_é_Django">O que é Django?</h2> + +<p>Django é um framework web Python de alto nível que permite o rápido desenvolvimento de sites seguros e de fácil manutenção. Construido por desenvolvedores experientes, o Django cuida de grande parte do trabalho de desenvolvimento web, para que você possa se concentrar em escrever seu aplicativo sem precisar reinventar a roda. É gratuito e de código aberto, tem uma comunidade próspera e ativa, ótima documentação e muitas opções de suporte gratuito e pago. </p> + +<p>Django ajuda você a escrever programas que são:</p> + +<dl> + <dt>Completo</dt> + <dd>Django segue a filosofia de "baterias incluídas" e fornece quase tudo que desenvolvedores possam querer fazer "fora da caixa". Como tudo o que você precisa é parte de um "produto", tudo funciona perfeitamente junto, seguindo princípios de design consistentes, contando uma extensa e <a href="https://docs.djangoproject.com/pt-br/2.1/">atualizada documentação</a>.</dd> + <dt>Versátil</dt> + <dd>Django pode ser (e tem sido) utilizado para construir quase todo tipo de website - desde sistema de gestão de conteúdo e wikis, passando por redes sociais e sites de notícias. Ele pode trabalhar com qualquer framework do lado do cliente, e pode entregar conteúdo em praticamente qualquer formato (incluindo HTML, feeds RSS, JSON, XML, etc). Esse site que você está lendo agora é baseado em Django.</dd> + <dd>À medida em que, internamente, fornece opções para quase todo tipo de funcionalidade que você possa querer (por exemplo: vários banco de dados que são populares, motores de template, etc), ele pode também ser extendido para utilizar outros componentes, caso seja necessário.</dd> + <dt>Seguro</dt> + <dd>Django ajuda os desenvolvedores a evitar os erros de segurança mais comuns, fornecendo um framework que foi desenhado para "fazer as coisas certas", de modo a proteger o website automaticamente. Por exemplo, Django fornece uma maneira segura de gerenciar as contas dos usuários e suas senhas, evitando erros comuns, tais como colocar informações da sessão em cookies, onde ficam vulneráveis (ao invés disso os cookies contém apenas uma chave e os dados são armazenados no banco de dados), ou armazenar as senhas de forma direta, ao invés de gravar um hash para essas senhas.</dd> + <dd><em>Um hash de senha é um valor fixed-length (tamanho-fixo) criado mandando a senha por uma <a href="https://pt.wikipedia.org/wiki/Fun%C3%A7%C3%A3o_hash_criptogr%C3%A1fica">cryptographic hash function (função hash criptográfica)</a>. Django pode checar se uma senha inserida está correta executando ela pela função hash e comparando a saída com o valor hash armazenado. Porém devido a natureza "one-way" ("um-caminho") da função, mesmo que o valor hash armazenado estiver comprometido, é difcil para uma pessoa comentendo um ataque resolver a senha original.</em></dd> + <dd>O Django ativa a proteção contra muitas vulnerabilidades por padrão, incluindo SQL injection (injeção de SQL), cross-site scripting, cross-site request forgery (Falsificação de solicitação entre sites), e clickjacking ("furto de click") (veja <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps/Website_security">Segurança de sites</a> para mais detalhes de tais ataques).</dd> + <dt>Escalável</dt> + <dd>Django usa uma arquitetura baseada em componentes “<a href="https://en.wikipedia.org/wiki/Shared_nothing_architecture">shared-nothing</a>” ("nada-compartilhado") (cada parte da arquitetura é idependente das outras, e consequentemente podem ser subistituidas ou mudadas caso necessário). Ter uma separação clara entre as partes diferentes significa que pode se escalar para um trágefo aumentado adicionando hardware em qualquer nível: servidores de cache, servidores de banco de dados ou servidores de aplicação. Alguns dos sites mais ocupados escalaram o Django com sucesso para cumprir com as suas demandas (ex: Instagram e Disqus).</dd> + <dt>Sustentável</dt> + <dd>O código do Django é escrito usando princípios de design e padrões que encorajam a criação de codigo sustentável (que facilita a manutenção) e reusável. Em particular, isso utiliza o principio DRY - Don't Repeat Yourself (Não Repita a Si Mesmo) para que não haja duplicações desnecessárias, reduzindo a quantidade de código. O Django também promove o agrupamento de funcionalidades relacionadas para aplicativos reusáveis e, em um nível mais baixo, grupos de código relacionados para modulos (juntamente as linhas do padrão <a href="https://pt.wikipedia.org/wiki/MVC">MVC - Model View Controller</a>).</dd> + <dt>Portável</dt> + <dd>Django é escrito em Python, que executa em muitas plataformas. Isso significa que você não esta preso em nenhuma plataforma de servidor em particular, e pode executar seus aplicativos em muitas distrubuições do Linux, Windows e Mac OS X. Além disso, o Django tem um bom suporte em muitos provedores de servidores de web, que muitas vezes provem infraestrutura especifca e documentação para hospedar sites feitos com Django.</dd> +</dl> + +<h2 id="De_onde_o_Django_veio">De onde o Django veio?</h2> + +<p>Django foi inicialmente desenvolvido entre 2003 e 2005 por um time de web que era responsável por criar e manter sites de jornal. Depois de criar um número de sites, o time começou a fatorar e reutilizar muitos de seus códigos comuns e padrões de design. Esse código comum evoluiu para um framework genérico de desenvolvimento web, que foi lançado como um projeto de código aberto nomeado "Django" em Julho de 2005.</p> + +<p>Django continou a crescer e aprimorar, desde seu lançamento (1.0) em Setembro de 2008 até a versão recentemente lançada 2.0 em 2017. Cada lançamento adicionou novas funcionalidades e consertou falhas, variando entre suportar novos tipos de banco de dados, mecanismos de template e caches, até a adição de funções view "genéricas" e classes (que reduzem a quantidade de código que os desenvolvedores tem que escrever para um número de tarefas de programação).</p> + +<div class="note"> +<p><strong>Nota</strong>: Cheque as <span style="line-height: 1.5;"><a href="https://docs.djangoproject.com/pt-br/2.1/releases/">notas de lançamento</a> no site do Django para ver o que mudou nas versões mais recentes, e quanto trabalho esta sendo feito para tornar o Django melhor.</span></p> +</div> + +<p>Django é um projeto de código aberto, colaborativo e próspero, com milhares de usuários contribuindo. Embora ainda tenha alguns recursos que refletem sua origem, Django evoluiu para um framework versátil que é capaz de desenvovler qualquer tipo de website.</p> + +<h2 id="Quão_popular_é_o_Django">Quão popular é o Django?</h2> + +<p>Não há nenhum método disponível e definitivo para medir a popularidade dos framework server-side (lado do servidor) (apesar de sites como <a href="http://hotframeworks.com/">Hot Frameworks</a> tentam acessar a popularidade usando mecanismos como contar o numero de projetos no GitHub e perguntas no StackOverflow para cada cada platafroma). Uma questão melhor é se o Django é "popular o suficiente" para evitar problemas de plataformas não populares. Ele continua a evoluir? Você consegue ajuda se precisar? Existem oportunidades para você ganhar dinheiro se voce aprender Django?</p> + +<p>Baseado no número de sites com alto perfil que usam Django, o número de pessoas contribuindo para a base de código, e o número de pessoas provendo ambos suporte gratuito e pago, então sim, Django é um framework popular!</p> + +<p>Alguns sites de alto perfil que usam Django são: Disqus, Instagram, Knight Foundation, MacArthur Foundation, Mozilla, National Geographic, Open Knowledge Foundation, Pinterest, and Open Stack (fonte: <a href="https://www.djangoproject.com/">Página inicial do django</a>).</p> + +<h2 id="O_Django_é_opinativo">O Django é opinativo?</h2> + +<p>Frameworks de web frequentemente referem a si mesmos como "opinativo" e "não opinativo".</p> + +<p>Frameworks opinativos são aqueles com opiniões sobre o "modo correto" de como lidar com uma tarefa em particular. Eles frequentemente auxiliam no desenvolvimento rapido <em>em um domínio em particular</em> (resolvendo problemas de um tipo em particular) porque o modo correto de fazer qualquer coisa normalmente já foi bem compreendido e bem documentado. Porém eles podem ser menos flexíveis para resolver problemas fora de seu principal domínio, e tendem a oferecer menos opções para quais componentes e abordagens eles podem usar.</p> + +<p>Frameworks não opinativos, em contraste, possuem bem menos restrições sobre a melhor maneira de unir os componentes para atingir um objetivo, ou até mesmo quais componentes devem ser usados. Eles tornam mais fácil para os desenvolvedores usar as ferramentas mais adequadas para completar uma tarefa em particular, apesar do custo de você mesmo ter que achar esses componentes.<br> + <br> + Django é "moderadamente opinativo" e, portantanto, oferece o "melhor dos dois mundo". Ele fornece um conjunto de componentes para lidar com a maioria das tarefas de desenvolvimento web, e uma (ou duas) maneiras preferidas de usá-las. No entanto, a arquitetura desacoplada do Django significa que você geralmente pode escolher entre várias opções diferentes, ou adicionar suporte para outras completamente novas, se desejar.</p> + +<h2 id="Com_o_que_o_código_do_Django_parece">Com o que o código do Django parece?</h2> + +<p>Em um site data-driven (orientado a dados) tradicional, um aplicativo web aguarda solicitações HTTP do navegador da web (ou outro cliente). Quando uma solicitação é recebida, o aplicativo calcula o que é necessário com base na URL e possivelmente nas informações dos dados <code>POST</code> ou <code>GET</code>. Dependendo do que for necessário, ele poderá ler ou gravar informações de um banco de dados ou executar outras tarefas necessárias para satisfazer a solicitação. O aplicativo retornará uma resposta para o navegador da web, normalmente criando dinamicamente uma página HTML para o navegador exibir, inserindo os dados recuperados em espaços reservados em um template HTML.</p> + +<p>Aplicativos web feitos com Django geralmente agrupam o código que manipula cada uma dessas etapas em arquivos separados:</p> + +<p><img alt="" src="https://i.postimg.cc/W4yzpVcd/arq.png" style="border-style: solid; border-width: 1px; height: 503px; width: 713px;"></p> + +<ul> + <li><strong>URLs: </strong>Embora seja possível processar solicitações de cada URL por meio de uma única função, é muito mais simples fazer a manutenção do código escrevendo uma função view (vista) separada para manipular cada recurso. Um mapeador de URLs é usado para redirecionar solicitações HTTP para a view apropriada com base na URL da solicitação. O mapeador de URLs também pode corresponder padrões específicos de strings (cadeia de caracteres) ou dígitos que aparecem em um URL e transmiti-los a uma função view como dados.</li> + <li><strong>View (Vista):</strong> Uma view é uma função manipuladora de solicitações, que recebe solicitações HTTP e retorna respostas HTTP. As views acessam os dados necessários para satisfazer solicitações por meio dos <em>models (modelos)</em> e encarregam a formatação da resposta aos <em>templates</em>.</li> + <li><strong>Models (Modelos):</strong> Modelos são objetos em Python que definem a estrutura dos dados de um aplicativo, e fornecem mecanismos para gerenciar (adicionar, modificar e excluir) e consultar registros no banco de dados.</li> + <li><strong>Templates:</strong> Um template é um arquivo de texto que define a estrutura ou o layout de um arquivo (como uma página HTML), com espaços reservados usados para representar o conteúdo real. Uma <em>view</em> pode criar dinamicamente uma página HTML usando um template HTML, preenchendo-a com dados de um <em>model (modelo)</em>. Um template pode ser usado para definir a estrutura de qualquer tipo de arquivo; não precisa ser HTML!</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Django refere a essa organização como uma arquitetura nomeada "Model View Template (MVT)" ("Modelo Vista Template"). Ela tem muitas semelhanças com a familiar arquitetura <a href="https://pt.wikipedia.org/wiki/MVC">Model View Controller (Modelo Vista Controlador)</a>.</p> +</div> + +<ul> +</ul> + +<p>As seções abaixo lhe darão uma idéia de como essas partes principais de um aplicativo do Django se parecerão (nos vamos entrar em mais detalhes mais tarde no curso, assim que configurarmos um ambiente de desenvolvimento).</p> + +<h3 id="Enviando_a_solicitação_para_a_view_correta_urls.py">Enviando a solicitação para a view correta (urls.py)</h3> + +<p>Um mapeador de URLs normalmente é armazenado em um arquivo chamado <strong>urls.py</strong>. No exemplo abaixo, o mapeador (<code>urlpatterns</code>) (<em>padrões de url</em>) define uma lista de mapeamentos entre <em>rotas</em> (<em>padrões</em> específicos de URL) e funções view correspondentes. Se uma solicitação HTTP for recebida com uma URL correspondente a um padrão especificado, a função view associada será chamada e a solicitação/requisição sera transmitida.</p> + +<pre class="notranslate"><code>urlpatterns = [ + <strong>path('admin/', admin.site.urls),</strong> + path('book/<int:id>/', views.book-detail, name='book-detail'), + path('catalog/', include('catalog.urls')), + re_path(r'^([0-9]+)/$', views.best), +] + +# favor utilizar o código acima no seu projeto ao invés do que está abaixo +# urlpatterns = [ +# path('admin/', admin.site.urls), +# path('livro/<int:id>/', views.livro-detalhes, name='livro-detalhes'), +# path('catalogo/', include('catalogo.urls')), +# re_path(r'^([0-9]+)/$', views.melhor), +# ]</code> +</pre> + +<p>O objeto <code>urlpatterns</code> é uma lista de funções <code>path()</code> (caminhos) e/ou <code>re_path()</code> (listas em Python são definidas usando colchetes, onde os itens são separados por vírgulas e podem conter opcionalmente uma vírgula no final. Por exemplo: <strong><code>[item1, item2, item3,]</code></strong>).</p> + +<p>O primeiro argumento para ambos os métodos é uma rota (padrão) que será correspondida. O método <code>path()</code> usa sinais de menor e maior (<, >) para definir partes de uma URL que serão capturadas e passadas para a função view como argumentos nomeados. A função <code>re_path()</code> usa uma abordagem de correspondência de padrões flexível, conhecida como expressão regular. Nós vamos falar sobre isso em um artigo posterior!</p> + +<p>O segundo argumento é outra função que será chamada quando o padrão for correspondido. A notação <code>views.book-detail</code> (<code>views.livro-detalhes</code>) indica que a função é chamada de <code>book-detail()</code> (<code>livro-detalhes()</code>) e pode ser encontrada em um módulo chamado <code>views</code> (ou seja, dentro de um arquivo chamado <code>views.py</code>)</p> + +<h3 id="Manipulando_a_solicitação_views.py">Manipulando a solicitação (views.py)</h3> + +<p>As view são o coração do aplicativo web, recebendo solicitações HTTP de clientes da web e retornando respostas HTTP. No meio disto, eles preparam os outros recursos do framework para acessar bancos de dados, renderizar (exibir) templates, etc.</p> + +<p>O exemplo abaixo mostra uma função view mínima chamada <code>index()</code>, que poderia ter sido chamado pelo nosso mapeador de URLs na seção anterior. Como todas as funções <em>view</em>, ele recebe um objeto <code>HttpRequest</code> como um parâmetro (<code>request</code>) e retorna um objeto <code>HttpResponse</code>. Nesse caso, não fazemos nada com a solicitação, e nossa resposta simplesmente retorna uma string. Mostraremos uma solicitação que faz algo mais interessante em uma seção posterior.</p> + +<pre class="brush: python notranslate">## filename: views.py (Django view functions) + +from django.http import HttpResponse + +def index(request): + # Get an HttpRequest - the request parameter + # perform operations using information from the request. + # Return HttpResponse + return HttpResponse('Hello from Django!') + +<code># favor utilizar o código acima no seu projeto ao invés do que está abaixo</code> +## nome do arquivo: views.py (Onde as funções view ficam) + +from django.http import HttpResponse + +def index(requisito): + # Recebe um HttpRequest - o parametro requisito + # Executar operações usando informações do requisito (solicitação). + # Retornar HttpResponse + return HttpResponse('Um oi do Django!') +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Um pouquinho de Python:</p> + +<ul> + <li><a href="https://docs.python.org/3/tutorial/modules.html">Módulos do Python</a> são "bibliotecas" de funções, armazenadas em arquivos separados, que podemos utilizar em nosso código. Aqui nós importamos apenas o objeto <code>HttpResponse</code> do módulo <code>django.http</code> para que possamos usá-lo em nossa view: <code>from django.http import HttpResponse</code>. Existem outras maneiras de importar alguns ou todos os objetos de um módulo.</li> + <li>As funções em Python são declaradas usando a palavra-chave <code>def</code> como mostrado acima, com parâmetros nomeados listados entre parênteses após o nome da função; a linha inteira termina em dois pontos. Observe como as próximas linhas são todas <strong>recuadas</strong>. O recuo é importante, pois especifica que as linhas de código estão dentro desse bloco específico (a indentação obrigatória é um recurso chave do Python e é um dos motivos pelos quais o código Python é tão fácil de ler).</li> +</ul> +</div> + +<ul> +</ul> + +<p>Views geralmente são armazenadas em um arquivo chamado <strong>views.py</strong>.</p> + +<h3 id="Definindo_o_modelo_dos_dados_models.py">Definindo o modelo dos dados (models.py)</h3> + +<p>Os aplicativos web feitos com Django gerenciam e consultam dados por meio de objetos do Python chamados de modelos. Os modelos definem a estrutura dos dados armazenados, incluindo os <em>tipos </em>do campo e possivelmente também seu tamanho máximo, valores padrão, opções de lista de seleção, texto de ajuda para documentação, texto de etiqueta (label) para formulários etc. A definição do modelo é independente do banco de dados subjacente — você pode escolher um dentre vários como parte das configurações do seu projeto. Uma vez que você escolheu qual banco de dados você quer usar, você não precisa se comunicar diretamente com ele — você apenas escreve a estrutura dos seus modelos e qualquer outro código, e o Django lida com todo o trabalho de se comunicar com o banco de dados para você.</p> + +<p>O trecho de código abaixo mostra um modelo simples do Django para um objeto <code>Team</code> (Time). A classe <code>Team</code> é derivada da classe do Django <code>models.Model</code>. Ela define o nome e o nível da equipe como campos de caractere e especifica um número máximo de caracteres a serem armazenados para cada registro. O <code>team_level</code> (time_nivel) pode ser um de vários valores, portanto, o definimos como um campo de opção e fornecemos um mapeamento entre as opções a serem exibidas e os dados a serem armazenados, junto com um valor padrão.</p> + +<pre class="brush: python notranslate">## filename: models.py + +from django.db import models + +class Team(models.Model): + team_name = models.CharField(max_length=40) + + TEAM_LEVELS = ( + ('U09', 'Under 09s'), + ('U10', 'Under 10s'), + ('U11', 'Under 11s'), + ... #list other team levels + ) + + team_level = models.CharField(max_length=3,choices=TEAM_LEVELS,default='U11') + +<code># favor utilizar o código acima no seu projeto ao invés do que está abaixo</code> +## nome do arquivo: models.py + +from django.db import models + +class Time(models.Model): + # models.CharField define um campo de caractere no banco de dados e max_length define o tamanho maximo permitido + time_nome = models.CharField(max_length=40) + + TIME_NIVEIS = ( + ('A09', 'Abaixo de 09'), + ('A10', 'Abaixo de 10'), + ('A11', 'Abaixo de 11'), + ... #list other team levels + ) + + time_nivel = models.CharField(max_length=3,choices=TIME_NIVEIS,default='A11') # choices-opções / default-padrão +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Um pouquinho de Python:</p> + +<ul> + <li>O Python suporta "programação orientada a objetos", um estilo de programação onde organizamos nosso código em objetos, que incluem dados e funções relacionadas para operar nesses dados. Os objetos também podem herdar/estender/derivar de outros objetos, permitindo que um comportamento comum entre objetos relacionados seja compartilhado. Em Python, usamos a palavra-chave <code>class</code> (classe) para definir o "blueprint" (modelo/planta/plano) de um objeto. Podemos criar várias <em>instâncias</em> específicas do tipo de objeto com base no modelo da classe.<br> + <br> + Por exemplo, aqui temos uma classe <code>Team</code> (Time), que deriva da classe <code>Model</code>. Isso significa que é um modelo e conterá todos os métodos de um modelo, mas também podemos fornecer recursos especializados próprios. Em nosso modelo, definimos os campos que nosso banco de dados precisará para armazenar nossos dados, dando-lhes nomes específicos. O Django usa essas definições, incluindo os nomes dos campos, para criar o banco de dados subjacente.</li> +</ul> +</div> + +<h3 id="Consultando_dados_views.py">Consultando dados (views.py)</h3> + +<p>O modelo Django fornece uma query API simples para buscas no banco de dados. Isto pode combinar com um grande número de campos ao mesmo tempo utilizando diversos critérios (ex.: exato, maiúsculas e minúsculas (case-sensitive), maior que, etc.), e pode suportar definições complexas (por exemplo, você pode especificar a busca por times U11 que tem os nomes começando com 'Fr" ou terminando com "al").</p> + +<p>O trecho de código mostra uma função da View (manipulador de recursos) para exibir todos os nossos times U09. A linha em negrito mostra como podemos usar a API modelo de consulta para filtrar todos os registros em que o campo <code>team_level</code> possui exatamente o texto 'U09' (observe como esse critério é passado para a função <code>filter()</code> com o argumento no campo de nome e o tipo de busca de correspondência (<strong>exact</strong>) separado por um sublinhado duplo: <strong>(team_level__exact</strong>).</p> + +<pre class="brush: python notranslate">## filename: views.py + +from django.shortcuts import render +from .models import Team + +def index(request): + <strong>list_teams = Team.objects.filter(team_level__exact="U09")</strong> + context = {'youngest_teams': list_teams} + return render(request, '/best/index.html', context) + +# favor utilizar o código acima no seu projeto ao invés do código abaixo +## nome do arquivo: views.py + +from django.shortcuts import render +from .models import Team + +def index(request): + <strong>lista_times =</strong> <strong>Team.objects.filter(team_level__exact="U09")</strong> + contexto = {'times_jovens': lista_times} + return render(request, '/best/index.html', contexto) +</pre> + +<dl> +</dl> + +<p>A função <code>index()</code> usa a função <code>render()</code> para criar o <code>HttpResponse</code> que é enviado de volta para o navegador. Essa função é um atalho, ela cria um arquivo HTML combinando um modelo HTML específico com alguns dados (fornecidos pela variável denominada "<code>context</code>"). Na próxima seção, mostramos como os dados são inseridos no modelo para criar HTML.</p> + +<h3 id="Renderizando_dados_Modelos_HTML">Renderizando dados (Modelos HTML)</h3> + +<p>O sistema de modelo permite especificar a estrutura de um documento de saída, usando espaços reservados para dados que serão preenchidos quando uma página for gerada. Os modelos geralmente são usados para criar HTML, mas também podem criar outros tipos de documentos. O Django suporta o sistema de modelos nativo e outra biblioteca Python popular chamada Jinja2 pronta para uso (também pode ser feita para suportar outros sistemas, se necessário).</p> + +<p>O trecho de código mostra a aparência do modelo HTML chamado pela função <code>render()</code> na seção anterior. Este modelo foi escrito sob a premissa de que ele terá acesso a uma variável do tipo lista chamada <code>youngest_teams</code> quando for renderizada (contida na variável <code>context</code> dentro da função <code>render()</code> acima). Dentro do esqueleto HTML, temos um a expressão que primeiro verifica se a variável <code>youngest_teams</code> existe e a itera em um loop <code>for</code>. Em cada iteração, o modelo exibe o valor <code>team_name</code> de cada equipe em um elemento {{htmlelement("li")}}.</p> + +<pre class="brush: python notranslate">## filename: best/templates/best/index.html + +<!DOCTYPE html> +<html lang="en"> +<body> + + {% if youngest_teams %} + <ul> + {% for team in youngest_teams %} + <li>\{\{ team.team_name \}\}</li> + {% endfor %} + </ul> +{% else %} + <p>No teams are available.</p> +{% endif %} + +</body> +</html> + +#favor utilizar o código acima no seu projeto ao invés do código abaixo +## nome do arquivo: best/templates/best/index.html + +<!DOCTYPE html> +<html lang="pt"> +<body> + + {% if youngest_teams %} + <ul> + {% for team in youngest_teams %} + <li>\{\{ team.team_name \}\}</li> + {% endfor %} </ul> {% else %} + <p>Nenhum time disponível.</p> + {% endif %} + </body> + </html> +</pre> + +<h2 id="O_que_mais_você_pode_fazer">O que mais você pode fazer?</h2> + +<p>As seções anteriores mostram os principais recursos que você usará na maioria dos aplicativos Web: mapeamento de URL, views, moldes e modelos. O Django também fornece outras coisas, como:</p> + +<ul> + <li><strong>Formulários (Forms)</strong>: Os formulários HTML são usados para coletar dados do usuário para processamento no servidor. Django simplifica a criação, validação e processamento de formulários.</li> + <li><strong>Autenticação de usuário e permissões</strong>: Django inclui um sistema robusto de autenticção e permissão de usuário, construído com a segurança em mente.</li> + <li><strong>Caching</strong>: Criar conteúdo dinamicamente é muito mais pesado (e lento) computacionalmente do que exibir conteúdo estático. O Django fornece armazenamento em cache flexível para que você possa armazenar toda ou parte de uma página pronta para que ela não seja renderizada novamente, exceto quando necessário.</li> + <li><strong>Site de administração</strong>: O site de administração do Django é incluído por padrão quando você cria um aplicativo usando o esqueleto básico. Ele facilita o fornecimento de uma página de administração para os administradores do site criarem, editarem e exibirem quaisquer modelos de dados em seu site</li> + <li><strong>Serializando dados</strong>: O Django facilita a serialização e a veiculação de dados como XML ou JSON. Isso pode ser útil ap criar um serviço Web (um site que serve apenas para que dados sejam consumidos por outros aplicativos ou sites e não exibe nada por si só), ou ao criar um site no qual o código do lado do cliente lida com todas as renderizações.</li> +</ul> + +<h2 id="Resumo">Resumo</h2> + +<p>Parabéns, você completou o primeiro passo em sua jornada no Django! Agora você deve entender os principais benefícios do Django, um pouco sobre sua história e aproximadamente como podem ser as partes principais de um aplicativo Django. Você também deve ter aprendido algumas coisas sobre a linguagem de programação Python, incluindo a sintaxe para listas, funções e classes.</p> + +<p>Você já viu algum código real do Django acima, mas, diferentemente do código do lado do cliente, você precisa configurar um ambiente de desenvolvimento para executá-lo. Esse é o nosso próximo passo.</p> + +<div>{{NextMenu("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django")}}</div> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Introdução">Introdução ao Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django</a><a href="/en-US/docs/Learn/Server-side/Django/skeleton_website"> Parte 2: Criando um esqueleto de site</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django</a><a href="/en-US/docs/Learn/Server-side/Django/Models"> Parte 3: Usando moldes</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django</a><a href="/en-US/docs/Learn/Server-side/Django/Admin_site"> Parte 4: Site administrador do Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django</a><a href="/en-US/docs/Learn/Server-side/Django/Home_page"> Parte 5: Criando nossa página principal</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django</a><a href="/en-US/docs/Learn/Server-side/Django/Generic_views"> Parte 6: Generic list and detail views</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django</a><a href="/en-US/docs/Learn/Server-side/Django/Sessions"> Parte 7: Sessions framework</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django</a><a href="/en-US/docs/Learn/Server-side/Django/Authentication"> Parte 8: Autenticação de usuário e permissões</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django</a><a href="/en-US/docs/Learn/Server-side/Django/Forms"> Parte 9: Trabalhando com formulários</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django</a><a href="/en-US/docs/Learn/Server-side/Django/Testing"> Parte 10: Testando uma aplicação web Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django</a><a href="/en-US/docs/Learn/Server-side/Django/Deployment"> Parte 11: Implantando o Django na produção</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/web_application_security">Segurança da aplicação web Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">Criando um mini blog Django</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/models/index.html b/files/pt-br/learn/server-side/django/models/index.html new file mode 100644 index 0000000000..f0a5a3ca28 --- /dev/null +++ b/files/pt-br/learn/server-side/django/models/index.html @@ -0,0 +1,459 @@ +--- +title: 'Tutorial Django Parte 3: Usando models' +slug: Learn/Server-side/Django/Models +translation_of: Learn/Server-side/Django/Models +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django")}}</div> + +<p class="summary">Este artigo mostra como definir os modelos para o website <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a>. Ele explica o que é um modelo, como ele é declarado e mostra algum dos principais tipos de campo. Ele também mostra brevemente algumas das principais formas pelas quais você pode acessar dados do modelo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td><a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Django Tutorial Part 2: Criar um esqueleto de um site</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ser capaz de projetar e criar seus próprios modelos, escolhendo os campos de forma apropriada.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_Geral">Visão Geral</h2> + +<p>Aplicativos Django acessam e gerenciam dados através de objetos Python chamados de modelos (models). Modelos definem a <em>estrutura</em> dos dados armazenados, incluindo os tipos de campos e possivelmente também o seu tamanho máximo, valores default, opções de listas de seleção, texto de ajuda para documentação, texto de labels para formulários, etc. A definição do modelo é independente do banco de dados - você pode escolher um tipo de banco como parte das configurações do seu projeto. Uma vez que você tenha escolhido qual banco será utilizado você precisa conversar diretamente com ele - você somente escreve a estrutura do seu modelo e outros códigos, e o Django faz todo o trabalho sujo de comunicação com o banco para você.</p> + +<p>Este tutorial mostra como definir e acessar os modelos para o website <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary website</a>.</p> + +<h2 id="Projetando_os_modelos_para_o_website_LocalLibrary">Projetando os modelos para o website <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a></h2> + +<p>Antes de começarmos a criar nossos modelos, vale a pena perder alguns minutos pensando sobre os dados que iremos guardar e as relações entre os diferentes modelos que serão criados.</p> + +<p>Sabemos que precisamos armazenar informação sobre os livros (título, resumo, autor, idioma, gênero, ISBN) e também que existem várias cópias do mesmo livro na biblioteca (com um id único, status de disponibilidade, etc.). Talvez queiramos armazenar mais informações sobre o autor além de somente seu nome, até porque existem vários autores com o mesmo nome, ou com nomes parecidos. Queremos ordernar a busca dos livros por título, autor, idioma e gênero.</p> + +<p>Quando estamos projetando nossos modelos, faz sentido criar modelos separados para cada "objeto". Em nosso caso de estudo, os "objetos" são os livros (a informação de cada livro, não a cópia em si), as cópias dos livros (um livro pode ter mais de uma cópia) e os autores.</p> + +<p>Você pode também utilizar modelos para representar opções em uma lista de seleção (por exemplo numa lista suspensa), o que é melhor do que trabalhar com opções predefinidas — isso é recomendado quando nem todas as opções são conhecidas ou podem mudar de acordo com um filtro. Obviamente, para nosso tutorial, modelos candidatos para esse caso são o gênero e o idioma.</p> + +<p>Após decidirmos nossos modelos e campos, precisamos pensar no relacionamento dessas informações. Django permite que você defina relações que são um pra um (<code>OneToOneField</code>), um pra muitos (<code>ForeignKey</code>) e muitos pra muitos (<code>ManyToManyField</code>).</p> + +<p>Com isso em mente, os diagramas UML de associação, mostram abaixo os modelos que definiremos nesse caso (como caixas).</p> + +<p><img alt="LocalLibrary Model UML" src="https://mdn.mozillademos.org/files/15646/local_library_model_uml.png" style="height: 660px; width: 977px;"></p> + +<p><span lang="pt">Como acima, criamos modelos para <code>Book </code>(que contém os detalhes genéricos do livro),<br> + <code>BookInstance</code> (contém os status das cópias físicas e específicas dos livros disponíveis no sistema) e <code>Author.</code> Também decidimos ter um modelo para o gênero (<code>Genre</code>), para que os valores possam ser criados/selecionados através da interface administrativa. Decidimos não ter um modelo para o <code>BookInstance: status</code> - pois, codificamos os valores em (<code>LOAN_STATUS</code>) porque não esperamos que isso mude. Dentro de cada uma das caixas você pode ver o nome do modelo, os campos nomes e tipos e também os métodos e seus tipos de retorno.</span></p> + +<p><span lang="pt">O diagrama também mostra as relações entre os modelos, incluindo suas multiplicidades. As multiplicidades são os números no diagrama que mostram as quantidades (máxima e mínima) que cada modelo pode estar presente nos relacionamentos. Por exemplo, a linha que conecta as caixas mostra que <code>Book</code> e um <code>Genre</code> estão relacionados. Os números próximos ao modelo <code>Genre</code> mostram que um livro deve ter um ou mais gêneros (ou quantos você quiser), enquanto os números do outro lado da linha, ao lado do modelo <code>Book</code> mostram que um gênero pode ter zero ou muitos livros associados.</span></p> + +<div class="note"> +<p><strong>Nota</strong>: A próxima seção fornece uma explicação básica sobre como os modelos são definidos e usados. Ao ler sobre isso, considere como vamos construir cada um dos modelos conforme o diagrama acima.</p> +</div> + +<h2 id="Model_primer">Model primer</h2> + +<p>Esta seção fornece uma breve visão sobre como um modelo é definido e alguns dos mais importantes campos e argumentos dos campos.</p> + +<h3 id="Definição_do_Modelo">Definição do Modelo</h3> + +<p>Modelos são geralmente definidos no arquivo <strong>models.py</strong> em uma aplicação. Eles são implementados como subclasse de <code>django.db.models.Model</code>, e podem incluir campos, métodos e metadados. O fragmento de código abaixo, mostra um modelo "típico", chamado <code>MyModelName</code>:</p> + +<pre class="notranslate">from django.db import models + +class MyModelName(models.Model): + """Uma típica classe definindo um modelo, derivada da classe Model.""" + + # Campos + my_field_name = models.CharField(max_length=20, help_text='Enter field documentation') + ... + + # Metadados + class Meta: + ordering = ['-my_field_name'] + + # Métodos + def get_absolute_url(self): + """Retorna a url para acessar uma instancia específica de MyModelName.""" + return reverse('model-detail-view', args=[str(self.id)]) + + def __str__(self): + """ String para representar o objeto MyModelName (no site Admin).""" + return self.my_field_name</pre> + +<p>Nas seções abaixa, exploraremos detalhadamente cada um dos recursos dentro do modelo:</p> + +<h4 id="Campos_Fields">Campos (Fields)</h4> + +<p>Um modelo pode ter um número árbitrário de campos, de qualquer tipo -- cada um representa uma coluna de dados que queremos armazenar em uma de nossas tabelas de banco de dados. Cada registro do banco de dados (row - linha) consitirá em um valor de cada campo. Vamos ver o exemplo visto acima:</p> + +<pre class="brush: js notranslate">my_field_name = models.CharField(max_length=20, help_text='Enter field documentation')</pre> + +<div class="tw-swapa"> +<div class="DHcWmd"><span lang="pt">Nosso exemplo acima tem um único campo chamado <code>my_field_name</code>, do tipo <code>models.CharField</code> - o que significa que este campo conterá strings de caracteres alfanuméricos. Os tipos de cada campo são atribuídos usando classes específicas, que determinam o tipo de registro usado para armazenar os dados no banco de dados, juntamente com os critérios de validação a serem usados quando os valores são recebidos de um formulário HTML (ou seja, o que constitui um valor válido). Os tipos de cada campo também podem receber argumentos que especifiquem como o campo é armazenado ou pode ser usado. Neste caso, estamos dando ao nosso campo dois argumentos:</span></div> + +<div class="DHcWmd"></div> +</div> + +<ul> + <li><code>max_length=20</code> — Afima que o valor máximo do comprimento desse campo é de 20 caracteres.</li> + <li><code>help_text='Enter field documentation'</code> — <span class="tlid-translation translation" lang="pt"><span title="">fornece um rótulo de texto para exibir uma ajuda para os usuários saberem qual valor fornecer, quando esse valor é inserido por um usuário por meio de um formulário HTML.</span></span></li> +</ul> + +<p><span class="tlid-translation translation" lang="pt"><span title="">O nome do campo é usado para se referir a ele em consultas e modelos.</span> <span title="">Os campos também têm um rótulo, que é especificado como um argumento <code>(verbose_name)</code> ou inferido ao capitalizar a primeira letra do nome da variável do campo e substituindo quaisquer sublinhados por um espaço (por exemplo,<code> my_field_name</code> teria um rótulo padrão de <code>My field name</code>).</span></span></p> + +<p><span class="tlid-translation translation" lang="pt"><span title="">A ordem em que os campos são declarados afetará sua ordem padrão, se um modelo for representado em um formulário (por exemplo, no site Admin), embora isso possa ser substituído.</span></span></p> + +<h5 id="Argumentos_comuns_de_um_campo">Argumentos comuns de um campo</h5> + +<p>Os seguintes argumentos são comuns e podem ser usados quando declaramos muitos ou a maioria dos diferentes tipos de campos:</p> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#help-text">help_text</a>: <span class="tlid-translation translation" lang="pt"><span title="">Fornece um rótulo de texto para formulários HTML (por exemplo, no site admin), conforme descrito acima.</span></span></li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#verbose-name">verbose_name</a>: <span class="tlid-translation translation" lang="pt"><span title="">Um nome legível para o campo usado nos rótulos de campo.</span> <span title="">Se não for especificado, o Django irá inferir o nome detalhado do campo <code>name</code>.</span></span></li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#default">default</a>: <span class="tlid-translation translation" lang="pt"><span title="">O valor padrão para o campo.</span> <span title="">Isso pode ser um valor ou um objeto que pode ser chamado. Cada vez que o objeto for chamado será criado um novo registro.</span></span></li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#null">null</a>: <span class="tlid-translation translation" lang="pt"><span title="">Se for <code>True</code>, o Django armazenará valores em branco como <code>NULL</code> no banco de dados, para campos onde isso é apropriado (um <code>CharField </code>irá armazenar uma string vazia).</span> <span title="">O padrão é <code>False</code></span></span>.</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#blank">blank</a>:<span class="tlid-translation translation" lang="pt"><span title="">Se for <code>True</code>, o campo poderá ficar em branco nos seus formulários.</span> <span title="">O padrão é <code>False</code>, o que significa que a validação de formulário do Django forçará você a inserir um valor.</span> <span title="">Isso é frequentemente usado com <code>null = True</code>, porque se você permitir valores em branco, também desejará que o banco de dados possa representá-los adequadamente.</span></span></li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#choices">choices</a>: <span class="tlid-translation translation" lang="pt"><span title="">Um grupo de escolhas para este campo.</span> <span title="">Se isso for fornecido, o padrão widget de formulário correspondente será uma caixa de seleção com essas opções, em vez do campo de texto padrão.</span></span></li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#primary-key">primary_key</a>:<span class="tlid-translation translation" lang="pt"><span title="">Se <code>True,</code> define o campo atual como a chave primária do modelo (uma chave primária é uma coluna especial do banco de dados, designada para identificar exclusivamente as diferentes tabelas) .</span> <span title="">Se nenhum campo for especificado como a chave primária, o Django adicionará automaticamente um campo para essa finalidade.</span></span></li> +</ul> + +<p><span class="tlid-translation translation" lang="pt"><span title="">Existem muitas outras opções - você pode ver</span></span> <a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#field-options">a lista completa de opções aqui</a>.</p> + +<h5 id="Tipos_comuns_de_um_campo">Tipos comuns de um campo</h5> + +<p>A lista a seguir descreve alguns dos tipos de campos mais usados.</p> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#django.db.models.CharField">CharField</a> é usado para definir um tamanho fixo (médio a curto) para a string. Você deve especificar o <code>max_length (tamanho máximo) para o dado que será armazenado.</code></li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#django.db.models.TextField">TextField</a> é usado para grandes strings de comprimento variado. Você pode especificar um <code>max_length</code> (tamanho máximo) para o campo, mas isso é usado somente quando o campo é exibido em formulários (forms) (ele não é imposto no nível do banco de dados).</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#django.db.models.IntegerField" title="django.db.models.IntegerField">IntegerField</a> é um campo para armazenar números inteiros e para validar valores inseridos como números inteiros em formulários.</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#datefield">DateField</a> e <a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#datetimefield">DateTimeField</a> são usados para armazenar / representar datas e informações de data / hora (como os objetos Python <code>datetime.date</code> in e <code>datetime.datetime</code>, respectivamente). Esses campos também podem declarar os parâmetros (mutuamente exclusivos) <code>auto_now = True</code> (para definir o campo para a data atual toda vez que o modelo é salvo), <code>auto_now_add</code> (para definir a data em que o primeiro modelo foi criado) e <code>default</code> (para definir uma data padrão que pode ser substituída pelo usuário).</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#emailfield">EmailField</a> é usada para armazenara e validar em endereço de email.</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#filefield">FileField</a> e <a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#imagefield">ImageField</a> são usados para carregar arquivos e imagens respectivamente, (o <code>ImageField</code> simplesmente valida de forma adicional que o arquivo enviado é uma imagem). Eles têm parâmetros para definir como e onde os arquivos enviados são armazenados.</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#autofield">AutoField</a> é um tipo especial de <code>IntegerField</code> que é incrementada automaticamente. Uma chave primária desse tipo é adicionada de forma automatica ao seu modelo, se você não especificar explicitamente um.</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#foreignkey">ForeignKey</a> é usado para especificar um relacionamento um-para-muitos com outro modelo do banco de dados (por exemplo, um carro tem um fabricante, mas um fabricante pode fazer muitos carros). O lado "um" do relacionamento é o modelo que contém a "chave" (os modelos que contêm uma "chave estrangeira" referem-se a essa "chave" e estão no lado "muitos" de tal relacionamento).</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#manytomanyfield">ManyToManyField</a> é usado para especificar um relacionamento muitos-para-muitos (por exemplo, um livro pode ter vários gêneros e cada gênero pode conter vários livros). Em nosso aplicativo de biblioteca, usaremos isso de maneira muito semelhante às <code>ForeignKeys</code>, mas elas podem ser usadas de maneiras mais complicadas para descrever as relações entre os grupos. Eles têm o parâmetro <code>on_delete</code> para definir o que acontece quando o registro associado é excluído (por exemplo, um valor de <code>models.SET_NULL</code> simplesmente definiria o valor como <code>NULL</code>).</li> +</ul> + +<p>Existem muitos outros tipos de campos, incluindo campos para diferentes tipos de números (big integers, small integers, floats), booleanos, URLs, slugs, unique ids e outras informações "relacionadas ao tempo" (duração, tempo, etc.) . Você pode ver a <a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#field-types">lista completa AQUI</a>.</p> + +<h4 id="Metadados_metadada">Metadados (metadada)</h4> + +<p>Você pode declarar o nível de modelo para os metadados declarando <code>class Meta</code>, como mostrado.</p> + +<pre class="brush: python notranslate">class Meta: + ordering = ['-my_field_name'] +</pre> + +<p>Um dos recursos mais úteis desses metadados é controlar a ordem padrão dos registros retornados, quando você consulta o tipo de modelo. Você faz isso especificando a ordem de correspondência em uma lista de nomes para ordenar (<code>ordering</code>) o atributo , conforme mostrado acima. A ordem dependerá do tipo de campo (os campos de caractere são classificados em ordem alfabética, enquanto os campos de data são classificados em ordem cronológica). Como mostrado acima, você pode prefixar o nome do campo com um símbolo de menos (-) para inverter a ordem de classificação.</p> + +<p>Então, como exemplo, se optássemos por ordenar livros como este por padrão:</p> + +<pre class="brush: python notranslate">ordering = ['title', '-pubdate']</pre> + +<p>Os livros seriam classificados em ordem alfabética por título, de A-Z e depois por data de publicação dentro de cada título, do mais recente ao mais antigo.</p> + +<p>Outro atributo comum é <code>verbose_name</code>, um nome detalhado para a classe no singular e plural:</p> + +<pre class="brush: python notranslate">verbose_name = 'BetterName'</pre> + +<p>Outros atributos úteis permitem que você crie e aplique novas "permissões de acesso" para o modelo (as permissões padrão são aplicadas automaticamente), permitem a ordenação com base em outro campo ou declarar que a classe é "abstrata" (uma classe base que você não pode criar registros, e em vez disso, serão derivadas para criar outros modelos).</p> + +<p>Muitas das outras opções de metadados controlam qual banco de dados deve ser usado para o modelo e como os dados são armazenados (eles são realmente úteis somente se você precisar mapear um modelo para um banco de dados existente).</p> + +<p>A lista completa de opções de metadados pode ser encontrada aqui: <a href="https://docs.djangoproject.com/en/2.1/ref/models/options/">Opções de modelos de metadados</a> (Django docs).</p> + +<h4 id="Métodos">Métodos</h4> + +<p>Um modelo também pode ter métodos.</p> + +<p><strong>Minimamente, em cada modelo você deve definir o método de classe padrão do Python <code>__str__()</code> para retornar uma string legível para cada objeto.</strong> Essa sequência é usada para representar registros individuais no site de administração (e em qualquer outro lugar que você precise se referir a uma instância de modelo). Muitas vezes isso retornará um campo de título ou nome do modelo.</p> + +<pre class="brush: python notranslate">def __str__(self): + return self.field_name</pre> + +<p>Outro método comum a incluir nos modelos do Django é o <code>get_absolute_url()</code>, que retorna uma URL para exibir registros de modelos individuais no site (se você definir esse método, o Django adicionará automaticamente um botão "View on Site" às telas de edição de registros do modelo o site Admin). Um padrão típico para <code>get_absolute_url ()</code> é mostrado abaixo.</p> + +<pre class="brush: python notranslate">def get_absolute_url(self): + """Retorna o URL para acessar uma instância específica do modelo.""" + return reverse('model-detail-view', args=[str(self.id)]) +</pre> + +<div class="note"> +<p><strong>Nota: </strong>Supondo que você usará URLs como <code>/ myapplication / mymodelname / 2</code> para exibir registros individuais para seu modelo (onde "2" é o <code>id</code> para um registro específico), você precisará criar um mapeador de URL para passar a resposta e id para uma "vista detalhada do modelo" (que fará o trabalho necessário para exibir o registro). A função <code>reverse ()</code> acima é capaz de "inverter" seu mapeador de url (no caso acima chamado 'model-detail-view') para criar uma URL do formato correto.</p> + +<p>Claro que para fazer este trabalho você ainda tem que escrever o mapeamento de URL, visão e modelo!</p> +</div> + +<p>Você também pode definir outros métodos que desejar e chamá-los de seu código ou modelos (desde que eles não utilizem nenhum parâmetro).</p> + +<h3 id="Gestão_de_modelos">Gestão de modelos</h3> + +<p>Depois de definir suas classes de modelo, você pode usá-las para criar, atualizar ou excluir registros e executar consultas para obter todos os registros ou subconjuntos específicos de registros. Mostraremos como fazer isso no tutorial quando definirmos nossas visualizações, mas aqui está um breve resumo.</p> + +<h4 id="Criando_e_modificando_registros">Criando e modificando registros</h4> + +<p>Para criar um registro, você pode definir uma instância do modelo e, em seguida, chamar <code>save ()</code>.</p> + +<pre class="brush: python notranslate"># Crie um novo registro usando o construtor do modelo. +record = MyModelName(my_field_name="Instance #1") + +# Salve o objeto no banco de dados. +record.save() +</pre> + +<div class="note"> +<p><strong>Nota:</strong> Se você não tiver declarado qualquer campo como primary_key, o novo registro receberá um automaticamente, com o ID do nome do campo. Você poderia consultar este campo depois de salvar o registro acima e ele teria um valor de 1.</p> +</div> + +<p>Você pode acessar os campos nesse novo registro usando a sintaxe de ponto e alterar os valores. Você precisa chamar <code>save ()</code> para armazenar valores modificados no banco de dados.</p> + +<pre class="brush: python notranslate"># Acessar valores de campo de modelo usando atributos do Python. +print(record.id) # should return 1 for the first record. +print(record.my_field_name) # should print 'Instance #1' + +# Altere o registro modificando os campos e, em seguida, chamando save (). +record.my_field_name = "New Instance Name" +record.save()</pre> + +<h4 id="Procurando_por_registros">Procurando por registros</h4> + +<p>Você pode procurar registros que correspondam a um determinado critério usando o atributo de objetos do modelo (fornecido pela classe base).</p> + +<div class="note"> +<p><strong>Nota: </strong>Explicar como procurar registros usando nomes de campos e modelos "abstratos" pode ser um pouco confuso. Na discussão abaixo, vamos nos referir a um modelo de livro com campos de título e gênero, onde o gênero também é um modelo com um único <code>nome</code> de campo.</p> +</div> + +<p>Podemos obter todos os registros para um modelo como um <code>QuerySet</code>, usando<code> objects.all ()</code>. O <code>QuerySet</code> é um objeto iterável, o que significa que ele contém um número de objetos que podemos iterar / percorrer.</p> + +<pre class="brush: python notranslate">all_books = Book.objects.all() +</pre> + +<p>O método <code>filter ()</code> do Django nos permite filtrar o <code>QuerySet</code> retornado para corresponder a um campo especificado de <strong>texto</strong> ou <strong>numérico</strong> em relação a um critério específico. Por exemplo, para filtrar por livros que contenham "wild" no título e, em seguida, contá-los, poderíamos fazer o seguinte.</p> + +<pre class="brush: python notranslate">wild_books = Book.objects.filter(title__contains='wild') +number_wild_books = Book.objects.filter(title__contains='wild').count() +</pre> + +<p>Os campos a serem correspondidos e o tipo de correspondência são definidos no nome do parâmetro de filtro, usando o formato: field_name__match_type (observe o sublinhado duplo entre título e contém acima). Acima, estamos filtrando o título com uma correspondência de maiúsculas e minúsculas. Existem muitos outros tipos de correspondência que você pode fazer: icontains (insensitivo a maiúsculas e minúsculas), iexact (correspondência exata que não diferencia maiúsculas e minúsculas), exata (correspondência exata diferencia maiúsculas de minúsculas), gt (maior que), startswith, etc. é <a href="https://docs.djangoproject.com/en/2.1/ref/models/querysets/#field-lookups">aqui</a>.</p> + +<p>Em alguns casos, você precisará filtrar um campo que defina um relacionamento um-para-muitos com outro modelo (por exemplo, uma <code>ForeignKey</code>). Nesse caso, você pode "indexar" campos no modelo relacionado com sublinhados duplos adicionais. Por exemplo, para filtrar livros com um padrão de gênero específico, você terá que indexar o <code>nome</code> por meio do campo de <code>gênero</code>, conforme mostrado abaixo:</p> + +<pre class="brush: python notranslate"># Combinará em: ficção, ficção científica, não-ficção etc. +books_containing_genre = Book.objects.filter(genre<strong>__</strong>name<strong>__</strong>icontains='fiction') +</pre> + +<div class="note"> +<p><strong>Nota:</strong> Você pode usar sublinhados (__) para navegar quantos níveis de relacionamentos (<code>ForeignKey / ManyToManyField</code>) desejar. Por exemplo, um <code>Livro</code> que tinha tipos diferentes, definidos usando um relacionamento "cover" adicional, pode ter um nome de parâmetro: <code>type__cover__name__exact = 'hard'</code>.</p> +</div> + +<p>Há muito mais que você pode fazer com as consultas, incluindo pesquisas para trás de modelos relacionados, encadeando filtros, retornando um conjunto menor de valores, etc. Para obter mais informações, consulte <a href="https://docs.djangoproject.com/en/2.1/topics/db/queries/">Fazendo consultas</a> (Django Docs).</p> + +<h2 id="Definindo_os_modelos_LocalLibrary">Definindo os modelos LocalLibrary</h2> + +<p>Nesta seção, começaremos a definir os modelos para a biblioteca. Abra models.py (em / locallibrary / catalog /). O código na parte superior da página importa o módulo de models, que contém os modelos da classe base do models. Modelo do qual nossos models herdarão.</p> + +<pre class="brush: python notranslate">from django.db import models + +# Create your models here.</pre> + +<h3 id="Genre_model">Genre model</h3> + +<p>Copie o código do model <code>Genre</code> , que aparece a baixo, e cole no seu arquivo <code>models.py</code> , abaixo do código de importação. Esse model guarda informaçoes sobre a categoria do livro — por exemplo se é ficção ou não ficção, romance ou história, etc. Como mencionado acima, criamos o genero como um model em vez de um campo de texto ou um lista de seleção para que os possíveis generos criados possam ser gerenciados pelo banco de dados, em vez de serem codificados.</p> + +<pre class="syntaxbox notranslate">class Genre(models.Model): + """Model representing a book genre.""" + name = models.CharField(max_length=200, help_text='Enter a book genre (e.g. Science Fiction)') + + def __str__(self): + """String for representing the Model object.""" + return self.name</pre> + +<p class="syntaxbox">O model tem apenas um campo do tipo <code>CharField</code> (<code>name</code>), que é usado para descrever o genero (esse campo é limitado a 200 caracteres e tem um <code>help_text</code>). No final da classe Genre declaramos o metodo <code>__str__()</code> que retorna o nome do genero definido por um registro especifico. Não foi definido um argumento <code>verbose_name</code> , assim o campo será referenciado como <code>Name</code> nos forms.</p> + +<h3 id="Book_model">Book model</h3> + +<p>Copie o model Book abaixo e cole novamente ao final do seu arquivo. O model Book representa todas as informações disponíveis sobre um livro de maneira geral, mas não incluí detalhes sobre o formato do encadernamento ou disponibilidade para empréstimo. O model usa um <code>CharField</code> para representar o <code>title</code> (tílutlo) do livro e o <code>isbn</code> (veja que o <code>isbn</code> recebe um rótulo como "ISBN", usando o primeiro parâmetro não nomeado, porque, de outra forma, o rótulo ficaria "Isbn"). O model usa <code>TextField</code> para o campo <code>summary</code> porque ele precisa ser um tanto longo.</p> + +<pre class="notranslate">from django.urls import reverse # Used to generate URLs by reversing the URL patterns + +class Book(models.Model): + """Model representing a book (but not a specific copy of a book).""" + title = models.CharField(max_length=200) + + # Foreign Key used because book can only have one author, but authors can have multiple books + # Author as a string rather than object because it hasn't been declared yet in the file + author = models.ForeignKey('Author', on_delete=models.SET_NULL, null=True) + + summary = models.TextField(max_length=1000, help_text='Enter a brief description of the book') + isbn = models.CharField('ISBN', max_length=13, help_text='13 Character <a href="https://www.isbn-international.org/content/what-isbn">ISBN number</a>') + + # ManyToManyField used because genre can contain many books. Books can cover many genres. + # Genre class has already been defined so we can specify the object above. + genre = models.ManyToManyField(Genre, help_text='Select a genre for this book') + + def __str__(self): + """String for representing the Model object.""" + return self.title + + def get_absolute_url(self): + """Returns the url to access a detail record for this book.""" + return reverse('book-detail', args=[str(self.id)])</pre> + +<p>Genre é um campo <code>ManyToManyField</code>, de forma que um livro pode ter múltiplos gêneros e um gênero pode ter muitos livros. O campor Author é declarado como um <code>ForeignKey</code>, logo, cada livro terá somente um autor, mas um autor por der muitos livros (na prática, um livro pode ter múltiplos autores, mas não nesta implementação!)</p> + +<p>Em ambos tipos de campo, a classe model relacionada é declarada como primeiro campo não nomeado usando a classe model ou contendo o nome do modelo relacionado. Você deve usar o nome do model como uma string se a classe associada ainda não tiver sido definida no arquivo, antes de referenciá-la. Outro parâmetro de interesse no campo <code>author</code> é <code>null=True</code>, o qual permite ao banco de dados armazer um valor <code>Null</code> se nenhum autor for selecionado, e, <code>on_delete=models.SET_NULL</code>, o qual definirá o valor <code>author</code> como <code>Null</code> se o registro do autor associado for excluído.</p> + +<p>O mode também defini <code>__str__()</code>, usando o <code>title</code> do livro para representar o registro do <code>Book</code>. O método final, <code>get_absolute_url()</code>, retorna a URL que pode ser usada para acessar o registro detalhado deste modelo (para que isto funcione, teremos que definir um mapa de URL com o nome <code>book-detail</code> e associá-la a uma view e a um template.).</p> + +<h3 id="BookInstance_model">BookInstance model</h3> + +<p>Em seguida, copie o modelo <code>BookInstance</code> (exibido a abaixo) depois dos outros modelos. O <code>BookInstance</code> representa um exemplar específico do livro que pode ser emprestado, indica se ela está disponível ou a data programada de restituição, "imprint" ou detalhes da versão, e, um id único do livro na biblioteca.</p> + +<p>Alguns dos campos e métodos serão familiares agora. O model usa</p> + +<ul> + <li><code>ForeignKey</code> para identificar o <code>Book</code> associado (cada livro pode ter muitos exemplares, porém uma cópia pode ter sometne um <code>Book</code>).</li> + <li><code>CharField</code> para representar o imprint (edição específica) do livro.</li> +</ul> + +<pre class="brush: python notranslate">import uuid # Required for unique book instances + +class BookInstance(models.Model): + """Model representing a specific copy of a book (i.e. that can be borrowed from the library).""" + id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular book across whole library') + book = models.ForeignKey('Book', on_delete=models.SET_NULL, null=True) + imprint = models.CharField(max_length=200) + due_back = models.DateField(null=True, blank=True) + + LOAN_STATUS = ( + ('m', 'Maintenance'), + ('o', 'On loan'), + ('a', 'Available'), + ('r', 'Reserved'), + ) + + status = models.CharField( + max_length=1, + choices=LOAN_STATUS, + blank=True, + default='m', + help_text='Book availability', + ) + + class Meta: + ordering = ['due_back'] + + def __str__(self): + """String for representing the Model object.""" + return f'{self.id} ({self.book.title})'</pre> + +<p>Nós declaramos adicionalmente alguns tipos novos de campos:</p> + +<ul> + <li><code>UUIDField</code> é usado no campo <code>id</code> para definí-lo como <code>primary_key</code> deste model. Este tipo de campo aloca um valor único global para cada instância (um para cada livro encontrado na biblioteca).</li> + <li><code>DateField</code> é usado para a data <code>due_back</code> (na qual o livro deve retonar e ficar disponível após um empréstimo ou uma manutenção). O valor pode ser <code>blank</code> ou <code>null</code> (para quando o livro estiver disponível). O model metadata (<code>Class Meta</code>) usa este campo para ordenar os registros quando eles são retornados em uma query.</li> + <li><code>status</code> é um <code>CharField</code> que define uma lista de opção/seleção. Como pode ser visto, nós definimos uma dupla contendo pares de valores-chave e a passamos no argumento da opção. O valor do par valor-chave é um valor que o usuário pode selecionar, enquanto que a chave é o valor que realmetne será salvo se a opção for selecionada. Nós também definimos um valor default como "m" (maintenance), uma vez que os livros serão inicialmente criados como indisponíveis até que eles sejam disponibilizados nas prateleiras.</li> +</ul> + +<p>O model <code>__str__()</code> representa o objeto <code>BookInstance</code> usando a combinação do seu id único e o título do <code>Book</code> associado.</p> + +<div class="note"> +<p><strong>Nota</strong>: Um pouco sobre Python:</p> + +<ul> + <li>Começando com Python 3.6, pode ser usada a sintaxe de interpolação (também conhecida como f-strings): <code>f'{self.id} ({self.book.title})'</code>.</li> + <li>Em versões anteriores deste tutorial, nós estávamos usando a sintaxe de <a href="https://www.python.org/dev/peps/pep-3101/">formatted string</a>, a qual também é uma maneira válida de formatar strings em Python (e.g. <code>'{0} ({1})'.format(self.id,self.book.title)</code>).</li> +</ul> +</div> + +<h3 id="Author_model">Author model</h3> + +<p>Copie o model <code>Author</code> (exibido abaixo) na sequência do código existente em <strong>models.py</strong>.</p> + +<p>Todos os campos/métodos já devem ser familiares agora. O model define um autor como tendo um nome, sobrenome, data de nascimento e data de morte (opcionalmente). Ele especifica que <code>__str__()</code> retorna por default sobrenome e nome, nesta ordem. O método <code>get_absolute_url()</code> reverte o mapaeamento da URL <code>author-detail</code> para obter a URL de display individual author.</p> + +<pre class="brush: python notranslate">class Author(models.Model): + """Model representing an author.""" + first_name = models.CharField(max_length=100) + last_name = models.CharField(max_length=100) + date_of_birth = models.DateField(null=True, blank=True) + date_of_death = models.DateField('Died', null=True, blank=True) + + class Meta: + ordering = ['last_name', 'first_name'] + + def get_absolute_url(self): + """Returns the url to access a particular author instance.""" + return reverse('author-detail', args=[str(self.id)]) + + def __str__(self): + """String for representing the Model object.""" + return f'{self.last_name}, {self.first_name}' + +</pre> + +<h2 id="Rode_novamente_a_migração_do_banco_de_dados">Rode novamente a migração do banco de dados</h2> + +<p>Todos os modelos foram criados. Agora rode a migração do banco de dados para adicioná-los ao seu banco de dados.</p> + +<pre class="notranslate"><code>python3 manage.py makemigrations +python3 manage.py migrate</code></pre> + +<h2 id="Language_model_—_desafio">Language model — desafio</h2> + +<p>Considere que um benfeitor local doe uma quantidade de livros escritos em outro idioma (digamos, Farsi). O desafio é desenvolver como eles seriam melhor representados no website da nossa biblioteca, e, então, adicioná-lo no models.</p> + +<p>Algumas coisas a considerar:</p> + +<ul> + <li>O idioma seria associado ao <code>Book</code>, <code>BookInstance</code>, ou algum outro objeto?</li> + <li>Os diferentes idiomas seriam representados usando model, como campo de texto livre ou codificado como uma lista de seleção?</li> +</ul> + +<p>Depois de decidido, adicione o campo. Pode ser visto o que decidimos no Github <a href="https://github.com/mdn/django-locallibrary-tutorial/blob/master/catalog/models.py">aqui</a>.</p> + +<ul> +</ul> + +<ul> +</ul> + +<h2 id="Resumo">Resumo</h2> + +<p>Neste artículo vimos como os models são definidos, e, então, usamos esta informação para desenhar e implementar modelos apropriados para o website <em>LocalLibrary</em>.</p> + +<p>Neste ponto faremos um rápido desvio da criação do site para ver o <em>Django Administration site</em>. Este site nos permitirá adicionar alguns dados à biblioteca, os quais podemos então exibir usando nossos próprios views e templates (ainda não criados).</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.1/intro/tutorial02/">Escrevendo nossa primeira app Django, parte 2</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/db/queries/">Fazendo queries</a> (Django Docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/querysets/">Referência a QuerySet API</a> (Django Docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: Website de uma biblioteca local</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Tutorial Django Parte 2: Criando o escopo do website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Models">Django Parte 3: Utilizando models</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Admin_site">Django Parte 4: Django admin site</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Home_page">Django Parte 5: Criando nossa página principal</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Generic_views">Django Parte 6: Lista genérica e detail views</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Sessions">Django Parte 7: Framework de Sessões</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Authentication">Django Parte 8: Autenticação de Usuário e permissões</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Forms">Django Parte 9: Trabalhando com formulários</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Testing">Django Parte 10: Testando uma aplicação web Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial Django Parte 11: Implantando Django em produção</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/web_application_security">Segurança de aplicações Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/sessões/index.html b/files/pt-br/learn/server-side/django/sessões/index.html new file mode 100644 index 0000000000..f2f16b521f --- /dev/null +++ b/files/pt-br/learn/server-side/django/sessões/index.html @@ -0,0 +1,205 @@ +--- +title: 'Tutorial Django Parte 7: Sessões' +slug: Learn/Server-side/Django/Sessões +tags: + - Artigo + - Iniciante + - Programação + - Python + - Script + - Servidor + - Tutorial + - aprenda + - django + - django português + - server-side + - sessões django +translation_of: Learn/Server-side/Django/Sessions +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django/authentication_and_sessions", "Learn/Server-side/Django")}}</div> + +<div>Esse tutorial estende nosso site <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a>, adicionando um contador de visitas baseado em sessões à página inicial. Esse é um exemplo relativamente simples, mas, capaz de mostrar como você pode usar a estrutura de sessão do framework para providenciar um comportamento persistente para usuários anônimos em seu próprio site.</div> + +<div></div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Completar todos os tópicos anteriores do tutorial, incluindo <a href="/en-US/docs/Learn/Server-side/Django/Generic_views">Django Tutorial Part 6: Generic list and detail views</a></td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender como as sessões são usadas.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_Geral">Visão Geral</h2> + +<p>O site <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a> que criamos nos tutoriais anteriores permite que os usuarios busquem por livros e autores no catálogo. Enquanto o conteúdo é dinamicamente gerado a partir da base de dados, todos os usuários terão acessos às mesmas páginas e às mesmas informações quando acessarem o site.</p> + +<p><span class="tlid-translation translation"><span title="">Em uma biblioteca "real", você pode querer fornecer uma experiência personalizada para cada usuário, com base no uso anterior do site, nas preferências, etc. Por exemplo, você pode ocultar mensagens de aviso que o usuário reconheceu anteriormente na próxima visita deles ao</span> <span title="">site ou armazenar e respeitar suas preferências (por exemplo, o número de resultados de pesquisa que eles querem exibir em cada página).</span></span></p> + +<div class="text-wrap tlid-copy-target"> +<div class="result-shield-container tlid-copy-target"><span class="tlid-translation translation"><span title="">A estrutura da sessão permite implementar esse tipo de comportamento, permitindo que você armazene e recupere dados arbitrários baseados em cada visitante do site.</span></span></div> +</div> + +<h2 id="O_que_são_sessões">O que são sessões?</h2> + +<p>Toda a comunicação entre os navegadores web e os servidores é feita via protocolo HTTP, qual é <em>stateless</em> (sem estados). O fato do protocolo ser stateless significa que as mensagenns entre o cliente e o servidor são completamente independentes uma da outra — não há uma noção de "sequência" ou comportamento diferente baseado nas mensagens anteriores. <span class="tlid-translation translation"><span title="">Como resultado, se você quiser ter um site que monitore os relacionamentos contínuos com um cliente, é necessário implementá-lo por conta própria.</span></span></p> + +<p>Sessões são o mecanismo usado pelo Django (e muitos outros na Internet) para monitorar o "estado" entre o site e um navegador web em particular. Sessões permitem que você armazene dados arbitrários por navegador web, e têm esse dado disponível no site sempre que o navegador conectar. Dados de itens individuais associados com a sessão são referenciados por uma "chave", que é usada para armazenar e recuperar os dados.</p> + +<p>O Django usa um cookie contendo um <em>identificador</em> especial de sessão para identificar cada navegador e associar com o site. Os dados da sessão atual são armazenados na base de dados do site por padrão (é mais seguro do que armazenar os dados em cookie, onde é mais vulnerável aos usuários perigisos). Você pode configurar o Django para armazenar os dados da sessão em outros lugares (cache, arquivos, cookies "seguros"), mas o local padrão é uma opção boa e relativamente "segura".</p> + +<h2 id="Habilitando_as_Sessões">Habilitando as Sessões</h2> + +<p>As sessões foram ativadas automaticamente quando <a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">criamos o esqueleto do site</a> (no tutorial 2).</p> + +<p>A configuração e feita nas seções <code>INSTALLED_APPS</code> e <code>MIDDLEWARE</code> do arquivo (<strong>locallibrary/locallibrary/settings.py</strong>), exibidas a seguir:</p> + +<pre class="brush: python">INSTALLED_APPS = [ + ... +<strong> 'django.contrib.sessions',</strong> + .... + +MIDDLEWARE = [ + ... +<strong> 'django.contrib.sessions.middleware.SessionMiddleware',</strong> + ....</pre> + +<h2 id="Usando_Sessões">Usando Sessões</h2> + +<p>Você pode acessar o atributo <code>session</code> na view a partir do parâmetro <code>request</code> (um <code>HttpRequest</code> passado como primeiro argumento na view). Esse atributo de sessão representa a conexão atual específica com um usuário<span class="tlid-translation translation"><span title=""> (ou, para ser mais preciso, a conexão com o navegador atual, conforme identificado pelo id da sessão no cookie do navegador para este site)</span></span>.</p> + +<p>O atributo <code>session</code> é como um objeto dicionário que você pode ler e escrever quantas vezes você quiser na sua view, modificando-o como desejar. Você pode fazer todas as operações normais de um dicionário, incluindo limpar todos os dados, testar se uma chave está presente, loop em torno dos dados, etc. Na maior parte do tempo, você usará apenas a API padrão "dictionary" para obter e setar valores.</p> + +<p>O fragmento de código abaixo mostra como você pode obter, setar e deletar qualquer dado com com a chave "<code>my_car</code>", associada com a sessão atual (navegador).</p> + +<div class="note"> +<p><strong>Nota</strong>: Uma das coisas boas sobre o Django é que você não precisa pensar sobre os mecanismos que vinculam a sessão atual à requisição em sua view. Se nós usarmos os fragmentos abaixo em nossa view, saberemos que as informações sobre <code>my_car</code> estão associadas apenas com o navegador que enviou a requisição atual.</p> +</div> + +<pre class="brush: python"># Pega um valor de sessão baseado na sua chave (ex.:'my_car'), disparando um KeyError se a chave não for encontrada. +my_car = request.session['my_car'] + +# Pega o valor da sessão, seta o valor padrão ('mini') se a chave não estiver presente. +my_car = request.session.get('my_car', 'mini') + +# Seta o valor da sessão +request.session['my_car'] = 'mini' + +# Deleta o valor da sessão +del request.session['my_car'] +</pre> + +<p>A API também oferece um número de outros métodos que são muito usados para gerenciar a os cookies da sessão associada. Por exemplo, há metodos para testar se cookies são suportados no navegador do cliente, para setar e checar a data de validade do cookie, e para limpar sessões expiradas do armazenamento de dados. Você pode encontrar sobre a API completa em <a href="https://docs.djangoproject.com/en/2.1/topics/http/sessions/">How to use sessions</a> (documentação do Django).</p> + +<h2 id="Salvando_os_dados_da_sessão">Salvando os dados da sessão</h2> + +<p>Por padrão, o Django só salva na base de dados da sessão e envia o cookie da sessão para o cliente quando a sessão é <em>modificada </em>(atribuida) ou <em>deletada</em>. Se você está atualizando alguns dados utilizando sua chave de sessão, como mostrado na seção anterior, então você não precisa se preocupar com isso! Por exemplo:</p> + +<pre class="brush: python"># This is detected as an update to the session, so session data is saved. +request.session['my_car'] = 'mini'</pre> + +<p>Se você está atualizando algumas informações <em>dentro </em>dos dados da sessão, então o Django não reconhecerá que você fez uma alteração nos dados da sessão e não salvará os dados (por exemplo, se você alterasse os dados de "<code>wheels</code>" dentro dos dados do seu "<code>my_car</code>", como mostrado abaixo). Nesse caso você precisará marcar explicitamente a sessão como tendo sido modificada.</p> + +<pre class="brush: python"># Session object not directly modified, only data within the session. Session changes not saved! +request.session['my_car']['wheels'] = 'alloy' + +# Set session as modified to force data updates/cookie to be saved. +<code>request.session.modified = True</code> +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Você pode mudar o comportamento do site para atualizar a base de dados/enviar cookie em qualquer requisição adicionando <code>SESSION_SAVE_EVERY_REQUEST = True</code> nas configurações (<strong>locallibrary/locallibrary/settings.py</strong>) do seu projeto.</p> +</div> + +<h2 id="Exemplo_simples_-_obtendo_a_contagem_de_visitas">Exemplo simples - obtendo a contagem de visitas</h2> + +<p>Como um exemplo simples do mundo real, atualizaremos nossa biblioteca para informar ao usuário atual quantas vezes ele visitou o site <em>LocalLibrary</em>. </p> + +<p>Abra <strong>/locallibrary/catalog/views.py</strong>, e faça as alterações mostradas em negrito abaixo.</p> + +<pre class="brush: python">def index(request): + ... + + num_authors = Author.objects.count() # The 'all()' is implied by default. + +<strong> # Number of visits to this view, as counted in the session variable. + num_visits = request.session.get('num_visits', 0) + request.session['num_visits'] = num_visits + 1</strong> + +<strong> context = { + 'num_books': num_books, + 'num_instances': num_instances, + 'num_instances_available': num_instances_available, + 'num_authors': num_authors, + 'num_visits': num_visits, + }</strong> + + # Render the HTML template index.html with the data in the context variable. + return render(request, 'index.html', context=context)</pre> + +<p>Aqui primeiro obtemos o valor da <em>session key</em> <code>'num_visits'</code>, setando o valor para 0 se não tiver sido definido anteiormente. Cada vez que uma requisição é recebida, nós então incrementamos o valor e armazenamos novamente na sessão (para a próxima vez que o usuário visitar a página). A variável <code>num_visits</code> é então passada para o <em>template</em> na nossa varável <em>context</em>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Também podemos testar se os cookies são suportados no navegador (veja <a href="https://docs.djangoproject.com/en/2.1/topics/http/sessions/">Como usar sessões</a> para exemplos) ou projetar nossa UI (interface do usuário) para que não se importe se os <em>cookies</em> são ou não suportados.</p> +</div> + +<p>Adicione a linha vista na parte inferior do bloco a seguir ao seu <em>template</em> HTML principal (<strong>/locallibrary/catalog/templates/index.html</strong>) na parte inferior da sessão <em>"Dynamic content"</em>, para exibir a variável <em>context</em>:</p> + +<pre class="brush: html"><h2>Dynamic content</h2> + +<p>The library has the following record counts:</p> +<ul> + <li><strong>Books:</strong> \{{ num_books }}</li> + <li><strong>Copies:</strong> \{{ num_instances }}</li> + <li><strong>Copies available:</strong> \{{ num_instances_available }}</li> + <li><strong>Authors:</strong> \{{ num_authors }}</li> +</ul> + +<strong><p>You have visited this page \{{ num_visits }}{% if num_visits == 1 %} time{% else %} times{% endif %}.</p></strong> +</pre> + +<p>Salve suas alterações e reinicie o servidor de teste. Sempre que você atualiza a página, o número deve ser atualizado.</p> + +<ul> +</ul> + +<h2 id="Resumo">Resumo</h2> + +<p>Agora você sabe como é fácil utilizar sessões para melhorar sua interação com usuários anônimos. </p> + +<p>Em nosso próximo artigo nós iremos explicar a estrutura de autenticação e autorização (permissão), e mostrar como oferecer suporte a contas de usuário.</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/http/sessions/">Como usar sessões</a> (Django docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django/Authentication", "Learn/Server-side/Django")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: </a><a rel="nofollow" title="A página ainda não foi criada.">Website de uma Biblioteca Local</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Django Parte 2: </a><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/skeleton_website">Criando a base do website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Models">Django Parte 3: Usando <em>models</em></a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Admin_site">Django Parte 4: Django admin site</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Home_page">Django Parte 5: Criando nossa página principal</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Generic_views">Django Parte 6: </a><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Generic_views">Lista genérica e <em>detail views</em></a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Sessions">Django Parte 7: </a><a rel="nofollow" title="A página ainda não foi criada.">Framework de Sessões</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Authentication">Django Parte 8: </a><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Authentication">Autenticação de Usuário e permissões</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Forms">Django Parte 9: </a><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Forms">Trabalhando com formulários</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Testing">Django Parte 10: </a><a rel="nofollow" title="A página ainda não foi criada.">Testando uma aplicação web Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial</a> <a href="/en-US/docs/Learn/Server-side/Django/Deployment">Django Parte 11: </a><a rel="nofollow" title="A página ainda não foi criada.">Implantando Django em produção</a></li> + <li><a rel="nofollow" title="A página ainda não foi criada.">Segurança de aplicações web Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/skeleton_website/index.html b/files/pt-br/learn/server-side/django/skeleton_website/index.html new file mode 100644 index 0000000000..5a453131b2 --- /dev/null +++ b/files/pt-br/learn/server-side/django/skeleton_website/index.html @@ -0,0 +1,393 @@ +--- +title: 'Django Tutorial Parte 2: Criando o "esqueleto" de um site' +slug: Learn/Server-side/Django/skeleton_website +tags: + - Artigo + - Guía + - Iniciante + - Python + - locallibrary +translation_of: Learn/Server-side/Django/skeleton_website +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django/Models", "Learn/Server-side/Django")}}</div> + +<p class="summary">O segundo artigo do tutorial de Django mostra uma forma de criar o "esqueleto" de um website, permitindo que você possa ampliá-lo com caracteristicas especificas do site, caminhos (patchs), modelos (models), visualizações (views) e templates. </p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td><a href="/en-US/docs/Learn/Server-side/Django/development_environment">Configurar um ambiente de desenvolvimento Django</a>. Ter lido <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: Website de uma Biblioteca Local</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ser capaz de usar as ferramentas do Django para começar seus próprios novos projetos de websites.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_Geral">Visão Geral</h2> + +<p>Este artigo mostra como você pode criar o escopo de um website, permitindo popul-a-lo com características específicas do seu site, tais como configurações, paths, modelos, views e templates (nós os discutiremos em artigos que seguem à frente).</p> + +<p>O processo é direto:</p> + +<ol> + <li><span style="line-height: 1.5;">Use a ferramenta </span><code style="font-style: normal; font-weight: normal; line-height: 1.5;">django-admin</code><span style="line-height: 1.5;"> para criar a pasta do projeto, arquivos de template básicos, e o script de gestão do projeto (</span><strong style="line-height: 1.5;">manage.py</strong><span style="line-height: 1.5;">).</span></li> + <li><span style="line-height: 1.5;">Use o script </span><strong style="line-height: 1.5;">manage.py</strong><span style="line-height: 1.5;"> para criar um ou mais <em>aplicativos</em>.</span> + <div class="note"> + <p><strong>Nota</strong>: Um website pode consistir de uma ou mais áreas, como por exemplo, site, blog, wiki, área de download, etc. Django te encoraja a desenvolver esses componentes como aplicativos separados, que podem então ser reutilizados em diferentes projetos, caso seja necessário.</p> + </div> + </li> + <li><span style="line-height: 1.5;">Registre os novos aplicativos para inclui-los no projeto. </span></li> + <li><span style="line-height: 1.5;">Conecte o mapeador de url/path para cada aplicativo.</span></li> +</ol> + +<p>Para o <a href="/pt-BR/docs/Learn/Server-side/Django/Tutorial_local_library_website">website Biblioteca Local</a> a pasta do website e a pasta do projeto terão, ambas, o nome <em>locallibrary</em>, e nós teremos apenas um aplicativo chamado <em>catalog</em>. O nível hierárquico mais alto da estrutura de pastas ficará assim:</p> + +<pre class="brush: bash notranslate"><em>locallibrary/ # Pasta do website</em> + <strong>manage.py </strong> # Script para executara as ferramentas do Django para este projeto (criado utilizando o django-admin) + <em>locallibrary/ # Pasta do project folder </em>(criado utilizando o django-admin) + <em>catalog/ # Pasta do aplicativo </em>(criado utilizando o django-admin) +</pre> + +<p><span style="line-height: 1.5;">As próximas seções discutem esse processo em detalhes e mostram como você pode testar as mudanças. No final do artigo nós discutiremos algumas das outras configurações do site como um todo, você também pode fazer isso.</span></p> + +<h2 id="Criando_o_projeto">Criando o projeto</h2> + +<p>Primeiro abra o prompt de comando/terminal t(enha certeza que está em seu <a href="/pt-BR/docs/Learn/Server-side/Django/ambiente_de_desenvolvimento">ambiente virtual)</a>, navegue até o diretório que deseja colocar seus aplicativos Django (coloque em um lugar fácil de achar, como dentro da pasta <em>documentos</em>), e crie uma pasta para seu novo website (nesse caso: <em>django_projects</em>). Acesse então a pasta usando o comando cd:</p> + +<pre class="brush: bash notranslate">mkdir locallibrary +cd locallibrary</pre> + +<p>Crie um novo projeto usando o comando <code>django-admin startproject</code>, como mostrado abaixo, e entre nessa pasta.</p> + +<pre class="brush: bash notranslate">django-admin startproject locallibrary +cd locallibrary</pre> + +<p>O comando <code>django-admin</code> cria uma estrutura com pastas e arquivos como a mostrada abaixo:</p> + +<pre class="brush: bash notranslate"><em>locallibrary/</em> + manage.py + <em>locallibrary/</em> + __init__.py + settings.py + urls.py + wsgi.py</pre> + +<p>Nosso diretório de trabalho atual deve parecer com isso:</p> + +<pre class="syntaxbox notranslate">../django_projects/locallibrary/</pre> + +<p> A sub-pasta do projeto <em>locallibrary</em> será a raíz para nosso site:</p> + +<ul> + <li><strong>__init__.py </strong>é um arquivo em branco que instrui o Python a tratar esse diretório como um pacote Python.</li> + <li><strong>settings.py</strong> contém todas as definições do website. É onde nós registramos qualquer aplicação que criarmos, a localização de nossos arquivos estáticos, configurações de banco de dados etc. </li> + <li><strong>urls.py</strong> define os mapeamentos de URL para visualização do site<span style="line-height: 1.5;">. Mesmo que esse</span> arquivo possa conter <em>todo </em>o código para mapeamento de URL, é mais comum delegar apenas o mapeamento para aplicativos específicos, como será visto mais adiante.</li> + <li><strong style="line-height: 1.5;">wsgi.py</strong><span style="line-height: 1.5;"> é usado para ajudar na comunicação entre seu aplicativo Django e o web server. Você pode tratar isso como um boilerplate.</span></li> +</ul> + +<p>O script <strong>manage.py</strong> é usado para criar aplicações, trabalhar com bancos de dados, e iniciar o webserver de desenvolvimento. </p> + +<h2 id="Criando_o_aplicativo_de_catálogo">Criando o aplicativo de catálogo</h2> + +<p>Agora execute o seguinte comando para criar o <em>catálogo</em> da aplicação que fará parte de nosso projeto localibrary (o comando deve ser executado na mesma pasta que está o <strong>manage.py</strong> do seu projeto):</p> + +<pre class="brush: bash notranslate">python3 manage.py startapp catalog</pre> + +<div class="note"> +<p><strong>Nota</strong>: O comando acima é para Linux/macOS X. No windows o comando deve ser: <code>py -3 manage.py startapp catalog</code></p> + +<p>Se você está trabalhando com o Windows, substitua <code>python3</code> por <code>py -3</code> ao longo deste módulo.</p> + +<p>Se você está usando Python 3.7.0, use <code>py manage.py startapp catalog</code></p> +</div> + +<p>A ferramenta cria uma nova pasta e adiciona alguns arquivos para diferentes partes da aplicação (destacado em negrito abaixo). A maior parte dos arquivos é armazenada de acordo com seu propósito (e.g. views devem ser armazenadas em <strong>views.py</strong>, models em <strong>models.py</strong>, testes em <strong>tests.py</strong>, configurações de administração do site em <strong>admin.py</strong>, registro da aplicação em <strong>apps.py</strong>) e contém algum código mínimo para trabalhar com os objetos associados.</p> + +<p>O diretório do projeto atualizado deve parecer com esse:</p> + +<pre class="brush: bash notranslate"><em>locallibrary/</em> + manage.py + <em>locallibrary/ +</em><strong> <em>catalog/</em> + admin.py + apps.py + models.py + tests.py + views.py + __init__.py + <em>migrations/</em></strong> +</pre> + +<p>Além disso, nós temos:</p> + +<ul> + <li>Uma pasta <em>migrations</em>, usada para guardar "<em>migrações</em>" — arquivos que permitem atualizar automaticamente seu banco de dados à medida que você modifica seus models. </li> + <li><strong>__init__.py</strong> — Um arquivo em branco criado de modo que Django/Python reconheça a pasta como um <a href="https://docs.python.org/3/tutorial/modules.html#packages">Python Package</a> e permita que você use seus objetos dentro de outras partes do projeto.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Você notou o que falta na lista de arquivos acima? Apesar de existir um lugar para suas views e seus models, não há nenhum lugar para colocar seus mapeamentos de URL, templates ou arquivos estáticos. Nós iremos te ensinar como criá-los mais adiante (isso não é necessário em todos websites, mas precisarem em nosso exemplo).</p> +</div> + +<h2 id="Registrando_o_aplicativo_de_catálogo">Registrando o aplicativo de catálogo</h2> + +<p>Agora que a aplicação foi criada, iremos registrá-la com o projeto para que ela seja incluída quando qualquer ferramenta for executada (por exemplo para adicionar models para o banco de dados). Aplicações são registradas adicionando-as à lista <code>INSTALLED_APPS</code> que fica nas configurações do projeto.</p> + +<p>Abra o arquivo de configurações do projeto <strong>locallibrary/locallibrary/settings.py</strong> e encontre a definição para a lista <code>INSTALLED_APPS</code>. Agora adicione uma nova linha no fim da lista, como a mostrada em negrito abaixo.</p> + +<pre class="brush: bash notranslate">INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +<strong> 'catalog.apps.CatalogConfig', </strong> +]</pre> + +<p>A nova linha especifica o objeto de configuração do aplicativo (<code>CatalogConfig</code>) que foi gerado em <strong>/locallibrary/catalog/apps.py</strong> onde a aplicação foi criada.</p> + +<div class="note"> +<p><strong>Nota</strong>: Você deve ter notado que existem vários outros <code>INSTALLED_APPS</code> (e <code>MIDDLEWARE</code>, pelo final do arquivo de configuração). Eles permitem suporte para o <a href="/en-US/docs/Learn/Server-side/Django/Admin_site">site de administração do Django</a> e, como resultado, várias funcionalidades que ele utiliza (incluindo seções, autenticação etc).</p> +</div> + +<h2 id="Especificando_o_Banco_de_Dados">Especificando o Banco de Dados</h2> + +<p>Tipicamente, esse é o momento em que você também especifica o banco de dados que será usado no projeto— faz mais sentido usar o mesmo banco de dados tanto para desenvolvimento quanto para a produção (quando possível), a fim de evitar pequenas diferenças de comportamento. Você pode encontrar mais sobre as outras opções em <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#databases">Databases</a> (Documentação Django).</p> + +<p>Usaremos o banco de dados SQLite para este exemplo porque não esperamos ter muito acesso simultâneo em um banco de dados para demonstração, e também porque ele não requer trabalho adicional de configuração! Você pode ver como o banco de dados é configurado em <strong>settings.py</strong> (mais informações estão incluidas abaixo).</p> + +<pre class="brush: python notranslate">DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +</pre> + +<p>Já que nós estamos usando SQLite, nós não precisamos de nenhum outro passo aqui. Vamos ir em frente!</p> + +<h2 id="Outras_configurações_do_projeto">Outras configurações do projeto</h2> + +<p>O arquivo <strong>settings.py</strong> também é usado para configurar várias outras definições, mas por ora você provavelmente quer mudar apenas a <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-TIME_ZONE">TIME_ZONE</a> — deve se utilizar uma string padrão da <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">Lista de tz time zones</a> (a coluna TZ na tabela contém os valores que você precisa). Mude seu valor de <code>TIME_ZONE</code> para uma string relativa ao seu fuso-horário, por exemplo:</p> + +<pre class="brush: python notranslate">TIME_ZONE = 'America/Sao_Paulo'</pre> + +<p>Tem outras duas definições que você não vai mudar agora, mas que deve ficar ciente:</p> + +<ul> + <li><code>SECRET_KEY</code>. É uma chave secreta que é usada como parte da estratégia de segurança dos websites Django. Se você não está protegendo seu código durante o desenvolvimento, você precisará usar um código diferente (que talvez seja lido de uma variável de ambiente ou arquivo) quando colocar no ambiente de produção.</li> + <li><code>DEBUG</code>. Isto habilita a depuração de logs sejam exibidos em um erro ao invés de respostas de status de código HTTP. Isso deve ser definido como <code>False</code> na produção, já que informações de debug são úteis para invasores, mas por enquanto nós manteremos <code>True.</code></li> +</ul> + +<h2 id="Conectando_o_mapeador_de_URL">Conectando o mapeador de URL</h2> + +<p>O website foi criado com um arquivo mapeador de URL (<strong>urls.py</strong>) na pasta do projeto. Embora você possa usar esse arquivo para gerenciar todos seus mapeamentos de URL, é mais comum fazer os mapeamentos diretamente no aplicativo associado.</p> + +<p>Abra <strong>locallibrary/locallibrary/urls.py</strong> e leia o texto que explica alguma formas de usar o mapeador de URL.</p> + +<pre class="brush: python notranslate">"""locallibrary URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/2.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +</pre> + +<p>Os mapeamentos de URL são gerenciados através da variável <code>urlpatterns</code> que é uma lista Python de funções <code>path()</code>. Cada função <code>path()</code> associa um padrão de URL para uma <em>view específica</em>, que será exibida quando o padrão for correspondido, ou com outra lista de testes de padrões de URL (no segundo caso, o padrão vem da "URL base" para padrões definidos no módulo target). A lista <code>urlpatterns</code> define inicialmente uma função única que mapeia todas URLs com o padrão admin para o módulo <code>admin.site.urls</code>, que contém as próprias definições de mapeamento de URL da área de administração do aplicativo.</p> + +<div class="note"> +<p><strong>Nota:</strong> A rota em <code>path()</code> é uma string que define um padrão de URL para correspondência. Essa string pode incluir um nome de variável (entre tags), e.g. <code>'catalog/<id>/'</code>. Esse padrão corresponderá a uma URL como <strong>/catalog/</strong><em>any_chars</em><strong>/</strong> e passa <em>any_chars</em> para a view como uma string com paramêtros nome <code>id</code>). Nós discutiremos métodos de caminho e padrões de rota ainda mais em tópicos posteriores</p> +</div> + +<p>Adicione as linhas abaixo no fim do arquivo a fim de adicionar um novo item à lista <code>urlpatterns</code>. Esse novo item inclui um <code>path()</code> que encaminha solicitações com o padrão <code>catalog/</code> para o módulo <code>catalog.urls</code> (o arquivo com a URL relativa <strong>/catalog/urls.py</strong>). </p> + +<pre class="brush: python notranslate"># Use include() to add paths from the catalog application +from django.conf.urls import include +from django.urls import path + +urlpatterns += [ + path('catalog/', include('catalog.urls')), +] +</pre> + +<p>Agora iremos mudar a URL raíz de nosso site (i.e. <code>127.0.0.1:8000</code>) para <code>127.0.0.1:8000/catalog/</code>; pois esse é o único app que iremos usar neste projeto. Para isso, usaremos uma função view especial (<code>RedirectView</code>), que leva como primeiro argumento a nova URL relativa para redirecionar para <code>/catalog/</code> quando o padrão URL especificado na função <code>path()</code> for chamado (a URL raíz nesse caso).</p> + +<p>Adicione as linhas abaixo, novamente no fim do arquivo:</p> + +<pre class="brush: python notranslate">#Add URL maps to redirect the base URL to our application +from django.views.generic import RedirectView +urlpatterns += [ + path('', RedirectView.as_view(url='/catalog/')), +]</pre> + +<p>Deixe o primeiro parâmetro da função path vazio, implicando em '/'. Se você escrever o primeiro parâmetro como '/', Django irá te mostar o seguinte aviso assim que iniciar o servidor de desenvolvimento.</p> + +<pre class="brush: python notranslate">System check identified some issues: + +WARNINGS: +?: (urls.W002) Your URL pattern '/' has a route beginning with a '/'. +Remove this slash as it is unnecessary. +If this pattern is targeted in an include(), ensure the include() pattern has a trailing '/'. +</pre> + +<p>Por padrão, Django não "serve" arquivos estáticos como CSS, JavaScript e imagens, mas ele pode ser útil para o servidor web de desenvolvimento enquanto você cria seu site. Como comentário final sobre o mapeador de URL, você pode habilitar a veiculação de arquivos estáticos durante o desenvolvimento adicionando as seguintes linhas.</p> + +<p>Coloque o seguinte bloco no fim do arquivo:</p> + +<pre class="notranslate"><code># Use static() to add url mapping to serve static files during development (only) +from django.conf import settings +from django.conf.urls.static import static + +urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)</code> +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Existem várias maneiras de estender a lista <code>urlpatterns</code> (acima nós acrecentamos uma nova lista de itens usando o operador <code>+=</code> para separar claramente o velho do novo código). Poderiamos ter apenas incluído esse novo padrão de mapeamento na definição da lista original.</p> + +<pre class="brush: python notranslate">urlpatterns = [ + path('admin/', admin.site.urls), + path('catalog/', include('catalog.urls')), + path('', RedirectView.as_view(url='/catalog/', permanent=True)), +] + <code>static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)</code> +</pre> + +<p>Além disso, incluimos a linha para importação (<code>from django.urls import include</code>) com o código que usa-o (que facilita ver o que nós adicionamos), porém, é mais comum incluir todas as linhas de import no topo do arquivo Python.</p> +</div> + +<p>Finalmente, crie um arquivo dentro da pasta catalog e dê o nome <strong>urls.py</strong>, adicione então o seguinte texto para definir um <code>urlpatterns</code> importado (e vazio). É aqui onde você adicionará nossos padrões enquanto desenvolvemos o aplicativo.</p> + +<pre class="brush: python notranslate">from django.urls import path +from catalog import views + + +urlpatterns = [ + +] +</pre> + +<h2 id="Testando_o_framework_do_site">Testando o framework do site</h2> + +<p>Você acabou de criar o escopo do site. Por enquanto o site ainda não faz nada, mas vale a pena testá-lo para garantir que nenhuma de nossas mudanças tenha criado algum problema.</p> + +<p>Antes de começarmos, devemos primeiramente executar uma <em>migração de banco de dados</em>. Isso atualiza nosso banco de dados para incluir qualquer model em nossas aplicações instaladas (e remove avisos da build).</p> + +<h3 id="Migrando_Bancos_de_Dados">Migrando Bancos de Dados</h3> + +<p>Django usa um Object-Relational-Mapper (ORM) que mapeia as definições de Model no código Django para a estrutura do banco de dados subjacente. Como mudamos nossas definições de model, Django localiza as mudanças e cria scripts para migração de banco de dados (em<strong> /locallibrary/catalog/migrations/</strong>) para migrar automaticamente a estrutura de dados subjacente no banco de dados para manter a correnpondência com o model.</p> + +<p>Quando criamos nosso website, Django adicionou automaticamente um número de models para serem usados na área admin do site (que nós veremos depois). Execute os comandos abaixo para definir as tabelas para aqueles models no banco de dados (verifique se você está no diretório que contém o arquivo <strong>manage.py</strong>):</p> + +<pre class="brush: bash notranslate">python3 manage.py makemigrations +python3 manage.py migrate +</pre> + +<div class="warning"> +<p><strong>Importante</strong>: Você precisará executar os comandos acima sempre que alterar seus models de uma forma que afete a estrutura de dados que precisa ser armazenada (incluindo adição e remoção de todos models e campos individuais).</p> +</div> + +<p>O comando <code>makemigrations</code> <em>cria</em> (mas não aplica) as migrações para todos aplicativos instalados em seu projeto (você pode especificar o nome do aplicativo para executar apenas uma migração para um único projeto). Isso te permite checar o código para essas migrações antes delas serem aplicadas — quando você é experiente em Django, você pode escolher ajustá-los um pouco!</p> + +<p>O comando <code>migrate</code> aplica as migrações em seu banco de dados (Django rastreia quais foram adicionados ao banco de dados atual).</p> + +<div class="note"> +<p><strong>Nota</strong>: Leia <a href="https://docs.djangoproject.com/en/2.0/topics/migrations/">Migrations</a> (Documentação Django) para informações adicionais sobre os comandos de migração menos usados.</p> +</div> + +<h3 id="Testando_o_website">Testando o website</h3> + +<p>Durante o desenvolvimento você pode testar o website usando o <em>webserver de desenvolvimento</em>, e vê-lo em seu navegador local.</p> + +<div class="note"> +<p><strong>Nota</strong>: O web server de desenvolvimento não tem performance ou desempenho suficiente para uso em produção, mas é uma maneira bem fácil de atualizar seu website Django e utilizá-lo durante o desenvolvimento para conseguir um teste rápido e conveniente. Por padrão, o site é "hospedado" em seu computador local (<code>http://127.0.0.1:8000/)</code>, mas você também pode especificar que outros computadores da rede acessem-o. Para mais informações acesse <a href="https://docs.djangoproject.com/en/2.0/ref/django-admin/#runserver">django-admin and manage.py: runserver</a> (Documentação Django).</p> +</div> + +<p>Execute o <em>web server de desenvolvimento</em> com o comando <code>runserver</code> (no mesmo diretório de <strong>manage.py</strong>):</p> + +<pre class="brush: bash notranslate">python3 manage.py runserver + + Performing system checks... + + System check identified no issues (0 silenced). + August 15, 2018 - 16:11:26 + Django version 2.1, using settings 'locallibrary.settings' + Starting development server at http://127.0.0.1:8000/ + Quit the server with CTRL-BREAK. +</pre> + +<p>Com o servidor funcionando, você pode ver seu site colocando o endereço <code>http://127.0.0.1:8000/</code> em seu navegador local. Você deve ver uma página de erro como essa:</p> + +<p><img alt="Django Debug page for Django 2.0" src="https://mdn.mozillademos.org/files/15729/django_404_debug_page.png"></p> + +<p>Não se assuste! Essa página de erro é esperada, pois nós não temos nehuma página ou url definida no módulo <code>catalogs.urls</code> (que é para onde somos redirecionados quando usamos a URL para a raíz do site).</p> + +<div class="note"> +<p><strong>Nota</strong>: A página acima demontra um ótimo recurso do Django — o log de depuração automatizado. Uma tela de erro será exibida com informações referentes ao erro sempre que uma página não consiga ser encontrada, ou caso o código tenha algum erro. Nesse caso poderemos ver que a URL que nós fornecemos não corresponde a nenhum de nossos padrões de URL (como listado). O log será desativado durante a produção (quando colocamos nosso site online na WEB), nesse caso uma página menos informativa (porém, mais amigável ao usuário) será exibida.</p> +</div> + +<p>No momento basta saber que o Django está funcionando! </p> + +<div class="note"> +<p><strong>Nota</strong>: Você deve executar novamente as migrações e testar o site sempre que fizer alguma mudança signifcante. Não demora muito!</p> +</div> + +<h2 id="Desafio">Desafio</h2> + +<p>O diretório <strong>catalog/</strong> contém arquivos para views, models, e outras partes da aplicação. Abra esses arquivos e inspecione o bolierplate (códigos incluídos em muitos lugares com pouca ou nenhuma alteração). </p> + +<p>Como você viu acima, um mapeamento de URL para o site Admin já foi adicionado no arquivo <strong>urls.py</strong> do projeto. Vá à área do admin em seu navegador e veja o que acontece (você pode deduzir a URL correta para o mapeamento acima).</p> + +<h2 id="Sumário">Sumário</h2> + +<p>Você acabou de criar um "esqueleto" para websties, agora você pode popular o site com URL's, models, views e templates.</p> + +<p>Como o escopo para o <a href="/pt-BR/docs/Learn/Server-side/Django/Tutorial_local_library_website">website Local Library</a> está completo e executando, é hora de começar a escrever códigos que farão o website realizar sua função.</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.0/intro/tutorial01/">Codificando seu primeiro app Django - parte 1</a> (Documentação Django)</li> + <li><a href="https://docs.djangoproject.com/en/2.0/ref/applications/#configuring-applications">Aplicativos</a> (Documentação Django). Contém informações de como configurar aplicativos.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django/Models", "Learn/Server-side/Django")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: Website de uma biblioteca local</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Tutorial Django Parte 2: Criando o escopo do website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Models">Django Parte 3: Utilizando models</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Admin_site">Django Parte 4: Django admin site</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Home_page">Django Parte 5: Criando nossa página principal</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Generic_views">Django Parte 6: Lista genérica e detail views</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Sessions">Django Parte 7: Framework de Sessões</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Authentication">Django Parte 8: Autenticação de Usuário e permissões</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Forms">Django Parte 9: Trabalhando com formulários</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial </a><a href="/en-US/docs/Learn/Server-side/Django/Testing">Django Parte 10: Testando uma aplicação web Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Tutorial Django Parte 11: Implantando Django em produção</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/web_application_security">Segurança de aplicações Django</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/testing/index.html b/files/pt-br/learn/server-side/django/testing/index.html new file mode 100644 index 0000000000..19867b2eca --- /dev/null +++ b/files/pt-br/learn/server-side/django/testing/index.html @@ -0,0 +1,944 @@ +--- +title: 'Tutorial Django Parte 10: Testando uma aplicação web Django' +slug: Learn/Server-side/Django/Testing +translation_of: Learn/Server-side/Django/Testing +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Forms", "Learn/Server-side/Django/Deployment", "Learn/Server-side/Django")}}</div> + +<p class="summary">À medida que websites crescem, eles se tornam mais difíceis de testar manualmente. Não apenas mais para testar, mas, as interações entre componentes tornam-se mais complexas, uma pequena mudança em uma área pode impactar outras áreas, portanto mais mudanças serão necessárias para garantir que tudo permaneça funcionando e erros não sejam introduzidos à medida que mais alterações forem feitas. Uma maneira de mitigar esses problemas é escrever testes automatizados, que podem ser executados facilmente e confiavelmente toda vez que você faz uma alteração. Este tutorial mostra como automatizar testes unitários do seu website utilizando o <em>framework</em> de testes do Django.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Complete todos os tópicos de tutoriais anteriores, incluindo <a href="/en-US/docs/Learn/Server-side/Django/Forms">Tutorial Django Parte 9: Trabalhando com formulários</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender como escrever testes unitários para websites baseados em Django.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_Geral">Visão Geral</h2> + +<p>A <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Local Library</a> atualmente tem páginas para mostrar listas de todos livros e autores, visualização detalhada para itens <code>Book</code> e <code>Author</code>, uma página para renovar <code>BookInstance</code>s, e páginas para criar, atualizar e excluir itens <code>Author</code> (e também registros de <code>Book</code>, se você completou o desafio no <a href="/en-US/docs/Learn/Server-side/Django/Forms">forms tutorial</a>). Mesmo com este site relativamente pequeno, navegar manualmente por cada página e verificar superficialmente se tudo funciona como esperado pode levar vários minutos. À medida que fizemos mudanças e aumentamos o site, o tempo necessário para verificar manualmente se tudo funciona "devidamente" só aumentará. Se continuássemos como estamos, eventuamente estaríamos gastando a maior parte do tempo testando, e muito pouco tempo aprimorando nosso código.</p> + +<p>Testes automatizados podem realmente ajudar com este problema! Os benefícios óbvios são que eles podem ser executados muito mais rápido que testes manuais, podem testar com um nível mais baixo de detalhes, e testa exatamente a mesma funcionalidade (testadores humanos não são nem de longe tão confiáveis!). Por serem rápidos, testes automatizados podem ser executados mais regularmente, e se um teste falhar, eles apontam exatamente para onde o código não está funcionando como esperado .</p> + +<p>Além disso, testes automatizados podem atuar como o primeiro "usuário" do mundo real do seu código, forçando você a ser rigoroso ao definir e documentar como seu website deve se comportar. Geralmente, eles são a base para seus exemplos de código e documentação. Por essas razões, alguns processos de desenvolvimento de código iniciam com definição e implementação de teste, o qual após o código é escrito para corresponder ao comportamento necessário (ex. <a href="https://en.wikipedia.org/wiki/Test-driven_development">desenvolvimento guiado por testes</a> e <a href="https://en.wikipedia.org/wiki/Behavior-driven_development">desenvolvimento guiado por comportamento</a>).</p> + +<p>Este tutorial mostra como escrever testes automatizados para Django, adicionando um número de testes para o website <em>LocalLibrary</em>.</p> + +<h3 id="Tipos_de_teste">Tipos de teste</h3> + +<p>Há inúmeros tipos, níveis, e classificações de testes e abordagens de testes. Os testes automatizados mais importantes são:</p> + +<dl> + <dt>Testes unitários</dt> + <dd>Verifica o comportamento funcional de componentes individuais, geralmente ao nível de classe e função.</dd> + <dt>Testes de regressão</dt> + <dd>Testes que reproduzem erros históricos. Cada teste é executado inicialmente para verificar se o erro foi corrigido, e então executado novamente para garantir que não foi reintroduzido após alterações posteriores no código.</dd> + <dt>Testes de integração</dt> + <dd>Verifica como agrupamentos de componentes funcionam quando utilizados juntos. Testes de integração estão cientes das interações necessárias entre componentes, mas não necessariamente das operações internas de cada componente. Eles podem abranger agrupamentos simples de componentes através de todo website.</dd> +</dl> + +<div class="note"> +<p><strong>Nota: </strong>Outros tipos de testes comuns incluem caixa preta (black box), caixa branca (white box), manual, automatizado, canário (canary), fumaça (smoke), conformidade (conformance), aceitação (acceptance), funcional (functional), sistema (system), <em>performance</em>, carga (load) e testes de <em>stress</em>. Procure-os para mais informaçãos.</p> +</div> + +<h3 id="O_que_o_Django_fornece_para_testes">O que o Django fornece para testes?</h3> + +<p>Testar um website é uma tarefa complexa, porque isto é composto de várias camadas de lógica – do tratamento de requisições no nível HTTP, consultas de modelos, validação e processamento de formulários, e renderização de <em>template</em>.</p> + +<p>Django fornece um <em>framework</em> de teste com uma baixa hierarquia de classes construida na biblioteca padrão <code><a href="https://docs.python.org/3/library/unittest.html#module-unittest" title="(in Python v3.5)">unittest</a></code> de Python. Apesar do nome, este <em>framework</em> de teste é adequado para testes unitários e de integração. O <em>framework</em> Django adiciona métodos e ferramentas de API para ajudar a testar o comportamento web e específico do Django. Isso permite você simular requisições, inserir dados de teste e inspecionar as saídas do seu aplicativo. Django também fornece uma API (<a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/#liveservertestcase">LiveServerTestCase</a>) e ferramentas para <a href="https://docs.djangoproject.com/en/2.1/topics/testing/advanced/#other-testing-frameworks">usar diferentes frameworks de teste</a>, por exemplo, você pode integrar com o popular framework <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment">Selenium</a> para simular um usuário interagindo com um navegador.</p> + +<p>Para escrever um teste, você deriva de qualquer uma das classes base de teste de Django (ou <em>unittest</em>) (<a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/#simpletestcase">SimpleTestCase</a>, <a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/#transactiontestcase">TransactionTestCase</a>, <a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/#testcase">TestCase</a>, <a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/#liveservertestcase">LiveServerTestCase</a>) e então escreve métodos separados para verificar se a funcionalidade específica funciona como esperado (testes usam métodos "<em>assert</em>" para testar se a expressão resulta em valores <code>True</code> ou <code>False</code>, ou se os dois valores são iguais, etc.). Quando você inicia a execução de um teste, o framework executa os métodos de teste escolhidos em suas classes derivadas. Os métodos de teste são executados independentemente, com configuração comum e/ou comportamento <em>tear-down</em> definido na classe, como mostrado abaixo.</p> + +<pre class="brush: python notranslate">class YourTestClass(TestCase): + def setUp(self): + # Setup run before every test method. + pass + + def tearDown(self): + # Clean up run after every test method. + pass + + def test_something_that_will_pass(self): + self.assertFalse(False) + + def test_something_that_will_fail(self): + self.assertTrue(False) +</pre> + +<p>A melhor classe base para maioria dos testes é <a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/#testcase">django.test.TestCase</a>. Esta classe de teste cria um banco de dados limpo antes dos testes serem executados, e executa todas as funções de teste em sua própria transação. A classe também possui um <a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/#django.test.Client" title="django.test.Client">Client</a> de teste, que você pode utilizar para simular um usuário interagindo com o código no nível de <em>view</em>. Nas seções a seguir vamos nos concentrar nos testes unitários, criados utilizando a classe base <a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/#testcase">TestCase</a>.</p> + +<div class="note"> +<p><strong>Nota:</strong> A classe <a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/#testcase">django.test.TestCase</a> é muito conveniente, mas pode resultar em alguns testes mais lentos do que necessitam ser (nem todo teste necessita configurar seu próprio banco de dados ou simular interação de <em>view</em>). Uma vez que esteja familiar com o que você pode fazer com essa classe, você pode querer substituir alguns dos seus testes por classes de teste mais simples disponíveis.</p> +</div> + +<h3 id="O_que_você_deve_testar">O que você deve testar?</h3> + +<p>Você deve testar todos aspectos do seu próprio código, mas nenhuma biblioteca ou funcionalidade oferecida como parte do Python ou Django.</p> + +<p>Assim por exemplo, conseidere o <em>model</em> <code>Author</code> definido abaixo. Você não precisa testar explicitamente se <code>first_name</code> e <code>last_name</code> foram armazenados corretamente como <code>CharField</code> no banco de dados, porque isso é algo definido pelo Django (embora, é claro, na prática você inevitávelmente testará esta funcionalidade durante o desenvolvimento). Você também não precisa testar se o <code>date_of_birth</code> foi validado para ser um campo de data, porque isso novamente é algo implementeado no Django.</p> + +<p>No entanto, você deve verificar o texto utilizado para os <em>labels</em> (<em>First name, Last name, Date of birth, Died</em>), e o tamanho do campo alocado para o texto (<em>100 caracteres</em>), porque isso faz parte do seu <em>design</em> e algo que pode ser violado/alterado no futuro.</p> + +<pre class="brush: python notranslate">class Author(models.Model): + first_name = models.CharField(max_length=100) + last_name = models.CharField(max_length=100) + date_of_birth = models.DateField(null=True, blank=True) + date_of_death = models.DateField('Died', null=True, blank=True) + + def get_absolute_url(self): + return reverse('author-detail', args=[str(self.id)]) + + def __str__(self): + return '%s, %s' % (self.last_name, self.first_name)</pre> + +<p>Similarmente, você deve verificar se os métodos personalizados <code style="font-style: normal; font-weight: normal;">get_absolute_url()</code> e <code style="font-style: normal; font-weight: normal;">__str__()</code> se comportam como desejado, porque els são sua lógica de código/negócios. No caso de <code style="font-style: normal; font-weight: normal;">get_absolute_url()</code> você pode confiar que o método <code>reverse()</code> de Django, foi implementado corretamente, portanto, o que você esta testando é se a <em>view</em> associada foi realmente definida.</p> + +<div class="note"> +<p><strong>Nota:</strong> Leitores astutos podem notar que também gostariamos de restringir que a data de nascimento e morte como valores sensíveis, e verificar se a morte vem após o nascimento. Em Django, esta restrição seria adicionada a suas classes <em>form</em> (Embora você possa definir validadores para campos do modelo e validadores de modelo, estes só serão usados no nível do formulário se forem chamdos pelo método clean() do model. Isso requer um ModelForm ou o método clean() do modelo precisa ser especificamente chamado).</p> +</div> + +<p>Com isso em mente, vamos começar a ver como definir e executar testes.</p> + +<h2 id="Visão_geral_da_estrutura_de_teste">Visão geral da estrutura de teste</h2> + +<p>Antes de entrarmos nos detalhes de "o que testar", vamos primeiro examinar brevemente <em>onde</em> e <em>como</em> os testes são definidos.</p> + +<p>Django usa o módulo <em>unittest</em> com <a href="https://docs.python.org/3/library/unittest.html#unittest-test-discovery" title="(in Python v3.5)">descoberta de teste acoplada</a>, que descrobrirá testes no diretório de trabalho atual em qualquer arquivo nomeado com o padrão <strong>test*.py</strong>. Fornecido o nome do arquivo adequadamente, você pode usar qualquer estrutura que desejar. Recomendamos que você crie um módulo para seu código de teste, e tenha arquivos separados para <em>models</em>, <em>views</em>, <em>forms </em>e qualquer outro tipo de código que você precise testar. Por exemplo:</p> + +<pre class="notranslate">catalog/ + /tests/ + __init__.py + test_models.py + test_forms.py + test_views.py +</pre> + +<p>Crie uma estrutura de arquivos como mostrado acima em seu projeto <em>LocalLibrary</em>. O <strong>__init__.py</strong> deve ser um arquivo vazio (isso informa ao Python que o diretório é um pacote). Você pode criar os três arquivos de teste copiando e renomeando o arquivo de teste do "esqueleto" <strong>/catalog/tests.py</strong>.</p> + +<div class="note"> +<p><strong>Nota:</strong> O arquivo de teste <strong>/catalog/tests.py</strong> do "esqueleto", foi criado automaticamente quando nós <a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">construimos o "esqueleto" do website Django</a>. É perfeitamente "legal" colocar todos seus testes dentro dele, mas se você testar devidamente, você acabará rapidamente com um arquivo de teste muito grande e incontrolável.</p> + +<p>Exclua o arquivo do "esqueleto", pois não precisamos dele.</p> +</div> + +<p>Abra <strong>/catalog/tests/test_models.py</strong>. O arquivo deve importar <code>django.test.TestCase</code>, como mostrado:</p> + +<pre class="brush: python notranslate">from django.test import TestCase + +# Create your tests here. +</pre> + +<p>Frequentemente, você adicionará uma classe de teste para cada <em>model/view/form</em> que deseja testar, com métodos individuais para testar funcionalidades específicas. Em outros casos, você pode desejar ter uma classe separada para testar um caso de uso específico, com funções de teste individuais que testam aspectos desse caso de uso (por exemplo, uma classe para testar se um campo do <em>model</em> é validado corretamente, com funções para testar cada um dos possíveis casos de falha). Novamente, a estrutura depende muito de você, mas é melhor se você for consistente.</p> + +<p>Adicione a classe de teste abaixo na parte inferior do arquivo. A classe demonstra como construir uma classe de teste derivando de <code>TestCase</code>.</p> + +<pre class="brush: python notranslate">class YourTestClass(TestCase): + @classmethod + def setUpTestData(cls): + print("setUpTestData: Run once to set up non-modified data for all class methods.") + pass + + def setUp(self): + print("setUp: Run once for every test method to setup clean data.") + pass + + def test_false_is_false(self): + print("Method: test_false_is_false.") + self.assertFalse(False) + + def test_false_is_true(self): + print("Method: test_false_is_true.") + self.assertTrue(False) + + def test_one_plus_one_equals_two(self): + print("Method: test_one_plus_one_equals_two.") + self.assertEqual(1 + 1, 2)</pre> + +<p>A nova classe define dois métodos que você pode utilizar para aconfiguração de pré-teste (por exemplo, para criar quaisquer modelos ou outros objetos que precisará para to teste):</p> + +<ul> + <li><code>setUpTestData()</code> é chamado uma vez no início da execução do teste para configuração em nível de classe. Você usaria isso para criar objetos que não serão modificados ou alterados em nenhum dos métodos de teste.</li> + <li><code>setUp()</code> é chamado antes de toda função de teste para configurar qualquer objeto que possa ser modificado pelo teste (toda função de teste receberá uma versão "nova" desses objetos).</li> +</ul> + +<div class="note"> +<p>As classes de teste também têm um método <code>tearDown()</code>, que não usamos. Este método não é particularmente útil para testes de banco de dados, pois a classe base <code>TestCase</code> cuida da desmontagem do banco de dados para você.</p> +</div> + +<p>Abaixo desses, temos vários métodos de teste, que usam funções <code>Assert</code> para testar se as condições são verdadeiras, falsas ou iguais (<code>AssertTrue</code>, <code>AssertFalse</code>, <code>AssertEqual</code>). Se a condição não for avaliada como esperado, então o teste falhará e reportará o erro ao seu console.</p> + +<p><code>AssertTrue</code>, <code>AssertFalse</code>, <code>AssertEqual</code> são assertivas padrão fornecidas pelo <strong>unittest</strong>. Existem outras assertivas padão no <em>framework</em> e também <a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/#assertions">Django especifica assertivas</a> para testar se uma <em>view</em> redireciona (<code>assertRedirects</code>), para testar se um template específico foi utilizado (<code>assertTemplateUsed</code>), etc.</p> + +<div class="note"> +<p>Você normalmente não deve incluir funções <strong>print()</strong> em seus testes como mostrado acima. Nós fizemos isso aqui apenas para que você posssa ver no console a ordem que as funções de configuração são chamadas (na seção a seguir).</p> +</div> + +<h2 id="Como_executar_os_testes">Como executar os testes</h2> + +<p>A maneira mais fácil para executar todos os testes é usar o comando:</p> + +<pre class="brush: bash notranslate">python3 manage.py test</pre> + +<p>Isso descobrirá todos arquivos nomeados com o padrão <strong>test*.py</strong> no diretório atual e executará todos testes definidos usando as classes base apropriadas (aqui temos vários arquivos de teste, mas, atualmente, apenas <strong>/catalog/tests/test_models.py</strong> contém testes). Por padrão, os testes irão reportar individualmente apenas falhas no teste, seguidos por um resumo do teste.</p> + +<div class="note"> +<p>Se você obter erros semelhantes a: <code>ValueError: Missing staticfiles manifest entry ...</code> isso pode ocorrer porque o teste não é executado como <em>collectstatic</em> por padrão e seu <em>app</em> está usando uma classe de armazenamento que exige isto (veja <a href="https://docs.djangoproject.com/en/2.1/ref/contrib/staticfiles/#django.contrib.staticfiles.storage.ManifestStaticFilesStorage.manifest_strict">manifest_strict</a> para mais informações). Existem várias maneiras de solucionar esse problema - o mais fácil é simplesmente executar <em>collectstatic</em> antes de executar os testes:</p> + +<pre class="brush: bash notranslate">python3 manage.py collectstatic +</pre> +</div> + +<p>Execute os testes no diretório raiz de <em>LocalLibrary</em>. Você deve ver uma saída como a abaixo.</p> + +<pre class="brush: bash notranslate">> python3 manage.py test + +Creating test database for alias 'default'... +<strong>setUpTestData: Run once to set up non-modified data for all class methods. +setUp: Run once for every test method to setup clean data. +Method: test_false_is_false. +setUp: Run once for every test method to setup clean data. +Method: test_false_is_true. +setUp: Run once for every test method to setup clean data. +Method: test_one_plus_one_equals_two.</strong> +. +====================================================================== +FAIL: test_false_is_true (catalog.tests.tests_models.YourTestClass) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "D:\Github\django_tmp\library_w_t_2\locallibrary\catalog\tests\tests_models.py", line 22, in test_false_is_true + self.assertTrue(False) +AssertionError: False is not true + +---------------------------------------------------------------------- +Ran 3 tests in 0.075s + +FAILED (failures=1) +Destroying test database for alias 'default'...</pre> + +<p>Aqui vemos que tivemos uma falha no teste e podemos ver exatamente qual função falhou e por quê (essa falha é esperada, porque <code>False</code> não é <code>True</code>!).</p> + +<div class="note"> +<p><strong>Dica: </strong>A coisa mais importante para aprender com a saída do teste acima é que é muito mais valioso se você utilizar nomes descritivos/informativos para seus objetos e métodos.</p> +</div> + +<p>O texto acima mostrado em <strong>negrito</strong> normalmente não apareceria na saída do teste (isso é gerado pelas funções <code>print()</code> em nossos teste). Isso mostra como o método <code>setUpTestData()</code> é chamdo uma vez para classe e <code>setUp()</code> é chamado antes de cada método.</p> + +<p>As próximas seções mostram como você pode executar testes específicos e como controlar quanta infromação os testes exibem.</p> + +<h3 id="Mostrando_mais_informações_de_teste">Mostrando mais informações de teste</h3> + +<p>Se você deseja obter mais informação sobre a execução do teste, você pode mudar a verbosidade (<em>verbosity)</em>. Por exemplo, para listar os sucessos do teste, bem como as falhas (e um monte de informações sobre como o banco de dados de teste está configurado) vocêpode definir a <em>verbosity</em> para "2" como mostrado:</p> + +<pre class="brush: bash notranslate">python3 manage.py test --verbosity 2</pre> + +<p>Os níveis permitidos de <em>verbosity</em> são 0, 1, 2, e 3, com o padrão sendo "1".</p> + +<h3 id="Executando_testes_específicos">Executando testes específicos</h3> + +<p>Se você desseja executar um subconjunto de seus testes, você pode fazer isso especificando o caminho completo para o(s) pacote(s), módulos, subclasse <code>TestCase</code> ou método:</p> + +<pre class="brush: bash notranslate"># Run the specified module +python3 manage.py test catalog.tests + +# Run the specified module +python3 manage.py test catalog.tests.test_models + +# Run the specified class +python3 manage.py test catalog.tests.test_models.YourTestClass + +# Run the specified method +python3 manage.py test catalog.tests.test_models.YourTestClass.test_one_plus_one_equals_two +</pre> + +<h2 id="Testes_da_LocalLibrary">Testes da LocalLibrary</h2> + +<p>Agora que sabemos como executar nosso testes e que tipo de coisas precisams testar, vamos ver alguns exemplos práticos.</p> + +<div class="note"> +<p><strong>Nota: </strong>Não escreveremos todos os testes possíveis, mas isso deve lhe dar uma ideia de como testes trabalham e o que mais você pode fazer.</p> +</div> + +<h3 id="Models">Models</h3> + +<p>Como discutido acima, devemos testar qualquer coisa que faça parte do nosso projeto ou que seja definido por código que escrevemos, mas não bibliotecas/códigos que já foram testados pelo Django ou pela equipe de desenvolvimento do Python.</p> + +<p>Por exemplo, considere o <em>model</em> <code>Author</code> abaixo. Aqui devemos testar os <em>labels</em> para todos os campos, porque, embora não tenhamos específicado explicitamente a maioria deles, temos um projeto que diz quais devem ser esses valores. Se não testamos os valores, não sabemos se os <em>labels</em> dos campos têm os valores pretendidos. Similarmente, enquanto confiamos que o Django criará um campo com o tamanho específicado, vale a pena específicar um teste para este tamanho, para garantir que ele foi implementado como planejado.</p> + +<pre class="brush: python notranslate">class Author(models.Model): + first_name = models.CharField(max_length=100) + last_name = models.CharField(max_length=100) + date_of_birth = models.DateField(null=True, blank=True) + date_of_death = models.DateField('Died', null=True, blank=True) + + def get_absolute_url(self): + return reverse('author-detail', args=[str(self.id)]) + + def __str__(self): + return f'{self.last_name}, {self.first_name}'</pre> + +<p>Abra nosso <strong>/catalog/tests/test_models.py</strong>, e substitua qualquer código existente pelo seguinte código de teste para o <em>model</em> <code>Author</code>.</p> + +<p>Aqui você verá que primeiro importamos <code>TestCase</code> e derivamos nossa classe de teste (<code>AuthorModelTest</code>) a partir dela, usando um nome descritivo para que possamos identificar facilmente quaiquer testes com falha na saída do teste. Nós então chamamos <code>setUpTestData()</code> para criar um objeto autor que iremos usar mas não modificaremos em nenhum dos testes.</p> + +<pre class="brush: python notranslate">from django.test import TestCase + +from catalog.models import Author + +class AuthorModelTest(TestCase): + @classmethod + def setUpTestData(cls): + # Set up non-modified objects used by all test methods + Author.objects.create(first_name='Big', last_name='Bob') + + def test_first_name_label(self): + author = Author.objects.get(id=1) + field_label = author._meta.get_field('first_name').verbose_name + self.assertEquals(field_label, 'first name') + + def test_date_of_death_label(self): + author=Author.objects.get(id=1) + field_label = author._meta.get_field('date_of_death').verbose_name + self.assertEquals(field_label, 'died') + + def test_first_name_max_length(self): + author = Author.objects.get(id=1) + max_length = author._meta.get_field('first_name').max_length + self.assertEquals(max_length, 100) + + def test_object_name_is_last_name_comma_first_name(self): + author = Author.objects.get(id=1) + expected_object_name = f'{author.last_name}, {author.first_name}' + self.assertEquals(expected_object_name, str(author)) + + def test_get_absolute_url(self): + author = Author.objects.get(id=1) + # This will also fail if the urlconf is not defined. + self.assertEquals(author.get_absolute_url(), '/catalog/author/1')</pre> + +<p>Os testes de campo verificam se os valores dos <em>labels</em> dos campos (<code>verbose_name</code>) e se o tamanho dos campos de caracteres são como esperado. Todos esses métodos possuem nomes descritivos e seguem o mesmo padrão:</p> + +<pre class="brush: python notranslate"># Get an author object to test +author = Author.objects.get(id=1) + +# Get the metadata for the required field and use it to query the required field data +field_label = author._meta.get_field('first_name').verbose_name + +# Compare the value to the expected result +self.assertEquals(field_label, 'first name')</pre> + +<p>As coisas interessantes a serem observadas aqui:</p> + +<ul> + <li>Não podemos obter <code>verbose_name</code> diretamente utilizando <code>author.first_name.verbose_name</code>, porque <code>author.first_name</code> é uma <em>string</em> (não um identificador para o objeto <code>first_name</code> que podemos utilizar para acessar suas propriedades). Em vez disso, precisamos utilizar o atributo <code>_meta</code> de <em>author</em> para obter uma instância do campo e usá-la para consultar informações adicionais.</li> + <li>Optamos por utilizar <code>assertEquals(field_label,'first name')</code> em vez de <code>assertTrue(field_label == 'first name')</code>. A razão para isso é que, se o teste falhar a saída do primeiro informa o que realmente era o <em>label</em>, que torna a depuração do problema um pouco mais fácil.</li> +</ul> + +<div class="note"> +<p><strong>Nota:</strong> Testes para os rótulos <code>last_name</code> e <code>date_of_birth</code> e também para o teste para o tamanho do <code>last_name</code> field foram omitidos. Adicione suas próprias versões agora, seguindo as convenções de nomeclatura e abordagens mostradas acima.</p> +</div> + +<p>Também precisamos testar nossos métodos personalizados. Eles, essencialmente, apenas verificam se o nome do objeto foi construido como esperamos, usando o formato "Last Name", "First Name", e se a URL que obtemos para um item de <code>Author</code> é o que esperávamos.</p> + +<pre class="brush: python notranslate">def test_object_name_is_last_name_comma_first_name(self): + author = Author.objects.get(id=1) + expected_object_name = f'{author.last_name}, {author.first_name}' + self.assertEquals(expected_object_name, str(author)) + +def test_get_absolute_url(self): + author = Author.objects.get(id=1) + # This will also fail if the urlconf is not defined. + self.assertEquals(author.get_absolute_url(), '/catalog/author/1')</pre> + +<p>Execute os testes agora. Se você criou o modelo Author como descrevemos no tutorial de modelos, é bem provável que você obtenha um erro para o <em>label</em> <code>date_of_death</code> como mostrado abaixo. O teste está falhando porque foi escrito esperando que a definição do <em>label</em> siga a convenção do Django de não colocar em maíúscula a primeira letra do <em>label</em> (Django faz isso por você).</p> + +<pre class="brush: bash notranslate">====================================================================== +FAIL: test_date_of_death_label (catalog.tests.test_models.AuthorModelTest) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "D:\...\locallibrary\catalog\tests\test_models.py", line 32, in test_date_of_death_label + self.assertEquals(field_label,'died') +AssertionError: 'Died' != 'died' +- Died +? ^ ++ died +? ^</pre> + +<p>Este é um bug muito pequeno, mas destaca como a escrita de testes pode verificar mais minuciosamente quaislquer suposições que você tenha feito.</p> + +<div class="note"> +<p><strong>Nota:</strong> Altere o <em>label</em> para o campo date_of_death (/catalog/models.py) para "died" e re-executes os testes.</p> +</div> + +<p>Os padrões para testar os outros modelos são semelhantes, portanto não continuaremos discutindo mais isso. Sinta-se livre para criar seus próprios testes para nossos outros modelos.</p> + +<h3 id="Forms">Forms</h3> + +<p>A filosofia para testar seus <em>forms </em>é a mesma que para testar seus <em>models</em>; você precisa testar qualquer coisa que tenha codificado ou seu projeto especifica, mas não o comportamento do framework subjacente e outras bibliotecas de terceiros</p> + +<p>Geralmente, isso significa que você deve testar se os <em>forms</em> têm os campos que você deseja e se esses são exibidos com os <em>labels</em> e texto de ajuda apropriados. Você não precisa verificar se o Django o tipo de campo corretamente (a menos que você tenha criado seu próprio campo e validação personalizados) — ex. você não precisa testar se um campo de email aceita apenas email. No entanto, você precisaria testar qualquer validação adicional que você espera que seja executada nos campos e quaisquer mensagens que seu código irá gerar para erros.</p> + +<p>Considere nosso <em>form</em> para renovação de livros. Ele tem apenas um campo para data de renovação, que terá um <em>label</em> e um texto de ajuda que precisaremos verificar.</p> + +<pre class="brush: python notranslate">class RenewBookForm(forms.Form): + """Form for a librarian to renew books.""" + renewal_date = forms.DateField(help_text="Enter a date between now and 4 weeks (default 3).") + + def clean_renewal_date(self): + data = self.cleaned_data['renewal_date'] + + # Check if a date is not in the past. + if data < datetime.date.today(): + raise ValidationError(_('Invalid date - renewal in past')) + + # Check if date is in the allowed range (+4 weeks from today). + if data > datetime.date.today() + datetime.timedelta(weeks=4): + raise ValidationError(_('Invalid date - renewal more than 4 weeks ahead')) + + # Remember to always return the cleaned data. + return data</pre> + +<p>Abra nosso arquivo <strong>/catalog/tests/test_forms.py</strong> e substitua qualquer código existente pelo seguinte código de teste para o <em>form</em> <code>RenewBookForm</code>. Nós iniciamos importando nosso <em>form</em> e algumas bibliotecas Python e Django para ajudar testar funcionalidades relacionadas ao tempo. Em seguida, declaramos nossa classe de teste do <em>form,</em> da mesma maneira que fizemos para <em>models</em>, usando um nome descritivo para a classe de teste derivada de <code>TestCase</code>.</p> + +<pre class="brush: python notranslate">import datetime + +from django.test import TestCase +from django.utils import timezone + +from catalog.forms import RenewBookForm + +class RenewBookFormTest(TestCase): + def test_renew_form_date_field_label(self): + form = RenewBookForm() + self.assertTrue(form.fields['renewal_date'].label == None or form.fields['renewal_date'].label == 'renewal date') + + def test_renew_form_date_field_help_text(self): + form = RenewBookForm() + self.assertEqual(form.fields['renewal_date'].help_text, 'Enter a date between now and 4 weeks (default 3).') + + def test_renew_form_date_in_past(self): + date = datetime.date.today() - datetime.timedelta(days=1) + form = RenewBookForm(data={'renewal_date': date}) + self.assertFalse(form.is_valid()) + + def test_renew_form_date_too_far_in_future(self): + date = datetime.date.today() + datetime.timedelta(weeks=4) + datetime.timedelta(days=1) + form = RenewBookForm(data={'renewal_date': date}) + self.assertFalse(form.is_valid()) + + def test_renew_form_date_today(self): + date = datetime.date.today() + form = RenewBookForm(data={'renewal_date': date}) + self.assertTrue(form.is_valid()) + + def test_renew_form_date_max(self): + date = timezone.localtime() + datetime.timedelta(weeks=4) + form = RenewBookForm(data={'renewal_date': date}) + self.assertTrue(form.is_valid()) +</pre> + +<p>As primeiras duas funções testam se os campos <code>label</code> e <code>help_text</code> são como esperados. Temos que acessar o campo usando o dicionário de campos (ex. <code>form.fields['renewal_date']</code>). Observe aqui que também precisamos testar se o valor do <em>label</em> é <code>None</code>, porque mesmo que o Django processe o <em>label</em> correto, retornará <code>None</code> se o valor não estiver definido explicitamente.</p> + +<p>O restante das funções testam se o form é valido para datas de renovação dentro do intervalo aceitável e inválido para os valores foram do intervalo. Observe como construimos os valores teste de data em torno de nossa data atual (<code>datetime.date.today()</code>) usando <code>datetime.timedelta()</code> (nesse caso, especificando um número de dias ou semanas). Então, apenas criamos o <em>form</em>, passando nossos dados e testando se é válido.</p> + +<div class="note"> +<p><strong>Nota:</strong> Aqui, na realidade, não usamos o banco de dados ou cliente teste. Considere modificar essses testes para utilizar <a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/#django.test.SimpleTestCase">SimpleTestCase</a>.</p> + +<p>Também precisamos validar que os erros corretos sejam gerados se o form é inválido, no entanto, isso geralmente é feito no processamento da view, portanto trataremos disso na próxima seção.</p> +</div> + +<p>Isso é tudo para <em>forms</em>; nós temos alguns outros, mas eles são automaticamente criados pelas nossas <em>views</em> de edição baseada na classe genérica, e devem ser testadas lá! Execute os testes e confirme se nosso código ainda passa!</p> + +<h3 id="Views">Views</h3> + +<p>Para validar o comportamento das nossas <em>views</em>, utilzamos <a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/#django.test.Client">Client</a> de teste do Django. Essa classe funciona como um navegador web fictício que podemos usar para simular requisições <code>GET</code> and <code>POST</code> em uma URL e observar a resposta. Podemos ver quase tudo sobre a resposta, desde HTTP de baixo nível (cabeçalhos de resultados e códigos de status) até o <em>template</em> que estamos utilizando para renderizar o HTML e os dados de contexto que estamos passando para ele. Também podemos ver a cadeia de redirecionamentos (se houver) e verificar a URL e o código de status em cada etapa. Isso nos permite verificar se cada <em>view</em> esta fazendo o que é esperado.</p> + +<p>Vamos iniciar com uma de nossas <em>views</em> mais simples, que fornece uma lista de todos Autores. Isso é exibido na URL <strong>/catalog/authors/</strong> (uma URL chamada 'authors' na configuração de URL).</p> + +<pre class="brush: python notranslate">class AuthorListView(generic.ListView): + model = Author + paginate_by = 10 +</pre> + +<p>Como esta é uma <em>list view</em> genérica, quase tudo é feito para nós pelo Django. Provavelmente, se você confia no Django, então a única coisa que você precisa testar é se a <em>view</em> é acessível na URL correta e pode ser acessada usando seu nome. No entanto, se você está usando um desenvolvimento orientado a testes, você iniciará escrevendo testes que confirmam que a <em>view</em> exibe todos Autores, paginando-os em lotes de 10.</p> + +<p>Abra o arquivo <strong>/catalog/tests/test_views.py</strong> e substitua qualquer texto existente pelo seguinte código de teste para <code>AuthorListView</code>. Como antes, importamos nosso <em>model</em> e algumas classe úteis. No método <code>setUpTestData()</code> configuramos vários objetos <code>Author</code> para que possamos testar nossa paginação.</p> + +<pre class="brush: python notranslate">from django.test import TestCase +from django.urls import reverse + +from catalog.models import Author + +class AuthorListViewTest(TestCase): + @classmethod + def setUpTestData(cls): + # Create 13 authors for pagination tests + number_of_authors = 13 + + for author_id in range(number_of_authors): + Author.objects.create( + first_name=f'Christian {author_id}', + last_name=f'Surname {author_id}', + ) + + def test_view_url_exists_at_desired_location(self): + response = self.client.get('/catalog/authors/') + self.assertEqual(response.status_code, 200) + + def test_view_url_accessible_by_name(self): + response = self.client.get(reverse('authors')) + self.assertEqual(response.status_code, 200) + + def test_view_uses_correct_template(self): + response = self.client.get(reverse('authors')) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'catalog/author_list.html') + + def test_pagination_is_ten(self): + response = self.client.get(reverse('authors')) + self.assertEqual(response.status_code, 200) + self.assertTrue('is_paginated' in response.context) + self.assertTrue(response.context['is_paginated'] == True) + self.assertTrue(len(response.context['author_list']) == 10) + + def test_lists_all_authors(self): + # Get second page and confirm it has (exactly) remaining 3 items + response = self.client.get(reverse('authors')+'?page=2') + self.assertEqual(response.status_code, 200) + self.assertTrue('is_paginated' in response.context) + self.assertTrue(response.context['is_paginated'] == True) + self.assertTrue(len(response.context['author_list']) == 3)</pre> + +<p>Todos os teste usam o cliente (pertenecente a nossa classe derivada <code>TestCase</code>'s) para simular uma requisição <code>GET</code> e obter uma resposta. A primeira versão verifica uma URL específica URL (observe, apenas o caminho específico, sem o domínio), enquanto a segunda gera a URL a partir do seu nome na configuração da URL.</p> + +<pre class="brush: python notranslate">response = self.client.get('/catalog/authors/') +response = self.client.get(reverse('authors')) +</pre> + +<p>Uma vez que temos a resposta, consultamos o seu código de status, o <em>template</em> usado, se a resposta é paginada ou não, o número de itens retonado e o número total de itens.</p> + +<div class="blockIndicator note"> +<p class="brush: python">Nota: Se você definir a variável <code>paginate_by</code> em seu arquivo <strong>/c</strong><strong>atalog/views.py</strong> para um número diferente de 10, atualize as linhas que testam se o número correto de itens é exibido nos <em>templates</em> paginados acima e nas seções seguintes. Por exemplo, se você definiu a variável para a lista de autor para 5, atualize a linha acima para:</p> + +<pre class="brush: python notranslate">self.assertTrue(len(response.context['author_list']) == 5) +</pre> +</div> + +<p>A variável mais importante que demonstramos acima é <code>response.context</code>, que é a variável de contexto passada para o <em>template</em> pela <em>view</em>. Isso é incrivelmente útil para testes, porque permite confirmar que nosso template está obtendo todos os dados necessários. Em outras palavras, podemos verificar se estamos utilizando o <em>template</em> pretendido e quais dados o <em>template</em> está obtendo, o que ajuda bastante a verificar que alguns problemas de renderização são apenas devido ao <em>template</em>.</p> + +<h4 id="Views_restritas_a_usuários_logados"><em>Views</em> restritas a usuários logados</h4> + +<p>Em alguns casos, você desejará testar uma <em>view</em> que é restrita apenas aos usuários logados. Por exemplo, nossa <code>LoanedBooksByUserListView</code> é muito similar a nossa <em>view</em> anterior, mas está disponível apenas para usuários logados e exibe apenas os registros <code>BookInstance</code> que são emprestados pelo usuário atual, têm o status 'emprestado' e são ordenados "mais antigos primeiro".</p> + +<pre class="brush: python notranslate">from django.contrib.auth.mixins import LoginRequiredMixin + +class LoanedBooksByUserListView(LoginRequiredMixin, generic.ListView): + """Generic class-based view listing books on loan to current user.""" + model = BookInstance + template_name ='catalog/bookinstance_list_borrowed_user.html' + paginate_by = 10 + + def get_queryset(self): + return BookInstance.objects.filter(borrower=self.request.user).filter(status__exact='o').order_by('due_back')</pre> + +<p>Adicione o código seguinte ao <strong>/catalog/tests/test_views.py</strong>. Aqui, primeiro usamos <code>SetUp()</code> para criar alguma contas de login de usuário e objetos <code>BookInstance</code> (junto com seus livros associados e outros registros) que usaremos posteriormente nos testes. Metade dos livros são emprestados para cada usuário teste, mas inicialmente definimos o status de todos os livros como "manutenção". Usamos <code>SetUp()</code> em vez de <code>setUpTestData()</code> porque modificaremos alguns desses objetos depois.</p> + +<div class="note"> +<p><strong>Nota:</strong> O código <code>setUp()</code> abaixo, cria um livro com uma <code>Language</code> especificada, mas seu código pode não incluir o <em>model</em> <code>Language</code>, pois foi criado como um desafio. Se esse for o caso, simplesmente comente as partes do código que cria ou importa objetos <em>Language</em>. Você também deve fazer isso na seção <code>RenewBookInstancesViewTest</code> a seguir.</p> +</div> + +<pre class="brush: python notranslate">import datetime + +from django.utils import timezone +from django.contrib.auth.models import User # Required to assign User as a borrower + +from catalog.models import BookInstance, Book, Genre, Language + +class LoanedBookInstancesByUserListViewTest(TestCase): + def setUp(self): + # Create two users + test_user1 = User.objects.create_user(username='testuser1', password='1X<ISRUkw+tuK') + test_user2 = User.objects.create_user(username='testuser2', password='2HJ1vRV0Z&3iD') + + test_user1.save() + test_user2.save() + + # Create a book + test_author = Author.objects.create(first_name='John', last_name='Smith') + test_genre = Genre.objects.create(name='Fantasy') + test_language = Language.objects.create(name='English') + test_book = Book.objects.create( + title='Book Title', + summary='My book summary', + isbn='ABCDEFG', + author=test_author, + language=test_language, + ) + + # Create genre as a post-step + genre_objects_for_book = Genre.objects.all() + test_book.genre.set(genre_objects_for_book) # Direct assignment of many-to-many types not allowed. + test_book.save() + + # Create 30 BookInstance objects + number_of_book_copies = 30 + for book_copy in range(number_of_book_copies): + return_date = timezone.localtime() + datetime.timedelta(days=book_copy%5) + the_borrower = test_user1 if book_copy % 2 else test_user2 + status = 'm' + BookInstance.objects.create( + book=test_book, + imprint='Unlikely Imprint, 2016', + due_back=return_date, + borrower=the_borrower, + status=status, + ) + + def test_redirect_if_not_logged_in(self): + response = self.client.get(reverse('my-borrowed')) + self.assertRedirects(response, '/accounts/login/?next=/catalog/mybooks/') + + def test_logged_in_uses_correct_template(self): + login = self.client.login(username='testuser1', password='1X<ISRUkw+tuK') + response = self.client.get(reverse('my-borrowed')) + + # Check our user is logged in + self.assertEqual(str(response.context['user']), 'testuser1') + # Check that we got a response "success" + self.assertEqual(response.status_code, 200) + + # Check we used correct template + self.assertTemplateUsed(response, 'catalog/bookinstance_list_borrowed_user.html') +</pre> + +<p>Para verificar se a <em>view</em> será redirecionada para uma página de login se o usuário não estiver logado, usamos <code>assertRedirects</code>, como demonstrado em <code>test_redirect_if_not_logged_in()</code>. Para verificar se a página é exibida para um usuário logado, primeiro logamos com nosso usuário teste e então acessamos a página novamente e verificamos se obtivemos um <code>status_code</code> de 200 (successo). </p> + +<p>O restante dos testes verificam se nossa <em>view</em> retorna apenas livros emprestados ao nosso usuário atual. Copie o código abaixo e cole no final da classe de teste acima.</p> + +<pre class="brush: python notranslate"> def test_only_borrowed_books_in_list(self): + login = self.client.login(username='testuser1', password='1X<ISRUkw+tuK') + response = self.client.get(reverse('my-borrowed')) + + # Check our user is logged in + self.assertEqual(str(response.context['user']), 'testuser1') + # Check that we got a response "success" + self.assertEqual(response.status_code, 200) + + # Check that initially we don't have any books in list (none on loan) + self.assertTrue('bookinstance_list' in response.context) + self.assertEqual(len(response.context['bookinstance_list']), 0) + + # Now change all books to be on loan + books = BookInstance.objects.all()[:10] + + for book in books: + book.status = 'o' + book.save() + + # Check that now we have borrowed books in the list + response = self.client.get(reverse('my-borrowed')) + # Check our user is logged in + self.assertEqual(str(response.context['user']), 'testuser1') + # Check that we got a response "success" + self.assertEqual(response.status_code, 200) + + self.assertTrue('bookinstance_list' in response.context) + + # Confirm all books belong to testuser1 and are on loan + for bookitem in response.context['bookinstance_list']: + self.assertEqual(response.context['user'], bookitem.borrower) + self.assertEqual('o', bookitem.status) + + def test_pages_ordered_by_due_date(self): + # Change all books to be on loan + for book in BookInstance.objects.all(): + book.status='o' + book.save() + + login = self.client.login(username='testuser1', password='1X<ISRUkw+tuK') + response = self.client.get(reverse('my-borrowed')) + + # Check our user is logged in + self.assertEqual(str(response.context['user']), 'testuser1') + # Check that we got a response "success" + self.assertEqual(response.status_code, 200) + + # Confirm that of the items, only 10 are displayed due to pagination. + self.assertEqual(len(response.context['bookinstance_list']), 10) + + last_date = 0 + for book in response.context['bookinstance_list']: + if last_date == 0: + last_date = book.due_back + else: + self.assertTrue(last_date <= book.due_back) + last_date = book.due_back</pre> + +<p>Você também pode adicionar testes de paginação, se desejar!</p> + +<h4 id="Testando_views_com_forms">Testando <em>views</em> com <em>forms</em></h4> + +<p>Testar views com forms é um pouco mais complicado que nos casos acima, porque você precisa testar mais caminhos de código: exibição inicial, exibição após falha de validação de dados e exibição após validação com sucesso. A boa notícia é que usamos o cliente para testar quase exatamente da mesma maneira que fizemos para <em>views</em> somente de exibição.</p> + +<p>Para demonstrar, vamos escrever alguns testes para a <em>view</em> usada para renovar livros (<code>renew_book_librarian()</code>):</p> + +<pre class="brush: python notranslate">from catalog.forms import RenewBookForm + +@permission_required('catalog.can_mark_returned') +def renew_book_librarian(request, pk): + """View function for renewing a specific BookInstance by librarian.""" + book_instance = get_object_or_404(BookInstance, pk=pk) + + # If this is a POST request then process the Form data + if request.method == 'POST': + + # Create a form instance and populate it with data from the request (binding): + book_renewal_form = RenewBookForm(request.POST) + + # Check if the form is valid: + if form.is_valid(): + # process the data in form.cleaned_data as required (here we just write it to the model due_back field) + book_instance.due_back = form.cleaned_data['renewal_date'] + book_instance.save() + + # redirect to a new URL: + return HttpResponseRedirect(reverse('all-borrowed')) + + # If this is a GET (or any other method) create the default form + else: + proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3) + book_renewal_form = RenewBookForm(initial={'renewal_date': proposed_renewal_date}) + + context = { + 'book_renewal_form': book_renewal_form, + 'book_instance': book_instance, + } + + return render(request, 'catalog/book_renew_librarian.html', context)</pre> + +<p>Precisamos testar se a <em>view</em> está disponível apenas para usuários que têm a permissão <code>can_mark_returned </code>, e se eles são direcionados para uma página de erro HTTP 404 se tentarem renovar um <code>BookInstance</code> que não existe. Devemos verificar se o valor inicial do form é propagado com uma data três semanas no futuro e se a validação for bem sucedida somos redirecionados para a <em>view</em> "all-borrowed books". Como parte da verificação dos testes de falha de validação, também verificaremos se nosso <em>form</em> está enviando mensagens de erro apropriadas.</p> + +<p>Adicione a primeira parte da classe de teste (mostrada abaixo) na parte inferior de <strong>/catalog/tests/test_views.py</strong>. Isso cria dois usuários e duas instâncias de livro, mas apenas concede a um usuário a permissão necessária para acessar a <em>view</em>. O código para conceder permissões durante os testes é mostrado em negrito:</p> + +<pre class="brush: python notranslate">import uuid + +from django.contrib.auth.models import Permission # Required to grant the permission needed to set a book as returned. + +class RenewBookInstancesViewTest(TestCase): + def setUp(self): + # Create a user + test_user1 = User.objects.create_user(username='testuser1', password='1X<ISRUkw+tuK') + test_user2 = User.objects.create_user(username='testuser2', password='2HJ1vRV0Z&3iD') + + test_user1.save() + test_user2.save() + +<strong> permission = Permission.objects.get(name='Set book as returned') + test_user2.user_permissions.add(permission) + test_user2.save()</strong> + + # Create a book + test_author = Author.objects.create(first_name='John', last_name='Smith') + test_genre = Genre.objects.create(name='Fantasy') + test_language = Language.objects.create(name='English') + test_book = Book.objects.create( + title='Book Title', + summary='My book summary', + isbn='ABCDEFG', + author=test_author, + language=test_language, + ) + + # Create genre as a post-step + genre_objects_for_book = Genre.objects.all() + test_book.genre.set(genre_objects_for_book) # Direct assignment of many-to-many types not allowed. + test_book.save() + + # Create a BookInstance object for test_user1 + return_date = datetime.date.today() + datetime.timedelta(days=5) + self.test_bookinstance1 = BookInstance.objects.create( + book=test_book, + imprint='Unlikely Imprint, 2016', + due_back=return_date, + borrower=test_user1, + status='o', + ) + + # Create a BookInstance object for test_user2 + return_date = datetime.date.today() + datetime.timedelta(days=5) + self.test_bookinstance2 = BookInstance.objects.create( + book=test_book, + imprint='Unlikely Imprint, 2016', + due_back=return_date, + borrower=test_user2, + status='o', + )</pre> + +<p>Adicione os seguintes testes na parte inferior da classe de teste. Eles verificam se apenas usuários com a permissão correta (testuser2) podem aceesar a <em>view</em>. Verificamos todos os casos: quando o usuários não está logado, quando um usuário está logado mas não tem as permissões corretas, quando o usuário possui permissões, mas não é o tomador do empréstimo (deve ter êxito), e o que acontece quando eles tentam acessar uma <code>BookInstance</code> que não existe. Também verificamos se o <em>template</em> correto é utilizado.</p> + +<pre class="brush: python notranslate"> def test_redirect_if_not_logged_in(self): + response = self.client.get(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk})) + # Manually check redirect (Can't use assertRedirect, because the redirect URL is unpredictable) + self.assertEqual(response.status_code, 302) + self.assertTrue(response.url.startswith('/accounts/login/')) + + def test_redirect_if_logged_in_but_not_correct_permission(self): + login = self.client.login(username='testuser1', password='1X<ISRUkw+tuK') + response = self.client.get(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk})) + self.assertEqual(response.status_code, 403) + + def test_logged_in_with_permission_borrowed_book(self): + login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') + response = self.client.get(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance2.pk})) + + # Check that it lets us login - this is our book and we have the right permissions. + self.assertEqual(response.status_code, 200) + + def test_logged_in_with_permission_another_users_borrowed_book(self): + login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') + response = self.client.get(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk})) + + # Check that it lets us login. We're a librarian, so we can view any users book + self.assertEqual(response.status_code, 200) + + def test_HTTP404_for_invalid_book_if_logged_in(self): + # unlikely UID to match our bookinstance! + test_uid = uuid.uuid4() + login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') + response = self.client.get(reverse('renew-book-librarian', kwargs={'pk':test_uid})) + self.assertEqual(response.status_code, 404) + + def test_uses_correct_template(self): + login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') + response = self.client.get(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk})) + self.assertEqual(response.status_code, 200) + + # Check we used correct template + self.assertTemplateUsed(response, 'catalog/book_renew_librarian.html') +</pre> + +<p>Adicione o próximo método de teste, como mostrado abaixo. Isso verifica se a data inicial para o form é três semanas no futuro. Observe como podemos acessar o valor do valor inicial do campo do form (mostrado em negrito).</p> + +<pre class="brush: python notranslate"> def test_form_renewal_date_initially_has_date_three_weeks_in_future(self): + login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') + response = self.client.get(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk})) + self.assertEqual(response.status_code, 200) + + date_3_weeks_in_future = datetime.date.today() + datetime.timedelta(weeks=3) + self.assertEqual(response<strong>.context['form'].initial['renewal_date']</strong>, date_3_weeks_in_future) +</pre> + +<div class="warning"> +<p>Se você usar a classe <em>form</em> <code>RenewBookModelForm(forms.ModelForm)</code> em vez da classe <code>RenewBookForm(forms.Form)</code>, então o nome do campo do <em>form</em> será <strong>'due_back' </strong>em vez de <strong>'renewal_date'</strong>.</p> +</div> + +<p>O próximo teste (adicione isso a classe também) verifica se a <em>view</em> redireciona para uma lista de todos livros emprestados, se a renovação for bem-sucedida. O que difere aqui é que pela primeira vez mostramos como você pode fazer <code>POST</code> de dados usando o cliente. Os dados do <em>post</em> são o segundo argumento da função <em>post</em>, e são especificados como um dicionário de chave/valores.</p> + +<pre class="brush: python notranslate"> def test_redirects_to_all_borrowed_book_list_on_success(self): + login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') + valid_date_in_future = datetime.date.today() + datetime.timedelta(weeks=2) + <strong>response = self.client.post(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}), {'renewal_date':valid_date_in_future})</strong> + self.assertRedirects(response, reverse('all-borrowed')) +</pre> + +<div class="warning"> +<p>A view <em>all-borrowed</em> foi adicionada como um <em>desafio</em>, e seu código pode, em vez disso, direcionar para a página inicial '/'. Nesse caso, modifique as últimas duas linhas do código de teste para que sejam como o código abaixo. O <code>follow=True</code> na solicitação, garante que a solicitação retorna a URL final de destino (portanto verifique <code>/catalog/</code> em vez de <code>/</code>).</p> + +<pre class="brush: python notranslate"> response = self.client.post(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}), {'renewal_date':valid_date_in_future}, <strong>follow=True</strong> ) + <strong>self.assertRedirects(</strong><strong>response, '/catalog/')</strong></pre> +</div> + +<p>Copie as última duas funções para a classe, como visto abaixo. Elas testam novamente as requisições <code>POST</code>, mas nesse caso, com datas inválidas de renovação. Utilizamos <code>assertFormError()</code> para verificar se as mensagens de erro são as esperadas.</p> + +<pre class="brush: python notranslate"> def test_form_invalid_renewal_date_past(self): + login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') + date_in_past = datetime.date.today() - datetime.timedelta(weeks=1) + response = self.client.post(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk}), {'renewal_date': date_in_past}) + self.assertEqual(response.status_code, 200) + <strong>self.assertFormError(</strong><strong>response, 'form', 'renewal_date', 'Invalid date - renewal in past')</strong> + + def test_form_invalid_renewal_date_future(self): + login = self.client.login(username='testuser2', password='2HJ1vRV0Z&3iD') + invalid_date_in_future = datetime.date.today() + datetime.timedelta(weeks=5) + response = self.client.post(reverse('renew-book-librarian', kwargs={'pk': self.test_bookinstance1.pk}), {'renewal_date': invalid_date_in_future}) + self.assertEqual(response.status_code, 200) + <strong>self.assertFormError(</strong><strong>response, 'form', 'renewal_date', 'Invalid date - renewal more than 4 weeks ahead')</strong> +</pre> + +<p>Os mesmos tipos de técnicas podem ser usadas para testar a outra <em>view</em>.</p> + +<h3 id="Templates"><em>Templates</em></h3> + +<p>Django fornece APIs de teste para verificar se o template correto esta sendo chamado por suas views, e para permitir que você verifique se a informação correta está sendo enviada. Entretanto, não há suporte específico à API para testar no Django que sua saída HTML seja renderizada conforme esperado.</p> + +<h2 id="Outras_ferramentas_de_teste_recomendadas">Outras ferramentas de teste recomendadas</h2> + +<p>O framework de teste do Django pode ajudar você a escrever eficazes testes unitários e de integração — nós apenas arranhamos a superfície do que o framework <strong>unittest</strong> pode fazer, muito menos as adições de Django (por exemplo, confira como você pode usar <a href="https://docs.python.org/3.5/library/unittest.mock-examples.html">unittest.mock</a> para corrigir bibliotecas de terceiros para que você possa testar mais detalhadamente seu próprio código).</p> + +<p>Embora existam inúmeras outras ferramentas de teste que você pode utilizar, destacaremos apenas duas:</p> + +<ul> + <li><a href="http://coverage.readthedocs.io/en/latest/">Coverage</a>: Essa ferramenta Python reporta quando do seu código é realmente executado pelos seus testes. É particularmente útil quando você começando e está tentando descobrir o que exatamente deve testar.</li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment">Selenium</a> é um framework para automatizar testes em um navegador real. Ele permite simular um usuário real interagindo com o site e fornece uma excelente estrutura para o sistema testar seu site (a próxima etapa do teste de integração).</li> +</ul> + +<h2 id="Desafie-se">Desafie-se</h2> + +<p>Existem muito mais <em>models</em> e <em>views</em> que podemos testar. Como uma tarefa simples, tente criar um caso de teste para a <em>view</em> <code>AuthorCreate</code>.</p> + +<pre class="brush: python notranslate">class AuthorCreate(PermissionRequiredMixin, CreateView): + model = Author + fields = '__all__' + initial = {'date_of_death':'12/10/2016'} + permission_required = 'catalog.can_mark_returned'</pre> + +<p>Lembre-se de que você precisa verificar qualquer coisa que você especificar ou que faça parte do projeto. Isso incluirá quem tem acesso, a data inicial, o <em>template</em> utilizado e para onde a view é redirecionada quando bem-sucedida.</p> + +<h2 id="Resumo">Resumo</h2> + +<p>Escrever código de teste não é divertido nem glamuroso, e é consequentemente muitas vezes deixado por último (ou nem isso) ao criar um site. No entanto, é uma parte essencial para garantir que seu código esteja seguro para <em>release</em> após fazer alterações e de baixo custo de manutenção.</p> + +<p>Neste tutorial, mostramos como escrever e executar testes para seus <em>models</em>, <em>forms</em> e <em>views</em>. Mais importante ainda, fornecemos um breve resumo do que você deve testar, que geralmente é a coisa mais difícil de resolver quando você está iniciando. Há muito mais para conhecer, mas mesmo com o que você já aprendeu, poderá criar testes unitários eficazes para seus websites.</p> + +<p>O próximo e último tutorial mostra como você pode implantar seu maravilhoso (e totalmente testado!) website Django.</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/testing/overview/">Escrevendo e executando testes</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/intro/tutorial05/">Escrevendo seu primeiro app Django, parte 5 > Introduzindo testes automatizados</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/testing/tools/">Refererências de ferramentas de teste</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.1/topics/testing/advanced/">Tópicos avançados de testes</a> (Django docs)</li> + <li><a href="http://toastdriven.com/blog/2011/apr/10/guide-to-testing-in-django/">Um Guia para testes no Django</a> (Toast Driven Blog, 2011)</li> + <li><a href="http://test-driven-django-development.readthedocs.io/en/latest/index.html">Workshop: Desenvolvimento web Orientado a Testes com Django</a> (San Diego Python, 2014)</li> + <li><a href="https://realpython.com/blog/python/testing-in-django-part-1-best-practices-and-examples/">Testando no Django (Parte 1) - Melhores práticas e Exemplos</a> (RealPython, 2013)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Forms", "Learn/Server-side/Django/Deployment", "Learn/Server-side/Django")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: Website de uma Biblioteca Local</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/skeleton_website">Tutorial Django Parte 2: Criando a base do website</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Models">Tutorial Django Parte 3: Usando models</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Admin_site">Tutorial Django Parte 4: Django admin site</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Home_page">Tutorial Django Parte 5: Criando nossa página principal</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Generic_views">Tutorial Django Parte 6: Lista genérica e detail views</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Sessions">Tutorial Django Parte 7: Framework de Sessões</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Authentication">Tutorial Django Parte 8: Autenticação de Usuário e permissões</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Forms">Tutorial Django Parte 9: Trabalhando com formulários</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Testing">Tutorial Django Parte 10: Testando uma aplicação web Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Deployment">Tutorial Django Parte 11: Implantando Django em produção</a></li> + <li><a rel="nofollow" title="A página ainda não foi criada.">Segurança de aplicações web Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/tutorial_website_biblioteca_local/index.html b/files/pt-br/learn/server-side/django/tutorial_website_biblioteca_local/index.html new file mode 100644 index 0000000000..da69f5c9de --- /dev/null +++ b/files/pt-br/learn/server-side/django/tutorial_website_biblioteca_local/index.html @@ -0,0 +1,98 @@ +--- +title: 'Tutorial Django: Website da Biblioteca Local' +slug: Learn/Server-side/Django/Tutorial_website_biblioteca_local +tags: + - Artigo + - Guía + - Iniciante + - Tutorial + - django +translation_of: Learn/Server-side/Django/Tutorial_local_library_website +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django")}}</div> + +<p class="summary">O primeiro artigo da nossa série de tutoriais práticos explica o que você irá aprender, e fornece uma visão do site de exemplo "biblioteca local" que estaremos trabalhando e evoluindo em artigos seguintes.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Ler a <a href="/pt-BR/docs/Learn/Server-side/Django/Introduction">introdução ao Django</a>. Para os próximos artigos você também necessitará ter montando o <a href="/pt-BR/docs/Learn/Server-side/Django/development_environment">ambiente de desenvolvimento</a> para o Django.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Introduzir o exemplo da aplicação usado neste tutorial, e permitir que os leitores entendam quais tópicos serão abordados.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_geral">Visão geral</h2> + +<p>Bem vindo ao tutorial Django "Biblioteca Local" do MDN, no qual desenvolveremos um website que pode ser usado para gerenciar um catálogo para uma biblioteca local.</p> + +<p>Nessa série de artigos você irá:</p> + +<ul> + <li>Usar as ferramentas do Django para criar a estrutura de um website e aplicação.</li> + <li>Começar e parar o servidor de desenvolvimento.</li> + <li>Criar models para representar os dados da aplicação.</li> + <li>Usar o <em>admin</em> do Django para popular os dados do seu site.</li> + <li>Criar <em>views </em>para recuperar dados específicos em resposta a diferentes requisições, e <em>templates</em> para renderizar os dados como HTML para serem exibidos no navegador.</li> + <li>Criar <em>mappers</em> para associar diferentes padrões de URL com as<em>views</em> específicas.</li> + <li>Adicionar autorização de usuário e sessões para controlar o comportamento e acesso do site.</li> + <li>Trabalhar com formulários.</li> + <li>Criar teste de código para a sua aplicação.</li> + <li>Usar a segurança do Django de forma eficaz.</li> + <li>Implantar sua aplicação para produção. </li> +</ul> + +<p>Você já aprendeu alguns desses tópicos e passou brevemente por outros. Até o final dessa série de tutoriais você deve saber o suficiente para desenvolver uma aplicação simples em Django sozinho.</p> + +<h2 id="Website_da_Biblioteca_Local_-_LocalLibrary">Website da Biblioteca Local - LocalLibrary</h2> + +<p><em>LocalLibrary</em> é o nome do site que vamos criar e evoluir ao longo dessa série de tutoriais. Como seria de esperar, a proposta do site é fornecer um catálogo online para uma pequena biblioteca local, onde os usuários podem procurar por livros disponíveis e gerenciar suas contas.</p> + +<p>Esse exemplo foi cuidadosamente escolhido porque escalar para mostrar quanto detalhe precisamos, muito ou pouco, e pode ser usado para mostrar quase qualquer recurso do Django. Mais importante ainda, nos permite fornecer um caminho <em>guiado</em> através da funcionalidade mais importante do estrutura web do Django:</p> + +<ul> + <li>Nos primeiros tutoriais, vamos definir uma biblioteca simples de <em>navegação exclusiva</em> que os membros podem usar para procurar quais livros estão disponíveis. Isso nos permite explorar operações simples que são comuns para quase todos os sites: leitura e exibição de conteúdo de um banco de dados</li> + <li>Conforme formos progredindo, o exemplo da biblioteca irá (naturalmente) se estender para demonstrar recursos mais avançados do Django. Nós podemos expandir a biblioteca, por exemplo, para permitir que usuários reservem livros, e usar isto para demonstrar como usar formulários e suporte a autenticação de usuários.</li> +</ul> + +<p>Embora este seja um exemplo extenso, ele é chamado Biblioteca<strong> Local</strong> por uma razão - nós esperamos mostrar o mínimo de informação necessária para ajudar a desenvolver e executar uma aplicação com o Django rapidamente. Como resultado nós armazenaremos informações sobre livros, seus exemplares, autores e outras informações chave. Contudo, nós não armazenaremos informações sobre outros itens que uma biblioteca pode utilizar, ou fornecer a infraestrutura necessária para dar suporte a sites multi-biblioteca ou outros recursos do tipo "grande biblioteca".</p> + +<h2 id="Onde_posso_obter_o_código_fonte">Onde posso obter o código fonte?</h2> + +<p>Na medida em que você avança com o tutorial, nós forneceremos os fragmentos de código apropriados para que você possa copiá-los e colá-los em cada ponto. Também existirão outros códigos que você estenderá por conta própria (com alguma orientação).</p> + +<p>Se você travar, a versão completa do website pode ser encontrada<a href="https://github.com/mdn/django-locallibrary-tutorial"> aqui no Github</a>.</p> + +<h2 id="Resumo">Resumo</h2> + +<p>Agora que você sabe um pouco mais sobre o website <em>LocalLIbrary</em> e o que você irá aprender, é hora de começar a criar um <a href="/pt-BR/docs/Learn/Server-side/Django/skeleton_website">escopo do projeto</a>.</p> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django")}}</p> + + + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: Website de uma Biblioteca Local</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/skeleton_website">Tutorial Django Parte 2: Criando a base do website</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Models">Tutorial Django Parte 3: Usando models</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Admin_site">Tutorial Django Parte 4: Django admin site</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Home_page">Tutorial Django Parte 5: Criando nossa página principal</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Generic_views">Tutorial Django Parte 6: Lista genérica e detail views</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Sessions">Tutorial Django Parte 7: Framework de Sessões</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Authentication">Tutorial Django Parte 8: Autenticação de Usuário e permissões</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Forms">Tutorial Django Parte 9: Trabalhando com formulários</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Testing">Tutorial Django Parte 10: Testando uma aplicação web Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Deployment">Tutorial Django Parte 11: Implantando Django em produção</a></li> + <li><a rel="nofollow" title="A página ainda não foi criada.">Segurança de aplicações web Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/django/web_application_security/index.html b/files/pt-br/learn/server-side/django/web_application_security/index.html new file mode 100644 index 0000000000..777a24a7cc --- /dev/null +++ b/files/pt-br/learn/server-side/django/web_application_security/index.html @@ -0,0 +1,187 @@ +--- +title: Segurança de aplicações web Django +slug: Learn/Server-side/Django/web_application_security +tags: + - Aprender + - Artigo + - Codificação + - Iniciante + - Programação server-side + - Python + - Segurança + - Segurança web + - django + - lado servidor (server-side) +translation_of: Learn/Server-side/Django/web_application_security +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Deployment", "Learn/Server-side/Django/django_assessment_blog", "Learn/Server-side/Django")}}</div> + +<p class="summary">Proteger dados do usuário é uma parte essencial de qualquer projeto de website. Anteriormente, explicamos algumas das ameaças de segurança mais comuns no artigo <a href="https://developer.mozilla.org/en-US/docs/Web/Security">Web security</a> — esse artigo fornece uma demonstração prática de como as proteções internas de Django lidam com essas ameaças.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Ler o tópico "<a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps/Website_security">Website security</a>" de Programação Server-side. Conclua os tópicos do tutorial Django tutorial até (e incluindo) pelos menos <a href="/en-US/docs/Learn/Server-side/Django/Forms">Tutorial Django Parte 9: Trabalhando com formulários</a>.</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>Para entender as principais coisas que você precisa fazer (ou não fazer) para proteger seu aplicatico web Django.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_geral">Visão geral</h2> + +<p>O tópico <a href="https://developer.mozilla.org/en-US/docs/Web/Security">Website security</a> fornece uma visão geral do que a segurança de website siginifica para o projeto server-side e algumas das ameaças mais comuns contra as quais você deve se proteger. Uma das mensagens chave nesse artigo é que quase todos os ataques são bem sucedidos quando a aplicação web confia nos dados do navegador.</p> + +<div class="warning"> +<p><strong>Importante:</strong> A lição mais importante que você pode aprender sobre segurança de website é <strong>nunca confiar nos dados do navegador</strong>. Isso inclui dados de requisição GET em parâmetros de URL, dados <code>POST</code>, cabeçalhos HTTP e cookies, arquivos enviados por usuários, etc. Sempre verifique e "desinfete" todos os dados recebidos. Sempre assuma o pior.</p> +</div> + +<p>A boa notícia para usuários Django é que muitas das ameaças mais comuns são tratadas pelo framework! O artigo <a href="https://docs.djangoproject.com/en/2.0/topics/security/">Segurança no Django</a> (Django docs) explica os recursos de segurança e como proteger um website desenvolvido pelo Django.</p> + +<h2 id="Ameaçasproteções_comuns">Ameaças/proteções comuns</h2> + +<p>Em vez de duplicar a documentação do Django aqui, neste artigo demonstraremos apenas alguns dos recursos de segurança no contexto do nosso tutorial Django da <a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a>.</p> + +<h3 id="Cross_site_scripting_XSS">Cross site scripting (XSS)</h3> + +<p>XSS é um termo utilizado para descrever uma classe de ataques que permitem um invasor injetar scripts no lado cliente, através do website, no navegador de outros usuários. Issi geralmente é conseguido armazenando scripts maliciosos no banco de dados onde eles podem ser recuperado e exibidos para outros usuários, ou fazendo com que usuários cliquem em um link que fará com que o JavaScript do invasor seja executado pelo navegador do usuário.</p> + +<p>O sistema de <em>templates</em> do Django protege você da maioria dos ataques XSS <a href="https://docs.djangoproject.com/en/2.0/ref/templates/language/#automatic-html-escaping">escapando de caracteres específicos</a> que são "perigosos" em HTML. Podemos demonstrar isso tentando injetar algum JavaScript em nosso website LocalLibrary usando o <em>form</em> Create-author que configuramos em <a href="/en-US/docs/Learn/Server-side/Django/Forms">Django Tutorial Parte 9: Trabalhando com formulários</a>.</p> + +<ol> + <li>Inicie o website usando o servidor de desenvolvimento (<code>python3 manage.py runserver</code>).</li> + <li>Abra o site em seu navegador local e faça login em sua conta de superusuário.</li> + <li>Navegue até a página de criação do autor (que deve estar na URL: <code><a href="http://127.0.0.1:8000/catalog/author/create/">http://127.0.0.1:8000/catalog/author/create/</a></code>).</li> + <li>Digite os nomes e os detalhes de data para um novo usuário, e então acrescente o seguinte texto no campo Last Name :<br> + <code><script>alert('Test alert');</script></code>.<br> + <img alt="Author Form XSS test" src="https://mdn.mozillademos.org/files/14305/author_create_form_alert_xss.png" style="border-style: solid; border-width: 1px; height: 245px; width: 594px;"> + <div class="note"> + <p><strong>Nota:</strong> Este é um script inofensivo que, se executado, exibirá uma caixa de alerta em seu navegador. Se o alerta é exibido quando você submeter o registro então o site está vulnerável a ameaças XSS.</p> + </div> + </li> + <li>Pressione <strong>Submit</strong> para salvar o registro.</li> + <li>Quando você salvar o autor, ele será exibido como mostrado abaixo. Por causa das proteções XSS o <code>alert()</code> não deve ser executado. Em vez disso o script é exibido como texto simples.<img alt="Author detail view XSS test" src="https://mdn.mozillademos.org/files/14307/author_detail_alert_xss.png" style="border-style: solid; border-width: 1px; height: 248px; width: 986px;"></li> +</ol> + +<p>Se você visualizar o código fonte da página HTML, poderá ver que os carcteres perigosos para as tags de script foram trasnformadoes em seus equivalentes de código de escape inofensivos (ex. <code>></code> agora é <code>&gt;</code>)</p> + +<pre class="brush: html notranslate"><h1>Author: Boon&lt;script&gt;alert(&#39;Test alert&#39;);&lt;/script&gt;, David (Boonie) </h1> +</pre> + +<p>Usar templates Django protege você contra a maioria dos ataques de XSS. No entanto, é possível desativar esta proteção, e a proteção não é automaticamente aplicada a todas as tags que normalmente não seriam preenchidas pela entrada do usuário (por exemplo, o <code>help_text</code> em um campo de formulário normalmente não é preechido pelo usuário, então Django não escapa esses valores).</p> + +<p>Também é possível que os ataques XSS se originem de outra fonte de dados não confiável, como cookies, webservices ou upload de arquivos (sempre que os dados não forem suficientemente limpos antes de serem incluídos em uma página). Se estiver exibindo dados dessas fontes, então pode ser necessário adicionar seu próprio código de limpeza.</p> + +<h3 id="Proteção_contra_Cross_site_request_forgery_CSRF">Proteção contra Cross site request forgery (CSRF) </h3> + +<p>Ataques CSRF permitem que um usuário malicioso execute ações usando as credenciais de outro usuário sem o conhecimento ou consentimento desse usuário. Por exemplo, considere o caso em que temos um hacker que quer criar autores adicionais para nossa LocalLibrary.</p> + +<div class="note"> +<p><strong>Nota:</strong> Obviamente nosso hacker não está nisso por dinheiro! Um hacker mais ambicioso poderia usar a mesma abordagem em outros sites para realizar tarefas muito mais prejudiciais (ex. transferir dinheiro para suas prórpias contas, etc.)</p> +</div> + +<p>Para fazer isso, eles podem criar um arquivo HTML como o abaixo, que contém um form de criação de autor (como o que usamos na seção anterior) que é enviado assim que o arquivo é carregado. Eles então enviariam o arquivo para todos os bibliotecários e sugeririam que eles abrissem o arquivo (ele contém algumas informações inofensivas, honestamente!). Se o arquivo for aberto por qualquer bibliotecário logado, o formulário será enviado com suas credenciais e um novo autor será criado.</p> + +<pre class="brush: html notranslate"><html> +<body onload='document.EvilForm.submit()'> + +<form action="http://127.0.0.1:8000/catalog/author/create/" method="post" name='EvilForm'> + <table> + <tr><th><label for="id_first_name">First name:</label></th><td><input id="id_first_name" maxlength="100" name="first_name" type="text" value="Mad" required /></td></tr> + <tr><th><label for="id_last_name">Last name:</label></th><td><input id="id_last_name" maxlength="100" name="last_name" type="text" value="Man" required /></td></tr> + <tr><th><label for="id_date_of_birth">Date of birth:</label></th><td><input id="id_date_of_birth" name="date_of_birth" type="text" /></td></tr> + <tr><th><label for="id_date_of_death">Died:</label></th><td><input id="id_date_of_death" name="date_of_death" type="text" value="12/10/2016" /></td></tr> + </table> + <input type="submit" value="Submit" /> +</form> + +</body> +</html> +</pre> + +<p>Execute o servidor web de desenvolvimento e faça login com a conta de superusuário. Copie o texto acima em um arquivo e abra-o no navegado. Você deve obter um erro de CSRF, porque Django tem protteção contra esse tipo de coisa!</p> + +<p>A forma como a proteção é habilitada é incluindo a tag de template <code>{% csrf_token %}</code> em sua definição de formulário. Esse token é então renderizado em seu HTML como mostrado abaixo com um valor que é específico para o usuário no navegador atual.</p> + +<pre class="brush: html notranslate"><input type='hidden' name='csrfmiddlewaretoken' value='0QRWHnYVg776y2l66mcvZqp8alrv4lb8S8lZ4ZJUWGZFA5VHrVfL2mpH29YZ39PW' /> +</pre> + +<p>Django gera uma chave específica de usuário/navegador e irá rejeitar formulários que não contenham o campo, ou que contenham um valor de campo incorreto para o usuário/navegador.</p> + +<p>Para usar esse tipo de ataque o hacker agora precisa descobrir e incluir a chave CSRF para o usuário alvo específico. Eles também não podem usar a abordagem "scattergun" de enviar um arquivo malicioso para todos bibliotecários e esperar que um deles abra, já que a chave CSRF é específica do navegador.</p> + +<p>A proteção CSRF do Django é ativada por padrão. Você deve sempre usar a tag de template <code>{% csrf_token %}</code> em seus formulários e utilizar <code>POST</code> para requisições que podem alterar ou adicionar dados ao banco de dados.</p> + +<h3 id="Outras_proteções">Outras proteções</h3> + +<p>Django also provides other forms of protection (most of which would be hard or not particularly useful to demonstrate):</p> + +<dl> + <dt>Proteção contra Injeção de SQL</dt> + <dd>As vulnerabilidades de injeção de SQL (SQL injection) permitem usuários mal-intencionados executarem código SQL arbitrário em um banco de dados, permitindo que dados sejam acessados, modificados ou apagados independentemente das permissões do usuário. Em quase todos os casos você acessará o banco de dados usando querysets/models do Django, de mdo que o SQL resultante será devidamente escapado pelo driver de banco de dados subjacente. Se você precisa escrever consultas brutas ou SQL customizado precisará pensar explicitamente sobre como previnir injeção de SQL.</dd> + <dt>Proteção contra Clickjacking </dt> + <dd>Nesse ataque, um usuário malicioso sequestra clicks destinados a um site de visível no nível superior e os encaminha para uma página oculta abaixo. Essa técnica pode ser usada, por exemplo, para exibir um site de banco legítimo, mas capturar as credenciais de login em um <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe" title="The HTML Inline Frame Element (<iframe>) represents a nested browsing context, effectively embedding another HTML page into the current page. In HTML 4.01, a document may contain a head and a body or a head and a frameset, but not both a body and a frameset. However, an <iframe> can be used within a normal document body. Each browsing context has its own session history and active document. The browsing context that contains the embedded content is called the parent browsing context. The top-level browsing context (which has no parent) is typically the browser window."><code><iframe></code></a> invisível, controlado pelo atacante. O Django possui <a href="https://docs.djangoproject.com/en/2.0/ref/clickjacking/#clickjacking-prevention">proteção contra clickjacking</a> na forma do <a href="https://docs.djangoproject.com/en/2.0/ref/middleware/#django.middleware.clickjacking.XFrameOptionsMiddleware" title="django.middleware.clickjacking.XFrameOptionsMiddleware"><code>X-Frame-Options middleware</code></a> que, em um navegador de suporte, pode impedir que um site seja renderizado dentro de um frame.</dd> + <dt>Aplicação de SSL/HTTPS</dt> + <dd>SSL/HTTPS pode ser habilitado no servidor web para criptografar todo o tráfego entre o site e o navegador, incluindo credenciais de autenticação que seriam enviadas em texto simples (habilitar HTTPS é altamente recomendado). Se HTTPS estiver habilitado o Django fornece uma série de outras proteções que você pode utilizar:</dd> +</dl> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SECURE_PROXY_SSL_HEADER"><code>SECURE_PROXY_SSL_HEADER</code></a> pode ser utilizado para verificar se o conteúdo é seguro, mesmo se for recebido de um proxy não HTTP.</li> + <li><a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SECURE_SSL_REDIRECT"><code>SECURE_SSL_REDIRECT</code></a> é usado para redirecionar todas as requisições HTTP para HTTPS.</li> + <li>Usar <a href="https://docs.djangoproject.com/en/2.0/ref/middleware/#http-strict-transport-security">HTTP Strict Transport Security</a> (HSTS). Este é um cabeçalho HTTP que informa ao navegador que todas as conexões futuras com um determinado site devem sempre utilizar HTTPS. Combinada com o redirecionamento de requisições HTTP para HTTPS, essa configuração garante que HTTPS é sempre usado depois que uma conexão bem-sucedida ocorrer. HSTS pode ser configurado com <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SECURE_HSTS_SECONDS"><code>SECURE_HSTS_SECONDS</code></a> e <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SECURE_HSTS_INCLUDE_SUBDOMAINS"><code>SECURE_HSTS_INCLUDE_SUBDOMAINS</code></a> ou no servidor web.</li> + <li>Usar cookies "seguros" definindo <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SESSION_COOKIE_SECURE"><code>SESSION_COOKIE_SECURE</code></a> e <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-CSRF_COOKIE_SECURE"><code>CSRF_COOKIE_SECURE</code></a> como <code>True</code>. Isso garantirá que os cookies sejam enviados apenas por HTTPS.</li> +</ul> + +<dl> + <dt>Validação de cabeçalho de host</dt> + <dd>Usar <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-ALLOWED_HOSTS"><code>ALLOWED_HOSTS</code></a> para aceitar apenas requisições de hosts confiáveis.</dd> +</dl> + +<p>Existem muitas outras proteções, e ressalvas para o uso dos mecanismos acima. Embora esperamos que isso tenha dado a você uma visão geral do que o Django oferece, você ainda deve ler a documentação de segurança de Django.</p> + +<ul> +</ul> + +<h2 id="Resumo">Resumo</h2> + +<p>Django tem proteções eficazes contra uma série de ameaças comuns, incluindo ataques XSS e CSRF. Neste artigo demonstramos como essas ameaças específicas são tratadas pelo Django em nosso website <em>LocalLibrary</em>. Também fornecemos uma breve visão geral de algumas das outras proteções.</p> + +<p>Esta foi uma incursão muito breve em segurança web. Nós recomendamos fortemente que você leia <a href="https://docs.djangoproject.com/en/2.0/topics/security/">Segurança no Django</a> para obter um entendimento mais profundo.</p> + +<p>A próxima e última etapa neste módulo sobre Django é concluir a <a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">tarefa de avaliação</a>.</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.0/topics/security/">Segurança no Django</a> (Django docs)</li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/Security">Segurança de website no lado do servidor</a> (MDN)</li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/Security">Segurança web</a> (MDN)</li> + <li><a href="/en-US/docs/Web/Security/Securing_your_site">Protegendo seu site</a> (MDN)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Deployment", "Learn/Server-side/Django/django_assessment_blog", "Learn/Server-side/Django")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Introduction">Introdução ao Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/development_environment">Configurando um ambiente de desenvolvimento Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django: Website de uma Biblioteca Local</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/skeleton_website">Tutorial Django Parte 2: Criando a base do website</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Models">Tutorial Django Parte 3: Usando models</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Admin_site">Tutorial Django Parte 4: Django admin site</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Home_page">Tutorial Django Parte 5: Criando nossa página principal</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Generic_views">Tutorial Django Parte 6: Lista genérica e detail views</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Sessions">Tutorial Django Parte 7: Framework de Sessões</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Authentication">Tutorial Django Parte 8: Autenticação de Usuário e permissões</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Forms">Tutorial Django Parte 9: Trabalhando com formulários</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Testing">Tutorial Django Parte 10: Testando uma aplicação web Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/Deployment">Tutorial Django Parte 11: Implantando Django em produção</a></li> + <li><a rel="nofollow" title="A página ainda não foi criada.">Segurança de aplicações web Django</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/express_nodejs/ambiente_de_desenvolvimento/index.html b/files/pt-br/learn/server-side/express_nodejs/ambiente_de_desenvolvimento/index.html new file mode 100644 index 0000000000..289af21dde --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/ambiente_de_desenvolvimento/index.html @@ -0,0 +1,387 @@ +--- +title: Configurando o Node como ambiente de desenvolvimento +slug: Learn/Server-side/Express_Nodejs/ambiente_de_desenvolvimento +tags: + - Express + - Iniciante + - Introdução + - Node + - nodejs + - npm + - server-side + - web server +translation_of: Learn/Server-side/Express_Nodejs/development_environment +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Introduction", "Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs")}}</div> + +<p class="summary">Agora que você sabe para que serve o Express, nós vamos lhe mostrar como configurar e testar o ambiente Node/Express no Windows, Linux (Ubuntu) e macOS. Independentemente do sistema operacional que você prefere, este artigo deve lhe proporcionar o que você precisa para desenvolver aplicativos em Express.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-Requisitos:</th> + <td>Saber como abrir um terminal/linha de comando. Saber como instalar pacotes de software no sistema operacional do computador utilizado para desenvolvimento</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Configurar o ambiente de desenvolvimento para Express (X.XX) em seu computador</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_geral_do_ambiente_de_desenvolvimento_do_Express">Visão geral do ambiente de desenvolvimento do Express</h2> + +<p><em>Node</em> e <em>Express </em>facilitam a configuração de seu computador para começar a desenvolver aplicações web. Esta seção fornece uma visão ampla de quais ferramentas serão necessárias, explica alguns métodos simples para instalar o Node (e Express) no Ubuntu, macOS e Windows e também mostra como você pode testar sua aplicação.</p> + +<h3 id="O_que_é_o_ambiente_de_desenvolvimento_Express">O que é o ambiente de desenvolvimento Express?</h3> + +<p>O ambiente de desenvolvimento <em>Express</em> inclui uma instalação do <em>Nodejs, </em>o pacote de gerenciamento<em> NPM </em>e (opcionalmente) o <em>Gerador de Aplicações Express </em>em seu computador local.</p> + +<p>O <em>Node </em>e o <em>NPM </em>são instalados em conjunto por meio de um pacote binário preparado, instaladores, pacotes de gerenciamento de sistemas operacionais ou diretamente da fonte (como mostra a seção seguinte). O <em>Express </em>é então instalado pelo NPM como uma dependência de sua aplicação web <em>Express </em>individual (junto a outras bibliotecas como motores de modelo, drivers de banco de dados, autenticações middleware, middleware para arquivos estáticos, etc.)</p> + +<p>NPM também pode ser utilizado para instalar (globalmente) o Express Application Generator, uma ferramenta que cria um "esqueleto" de um app Express, seguindo o padrão MVC. O gerador de app é opcional porque você não precisa dessa ferramenta para criar um app ou um construtor Express para ter a mesma arquitetura. Nós vamos usá-lo nesta seção porque nos permite iniciar uma aplicação de uma maneira mais rápida e promover uma estrutura modular.</p> + +<div class="note"> +<p><strong>Nota:</strong> Ao contrário de muitos outros framework que não oferecem um servidor web junto ao ambiente de desenvolvimento, o Node/Express cria e roda o seu próprio servidor web.</p> +</div> + +<p>Há outras ferramentas periféricas que integram o ambiente de desenvolvimento, é o caso dos editores de textos (códigos), conhecidos como IDE, e versionadores de códigos, como o Git, que ajudam a gerenciar diferentes versões do código. Estamos partindo da ideia de que você já conhece essas ferramentas e as têm instaladas (em especial o editor de texto).</p> + +<h3 id="Quais_sistemas_operacionais_têm_suporte">Quais sistemas operacionais têm suporte?</h3> + +<p><em>Node</em> roda em Windows, macOS, diferentes versões do Linux, Docker, etc. Há uma lista de sistemas suportados que pode ser encontrada na página de <a href="https://nodejs.org/en/download/">Downloads</a> do Nodejs. Quase todos os computadores pessoais têm o que é necessário para rodar o Node. O Express roda no ambiente Node e, consequentemente, roda em qualquer plataforma que roda o <em>Node</em>.</p> + +<p>Neste artigo, vamos abordar as instruções de configuração para Windows, macOS, e Ubuntu Linux.</p> + +<h3 id="Qual_versão_do_NodeExpress_você_deve_usar">Qual versão do Node/Express você deve usar?</h3> + +<p>Há várias <a href="https://nodejs.org/en/blog/release/">versões do Node</a> - as mais recentes contém correção de bugs, suporte para EMCAScript (JavaScript) e melhorias nas APIs do Node.</p> + +<p>De maneira geral, você deve usar a versão mais recente do LTS (long-term supported), pois é a mais estável do que a versão "current". Além disso, você deve usar a versão current apenas se precisar de alguma funcionalidade que não está presente na versão LTS.</p> + +<p>Para o Express, você deve usar sempre a versão mais completa.</p> + +<h3 id="Sobre_o_banco_de_dados_e_outras_dependências">Sobre o banco de dados e outras dependências?</h3> + +<p>Outras dependências, como database drivers, engine para templates, ferramentas para autenticação, etc, são parte da aplicação e são importadas para o ambiente a partir do NPM. Nós vamos falar sobre essa parte mais para frente.</p> + +<h2 id="Instalando_o_Node">Instalando o Node</h2> + +<p>Para utilizar o Express, você terá que instalar o Nodejs e o <a href="https://docs.npmjs.com/">NPM</a> em seu sistema operacional. Nas seções a seguir, vamos explicar o jeito mais fácil de instalar a versão LTS do Nodejs no Ubuntu Linux 16.04, macOS e Windows 10.</p> + +<div class="note"> +<p><strong>Dica:</strong> As seções abaixo mostram o jeito mais fácil de instalar o NPM nos Sistemas Operacionais. Se você utilizar outro sistema ou quer ver uma abordagem diferente para as plataformas atuais acesse <a href="https://nodejs.org/en/download/package-manager/">Instalando Node.js via NPM</a> (nodejs.org).</p> +</div> + +<h3 id="Windows_e_macOS">Windows e macOS</h3> + +<p>Instalar o Node e o NPM no Windows ou no macOS é uma tarefa rápida e simples. Siga os seguintes passos:</p> + +<ol> + <li>Baixar o instalador: + <ol> + <li>Vá para <a href="https://nodejs.org/en/">https://nodejs.org/en/</a></li> + <li>Selecione o botão de download da versão LTS, que é a recomendada para a maioria dos usuários.</li> + </ol> + </li> + <li>Instale o Node ao clicar duas vezes no arquivo de download. Siga a instalação a partir das janelas que vão aparecer na sua tela.</li> +</ol> + +<h3 id="Ubuntu_16.04">Ubuntu 16.04</h3> + +<p>O jeito mais fácil de instalar a versão LTS do Node é usar o NPM a partir do Ubuntu <em>binary distributions repository</em>. Isso pode ser feito de uma maneira muito simples. Rode os seguintes comandos no seu terminal.</p> + +<pre class="brush: bash notranslate"><code>curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - +sudo apt-get install -y nodejs</code> +</pre> + +<div class="warning"> +<p><strong>Atenção:</strong> Não faça a instalação direto do repositório normal do Ubuntu pois ele contém versões antigas do Node.</p> +</div> + +<ol> +</ol> + +<h3 id="Testando_a_instalação_do_Nodejs_e_do_NPM">Testando a instalação do Nodejs e do NPM</h3> + +<p>O jeito mais fácil de testar se tudo correu bem na instalação é checar qual a versão do Node está rodando no computador. Para isso, vá ao terminal/command prompt e digite o seguinte comando para retornar a resposta com a versão mais recente.</p> + +<pre class="brush: bash notranslate">>node -v +v8.9.4</pre> + +<p>O <em>NPM</em> também deve ter sido instalado. Você pode checar da seguinte maneira:</p> + +<pre class="brush: bash notranslate">>npm -v +5.6.0</pre> + +<p>Uma maneira um pouco mais divertida de testar é criar um servidor web em "puro node". Vamos imprimir a tradicional frase "Hello World" no browser quando visitarmos uma determinada URL.</p> + +<ol> + <li>Crie um arquivo chamado hellonode.js e cole dentro dele o código abaixo. Estamos usando apenas o Node, sem o Express, e com sintaxe do ES6. + <pre class="brush: js notranslate">//Chame o módulo HTTP +var http = require("http"); + +//Crie um servidor HTTP para ouvir as requisições na porta 8000 +http.createServer(function (request, response) { + + // Configure o resposta HTTP header com o HTTP status e Content type + response.writeHead(200, {'Content-Type': 'text/plain'}); + + // Envie a resposta do body "Hello World" + response.end('Hello World\n'); +}).listen(8000); + +// Imprima URL para acessar o servidor +console.log('Server running at http://127.0.0.1:8000/') +</pre> + + <p>O código importa o módulo "http" e o utiliza para criar um servidor (<code>createServer()</code>) que escuta as requisições HTTP na porta 8000. O script, então, imprime a mensagem no console. A função <code>createServer()</code> recebe como argumento uma função callback que é chamada quando recebe uma requisição HTTP - isso retorna uma resposta com um status 200 ("OK") do HTTP e o texto "Hello World".</p> + </li> + <li> + <div class="note"> + <p><strong>Nota:</strong> Não se preocupe se você não entendeu exatamente o que esse código faz. Nós vamos explicar isso em mais detalhes quando iniciarmos a parte do Express.</p> + </div> + </li> + <li>Inicie o servidor e navegue pelo mesmo diretório que o seu arquivo hellonode.js no terminal. Depois chame o Node da seguinte forma: + <pre class="brush: bash notranslate">>node hellonode.js +Server running at http://127.0.0.1:8000/ +</pre> + </li> + <li>Navegue até a URL (<a href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a>). Se tudo estiver funcionando bem, o browser vai apresentar a frase "Hello World".</li> +</ol> + +<h2 id="Usando_o_NPM">Usando o NPM</h2> + +<p>Ao lado do próprio Node, o NPM é a ferramenta de trabalho mais importante nas aplicações Node. O NPM é usado para buscar qualquer pacote (biblioteca JavaScript) que uma aplicação precisa para ser desenvolvida, testada ou produzida, além de ser adotado para rodar testes ao longo de todo o processo de desenvolvimento.</p> + +<div class="note"> +<p><strong>Nota:</strong> A partir da perspectiva do Node, Express é um pacote que precisa ser instalado utilizando o NPM e depois importado para o seu código.</p> +</div> + +<p>Você pode usar o NPM separadamente para buscar cada pacote desejado. Em geral, nós gerenciamos as dependências com um arquivo chamado <a href="https://docs.npmjs.com/files/package.json">package.json</a>. Esse arquivo lista todas as dependências para um pacote JavaScript específico, incluindo o nome do pacote, a versão, descrição, arquivo de inicialização, produção de dependências, desenvolvimento de dependências, versões do Node que podem ser utilizadas. O <strong>package.json</strong> contém tudo que o NPM precisa para buscar e rodar a sua aplicação (se você está escrevendo uma biblioteca para ser reutilizável, você pode usar essa definição para fazer o upload do pacote para o repositório npm e deixá-lo acessível a qualquer usuário).</p> + +<h3 id="Adicionando_dependências">Adicionando dependências</h3> + +<p>Os passos seguintes mostram como baixar pacotes via NPM, salvá-los nas dependências do projeto e importá-los/chamá-los para dentro da aplicação Node.</p> + +<div class="note"> +<p><strong>Nota:</strong> Nesta seção mostraremos como buscar e instalar o pacote do Express. Depois, explicaremos como esse e outros pacotes já estão especificados para nós graças ao <em>Express Application Generator</em>. É muito importante entendermos como o NPM funciona e o que é criado com o generator. </p> +</div> + +<ol> + <li>Primeiro passo é criar um diretório para sua aplicação. No prompt, insira os comandos a seguir. + <pre class="brush: bash notranslate">mkdir myapp +cd myapp</pre> + </li> + <li> Use o comando <code>npm init</code> para criar o arquivo <strong>package.json</strong> da sua aplicação. Esse comando registra para você uma série de informações, como o nome e a versão do seu aplicativo, além do nome do seu "entry point" (<strong>index.js</strong> por padrão). Por hora, vamos manter a configuração padrão. + <pre class="brush: bash notranslate">npm init</pre> + + <p>Se você acessar o arquivo <strong>package.json</strong> (<code>cat packge.json</code>), você verá toda a configuração padrão e, ao final, o tipo de licença que o app está utilizando.</p> + + <pre class="brush: json notranslate">{ + "name": "myapp", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} +</pre> + </li> + <li>Agora, instale o Express dentro do diretório <strong>myapp</strong>. O pacote será salvo automaticamente na lista de dependências do seu <strong>package.json</strong>.</li> + <li> + <pre class="brush: bash notranslate">npm install express</pre> + + <p>A lista de dependências do <strong>package.json</strong> agora mostra também a versão do Express que estamos usando. Está grifada no final do arquivo.</p> + + <pre class="brush: json notranslate">{ + "name": "myapp", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", +<strong> "dependencies": { + "express": "^4.16.2" + }</strong> +} +</pre> + </li> + <li>Para usar o Express, é preciso incluir a função <code>require()</code> no arquivo index.js dentro da sua aplicação. Crie esse arquivo agora mesmo na pasta raiz "<strong>myapp</strong>" e inclua o código a seguir. + <pre class="notranslate"><code><strong>var express = require('express')</strong> +var app = express() + +app.get('/', function (req, res) { + res.send('Hello World!') +}) + +app.listen(</code>8000<code>, function () { + console.log('Example app listening on port </code>8000<code>!') +})</code> +</pre> + + <p>O código mostra uma aplicação web bem simples cujo objetivo único é imprimir a mensagem "HelloWorld". Em linhas gerais, esse arquivo importa o módulo do express e o utiliza para criar um servidor (<code>app</code>) que escuta as requisições HTTP pela porta 8000 e imprime a mensagem no console, além de definir qual URL usada para testar o servidor. A função <code>app.get()</code> responde apenas às requisições HTTP feitas com o método GET, desde que especificadas com o path ('/'). Nesse caso, chamando a função para enviar a mensagem <em>Hello World</em>!</p> + </li> + <li>Rode a linha de comando abaixo para iniciar o servidor. + <pre class="brush: bash notranslate">>node index.js +Example app listening on port 8000 +</pre> + </li> + <li>Vá para a seguinte URL (<a href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a>). Se tudo estiver funcionando corretamente, o browser vai mostrar a mensagem "Hello World!".</li> +</ol> + +<h3 id="Desenvolvendo_dependências">Desenvolvendo dependências</h3> + +<p>Se você utilizar uma dependência apenas durante o desenvolvimento da aplicação, é recomendado que você a salve como uma "development dependency". Dessa forma, o pacote não será utilizado no ambiente de produção. Por exemplo: caso utilizar o pacote <a href="http://eslint.org/">esling</a> (JavaScript Linting), você faria a instalação via NPM da seguinte forma.</p> + +<pre class="brush: bash notranslate"><code>npm install eslint --save-dev</code></pre> + +<p>Assim, a esling vai aparecer da seguinte forma na lista de dependências do <strong>package.json</strong>.</p> + +<pre class="brush: js notranslate"> "devDependencies": { + "eslint": "^4.12.1" + } +</pre> + +<div class="note"> +<p><strong>Note:</strong> "<a href="https://en.wikipedia.org/wiki/Lint_(software)">Linters</a>" são ferramentas que nos ajudam a identificar e reportar que o código está sendo escrito dentro das melhores práticas.</p> +</div> + +<h3 id="Rodando_tarefas">Rodando tarefas</h3> + +<p>Além de definir e buscar dependências, você também pode nomear scripts dentro do seu arquivo <strong>package.json</strong> e chamar o NPM para executá-lo a partir de um <a href="https://docs.npmjs.com/cli/run-script">run-script</a> command. Essa abordagem é comum para automatizar testes e tarefas ao longo do desenvolvimento (por exemplo: minificar o JavaScript, reduzir imagens, LINT/análise de códigos, etc).</p> + +<div class="note"> +<p><strong>Nota:</strong> Ferramentas de automação de tarefas como o <a href="http://gulpjs.com/">Gulp</a> e o <a href="http://gruntjs.com/">Grunt</a> também podem ser utilizados, além de outros pacotes externos. </p> +</div> + +<p>Para definir o script que roda o <em>esling</em>, citado na seção acima, nós precisamos adicionar o seguinte bloco no nosso <strong>package.json</strong> (importante: sua aplicação precisa ter como source está na pasta /src/js):</p> + +<pre class="brush: js notranslate">"scripts": { + ... + "lint": "eslint src/js" + ... +} +</pre> + +<p>Explicando um pouco mais: <code>eslint src/js</code> é o comando que colocamos no nosso terminal para rodar o <code>eslint</code> nos arquivos JavaScript situados no diretório <code>src/js</code> dentro do diretório do nosso app. Incluindo o comando, criamos o comando de atalho - <code>lint</code>.</p> + +<pre class="brush: bash notranslate"><code>npm run-script lint +# OR (using the alias) +npm run lint</code> +</pre> + +<p>O exemplo pode não parecer mais curto do que o comando original, mas com o que você aprendeu é possível incluir comandos bem maiores dentro do npm scripts, como as cadeias de múltiplos comandos. Você pode até escrever um único script npm para rodar todos os seus testes de uma só vez.</p> + +<h2 id="Instalando_o_Express_Application_Generator">Instalando o Express Application Generator</h2> + +<p>O <a href="https://expressjs.com/en/starter/generator.html">Express Application Generator</a> é uma ferramenta que cria "esqueleto" para aplicações Express. A instalação é realizada via NPM como mostrada a seguir (o comando <code>-g</code> instala a pacote globalmente, ou seja, você pode acessá-lo de qualquer lugar do seu computador).</p> + +<pre class="notranslate"><code>npm install express-generator -g</code></pre> + +<p>Para criar um aplicativo Express chamado "helloworld" com as configurações padrões, vá até o local/pasta em que você deseja desenvolver o projeto e escreva a seguinte linha de comando:</p> + +<pre class="brush: bash notranslate">express helloworld</pre> + +<div class="note"> +<p>Nota: Você também pode definir a biblioteca de template que pretende usar e muitas outras configurações. Use o comando <code>help</code> para ver todas as opções. </p> + +<pre class="brush: bash notranslate">express --help +</pre> +</div> + +<p>O NPM vai criar um novo aplicativo Express em uma subpasta na localização em que você está. O progresso será apresentado no console. Para finalizar, o processo, a ferramenta mostrará os comandos que você precisa seguir para instalar a dependência Node e iniciar o seu app.</p> + +<div class="note"> +<p>O novo app terá um arquivo package.json no diretório raiz. Você pode abrir esse arquivo para checar o que foi instalado, incluindo o Express e Jade (template library) .</p> + +<pre class="brush: js notranslate">{ + "name": "helloworld", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www" + }, + "dependencies": { + "body-parser": "~1.18.2", + "cookie-parser": "~1.4.3", + "debug": "~2.6.9", + "express": "~4.15.5", + "jade": "~1.11.0", + "morgan": "~1.9.0", + "serve-favicon": "~2.4.5" + } +}</pre> +</div> + +<p>Instale todas as dependências para o app helloworld com o NPM, de acordo com os comandos abaixo:</p> + +<pre class="brush: bash notranslate">cd helloworld +npm install +</pre> + +<p>Agora, rode o aplicativo (o comando muda um pouco entre Windows, Linux/macOS), como está no código a seguir:</p> + +<pre class="brush: bash notranslate"># Rode o helloworld no Windows +SET DEBUG=helloworld:* & npm start + +# Rode helloworld no Linux/macOS +DEBUG=helloworld:* npm start +</pre> + +<p>O comando DEBUG gera um loggin bem útil, apresentando resultados, como abaixo:</p> + +<pre class="brush: bash notranslate">>SET DEBUG=helloworld:* & npm start + +> helloworld@0.0.0 start D:\Github\expresstests\helloworld +> node ./bin/www + + helloworld:server Listening on port 3000 +0ms</pre> + +<p>Abre um browser e navegue para <a href="http://127.0.0.1:3000/">http://127.0.0.1:3000/</a> e veja a página default apresentada pelo aplicativo.</p> + +<p><img alt="Express - Generated App Default Screen" src="https://mdn.mozillademos.org/files/14331/express_default_screen.png" style="border-style: solid; border-width: 1px; display: block; height: 301px; margin: 0px auto; width: 675px;"></p> + +<p>Vamos falar mais sobre o "gerador" quando chegarmos ao artigo referente à geração de esqueletos de uma aplicação.</p> + +<ul> +</ul> + +<h2 id="Sumário">Sumário</h2> + +<p>Agora você tem o desenvolvimento do Node pronto para rodar no seu computador e que pode ser utilizado para criar aplicações web com o framework Express. Você também viu como o NPM é utilizado para importar o Express em sua aplicação e como criar um esqueleto a partir do Express Aplication Generator.</p> + +<p>No próximo artigo, nós vamos iniciar um tutorial para construir uma aplicação web completa utilizando esse ambiente junto com as ferramentas.</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://nodejs.org/en/download/">Downloads</a> página (nodejs.org)</li> + <li><a href="https://nodejs.org/en/download/package-manager/">Installing Node.js via package manager</a> (nodejs.org)</li> + <li><a href="http://expressjs.com/en/starter/installing.html">Installing Express</a> (expressjs.com)</li> + <li><a href="https://expressjs.com/en/starter/generator.html">Express Application Generator</a> (expressjs.com)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Introduction", "Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs")}}</p> + +<h2 id="Outros_módulos">Outros módulos</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introduction</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Setting up a Node (Express) development environment</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/express_nodejs/deployment/index.html b/files/pt-br/learn/server-side/express_nodejs/deployment/index.html new file mode 100644 index 0000000000..77e9914e87 --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/deployment/index.html @@ -0,0 +1,527 @@ +--- +title: 'Express Tutorial Part 7: Deploying to production' +slug: Learn/Server-side/Express_Nodejs/deployment +tags: + - Express + - Implantação + - Iniciante + - Node + - aprendizado + - heroku +translation_of: Learn/Server-side/Express_Nodejs/deployment +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}</div> + +<p class="summary">Now you've created (and tested) an awesome <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">LocalLibrary</a> website, you're going to want to install it on a public web server so that it can be accessed by library staff and members over the Internet. This article provides an overview of how you might go about finding a host to deploy your website, and what you need to do in order to get your site ready for production.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Complete todos os tópicos anteriores do turotrial, inclusive o <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender onde e como você pode implantar um app Express app em produção.</td> + </tr> + </tbody> +</table> + +<h2 id="Overview">Overview</h2> + +<p>Once your site is finished (or finished "enough" to start public testing) you're going to need to host it somewhere more public and accessible than your personal development computer.</p> + +<p>Up to now you've been working in a <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">development environment</a>, using Express/Node as a web server to share your site to the local browser/network, and running your website with (insecure) development settings that expose debugging and other private information. Before you can host a website externally you're first going to have to:</p> + +<ul> + <li>Choose an environment for hosting the Express app.</li> + <li>Make a few changes to your project settings.</li> + <li>Set up a production-level infrastructure for serving your website.</li> +</ul> + +<p>This tutorial provides some guidance on your options for choosing a hosting site, a brief overview of what you need to do in order to get your Express app ready for production, and a worked example of how to install the LocalLibrary website onto the <a href="https://www.heroku.com/">Heroku</a> cloud hosting service.</p> + +<p>Bear in mind that you don't have to use Heroku — there are other hosting service available. We've also provided a separate tutorial to show how to <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Installing_on_PWS_Cloud_Foundry">Install LocalLibrary on PWS/Cloud Foundry</a>.</p> + +<h2 id="What_is_a_production_environment">What is a production environment?</h2> + +<p>The production environment is the environment provided by the server computer where you will run your website for external consumption. The environment includes:</p> + +<ul> + <li>Computer hardware on which the website runs.</li> + <li>Operating system (e.g. Linux or Windows).</li> + <li>Programming language runtime and framework libraries on top of which your website is written.</li> + <li>Web server infrastructure, possibly incuding a web server, reverse proxy, load balancer, etc.</li> + <li>Databases on which your website is dependent.</li> +</ul> + +<p>The server computer could be located on your premises and connected to the Internet by a fast link, but it is far more common to use a computer that is hosted "in the cloud". What this actually means is that your code is run on some remote computer (or possibly a "virtual" computer) in your hosting company's data center(s). The remote server will usually offer some guaranteed level of computing resources (e.g. CPU, RAM, storage memory, etc.) and Internet connectivity for a certain price.</p> + +<p>This sort of remotely accessible computing/networking hardware is referred to as <em>Infrastructure as a Service (IaaS)</em>. Many IaaS vendors provide options to preinstall a particular operating system, onto which you must install the other components of your production environment. Other vendors allow you to select more fully-featured environments, perhaps including a complete Node setup.</p> + +<div class="note"> +<p><strong>Note:</strong> Pre-built environments can make setting up your website very easy because they reduce the configuration, but the available options may limit you to an unfamiliar server (or other components) and may be based on an older version of the OS. Often it is better to install components yourself, so that you get the ones that you want, and when you need to upgrade parts of the system, you have some idea of where to start!</p> +</div> + +<p>Other hosting providers support Express as part of a <em>Platform as a Service</em> (<em>PaaS</em>) offering. When using this sort of hosting you don't need to worry about most of your production environment (servers, load balancers, etc.) as the host platform takes care of those for you. That makes deployment quite easy, because you just need to concentrate on your web application and not any other server infrastructure.</p> + +<p>Some developers will choose the increased flexibility provided by IaaS over PaaS, while others will appreciate the reduced maintenance overhead and easier scaling of PaaS. When you're getting started, setting up your website on a PaaS system is much easier, so that is what we'll do in this tutorial.</p> + +<div class="note"> +<p><strong>Tip:</strong> If you choose a Node/Express-friendly hosting provider they should provide instructions on how to set up an Express website using different configurations of webserver, application server, reverse proxy, etc. For example, there are many step-by-step guides for various configurations in the <a href="https://www.digitalocean.com/community/tutorials?q=node">Digital Ocean Node community docs</a>.</p> +</div> + +<h2 id="Choosing_a_hosting_provider">Choosing a hosting provider</h2> + +<p>There are numerous hosting providers that are known to either actively support or work well with <em>Node</em> (and <em>Express</em>). These vendors provide different types of environments (IaaS, PaaS), and different levels of computing and network resources at different prices.</p> + +<div class="note"> +<p><strong>Tip:</strong> There are a lot of hosting solutions, and their services and pricing can change over time. While we introduce a few options below, it is worth performing your own Internet search before selecting a hosting provider.</p> +</div> + +<p>Some of the things to consider when choosing a host:</p> + +<ul> + <li>How busy your site is likely to be and the cost of data and computing resources required to meet that demand.</li> + <li>Level of support for scaling horizontally (adding more machines) and vertically (upgrading to more powerful machines) and the costs of doing so.</li> + <li>Where the supplier has data centres, and hence where access is likely to be fastest.</li> + <li>The host's historical uptime and downtime performance.</li> + <li>Tools provided for managing the site — are they easy to use and are they secure (e.g. SFTP vs FTP).</li> + <li>Inbuilt frameworks for monitoring your server.</li> + <li>Known limitations. Some hosts will deliberately block certain services (e.g. email). Others offer only a certain number of hours of "live time" in some price tiers, or only offer a small amount of storage.</li> + <li>Additional benefits. Some providers will offer free domain names and support for SSL certificates that you would otherwise have to pay for.</li> + <li>Whether the "free" tier you're relying on expires over time, and whether the cost of migrating to a more expensive tier means you would have been better off using some other service in the first place!</li> +</ul> + +<p>The good news when you're starting out is that there are quite a few sites that provide computing environments for "free", albeit with some conditions. For example, <a href="https://www.heroku.com/">Heroku</a> provides a free but resource-limited <em>PaaS</em> environment "forever", while <a href="http://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/billing-free-tier.html">Amazon Web Services</a>, <a href="https://azure.microsoft.com/en-us/pricing/details/app-service/">Microsoft Azure</a>, and the open source option <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Installing_on_PWS_Cloud_Foundry">PWS/Cloud Foundry</a> provide free credit when you first join.</p> + +<p>Many providers also have a "basic" tier that provides more useful levels of computing power and fewer limitations. <a href="https://www.digitalocean.com/">Digital Ocean</a> is an example of a popular hosting provider that offers a relatively inexpensive basic computing tier (in the $5 per month lower range at time of writing).</p> + +<div class="note"> +<p><strong>Note:</strong> Remember that price is not the only selection criterion. If your website is successful, it may turn out that scalability is the most important consideration.</p> +</div> + +<h2 id="Getting_your_website_ready_to_publish">Getting your website ready to publish</h2> + +<p>The main things to think about when publishing your website are web security and performance. At the bare minimum, you will want to remove the stack traces that are included on error pages during development, tidy up your logging, and set the appropriate headers to avoid many common security threats.</p> + +<p>In the following subsections we outline the most important changes that you should make to your app.</p> + +<div class="note"> +<p><strong>Tip:</strong> There are other useful tips in the Express docs — see <a href="https://expressjs.com/en/advanced/best-practice-performance.html">Production best practices: performance and reliability</a> and <a href="https://expressjs.com/en/advanced/best-practice-security.html">Production Best Practices: Security</a>.</p> +</div> + +<h3 id="Set_NODE_ENV_to_'production'">Set NODE_ENV to 'production'</h3> + +<p>We can remove stack traces in error pages by setting the <code>NODE_ENV</code> environment variable to <em>production</em> (it is set to '<em>development</em>' by default). In addition to generating less-verbose error messages, setting the variable to <em>production</em> caches view templates and CSS files generated from CSS extensions. Tests indicate that setting <code>NODE_ENV</code> to <em>production</em> can improve app performance by a factor of three!</p> + +<p>This change can be made either by using export or an environment file, or using the OS initialisation system. </p> + +<div class="note"> +<p><strong>Note:</strong> This is actually a change you make in your environment setup rather than your app, but important enough to note here! We'll show how this is set for our hosting example below. </p> +</div> + +<h3 id="Log_appropriately">Log appropriately</h3> + +<p>Logging calls can have an impact on a high-traffic website. In a production environment you may need to log website activity (e.g. tracking traffic or logging API calls) but you should attempt to minimise the amount of logging added for debugging purposes.</p> + +<p>One way to minimise "debug" logging in production is to use a module like <a href="https://www.npmjs.com/package/debug">debug </a>that allows you to control what logging is performed by setting an environment variable. For example, the code fragment below shows how you might set up "author" logging. The debug variable is declared with the name 'author', and the prefix "author" will be automatically displayed for all logs from this object.</p> + +<pre class="brush: js"><strong>var debug = require('debug')('author');</strong> + +// Display Author update form on GET +exports.author_update_get = function(req, res, next) { + + req.sanitize('id').escape().trim(); + Author.findById(req.params.id, function(err, author) { + if (err) { +<strong> debug('update error:' + err);</strong> + return next(err); + } + //On success + res.render('author_form', { title: 'Update Author', author: author }); + }); + +};</pre> + +<p>You can then enable a particular set of logs by specifying them as a comma-separated list in the <code>DEBUG</code> environment variable. You can set the variables for displaying author and book logs as shown (wildcards are also supported).</p> + +<pre class="brush: bash">#Windows +set DEBUG=author,book + +#Linux +export DEBUG="author,book" +</pre> + +<div class="note"> +<p><strong>Challenge:</strong> Calls to <code>debug</code> can replace logging you might previously have done using <code>console.log()</code> or <code>console.error()</code>. Replace any <code>console.log()</code> calls in your code with logging via the <a href="https://www.npmjs.com/package/debug">debug </a>module. Turn the logging on and off in your development environment by setting the DEBUG variable and observe the impact this has on logging.</p> +</div> + +<p>If you need to log website activity you can use a logging library like <em>Winston</em> or <em>Bunyan</em>. For more information on this topic see: <a href="https://expressjs.com/en/advanced/best-practice-performance.html">Production best practices: performance and reliability</a>.</p> + +<h3 id="Use_gzipdeflate_compression_for_responses">Use gzip/deflate compression for responses</h3> + +<p>Web servers can often compress the HTTP response sent back to a client, significantly reducing the time taken to for the client to get and load the page. The compression method used will depend on what decompression methods the client says that it supports in the request (if no compression methods are supported the response will be sent uncompressed).</p> + +<p>You can add this to your site using <a href="https://www.npmjs.com/package/compression">compression</a> middleware. Install this to your project by running the following command at the root of the project.</p> + +<pre class="brush: bash">npm install compression</pre> + +<p>Open <strong>./app.js</strong> and require the compression library as shown. Add the compression library to the middleware chain with the <code>use()</code> method (this should appear before any routes that you want compressed — in this case all of them!)</p> + +<pre class="brush: js">var catalog = require('./routes/catalog'); //Import routes for "catalog" area of site +<strong>var compression = require('compression');</strong> + +// Create the Express application object +var app = express(); + +... + +<strong>app.use(compression()); //Compress all routes</strong> + +app.use(express.static(path.join(__dirname, 'public'))); + +app.use('/', index); +app.use('/users', users); +app.use('/catalog', catalog); // Add catalog routes to middleware chain. + +... +</pre> + +<div class="note"> +<p><strong>Note</strong>: For a high-traffic website in production you wouldn't use this middleware. Instead you would use a reverse proxy like <em>Nginx</em>.</p> +</div> + +<h3 id="Use_Helmet_to_protect_against_well_known_vulnerabilities">Use Helmet to protect against well known vulnerabilities</h3> + +<p><a href="https://www.npmjs.com/package/helmet">Helmet</a> is a middleware package that can help protect your app from some well-known web vulnerabilities by setting appropriate HTTP headers (see the <a href="https://helmetjs.github.io/docs/">docs</a> for more information on what headers it sets/vulnerabilities it protects against). </p> + +<p>Install this to your project by running the following command at the root of the project.</p> + +<pre class="brush: bash">npm install helmet +</pre> + +<p>Open <strong>./app.js</strong> and require the <em>helmet</em> library as shown. Then add the module to the middleware chain with the <code>use()</code> method.</p> + +<pre class="brush: js">var compression = require('compression'); +<strong>var helmet = require('helmet'); +</strong> +// Create the Express application object +var app = express(); + +<strong>app.use(helmet())</strong>; +...</pre> + +<div class="note"> +<p id="production-best-practices-performance-and-reliability"><strong>Note:</strong> The command above adds the <em>subset</em> of available headers that makes sense for most sites. You can add/disable specific headers as needed by following the instructions on <a href="https://www.npmjs.com/package/helmet">npm</a>.</p> +</div> + +<h2 id="Example_Installing_LocalLibrary_on_Heroku">Example: Installing LocalLibrary on Heroku</h2> + +<p>This section provides a practical demonstration of how to install <em>LocalLibrary</em> on the <a href="http://heroku.com">Heroku PaaS cloud</a>.</p> + +<h3 id="Why_Heroku">Why Heroku?</h3> + +<p>Heroku is one of the longest running and popular cloud-based PaaS services. It originally supported only Ruby apps, but now can be used to host apps from many programming environments, including Node (and hence Express)!</p> + +<p>We are choosing to use Heroku for several reasons:</p> + +<ul> + <li>Heroku has a <a href="https://www.heroku.com/pricing">free tier</a> that is <em>really</em> free (albeit with some limitations).</li> + <li>As a PaaS, Heroku takes care of a lot of the web infrastructure for us. This makes it much easier to get started, because you don't worry about servers, load balancers, reverse proxies, restarting your website on a crash, or any of the other web infrastructure that Heroku provides for us under the hood.</li> + <li>While it does have some limitations, these will not affect this particular application. For example: + <ul> + <li>Heroku provides only short-lived storage so user-uploaded files cannot safely be stored on Heroku itself.</li> + <li>The free tier will sleep an inactive web app if there are no requests within a half hour period. The site may then take several seconds to respond when it is woken up.</li> + <li>The free tier limits the time that your site is running to a certain amount of hours every month (not including the time that the site is "asleep"). This is fine for a low use/demonstration site, but will not be suitable if 100% uptime is required.</li> + <li>Other limitations are listed in <a href="https://devcenter.heroku.com/articles/limits">Limits</a> (Heroku docs).</li> + </ul> + </li> + <li>Mostly it just works, and if you end up loving it and want to upgrade, scaling your app is very easy.</li> +</ul> + +<p>While Heroku is perfect for hosting this demonstration it may not be perfect for your real website. Heroku makes things easy to set up and scale, at the cost of being less flexible, and potentially a lot more expensive once you get out of the free tier.</p> + +<h3 id="How_does_Heroku_work">How does Heroku work?</h3> + +<p>Heroku runs websites within one or more "<a href="https://devcenter.heroku.com/articles/dynos">Dynos</a>", which are isolated, virtualized Unix containers that provide the environment required to run an application. The dynos are completely isolated and have an <em>ephemeral</em> file system (a short-lived file system that is cleaned/emptied every time the dyno restarts). The only thing that dynos share by default are application <a href="https://devcenter.heroku.com/articles/config-vars">configuration variables</a>. Heroku internally uses a load balancer to distribute web traffic to all "web" dynos. Since nothing is shared between them, Heroku can scale an app horizontally by adding more dynos (though of course you may also need to scale your database to accept additional connections).</p> + +<p>Because the file system is ephemeral you can't install services required by your application directly (e.g. databases, queues, caching systems, storage, email services, etc). Instead Heroku web applications use backing services provided as independent "add-ons" by Heroku or 3rd parties. Once attached to your web application, the add-on services are accessed in your web application via environment variables.</p> + +<p>In order to execute your application Heroku needs to be able to set up the appropriate environment and dependencies, and also understand how it is launched. For Node apps all the information it needs is obtained from your <strong>package.json</strong> file.</p> + +<p>Developers interact with Heroku using a special client app/terminal, which is much like a Unix bash script. This allows you to upload code that is stored in a git repository, inspect the running processes, see logs, set configuration variables, and much more!</p> + +<p>In order to get our application to work on Heroku we'll need to put our Express web application into a git repository and make some minor changes to the package.json. Once we've done that we can set up a Heroku account, get the Heroku client, and use it to install our website.</p> + +<p>That's all the overview you need in order to get started (see <a href="https://devcenter.heroku.com/articles/getting-started-with-nodejs">Getting Started on Heroku with Node.js</a> for a more comprehensive guide).</p> + +<h3 id="Creating_an_application_repository_in_Github">Creating an application repository in Github</h3> + +<p>Heroku is closely integrated with the <strong>git</strong> source code version control system, using it to upload/synchronise any changes you make to the live system. It does this by adding a new Heroku "remote" repository named <em>heroku</em> pointing to a repository for your source on the Heroku cloud. During development you use git to store changes on your "master" repository. When you want to deploy your site, you sync your changes to the Heroku repository.</p> + +<div class="note"> +<p><strong>Note:</strong> If you're used to following good software development practices you are probably already using git or some other SCM system. If you already have a git repository, then you can skip this step.</p> +</div> + +<p>There are a lot of ways of to work with git, but one of the easiest is to first set up an account on <a href="https://github.com/">GitHub</a>, create the repository there, and then sync to it locally:</p> + +<ol> + <li>Visit <a href="https://github.com/">https://github.com/</a> and create an account.</li> + <li>Once you are logged in, click the <strong>+</strong> link in the top toolbar and select <strong>New repository</strong>.</li> + <li>Fill in all the fields on this form. While these are not compulsory, they are strongly recommended. + <ul> + <li>Enter a new repository name (e.g. <em>express-locallibrary-tutorial</em>), and description (e.g. "Local Library website written in Express (Node)".</li> + <li>Choose <strong>Node</strong> in the <em>Add .gitignore</em> selection list.</li> + <li>Choose your preferred license in the <em>Add license</em> selection list.</li> + <li>Check <strong>Initialize this repository with a README</strong>.</li> + </ul> + </li> + <li>Press <strong>Create repository</strong>.</li> + <li>Click the green "<strong>Clone or download</strong>" button on your new repo page.</li> + <li>Copy the URL value from the text field inside the dialog box that appears (it should be something like: <strong>https://github.com/<em><your_git_user_id></em>/express-locallibrary-tutorial.git</strong>).</li> +</ol> + +<p>Now the repository ("repo") is created we are going to want to clone it on our local computer:</p> + +<ol> + <li>Install <em>git</em> for your local computer (you can find versions for different platforms <a href="https://git-scm.com/downloads">here</a>).</li> + <li>Open a command prompt/terminal and clone your repository using the URL you copied above: + <pre class="brush: bash">git clone https://github.com/<strong><em><your_git_user_id></em></strong>/express-locallibrary-tutorial.git +</pre> + This will create the repository below the current point.</li> + <li>Navigate into the new repo. + <pre class="brush: bash">cd express-locallibrary-tutorial</pre> + </li> +</ol> + +<p>The final step is to copy in your application and then add the files to your repo using git:</p> + +<ol> + <li>Copy your Express application into this folder (excluding <strong>/node_modules</strong>, which contains dependency files that you should fetch from NPM as needed).</li> + <li>Open a command prompt/terminal and use the <code>add</code> command to add all files to git.</li> + <li> + <pre class="brush: bash">git add -A +</pre> + </li> + <li>Use the status command to check all files that you are about to add are correct (you want to include source files, not binaries, temporary files etc.). It should look a bit like the listing below. + <pre>> git status +On branch master +Your branch is up-to-date with 'origin/master'. +Changes to be committed: + (use "git reset HEAD <file>..." to unstage) + + new file: ...</pre> + </li> + <li>When you're satisfied commit the files to your local repository: + <pre class="brush: bash">git commit -m "First version of application moved into github"</pre> + </li> + <li>Then synchronise your local repository to the Github website, using the following: + <pre>git push origin master</pre> + </li> +</ol> + +<p>When this operation completes, you should be able to go back to the page on Github where you created your repo, refresh the page, and see that your whole application has now been uploaded. You can continue to update your repository as files change using this add/commit/push cycle.</p> + +<div class="note"> +<p><strong>Tip:</strong> This is a good point to make a backup of your "vanilla" project — while some of the changes we're going to be making in the following sections might be useful for deployment on any platform (or development) others might not.</p> + +<p>The <em>best</em> way to do this is to use <em>git</em> to manage your revisions. With <em>git</em> you can not only go back to a particular old version, but you can maintain this in a separate "branch" from your production changes and cherry-pick any changes to move between production and development branches. <a href="https://help.github.com/articles/good-resources-for-learning-git-and-github/">Learning Git</a> is well worth the effort, but is beyond the scope of this topic.</p> + +<p>The <em>easiest</em> way to do this is to just copy your files into another location. Use whichever approach best matches your knowledge of git!</p> +</div> + +<h3 id="Update_the_app_for_Heroku">Update the app for Heroku</h3> + +<p>This section explains the changes you'll need to make to our <em>LocalLibrary</em> application to get it to work on Heroku.</p> + +<h4 id="Set_node_version">Set node version </h4> + +<p>The <strong>package.json</strong> contains everything needed to work out your application dependencies and what file should be launched to start your site. Heroku detects the presence of this file, and will use it to provision your app environment.</p> + +<p>The only useful information missing in our current <strong>package.json</strong> is the version of node. We can find the version of node we're using for development by entering the command:</p> + +<pre class="brush: bash">>node --version +v8.9.1</pre> + +<p>Open <strong>package.json</strong>, and add this information as an <strong>engines > node</strong> section as shown (using the version number for your system).</p> + +<pre class="brush: json">{ + "name": "express-locallibrary-tutorial", + "version": "0.0.0", +<strong> "engines": { + "node": "8.9.1" + },</strong> + "private": true, + ... +</pre> + +<h4 id="Database_configuration">Database configuration</h4> + +<p>So far in this tutorial we've used a single database that is hard coded into <strong>app.js</strong>. Normally we'd like to be able to have a different database for production and development, so next we'll modify the LocalLibrary website to get the database URI from the OS environment (if it has been defined), and otherwise use our development database.</p> + +<p>Open <strong>app.js</strong> and find the line that sets the mongoDB connection variable. It will look something like this:</p> + +<pre class="brush: js">var mongoDB = 'mongodb://your_user_id:your_password@ds119748.mlab.com:19748/local_library';</pre> + +<p>Replace the line with the following code that uses <code>process.env.MONGODB_URI</code> to get the connection string from an environment variable named <code>MONGODB_URI</code> if has been set (use your own database URL instead of the placeholder below.)</p> + +<pre class="brush: js">var mongoDB = <strong>process.env.MONGODB_URI</strong> || 'mongodb://your_user_id:your_password@ds119748.mlab.com:19748/local_library'; +</pre> + +<h4 id="Get_dependencies_and_re-test">Get dependencies and re-test</h4> + +<p>Before we proceed, let's test the site again and make sure it wasn't affected by any of our changes. </p> + +<p>First we will need to fetch our dependencies (you will recall we didn't copy the <strong>node_modules</strong> folder into our git tree). You can do this by running the following command in your terminal at the root of the project:</p> + +<pre class="brush: bash">npm install +</pre> + +<p>Now run the site (see <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes#Testing_the_routes">Testing the routes</a> for the relevant commands) and check that the site still behaves as you expect.</p> + +<h4 id="Save_changes_to_Github">Save changes to Github</h4> + +<p>Next let's save all our changes to Github. In the terminal (whilst inside our repository), enter the following commands:</p> + +<pre class="brush: bash">git add -A +git commit -m "Added files and changes required for deployment to heroku" +git push origin master</pre> + +<p>We should now be ready to start deploying <em>LocalLibrary</em> on Heroku.</p> + +<h3 id="Get_a_Heroku_account">Get a Heroku account</h3> + +<p>To start using Heroku you will first need to create an account (skip ahead to <a href="#Create_and_upload_the_website">Create and upload the website</a> if you've already got an account and installed the Heroku client):</p> + +<ul> + <li>Go to <a href="https://www.heroku.com/">www.heroku.com</a> and click the <strong>SIGN UP FOR FREE</strong> button.</li> + <li>Enter your details and then press <strong>CREATE FREE ACCOUNT</strong>. You'll be asked to check your account for a sign-up email.</li> + <li>Click the account activation link in the signup email. You'll be taken back to your account on the web browser.</li> + <li>Enter your password and click <strong>SET PASSWORD AND LOGIN</strong>.</li> + <li>You'll then be logged in and taken to the Heroku dashboard: <a href="https://dashboard.heroku.com/apps">https://dashboard.heroku.com/apps</a>.</li> +</ul> + +<h3 id="Install_the_client">Install the client</h3> + +<p>Download and install the Heroku client by following the <a href="https://devcenter.heroku.com/articles/getting-started-with-python#set-up">instructions on Heroku here</a>.</p> + +<p>After the client is installed you will be able run commands. For example to get help on the client:</p> + +<pre class="brush: bash">heroku help +</pre> + +<h3 id="Create_and_upload_the_website">Create and upload the website</h3> + +<p>To create the app we run the "create" command in the root directory of our repository. This creates a git remote ("pointer to a remote repository") named <em>heroku</em> in our local git environment.</p> + +<pre class="brush: bash">heroku create</pre> + +<div class="note"> +<p><strong>Note:</strong> You can name the remote if you like by specifying a value after "create". If you don't then you'll get a random name. The name is used in the default URL.</p> +</div> + +<p>We can then push our app to the Heroku repository as shown below. This will upload the app, get all its dependencies, package it in a dyno, and start the site.</p> + +<pre class="brush: bash">git push heroku master</pre> + +<p>If we're lucky, the app is now "running" on the site. To open your browser and run the new website, use the command:</p> + +<pre class="brush: bash">heroku open</pre> + +<div class="note"> +<p><strong>Note</strong>: The site will be running using our development database. Create some books and other objects, and check out whether the site is behaving as you expect. In the next section we'll set it to use our new database.</p> +</div> + +<h3 id="Setting_configuration_variables">Setting configuration variables</h3> + +<p>You will recall from a preceding section that we need to <a href="#NODE_ENV">set NODE_ENV to 'production'</a> in order to improve our performance and generate less-verbose error messages. We do this by entering the following command:</p> + +<pre class="brush: bash">>heroku config:set NODE_ENV='production' +Setting NODE_ENV and restarting limitless-tor-18923... done, v13 +NODE_ENV: production +</pre> + +<p>We should also use a separate database for production, setting its URI in the <strong>MONGODB_URI</strong> environment variable. You can set up a new database and database-user exactly <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose#Setting_up_the_MongoDB_database">as we did originally</a>, and get its URI. You can set the URI as shown (obviously, using your own URI!)</p> + +<pre class="brush: bash">>heroku config:set <strong>MONGODB_URI</strong>='mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production' +Setting MONGODB_URI and restarting limitless-tor-18923... done, v13 +MONGODB_URI: mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production +</pre> + +<p>You can inspect your configuration variables at any time using the <code>heroku config</code> command — try this now:</p> + +<pre class="brush: bash">>heroku config +=== limitless-tor-18923 Config Vars +MONGODB_URI: mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production +NODE_ENV: production +</pre> + +<p>Heroku will restart your app when it updates the variables. If you check the home page now it should show zero values for your object counts, as the changes above mean that we're now using a new (empty) database.</p> + +<h3 id="Managing_addons">Managing addons</h3> + +<p>Heroku uses independent add-ons to provide backing services to apps — for example email or database services. We don't use any addons in this website, but they are an important part of working with Heroku, so you may want to check out the topic <a href="https://devcenter.heroku.com/articles/managing-add-ons">Managing Add-ons</a> (Heroku docs).</p> + +<h3 id="Debugging">Debugging</h3> + +<p>The Heroku client provides a few tools for debugging:</p> + +<pre class="brush: bash">heroku logs # Show current logs +heroku logs --tail # Show current logs and keep updating with any new results +heroku ps #Display dyno status +</pre> + +<ul> +</ul> + +<h2 id="Summary">Summary</h2> + +<p>That's the end of this tutorial on setting up Express apps in production, and also the series of tutorials on working with Express. We hope you've found them useful. You can check out a fully worked-through version of the <a href="https://github.com/mdn/express-locallibrary-tutorial">source code on Github here</a>.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li id="production-best-practices-performance-and-reliability"><a href="https://expressjs.com/en/advanced/best-practice-performance.html">Production best practices: performance and reliability</a> (Express docs)</li> + <li><a href="https://expressjs.com/en/advanced/best-practice-security.html">Production Best Practices: Security</a> (Express docs)</li> + <li>Heroku + <ul> + <li><a href="https://devcenter.heroku.com/articles/getting-started-with-nodejs">Getting Started on Heroku with Node.js</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/deploying-nodejs">Deploying Node.js Applications on Heroku</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/nodejs-support">Heroku Node.js Support</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/node-concurrency">Optimizing Node.js Application Concurrency</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/how-heroku-works">How Heroku works</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/dynos">Dynos and the Dyno Manager</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/config-vars">Configuration and Config Vars</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/limits">Limits</a> (Heroku docs)</li> + </ul> + </li> + <li>Digital Ocean + <ul> + <li><a href="https://www.digitalocean.com/community/tutorials?q=express">Express</a> tutorials</li> + <li><a href="https://www.digitalocean.com/community/tutorials?q=node.js">Node.js</a> tutorials </li> + </ul> + </li> +</ul> + +<p>{{PreviousMenu("Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}</p> + +<p> </p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introduction</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Setting up a Node (Express) development environment</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li> +</ul> + +<p> </p> diff --git a/files/pt-br/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html b/files/pt-br/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html new file mode 100644 index 0000000000..1f4b09375b --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html @@ -0,0 +1,135 @@ +--- +title: Controle de fluxo assíncrono usando async +slug: Learn/Server-side/Express_Nodejs/Displaying_data/flow_control_using_async +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/flow_control_using_async +--- +<p>O código da <em>Controller</em>, para algumas de nossas páginas dependerá dos resultados de várias solicitações assíncronas, que talvez possam ser necessárias para serem executadas em uma ordem específica ou em paralelo. Para gerenciar o controle do nosso fluxo e renderizar páginas quando tivermos todas as informações necessárias disponíveis, usaremos o popular módulo <a href="https://www.npmjs.com/package/async">async</a>.</p> + +<div class="note"> +<p><strong>Nota:</strong> Há várias outras maneiras de gerenciar o comportamento assíncrono e o controle de fluxo em JavaScript, um dos recursos Javascript que pode ser utilizado, são as <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/Techniques/Promises">Promises</a>. </p> +</div> + +<p>Async has a lot of useful methods (check out <a class="external external-icon" href="http://caolan.github.io/async/docs.html" rel="noopener">the documentation</a>). Some of the more important functions are:</p> + +<ul> + <li><code><a class="external external-icon" href="http://caolan.github.io/async/docs.html#parallel" rel="noopener">async.parallel()</a></code> executa qualquer operação que deva ser processada em paralelo.</li> + <li><code><a class="external external-icon" href="http://caolan.github.io/async/docs.html#series" rel="noopener">async.series()</a></code> garante que as operações assíncronas sejam executadas em série.</li> + <li><code><a class="external external-icon" href="http://caolan.github.io/async/docs.html#waterfall" rel="noopener">async.waterfall()</a></code> operações que devem ser executadas em série, baseando-se no resultado de cada operação anterior. </li> +</ul> + +<h2 class="highlight-spanned" id="Por_que_isso_é_necessário"><span class="highlight-span">Por que isso é necessário ?</span></h2> + +<p>A maioria dos métodos que usamos no Express são assíncronos - você especifica uma operação para executar, passando um <em>callback</em>. O método retorna imediatamente e o <em>callback </em>é invocado quando a operação solicitada é concluída. Por convenção no <em>Express</em>, as funções de <em>callback </em>passam um valor de erro como o primeiro parâmetro (ou nulo em sucesso) e os resultados da função (se houver algum) como o segundo parâmetro.</p> + +<p>Se uma <em>Controller </em>só precisa <em>executar</em> <em><strong>uma </strong>operação assíncrona</em> para obter as informações necessárias para renderizar uma página, a implementação é fácil —simplesmente renderizamos o <em>template</em> no <em>callback</em>. O código abaixo ilustra uma função que renderiza a contagem de um <em>model</em> <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">ExampleModel </span></font>(usando o método <code><a href="http://mongoosejs.com/docs/api.html#model_Model.count" rel="noopener">count()</a> </code> do Mongoose.</p> + +<pre class="brush: js"><code>exports.example_model_count = function(req, res, next) { + +</code> <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">ExampleModel </span></font>.count({ a_model_field: 'match_value' }, function (err, count) { + // ... do something if there is an err + + // On success, render the result by passing count into the render function (here, as the variable 'data'). + res.render('the_template', { data: count } ); + }); +<code>}</code> +</pre> + +<p>However what if you need to make <strong>multiple </strong>asynchronous queries, and you can't render the page until all the operations have completed? A naive implementation could "daisy chain" the requests, kicking off subsequent requests in the callback of a previous request, and rendering the response in the final callback. The problem with this approach is that our requests would have to be run in series, even though it might be more efficient to run them in parallel. This could also result in complicated nested code, commonly referred to as <a class="external external-icon" href="http://callbackhell.com/" rel="noopener">callback hell</a>.</p> + +<p>A much better solution would be to execute all the requests in parallel and then have a single callback that executes when all of the queries have completed. This is the sort of flow operation that the <em>Async</em> module makes easy!</p> + +<h2 class="highlight-spanned" id="Operações_assíncronas_em_paralelo"><span class="highlight-span">Operações assíncronas em paralelo</span></h2> + +<p>The method <code><a class="external external-icon" href="http://caolan.github.io/async/docs.html#parallel" rel="noopener">async.parallel()</a></code> is used to run multiple asynchronous operations in parallel.</p> + +<p>The first argument to <code>async.parallel()</code> is a collection of the asynchronous functions to run (an array, object or other iterable). Each function is passed a <code>callback(err, result)</code> which it must call on completion with an error <code>err</code> (which can be <code>null</code>) and an optional <code>results</code> value.</p> + +<p>The optional second argument to <code>async.parallel()</code> is a callback that will be run when all the functions in the first argument have completed. The callback is invoked with an error argument and a result collection that contains the results of the individual asynchronous operations. The result collection is of the same type as the first argument (i.e. if you pass an array of asynchronous functions, the final callback will be invoked with an array of results). If any of the parallel functions reports an error the callback is invoked early (with the error value).</p> + +<p>The example below shows how this works when we pass an object as the first argument. As you can see, the results are <em>returned</em> in an object with the same property names as the original functions that were passed in.</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">async</span><span class="punctuation token">.</span><span class="function token">parallel</span><span class="punctuation token">(</span><span class="punctuation token">{</span> + one<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span>callback<span class="punctuation token">)</span> <span class="punctuation token">{</span> <span class="punctuation token">.</span><span class="punctuation token">.</span><span class="punctuation token">.</span> <span class="punctuation token">}</span><span class="punctuation token">,</span> + two<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span>callback<span class="punctuation token">)</span> <span class="punctuation token">{</span> <span class="punctuation token">.</span><span class="punctuation token">.</span><span class="punctuation token">.</span> <span class="punctuation token">}</span><span class="punctuation token">,</span> + <span class="punctuation token">.</span><span class="punctuation token">.</span><span class="punctuation token">.</span> + something_else<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span>callback<span class="punctuation token">)</span> <span class="punctuation token">{</span> <span class="punctuation token">.</span><span class="punctuation token">.</span><span class="punctuation token">.</span> <span class="punctuation token">}</span> + <span class="punctuation token">}</span><span class="punctuation token">,</span> + <span class="comment token">// optional callback</span> + <span class="keyword token">function</span><span class="punctuation token">(</span>err<span class="punctuation token">,</span> results<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="comment token">// 'results' is now equal to: {one: 1, two: 2, ..., something_else: some_value}</span> + <span class="punctuation token">}</span> +<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<p>If you instead pass an array of functions as the first argument, the results will be an array (the array order results will match the original order that the functions were declared—not the order in which they completed).</p> + +<h2 class="highlight-spanned" id="Operações_assíncronas_em_série"><span class="highlight-span">Operações assíncronas em série</span></h2> + +<p>The method <code><a class="external external-icon" href="http://caolan.github.io/async/docs.html#series" rel="noopener">async.series()</a></code> is used to run multiple asynchronous operations in sequence, when subsequent functions do not depend on the output of earlier functions. It is essentially declared and behaves in the same way as <code>async.parallel()</code>.</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">async</span><span class="punctuation token">.</span><span class="function token">series</span><span class="punctuation token">(</span><span class="punctuation token">{</span> + one<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span>callback<span class="punctuation token">)</span> <span class="punctuation token">{</span> <span class="punctuation token">.</span><span class="punctuation token">.</span><span class="punctuation token">.</span> <span class="punctuation token">}</span><span class="punctuation token">,</span> + two<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span>callback<span class="punctuation token">)</span> <span class="punctuation token">{</span> <span class="punctuation token">.</span><span class="punctuation token">.</span><span class="punctuation token">.</span> <span class="punctuation token">}</span><span class="punctuation token">,</span> + <span class="punctuation token">.</span><span class="punctuation token">.</span><span class="punctuation token">.</span> + something_else<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span>callback<span class="punctuation token">)</span> <span class="punctuation token">{</span> <span class="punctuation token">.</span><span class="punctuation token">.</span><span class="punctuation token">.</span> <span class="punctuation token">}</span> + <span class="punctuation token">}</span><span class="punctuation token">,</span> + <span class="comment token">// optional callback after the last asynchronous function completes.</span> + <span class="keyword token">function</span><span class="punctuation token">(</span>err<span class="punctuation token">,</span> results<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="comment token">// 'results' is now equals to: {one: 1, two: 2, ..., something_else: some_value} </span> + <span class="punctuation token">}</span> +<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<div class="note"> +<p><strong>Note:</strong> The ECMAScript (JavaScript) language specification states that the order of enumeration of an object is undefined, so it is possible that the functions will not be called in the same order as you specify them on all platforms. If the order really is important, then you should pass an array instead of an object, as shown below.</p> +</div> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">async</span><span class="punctuation token">.</span><span class="function token">series</span><span class="punctuation token">(</span><span class="punctuation token">[</span> + <span class="keyword token">function</span><span class="punctuation token">(</span>callback<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="comment token">// do some stuff ...</span> + <span class="function token">callback</span><span class="punctuation token">(</span><span class="keyword token">null</span><span class="punctuation token">,</span> <span class="string token">'one'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span><span class="punctuation token">,</span> + <span class="keyword token">function</span><span class="punctuation token">(</span>callback<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="comment token">// do some more stuff ... </span> + <span class="function token">callback</span><span class="punctuation token">(</span><span class="keyword token">null</span><span class="punctuation token">,</span> <span class="string token">'two'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span> + <span class="punctuation token">]</span><span class="punctuation token">,</span> + <span class="comment token">// optional callback</span> + <span class="keyword token">function</span><span class="punctuation token">(</span>err<span class="punctuation token">,</span> results<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="comment token">// results is now equal to ['one', 'two'] </span> + <span class="punctuation token">}</span> +<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<h2 class="highlight-spanned" id="Operações_assíncronas_dependentes_em_série"><span class="highlight-span">Operações assíncronas dependentes em série</span></h2> + +<p>The method <code><a class="external external-icon" href="http://caolan.github.io/async/docs.html#waterfall" rel="noopener">async.waterfall()</a></code> is used to run multiple asynchronous operations in sequence when each operation is dependent on the result of the previous operation.</p> + +<p>The callback invoked by each asynchronous function contains <code>null</code> for the first argument and results in subsequent arguments. Each function in the series takes the results arguments of the previous callback as the first parameters, and then a callback function. When all operations are complete, a final callback is invoked with the result of the last operation. The way this works is more clear when you consider the code fragment below (this example is from the <em>async</em> documentation):</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">async</span><span class="punctuation token">.</span><span class="function token">waterfall</span><span class="punctuation token">(</span><span class="punctuation token">[</span> + <span class="keyword token">function</span><span class="punctuation token">(</span>callback<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="function token">callback</span><span class="punctuation token">(</span><span class="keyword token">null</span><span class="punctuation token">,</span> <span class="string token">'one'</span><span class="punctuation token">,</span> <span class="string token">'two'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span><span class="punctuation token">,</span> + <span class="keyword token">function</span><span class="punctuation token">(</span>arg1<span class="punctuation token">,</span> arg2<span class="punctuation token">,</span> callback<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="comment token">// arg1 now equals 'one' and arg2 now equals 'two' </span> + <span class="function token">callback</span><span class="punctuation token">(</span><span class="keyword token">null</span><span class="punctuation token">,</span> <span class="string token">'three'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span><span class="punctuation token">,</span> + <span class="keyword token">function</span><span class="punctuation token">(</span>arg1<span class="punctuation token">,</span> callback<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="comment token">// arg1 now equals 'three'</span> + <span class="function token">callback</span><span class="punctuation token">(</span><span class="keyword token">null</span><span class="punctuation token">,</span> <span class="string token">'done'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span> +<span class="punctuation token">]</span><span class="punctuation token">,</span> <span class="keyword token">function</span> <span class="punctuation token">(</span>err<span class="punctuation token">,</span> result<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="comment token">// result now equals 'done'</span> +<span class="punctuation token">}</span> +<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<h2 class="highlight-spanned" id="Instalando_o_async"><span class="highlight-span">Instalando o async</span></h2> + +<p>Install the async module using the NPM package manager so that we can use it in our code. You do this in the usual way, by opening a prompt in the root of the <em>LocalLibrary</em> project and enter the following command:</p> + +<pre class="brush: bash line-numbers language-bash"><code class="language-bash">npm install async</code></pre> + +<h2 id="Next_steps">Next steps</h2> + +<ul> + <li>Return to <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a>.</li> + <li>Proceed to the next subarticle of Part 5: <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Template_primer">Template primer</a>.</li> +</ul> diff --git a/files/pt-br/learn/server-side/express_nodejs/displaying_data/index.html b/files/pt-br/learn/server-side/express_nodejs/displaying_data/index.html new file mode 100644 index 0000000000..732e4e4417 --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/displaying_data/index.html @@ -0,0 +1,87 @@ +--- +title: 'Express Tutorial Part 5: Displaying library data' +slug: Learn/Server-side/Express_Nodejs/Displaying_data +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}</div> + +<p class="summary">We're now ready to add the pages that display the <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">LocalLibrary</a> website books and other data. The pages will include a home page that shows how many records we have of each model type, and list and detail pages for all of our models. Along the way we'll gain practical experience in getting records from the database, and using templates.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Complete previous tutorial topics (including <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>To understand how to use the async module and Pug template language, and how to get data from the URL in our controller functions.</td> + </tr> + </tbody> +</table> + +<h2 id="Overview">Overview</h2> + +<p>In our previous tutorial articles we defined <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Mongoose models</a> that we can use to interact with a database and created some initial library records. We then <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">created all the routes</a> needed for the LocalLibrary website, but with "dummy controller" functions (these are skeleton controller functions that just return a "not implemented" message when a page is accessed).</p> + +<p>The next step is to provide proper implementations for the pages that <em>display</em> our library information (we'll look at implementing pages featuring forms to create, update, or delete information in later articles). This includes updating the controller functions to fetch records using our models, and defining templates to display this information to users.</p> + +<p>We will start by providing overview/primer topics explaining how to manage asynchronous operations in controller functions and how to write templates using Pug. Then we'll provide implementations for each of our main "read only" pages with a brief explanation of any special or new features that they use.</p> + +<p>At the end of this article you should have a good end-to-end understanding of how routes, asynchronous functions, views, and models work in practice.</p> + +<h2 id="Displaying_library_data_tutorial_subarticles">Displaying library data tutorial subarticles</h2> + +<p>The following subarticles go through the process of adding the different features required for us to display the required website pages. You need to read and work through each one of these in turn, before moving on to the next one.</p> + +<ol> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/flow_control_using_async">Asynchronous flow control using async</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Template_primer">Template primer</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/LocalLibrary_base_template">The LocalLibrary base template</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Home_page">Home page</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Book_list_page">Book list page</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/BookInstance_list_page">BookInstance list page</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Date_formatting_using_moment">Date formatting using moment</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Author_list_page">Author list page and Genre list page challenge</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Genre_detail_page">Genre detail page</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Book_detail_page">Book detail page</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Author_detail_page">Author detail page</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/BookInstance_detail_page_and_challenge">BookInstance detail page and challenge</a></li> +</ol> + +<h2 id="Summary">Summary</h2> + +<p>We've now created all the "read-only" pages for our site: a home page that displays counts of instances of each of our models, and list and detail pages for our books, book instances, authors, and genres. Along the way we've gained a lot of fundamental knowledge about controllers, managing flow control when using asynchronous operations, creating views using <em>Pug</em>, querying the database using our models, how to pass information to a template from your view, and how to create and extend templates. Those who completed the challenge will also have learned a little about date handling using <em>moment</em>.</p> + +<p>In our next article we'll build on our knowledge, creating HTML forms and form handling code to start modifying the data stored by the site.</p> + +<h2 id="Veja_mais">Veja mais</h2> + +<ul> + <li><a href="http://caolan.github.io/async/docs.html">Async module</a> (Async docs)</li> + <li><a href="https://expressjs.com/en/guide/using-template-engines.html">Using Template engines with Express</a> (Express docs)</li> + <li><a href="https://pugjs.org/api/getting-started.html">Pug</a> (Pug docs)</li> + <li><a href="http://momentjs.com/docs/">Moment</a> (Moment docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}</p> + +<p> </p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introduction</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Setting up a Node (Express) development environment</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li> +</ul> + +<p> </p> diff --git a/files/pt-br/learn/server-side/express_nodejs/index.html b/files/pt-br/learn/server-side/express_nodejs/index.html new file mode 100644 index 0000000000..a94962ad4d --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/index.html @@ -0,0 +1,65 @@ +--- +title: Express Web Framework (Node.js/JavaScript) +slug: Learn/Server-side/Express_Nodejs +translation_of: Learn/Server-side/Express_Nodejs +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Express é um popular framework web estruturado, escrito em JavaScript que roda sobre o ambiente node.js em tempo de execução. Este módulo explica alguns dos principais benefícios deste framework, como configurar o seu ambiente de desenvolvimento e como executar tarefas comuns de desenvolvimento e implantação da web.</p> + +<h2 id="Pré-requisitos">Pré-requisitos</h2> + +<p>Antes de iniciar este módulo, você precisará entender o que é programação web e as estruturas do lado do servidor são, o ideal é ler os tópicos em nosso <a href="/en-US/docs/Learn/Server-side/First_steps">Módulo de primeiros passos da programação de sites do lado servidor</a>. Um conhecimento geral de conceitos de programação e JavaScript é altamente recomendado, mas não é essencial para a compreensão dos conceitos fundamentais.</p> + +<div class="note"> +<p><strong>Nota</strong>: Nota: Este site possui muitos recursos úteis para aprender JavaScript no contexto do desenvolvimento do lado do cliente: JavaScript, Guia de JavaScript, princípios básicos de JavaScript, JavaScript (aprendizagem). O core JavaScript linguagem e conceitos são os mesmos para o desenvolvimento do lado do servidor no Node.js e este material será relevante. O Node.js oferece APIs adicionais para suportar funcionalidades que são úteis em ambientes sem navegador, e. Para criar servidores HTTP e acessar o sistema de arquivos, mas não suporta APIs JavaScript para trabalhar com o navegador e o DOM.</p> + +<p>Este guia fornecerá algumas informações sobre como trabalhar com o Node.js e o Express, e existem inúmeros outros recursos excelentes na Internet e em livros - alguns desses relacionados de Como faço para começar com Node.js (StackOverflow) e O que são os Melhores recursos para aprender Node.js? (Quora).</p> +</div> + +<h2 id="Tutoriais">Tutoriais</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introdução</a></dt> + <dd>Neste primeiro artigo Express, respondemos as perguntas "O que é Node?" E "O que é Express?" E dar-lhe uma visão geral do que torna a estrutura web Express especial. Apresentaremos os principais recursos e mostraremos alguns dos principais blocos de construção de um aplicativo Express (embora neste momento você ainda não tenha um ambiente de desenvolvimento para testá-lo).</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Configurando um ambiente de desenvolvimento em Node (Express) </a></dt> + <dd>Agora que você sabe o que o Express é, vamos mostrar-lhe como configurar e testar um ambiente de desenvolvimento de Node.js / Express no Windows, Linux (Ubuntu) e Mac OS X. Qualquer sistema operacional comum que você esteja usando, este artigo deve Dê o que você precisa para começar a desenvolver aplicativos Express.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Tutorial Express: O site da Biblioteca Local</a></dt> + <dd>O primeiro artigo da nossa série de tutoriais práticos explica o que você aprenderá e fornecer uma visão geral do exemplo de site da "biblioteca local", no qual estaremos trabalhando e evoluindo em artigos subsquentes.</dd> + <dt></dt> + <dt><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></dt> + <dd>Este artigo mostra como você pode criar um projeto de "esqueleto" de website, no qual você pode popular com as rotas específicas do site, modelos/vizualizações e bancos de dados.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></dt> + <dd>This article briefly introduces databases for Node/Express. It then goes on to show how we can use <a href="http://mongoosejs.com/">Mongoose</a> to provide database access for the <em>LocalLibrary</em> website. It explains how object schema and models are declared, the main field types, and basic validation. It also briefly shows a few of the main ways you can access model data.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></dt> + <dd>In this tutorial we'll set up routes (URL handling code) with "dummy" handler functions for all the resource endpoints that we'll eventually need in the <em>LocalLibrary</em> website. On completion, we'll have a modular structure for our route handling code, that we can extend with real handler functions in the following articles. We'll also have a really good understanding of how to create modular routes using Express.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></dt> + <dd>We're now ready to add the pages that display the <em>LocalLibrary</em> website books and other data. The pages will include a home page that shows how many records we have of each model type, and list and detail pages for all of our models. Along the way we'll gain practical experience in getting records from the database, and using templates.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></dt> + <dd>In this tutorial we'll show you how to work with <a href="/en-US/docs/Web/Guide/HTML/Forms">HTML Forms</a> in Express, using Pug, and in particular how to write forms to create, update, and delete documents from the database.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></dt> + <dd>Now you've created an awesome <em>LocalLibrary</em> website, you're going to want to install it on a public web server so that it can be accessed by library staff and members over the Internet. This article provides an overview of how you might go about finding a host to deploy your website, and what you need to do in order to get your site ready for production.</dd> +</dl> + +<h2 id="See_also">See also</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Installing_on_PWS_Cloud_Foundry">Installing LocalLibrary on PWS/Cloud Foundry</a></dt> + <dd>This article provides a practical demonstration of how to install <em>LocalLibrary</em> on the <a href="http://run.pivotal.io">Pivotal Web Services PaaS cloud</a> — this is a full-featured, open source alternative to Heroku, the PaaS cloud service used in Part 7 of the tutorial, listed above. PWS/Cloud Foundry is definitely worth checking out if you are looking for an alternative to Heroku (or another PaaS cloud service), or simply feel like trying something different.</dd> +</dl> + +<h2 id="Adding_more_tutorials">Adding more tutorials</h2> + +<div> +<p>That's the end of the tutorial articles (for now). If you would like to extend it, other interesting topics to cover are:</p> + +<ul> + <li>Using sessions</li> + <li>User authentication</li> + <li>User authorisation and permissions</li> + <li>Testing an Express web application</li> + <li>Web security for Express web applications.</li> +</ul> + +<p>And of course it would be excellent to have an assessment task!</p> +</div> diff --git a/files/pt-br/learn/server-side/express_nodejs/introdução/index.html b/files/pt-br/learn/server-side/express_nodejs/introdução/index.html new file mode 100644 index 0000000000..15ccfc6145 --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/introdução/index.html @@ -0,0 +1,519 @@ +--- +title: Introdução Express/Node +slug: Learn/Server-side/Express_Nodejs/Introdução +tags: + - Aprender + - Express + - Iniciante + - JavaScript + - Node + - Servidor + - Tutorial + - nodejs +translation_of: Learn/Server-side/Express_Nodejs/Introduction +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs")}}</div> + +<p class="summary">Neste primeiro artigo sobre Express responderemos as questões " O que é Node?" e "O que é Express?", além de dar a você uma visão geral sobre o que torna o Express um framework web tão especial. Vamos descrever as principais características e mostrar alguns dos principais blocos de códigos de construção de um aplicativo Express <span id="result_box" lang="pt"><span>(embora neste momento você ainda não tenha um ambiente de desenvolvimento para testá-lo).</span></span></p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimentos básicos em informática. Uma compreensão geral de <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/First_steps">programação web no lado servidor (backend)</a>, em particular, nos mecanismos de <a href="/pt-BR/docs/Learn/Server-side/First_steps/Client-Server_overview">interação cliente-servidor de websites</a>.</td> + </tr> + <tr> + <th scope="row">Objetivos:</th> + <td>Familiarizar-se com Express, como este framework trabalha junto ao Node, <span id="result_box" lang="pt"><span>quais as funcionalidades que fornece e quais são os principais blocos de construção de um aplicativo Express.</span></span></td> + </tr> + </tbody> +</table> + +<h2 id="O_que_é_Express_e_Node">O que é Express e Node ?</h2> + +<p><a href="https://nodejs.org/">Node</a> (ou formalmente <em>Node.js</em>) é um ambiente em tempo de execução open-source (código aberto) e multiplataforma que permite aos desenvolvedores criarem todo tipo de aplicativos e ferramentas do lado servidor (backend) em <a href="/pt-BR/docs/Glossary/JavaScript">JavaScript</a>. Node<span id="result_box" lang="pt"><span> é usado fora do contexto de um navegador</span></span> (ou seja executado diretamente no computador ou no servidor). Como tal, <span id="result_box" lang="pt"><span>o ambiente omite APIs JavaScript específicas do navegador e adiciona suporte para APIs de sistema operacional mais tradicionais, incluindo bibliotecas de sistemas HTTP e arquivos.</span></span></p> + +<p><span id="result_box" lang="pt"><span>Do ponto de vista do desenvolvimento de um servidor web, o Node possui vários benefícios:</span></span></p> + +<ul> + <li>Performance excelente. Node foi projetado para otimizar a taxa de transferência e a escalabilidade em aplicações web. É <span id="result_box" lang="pt"><span>uma ótima combinação para resolver muitos problemas comuns no desenvolvimento da web (por exemplo, aplicações em tempo real).</span></span></li> + <li>O código é escrito em "JavaScript simples e antigo". Isso significa menos tempo gasto para lidar com mudanças de código entre navegador e servidor web, não sendo necessária uma mudança na linguagem.</li> + <li>JavaScript é uma linguagem de programação relativamente nova e apresenta <span id="result_box" lang="pt"><span>algumas vantagens quando comparadas a outras linguagens tradicionais de servidor</span></span> (por exemplo Python, PHP, etc.). <span id="result_box" lang="pt"><span>Muitas outras linguagens novas e populares compilam/convertem em JavaScript, permitindo que você também use essas linguagens, como TypeScript, CoffeeScript, ClosureScript, Scala, LiveScript, etc.</span></span></li> + <li>O Gerenciador de Pacotes do Node (NPM, na sigla em inglês) provê acesso a centenas de milhares de pacotes reutiliváveis. <span id="result_box" lang="pt"><span>NPM possui a melhor coleção de dependências e também pode ser usado para automatizar a maior parte da cadeia de ferramentas de compilação.</span></span></li> + <li><span id="result_box" lang="pt"><span>É portátil, com versões para diferentes sistemas operacionais, como Microsoft Windows, OS X, Linux, Solaris, FreeBSD, OpenBSD, WebOS e NonStop.</span> <span>Além disso, tem excelente suporte de muitos provedores de hospedagem na web, que muitas vezes fornecem documentação e infraestrutura específica para hospedar sites desenvolvidos em Node.</span></span></li> + <li>P<span id="result_box" lang="pt"><span>ossui uma comunidade de desenvolvedores e um ecossistema muito ativo, com muitas pessoas dispostas a ajudar.</span></span></li> +</ul> + +<p>Você pode utilizar o Node.js para criar um simples servidor web, utilizando o pacote Node HTTP.</p> + +<h3 id="Olá_Node.js">Olá, Node.js</h3> + +<p>O exemplo a seguir cria um servidor web que escuta qualquer tipo de requisição HTTP na URL <code>http://127.0.0.1:8000/</code> -- quando uma requisição é recebida, o script vai responder com a string (texto) "Olá Mundo". Se você já instalou o Node, você pode seguir os passos seguintes deste exemplo.</p> + +<ol> + <li>Abre o Terminal (no Windows, abra o prompt da linha de comando)</li> + <li>Crie uma pasta onde você quer salvar o programa, por exemplo, <code>test-node</code>. Então, entre na pasta com o seguinte comando no terminal:</li> +</ol> + +<pre class="notranslate">cd test-node +</pre> + +<p>Use o seu editor de texto preferido, crie um arquivo chamado <code>hello.js</code> e cole o código a seguir:</p> + +<pre class="brush: js notranslate">// Carrega o modulo HTTP do Node +var http = require("http"); + +// Cria um servidor HTTP e uma escuta de requisições para a porta 8000 +http.createServer(function(request, response) { + + // Configura o cabeçalho da resposta com um status HTTP e um Tipo de Conteúdo + response.writeHead(200, {'Content-Type': 'text/plain'}); + + // Manda o corpo da resposta "Olá Mundo" + response.end('Olá Mundo\n'); +}).listen(8000, '127.0.0.1'); + +// Imprime no console a URL de acesso ao servidor +console.log('Servidor executando em http://127.0.0.1:8000/');</pre> + +<p>Salve o arquivo na pasta que você criou acima.</p> + +<p>Por último, vá para o terminal e digite o comando a seguir:</p> + +<p><code>node hello.js</code></p> + +<p>Enfim, abra o browser e digite <code>http://localhost:8000.</code> Você verá o texto "<strong>Olá, Mundo</strong>", no canto superior esquerdo.</p> + +<h2 id="Web_Frameworks">Web Frameworks</h2> + +<p>Algumas tarefas comuns no desenvolvimento web não são suportadas diretamente pelo Node. Se você quiser que a sua aplicação possua diferentes verbos HTTP (por exemplo <code>GET</code>, <code>POST</code>, <code>DELETE</code>, etc), que gerencie requisições de diferentes URLs ("rotas"), apresente arquivos estáticos ou utilize templates para mostrar as respostas (response) de maneira dinâmica, você não terá muita praticidade usando apenas o Node. Você terá duas opções. Escrever o código por conta própria ou então evitar todo esse trabalho de reinventar a roda ao utilizar um framework.</p> + +<h2 id="Introduzindo_o_Express">Introduzindo o Express</h2> + +<p><a href="https://expressjs.com/">Express</a> é o framework Node mais popular e a biblioteca subjacente para uma série de outros frameworks do Node. O Express oferece soluções para:</p> + +<ul> + <li>Gerenciar requisições de diferentes verbos HTTP em diferentes URLs.</li> + <li>Integrar "view engines" para inserir dados nos templates<span id="result_box" lang="pt"><span>.</span></span></li> + <li>Definir as configurações comuns da aplicação web, como a porta a ser usada para conexão e a localização dos modelos que são usados para renderizar a resposta.</li> + <li><span id="result_box" lang="pt"><span>Adicionar novos processos de requisição por meio de "middleware" em qualquer ponto da "fila" de requisições.</span></span></li> +</ul> + +<p>O <em>Express </em>é bastante minimalista, no entanto, os desenvolvedores têm liberdade para criar pacotes de middleware específicos com o objetivo de resolver problemas específicos que surgem no desenvolvimento de uma aplicação. Há bibliotecas para trabalhar com cookies, sessões, login de usuários, parâmetros de URL, dados em requisições POST, cabeçalho de segurança e tantos outros. Você pode achar uma lista de pacotes de middleware mantidos pela equipe Express em <a href="http://expressjs.com/en/resources/middleware.html">Express Middleware</a> <span id="result_box" lang="pt"><span>(juntamente com uma lista de pacotes populares desenvolvidos por terceiros).</span></span></p> + +<div class="note"> +<p><strong>Nota:</strong> <span id="result_box" lang="pt"><span>Essa flexibilidade do Express é uma espada de dois gumes.</span> <span>Há pacotes de middleware para resolver quase qualquer problema ou requisito ao longo do desenvolvimento, mas utilizar os pacotes corretos para cada situação às vezes se torna um grande desafio.</span> <span>Não há "caminho certo" para estruturar um aplicativo. Muitos exemplos que você encontra na Internet não são bons ou mostram apenas uma pequena parte do que você precisa fazer para desenvolver uma aplicação web.</span></span></p> +</div> + +<h2 id="De_onde_o_Node_e_o_Express_vieram"><span class="short_text" id="result_box" lang="pt"><span>De onde o Node e o Express vieram?</span></span></h2> + +<p><span id="result_box" lang="pt"><span>Node foi inicialmente lançado em 2009, mas naquela época apenas para Linux. O gerenciador de pacotes NPM veio no ano seguinte, 2010, e o suporte nativo do Windows chegou em 2012. A versão atual do </span></span>Long Term Support (LTS)<span lang="pt"><span> é o Node v8.9.3, enquanto a versão mais recente é o Node 9. Esse é um resumo da rica histórica do Node, mas é possível conhecer mais na</span><span> </span></span><a href="https://pt.wikipedia.org/wiki/Node.js#History">Wikipédia</a><span lang="pt"><span>.</span></span></p> + +<p><span id="result_box" lang="pt"><span>O Express foi lançado em novembro de 2010 e atualmente está na versão 4.16 da API.</span> <span>Você pode verificar o </span></span> <a href="https://expressjs.com/en/changelog/4x.html">changelog</a> <span lang="pt"><span> para obter informações sobre as mudanças na versão atual e o </span></span><a href="https://github.com/expressjs/express/blob/master/History.md">GitHub</a><span lang="pt"><span> para obter notas detalhadas das versões históricas.</span></span></p> + +<h2 id="O_quão_popular_é_NodeExpress">O quão popular é Node/Express ?</h2> + +<p><span id="result_box" lang="pt"><span>É importante considerar a popularidade de um framework web porque indica se a ferramenta continuará sendo mantida e atualizada, além de apontar quais recursos provavelmente estarão disponíveis na documentação, nas bibliotecas de complemento e no suporte técnico.</span></span></p> + +<p><span id="result_box" lang="pt"><span>Não há nenhum número capaz de medir precisamente a popularidade de um framework (apesar de que alguns sites como o <a href="http://hotframeworks.com/">Hot Frameworks</a> avaliarem a popularidade a partir do número de projetos do GitHub e do número de perguntas do StackOverflow relativas a cada tecnologia).</span></span><span id="result_box" lang="pt"><span> Diante dessa limitação, o mais importante é fazermos algumas outras perguntas para saber se o Node e o Express são "suficientemente populares" para não caírem nos problemas clássicos das tecnologias com pouca adesão da comunidade.</span></span></p> + +<p><span style="">O Node e o Express continuam a evoluir ?</span><span style=""> </span><span style="">Você pode obter ajuda na comunidade caso precise?</span><span style=""> </span><span style="">Existe uma oportunidade para você receber trabalho remunerado ao dominar o Node e o Express ?</span></p> + +<p>Baseado no <a href="https://expressjs.com/en/resources/companies-using-express.html">número de empresas de alto perfil</a> que usam Express, no número de pessoas contribuindo para o código base, e no número de pessoas que oferecem suporte (gratuito ou pago), a reposta é sim. O Node e o Express são tecnologias populares!</p> + +<h2 id="Express_é_opinativo">Express é opinativo ?</h2> + +<p><span id="result_box" lang="pt"><span>Os frameworks web costumam se autodeclararem "opinativos" ou "não opinativos".</span></span></p> + +<p><span id="result_box" lang="pt"><span>Os frameworks opinativos são aqueles com "opiniões" sobre o "caminho certo" para lidar com qualquer tarefa específica.</span> <span>Muitas vezes, apoiam o desenvolvimento rápido em um domínio particular (resolvendo problemas de um tipo específico) porque a maneira correta de fazer qualquer coisa geralmente é bem compreendida e bem documentada.</span> <span>No entanto, são menos flexíveis na resolução de problemas fora de seu domínio principal e tendem a oferecer menos opções para quais componentes e abordagens podem usar nesses casos.</span></span></p> + +<p>Frameworks não opinativos<span id="result_box" lang="pt"><span>, por outro lado, têm muito menos restrições sobre a melhor maneira de utilizar componentes para atingir um objetivo, ou mesmo quais componentes devem ser usados.</span> <span>Eles tornam mais fácil para os desenvolvedores usar as ferramentas mais adequadas para completar uma tarefa específica, embora você precise encontrar esses componentes por si próprio.</span></span></p> + +<p>Express é um framework não opinativo. Você pode inserir qualquer middleware que você goste no manuseio das solicitações em quase qualquer ordem que desejar. Pode estruturar o aplicativo em um arquivo ou em vários, usar qualquer estrutura de pastas dentro do diretório principal, etc.</p> + +<h2 id="Como_se_parece_o_código_do_Express">Como se parece o código do Express ?</h2> + +<p><span id="result_box" lang="pt"><span>Em um site tradicional baseado em dados, um aplicativo da Web aguarda pedidos HTTP do navegador da web (ou outro cliente).</span> <span>Quando um pedido é recebido, o aplicativo descreve quais ações são necessárias com base no padrão de URL e possivelmente informações associadas contidas em dados POST ou GET.</span> <span>Dependendo do que é necessário, pode-se ler ou escrever informações em um banco de dados ou executar outras tarefas necessárias para satisfazer a solicitação.</span> <span>O aplicativo retornará uma resposta ao navegador da Web, criando, de forma dinâmica, uma página HTML para o navegador, exibindo e inserindo os dados recuperados em espaços reservados em um modelo HTML.</span></span></p> + +<p><span id="result_box" lang="pt"><span>Express fornece métodos para especificar qual função é chamada quando chega requisição HTTP (GET, POST, SET, etc.) e de rotas e métodos para especificar o mecanismo de modelo ("view") usado, onde o modelo</span> <span>arquivos estão localizados e qual modelo usar para renderizar uma resposta.</span> <span>Você pode usar o middleware Express para adicionar suporte para cookies, sessões e usuários, obtendo parâmetros POST / GET, etc. Você pode usar qualquer mecanismo de banco de dados suportado por Node (o Express não define nenhum comportamento relacionado a banco de dados).</span></span></p> + +<p><span id="result_box" lang="pt"><span>As seções a seguir explicam algumas das coisas comuns que você verá ao trabalhar com o código Express e Node.</span></span></p> + +<h3 id="Olá_Mundo_Express">Olá Mundo Express</h3> + +<p><span id="result_box" lang="pt"><span>Primeiro, considere o padrão do exemplo do Express </span></span><a href="http://expressjs.com/pt-br/starter/hello-world.html">Olá Mundo</a><span lang="pt"><span> (discutiremos cada trecho do código nas seções abaixo e nas seções a seguir).</span></span></p> + +<div class="note"> +<p><strong>Dica:</strong> <span id="result_box" lang="pt"><span>Se você tiver o Node e o Express já instalados (ou se você os instalar como mostrado no </span></span><a href="/pt-BR/docs/Learn/Server-side/Express_Nodejs/development_environment">próximo artigo</a><span lang="pt"><span>, você pode salvar este código em um arquivo chamado <strong>app.js</strong> e executá-lo em um prompt, ao digitar o comando</span></span> <code>node app.js</code>.</p> +</div> + +<pre class="brush: js notranslate">var express = require('express'); +var app = express(); + +<strong>app.get('/', function(req, res) { + res.send('Olá Mundo!'); +});</strong> + +app.listen(3000, function() { + console.log('App de Exemplo escutando na porta 3000!'); +}); +</pre> + +<p>As duas primeiras linhas <code>require()</code> importam o módulo Express e criam uma aplicação <a href="https://expressjs.com/en/4x/api.html#app">Express</a>. Esse objeto (tradicionalmente nomeado de <code>app</code>), tem métodos de roteamento de requisições HTTP, configurações de middleware, renderização de views HTML, registro de engines de templates e <span id="result_box" lang="pt"><span>modificação das <a href="https://expressjs.com/en/4x/api.html#app.settings.table">configurações</a> que controlam como o aplicativo se comporta (por exemplo, o modo de ambiente, se as definições de rota são sensíveis a maiúsculas e minúsculas, etc).</span></span></p> + +<p><span id="result_box" lang="pt"><span>A parte do meio do código (as três linhas que começam com </span></span><code>app.get</code><span lang="pt"><span>) mostra uma definição de rota.</span> <span>O método </span></span><code>app.get()</code><span lang="pt"><span> especifica uma função de retorno de chamada que será invocada sempre que exista uma solicitação HTTP </span></span><code>GET</code><span lang="pt"><span> com um caminho (</span></span><code>'/'</code><span lang="pt"><span>) relativo à raiz do site.</span> <span>A função de retorno de chamada requer uma solicitação e um objeto de resposta como argumentos, e simplesmente chama </span></span><code><a href="https://expressjs.com/en/4x/api.html#res.send">send()</a></code><span lang="pt"><span> na resposta para retornar a string "Olá Mundo!"</span></span></p> + +<p><span id="result_box" lang="pt"><span>O bloco final inicia o servidor na porta '3000' e imprime um comentário de log no console.</span> <span>Com o servidor em execução, você pode acessar o </span></span><code>localhost:3000</code><span lang="pt"><span> em seu navegador para ver o exemplo de resposta retornado.</span></span></p> + +<h3 id="Importando_e_criando_módulos">Importando e criando módulos</h3> + +<p><span id="result_box" lang="pt"><span>Um módulo é uma biblioteca/arquivo de JavaScript que você pode importar para outro código usando a função </span></span><code>require()</code><span lang="pt"><span> do Node.</span> <span>Express por si é um módulo, assim como as bibliotecas de middleware e banco de dados que usamos em nossos aplicativos Express.</span></span></p> + +<p><span lang="pt"><span>O código abaixo mostra como importamos um módulo por nome, usando o quadro Express como um exemplo.</span> <span>Primeiro invocamos a função </span></span><code style="font-style: normal; font-weight: normal;">require()</code><span lang="pt"><span>, especificando o nome do módulo como uma string </span></span>(<code>'express'</code>), <span lang="pt"><span>e chamando o objeto retornado para criar um </span></span><a href="https://expressjs.com/en/4x/api.html#app">aplicativo Express</a><span lang="pt"><span>.</span> <span>Podemos então acessar as propriedades e funções do objeto da aplicação.</span></span></p> + +<pre class="brush: js notranslate">var express = require('express'); +var app = express(); +</pre> + +<p>Você também pode criar seus próprios módulos para serem importados da mesma maneira.</p> + +<div class="note"> +<p><strong>Dica:</strong> Você vai <em><strong>querer</strong></em> criar seus próprios módulos <span id="result_box" lang="pt"><span>porque isso permite que você organize seu código em peças gerenciáveis - um aplicativo monolítico (de arquivo único) é difícil de entender e manter.</span> <span>O uso de módulos também ajuda você a gerenciar o namespace, pois somente as variáveis que você exporta explicitamente são importadas quando você usa um módulo.</span></span></p> +</div> + +<p>Para tornar os objetos disponíveis fora do módulo, você precisa apenas atribuí-los ao objeto <code>exports</code>. Por Exemplo, o módulo <strong>square.js</strong> abaixo é um arquivo que exporta os métodos <code>area()</code> e <code>perimeter()</code>:</p> + +<pre class="brush: js notranslate">exports.area = function(width) { return width * width; }; +exports.perimeter = function(width) { return 4 * width; }; +</pre> + +<p>Nós podemos importar este módulo usando <code>require()</code>. D<span class="short_text" id="result_box" lang="pt"><span>epois, conecte ao(s) método(s) exportado(s) como mostrado a seguir:</span></span></p> + +<pre class="brush: js notranslate">var square = require('./square'); // Chamamos o arquivo utilizando o require() +console.log('The area of a square with a width of 4 is ' + square.area(4));</pre> + +<div class="note"> +<p><strong>Nota:</strong> <span id="result_box" lang="pt"><span>Você também pode especificar um caminho absoluto para o módulo (ou um nome, como fizemos inicialmente).</span></span></p> +</div> + +<p><span id="result_box" lang="pt"><span>Se você deseja exportar um objeto completo em uma atribuição, em vez de criar uma propriedade de cada vez, atribua ao module.exports como mostrado abaixo (você também pode fazer isso para tornar a raiz do objeto exporter um construtor ou outra função)</span><span>:</span></span></p> + +<pre class="brush: js notranslate">module.exports = { + area: function(width) { + return width * width; + }, + + perimeter: function(width) { + return 4 * width; + } +}; +</pre> + +<p>Para muitas outras informações sobre módulos veja <a href="https://nodejs.org/api/modules.html#modules_modules">Módulos</a> (Node API docs).</p> + +<h3 id="Usando_APIs_assíncronas">Usando APIs assíncronas</h3> + +<p>O código JavaScript frequentemente usa APIs assíncronas em vez de síncronas para operações que podem levar algum tempo para serem concluídas. <span id="result_box" lang="pt"><span>Uma API síncrona é aquela em que cada operação deve ser concluída antes que a próxima operação seja iniciada.</span> <span>Por exemplo, as seguintes funções de log são síncronas e imprimirão o texto no console em ordem (Primeiro, Segundo).</span></span></p> + +<pre class="brush: js notranslate">console.log('Primeiro'); +console.log('Segundo');</pre> + +<div id="gt-res-content"> +<div class="trans-verified-button-small" dir="ltr" id="gt-res-dir-ctr"><span id="result_box" lang="pt"><span>Em contrapartida, uma API assíncrona é aquela em que a API iniciará uma operação e retornará imediatamente (antes da conclusão da operação).</span> <span>Assim que a operação terminar, a API usará algum mecanismo para executar operações adicionais.</span> <span>Por exemplo, o código abaixo imprimirá "Segundo, Primeiro". Isso porque, mesmo que o método </span></span><code>setTimeout()</code><span lang="pt"><span> seja chamado primeiro e retornae imediatamente, a operação precisa de três segundos para finalizar.</span></span></div> + +<div class="trans-verified-button-small" dir="ltr"></div> +</div> + +<pre class="brush: js notranslate">setTimeout(function() { + console.log('Primeiro'); + }, 3000); +console.log('Segundo'); +</pre> + +<p><span id="result_box" lang="pt"><span>O uso de APIs assíncronas não bloqueadoras é ainda mais importante no Node do que no navegador, pois o Node é um ambiente de execução orientado por evento único (single threaded).</span> <span>"Single threaded" significa que todos os pedidos para o servidor são executados no mesmo tópico (em vez de serem gerados em processos separados).</span> <span>Esse modelo é extremamente eficiente em termos de velocidade e recursos do servidor, mas isso significa que, se qualquer uma das suas funções chamar métodos síncronos que demoram muito para completar, eles bloquearão não apenas a solicitação atual, mas todas as outras solicitações serão tratadas por</span> <span>sua aplicação web.</span></span></p> + +<p><span id="result_box" lang="pt"><span>Há várias maneiras de uma API assíncrona notificar para a aplicação que alguma função chegou ao fim.</span> <span>A maneira mais comum é registrar uma função de retorno de chamada quando você invoca a API assíncrona, que será chamada de volta quando a operação for concluída.</span> <span>Usamos essa abordagem acima.</span></span></p> + +<div class="note"> +<p><strong>Dica:</strong> O uso de callbacks pode ser bastante "bagunçado" se você tiver uma sequência de operações assíncronas dependentes que devem ser executadas em ordem, porque isto resulta em multiplo níveis de callbacks aninhados. Este problema é comumente conhecido como "inferno de callback" ou "código hadouken". Pode-se reduzir o problema ao adotar boas práticas de programação (veja <a href="http://callbackhell.com/">http://callbackhell.com/</a>), utilizar um módulo como <a href="https://www.npmjs.com/package/async">async</a>, <span class="short_text" id="result_box" lang="pt"><span>ou mesmo adotar recursos do ES6, como</span></span> <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a>.</p> +</div> + +<div class="note"> +<p><strong>Dica:</strong> <span id="result_box" lang="pt"><span>Uma convenção comum para Node e Express é usar as devoluções de retorno de erro.</span> <span>Nesta convenção, o primeiro valor em suas funções de retorno de chamada é um valor de erro, enquanto os argumentos subseqüentes contêm dados de sucesso.</span></span> <span id="result_box" lang="pt"><span>Há uma boa explicação de por que essa abordagem é útil neste blog</span></span>: <a href="http://fredkschott.com/post/2014/03/understanding-error-first-callbacks-in-node-js">The Node.js Way - Understanding Error-First Callbacks</a> (fredkschott.com).</p> +</div> + +<h3 id="Criando_manipuladores_de_rotas"><span class="short_text" id="result_box" lang="pt"><span>Criando manipuladores de rotas</span></span></h3> + +<p>No nosso <em>Olá Mundo</em> em Express (veja acima), nós definimos uma (callback) função manipuladora de rota para requisição <code>GET</code> HTTP para a raiz do site (<code>'/'</code>).</p> + +<pre class="brush: js notranslate">app.<strong>get</strong>('/', function(req, res) { + res.send('Olá Mundo'); +}); +</pre> + +<p><span id="result_box" lang="pt"><span>A função de retorno de chamada requer uma solicitação e um objeto de resposta como argumento.</span> <span>Neste caso, o método simplesmente chama </span></span><code><a href="https://expressjs.com/en/4x/api.html#res.send">send()</a></code><span lang="pt"><span> na resposta para retornar a string "Olá Mundo!"</span> <span><a href="https://expressjs.com/en/guide/routing.html#response-methods">Há uma série de outros métodos de resposta</a> para encerrar o ciclo de solicitação / resposta, por exemplo, você poderia chamar </span></span><code><a href="https://expressjs.com/en/4x/api.html#res.json">res.json()</a></code><span lang="pt"><span> para enviar uma resposta JSON ou </span></span><code><a href="https://expressjs.com/en/4x/api.html#res.sendFile">res.sendFile()</a></code> <span lang="pt"><span> para enviar um arquivo.</span></span></p> + +<div class="note"> +<p><strong>Dica JavaScript:</strong> <span id="result_box" lang="pt"><span>Você pode usar qualquer argumento que você gosta nas funções de retorno de chamada.</span> <span>Quando o retorno de chamada é invocado, o primeiro argumento sempre será o pedido e o segundo sempre será a resposta.</span> <span>Faz sentido nomeá-los de tal forma que você possa identificar o objeto que você está trabalhando no corpo do retorno de chamada.</span></span></p> +</div> + +<p><span id="result_box" lang="pt"><span>O Express também fornece métodos para definir manipuladores de rotas para todas as outras requisições HTTP, que são usadas exatamente da mesma maneira: </span></span> <code>post()</code>, <code>put()</code>, <code>delete()</code>, <code>options()</code>, <code>trace()</code>, <code>copy()</code>, <code>lock()</code>, <code>mkcol()</code>, <code>move()</code>, <code>purge()</code>, <code>propfind()</code>, <code>proppatch()</code>, <code>unlock()</code>, <code>report()</code>, <code>mkactivity()</code>, <code>checkout()</code>, <code>merge()</code>, <code>m-</code><code>search()</code>, <code>notify()</code>, <code>subscribe()</code>, <code>unsubscribe()</code>, <code>patch()</code>, <code>search()</code>, e <code>connect()</code>.</p> + +<p><span id="result_box" lang="pt"><span>Há um método de roteamento especial, </span></span><code>app.all()</code><span lang="pt"><span>, que será chamado em resposta a qualquer método HTTP.</span> <span>É usado para carregar funções de middleware em um caminho específico para todos os métodos de solicitação.</span> <span>O exemplo a seguir (da documentação Express) mostra um manipulador que será executado para solicitações </span></span><code>/secret</code><span lang="pt"><span>, independentemente do verbo HTTP usado (desde que seja suportado pelo módulo http).</span></span></p> + +<pre class="brush: js notranslate">app.all('/secret', function(req, res, next) { + console.log('Acessando a sessão secreta...'); + next(); // passa o controle para o próximo manipulador +});</pre> + +<p><span id="result_box" lang="pt"><span>As rotas permitem combinar padrões de caracteres específicos em um URL e extrair alguns valores do URL e passá-los como parâmetros para o manipulador de rotas (como atributos do objeto de solicitação passado como parâmetro).</span></span></p> + +<p><span id="result_box" lang="pt"><span>Muitas vezes, é útil agrupar manipuladores de rotas para uma determinada parte de um site e acessá-los usando um prefixo de rota comum (por exemplo, um site com um Wiki pode ter todas as rotas relacionadas ao wiki em um arquivo e tê-los acessado com um prefixo de rota</span> <span>de / wiki /).</span> <span>Em Express, isso é alcançado usando o objeto </span></span><code><a href="http://expressjs.com/en/guide/routing.html#express-router">express.Router</a></code><span lang="pt"><span>.</span> <span>Por exemplo, podemos criar nossa rota wiki em um módulo chamado wiki.js e, em seguida, exportar o objeto </span></span><code>Router</code><span lang="pt"><span>, conforme mostrado abaixo:</span></span></p> + +<pre class="brush: js notranslate">// wiki.js - Rotas de Wiki + +var express = require('express'); +var router = express.Router(); + +// Home page route +router.get('/', function(req, res) { + res.send('Wiki home page'); +}); + +// About page route +router.get('/about', function(req, res) { + res.send('About this wiki'); +}); + +module.exports = router; +</pre> + +<div class="note"> +<p><strong>Nota:</strong> <span id="result_box" lang="pt"><span>Adicionar rotas ao objeto </span></span><code>Router</code><span lang="pt"><span> é como adicionar rotas ao objeto </span></span><code>app</code><span lang="pt"><span> (como mostrado anteriormente).</span></span></p> +</div> + +<p><span id="result_box" lang="pt"><span>Para usar o roteador em nosso arquivo de aplicativo principal, então, </span></span><code>require()</code><span lang="pt"><span> o módulo de rota (<strong>wiki.js</strong>) e depois </span></span><code>use()</code><span lang="pt"><span> no aplicativo Express para adicionar o Router ao caminho de gerenciamento de middleware.</span> <span>As duas rotas serão acessíveis a partir de </span></span><code style="font-style: normal; font-weight: normal;">/wiki/</code><span lang="pt"><span> e </span></span><code style="font-style: normal; font-weight: normal;">/wiki/about/</code><span lang="pt"><span>.</span></span></p> + +<pre class="brush: js notranslate">var wiki = require('./wiki.js'); +// ... +app.use('/wiki', wiki);</pre> + +<p><span id="result_box" lang="pt"><span>Vamos mostrar-lhe muito mais sobre trabalhar com rotas e, em particular, sobre o uso do </span></span><code>Router</code><span lang="pt"><span>, mais tarde, na seção vinculada <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Express_Nodejs/routes">Rotas e controladores</a>.</span></span></p> + +<h3 id="Usando_middleware">Usando middleware</h3> + +<p><span id="result_box" lang="pt"><span>O Middleware é usado extensivamente em aplicativos Express para que as tarefas ofereçam arquivos estáticos ao tratamento de erros, a comprensão de respostas HTTP.</span> <span>Enquanto as funções de rota terminam o ciclo de solicitação-resposta HTTP, retornando alguma resposta ao cliente HTTP, as funções de middleware normalmente executam alguma operação na solicitação ou resposta e, em seguida, ligue para a próxima função na "pilha", que pode ser mais um middleware ou uma rota</span> <span>manipuladora.</span> <span>A ordem em que o middleware é chamado depende do desenvolvedor do aplicativo.</span></span></p> + +<div class="note"> +<p><strong>Nota:</strong> <span id="result_box" lang="pt"><span>O middleware pode executar qualquer operação, executar qualquer código, fazer alterações no objeto de solicitação e resposta, e também pode encerrar o ciclo de solicitação-resposta.</span> <span>Se não terminar o ciclo, ele deve chamar o </span></span><code>next()</code><span lang="pt"><span> para passar o controle para a próxima função de middleware (ou a solicitação ficará pendurada).</span></span></p> +</div> + +<p><span id="result_box" lang="pt"><span>A maioria dos aplicativos usará middleware de terceiros para simplificar tarefas comuns de desenvolvimento web, como trabalhar com cookies, sessões, autenticação de usuários, acessar dados </span></span><code>POST</code><span lang="pt"><span> e JSON, log, etc. Você pode encontrar uma<a href="http://expressjs.com/en/resources/middleware.html"> lista de pacotes de middleware</a> mantidos pela equipe Express</span> <span>(que também inclui outros pacotes populares de terceiros).</span> <span>Outros pacotes Express estão disponíveis no gerenciador de pacotes do NPM.</span></span></p> + +<p><span id="result_box" lang="pt"><span>Para usar middleware de terceiros, primeiro você precisa instalá-lo em seu aplicativo usando NPM.</span> <span>Por exemplo, para instalar o logger </span></span><a href="http://expressjs.com/en/resources/middleware/morgan.html">morgan</a><span lang="pt"><span> HTTP, você faria isso:</span></span></p> + +<pre class="brush: bash notranslate"><code>$ npm install morgan +</code></pre> + +<p><span id="result_box" lang="pt"><span>Você pode então chamar </span></span><code>use()</code><span lang="pt"><span> no objeto do aplicativo Express para adicionar o middleware à pilha:</span></span></p> + +<pre class="brush: js notranslate">var express = require('express'); +<strong>var logger = require('morgan');</strong> +var app = express(); +<strong>app.use(logger('dev'));</strong> +...</pre> + +<div class="note"> +<p><strong>Nota:</strong> <span id="result_box" lang="pt"><span>O middleware e as funções de roteamento são chamadas na ordem em que são declaradas.</span> <span>Para alguns middleware, a ordem é importante (por exemplo, se o middleware de sessão depende do middleware de cookies, então o manipulador de cookies deve ser adicionado primeiro).</span> <span>É quase sempre o caso em que o middleware é chamado antes de definir rotas, ou seus manipuladores de rotas não terão acesso à funcionalidade adicionada pelo seu middleware.</span></span></p> +</div> + +<p><span id="result_box" lang="pt"><span>Você pode escrever suas próprias funções de middleware. É provável que você tenha que fazê-lo (somente para criar código de manipulação de erro).</span> <span>A única diferença entre uma função de middleware e um retorno de chamada de manipulador de rotas é que as funções de middleware têm um terceiro argumento </span></span><code>next</code><span lang="pt"><span>, que as funções de middleware devem chamar se não completam o ciclo de solicitação (quando a função de middleware é chamada, isso contém a próxima função</span> <span>que deve ser chamado).</span></span></p> + +<p><span id="result_box" lang="pt"><span>Você pode adicionar uma função de middleware à cadeia de processamento com </span></span><code>app.use()</code><span lang="pt"><span> ou </span></span><code>app.add()</code><span lang="pt"><span>, dependendo se você deseja aplicar o middleware a todas as respostas ou a respostas com um verbo HTTP específico (</span></span><code>GET</code>, <code>POST</code><span lang="pt"><span>, etc.</span> <span>).</span> <span>Você especifica rotas o mesmo em ambos os casos, embora a rota seja opcional ao chamar </span></span><strong>app.use()</strong><span lang="pt"><span>.</span></span></p> + +<p><span id="result_box" lang="pt"><span>O exemplo abaixo mostra como você pode adicionar a função middleware usando ambos os métodos e com/sem rota.</span></span></p> + +<pre class="brush: js notranslate">var express = require('express'); +var app = express(); + +// Um exemplo de função middleware +var a_middleware_function = function(req, res, <em>next</em>) { + // ... Executa alguma operação + next(); // next() Chama o próximo middleware ou função de rotas +} + +// Função adicionada com use() para todas rotas e requisições +app.use(a_middleware_function); + +// Função adicionada com use() para uma rota específica +app.use('/someroute', a_middleware_function); + +// função middleware adicionado para uma rota e requisição específica +app.get('/', a_middleware_function); + +app.listen(3000);</pre> + +<div class="note"> +<p><strong>Dica JavaScript:</strong> <span id="result_box" lang="pt"><span>Acima, declaramos a função de middleware separadamente e, em seguida, configuramos como retorno de chamada.</span> <span>Na nossa função anterior do operador de rotas, declaramos a função de retorno de chamada quando foi utilizada.</span> <span>Em JavaScript, ambas abordagens são válidas.</span></span></p> +</div> + +<p><span id="result_box" lang="pt"><span>A documentação Express possui uma documentação excelente sobre como usar e escrever o middleware Express.</span></span></p> + +<h3 id="Servindo_arquivos_estáticos">Servindo arquivos estáticos</h3> + +<p><span id="result_box" lang="pt"><span>Você pode usar o middleware </span></span><a href="http://expressjs.com/en/4x/api.html#express.static">express.static</a><span lang="pt"><span> para servir arquivos estáticos, incluindo suas imagens, CSS e JavaScript (</span></span><code>static()</code><span lang="pt"><span> é a única função de middleware que é realmente parte do Express).</span> <span>Por exemplo, você usaria a linha abaixo para exibir imagens, arquivos CSS e arquivos JavaScript de um diretório chamado 'public' no mesmo nível onde você chama o nó:</span></span></p> + +<pre class="brush: js notranslate">app.use(express.static('public')); +</pre> + +<p><span id="result_box" lang="pt"><span>Todos os arquivos no diretório público são atendidos adicionando o nome do arquivo (relativo ao diretório "público" base) ao URL base.</span> <span>Então, por exemplo:</span></span></p> + +<pre class="notranslate"><code>http://localhost:3000/images/dog.jpg +http://localhost:3000/css/style.css +http://localhost:3000/js/app.js +http://localhost:3000/about.html +</code></pre> + +<p><span id="result_box" lang="pt"><span>Você pode chamar </span></span><code>static()</code><span lang="pt"><span> várias vezes para atender vários diretórios.</span> <span>Se um arquivo não puder ser encontrado por uma função de middleware, ele simplesmente será transmitido ao middleware subsequente (a ordem em que o middleware é chamado é baseada em sua ordem de declaração).</span></span></p> + +<pre class="brush: js notranslate">app.use(express.static('public')); +app.use(express.static('media')); +</pre> + +<p><span id="result_box" lang="pt"><span>Você também pode criar um prefixo virtual para seus URL estáticos, em vez de ter os arquivos adicionados ao URL base.</span> <span>Por exemplo, aqui <a href="http://expressjs.com/en/4x/api.html#app.use">especificamos um caminho de montagem</a> para que os arquivos sejam carregados com o prefixo "/media":</span></span></p> + +<pre class="brush: js notranslate">app.use('/media', express.static('public')); +</pre> + +<p><span id="result_box" lang="pt"><span>Agora, você pode carregar os arquivos que estão no diretório </span></span><code>public</code><span lang="pt"><span> a partir do prefixo de caminho </span></span><code>/media</code><span lang="pt"><span>.</span></span></p> + +<pre class="notranslate"><code>http://localhost:3000/media/images/dog.jpg +http://localhost:3000/media/video/cat.mp4 +http://localhost:3000/media/cry.mp3</code> +</pre> + +<p><span id="result_box" lang="pt"><span>Para obter mais informações, consulte <a href="Serving static files in Express">Servindo arquivos estáticos no Express</a>.</span></span></p> + +<h3 id="Erros_de_manipulação">Erros de manipulação</h3> + +<p><span id="result_box" lang="pt"><span>Os erros são tratados por uma ou mais funções de middleware especiais que possuem quatro argumentos, em vez dos três habituais: </span></span><code>(err, req, res, next)</code><span lang="pt"><span>.</span> <span>Por exemplo:</span></span></p> + +<pre class="brush: js notranslate">app.use(function(err, req, res, next) { + console.error(err.stack); + res.status(500).send('Something broke!'); +}); +</pre> + +<p><span id="result_box" lang="pt"><span>Isso pode retornar qualquer conteúdo exigido, mas deve ser chamado depois de todas as outras chamadas </span></span><code>app.use()</code><span lang="pt"><span> e rotas para que sejam o último middleware no processo de solicitação de pedidos!</span></span></p> + +<p><span id="result_box" lang="pt"><span>Express vem com um manipulador de erros embutido, que cuida de todos os erros que podem ser encontrados no aplicativo.</span> <span>Essa função de middleware de gerenciamento de erros padrão é adicionada no final da pilha de funções do middleware.</span> <span>Se você passar um erro para </span></span><code>next()</code><span lang="pt"><span> e você não lidar com isso em um manipulador de erro, ele será tratado pelo manipulador de erros incorporado;</span> <span>o erro será gravado no cliente com o rastreamento da pilha.</span></span></p> + +<div class="note"> +<p><strong>Nota:</strong> <span id="result_box" lang="pt"><span>O rastreamento da pilha não está incluído no ambiente de produção.</span> <span>Para executá-lo no modo de produção, você precisa configurar a variável de ambiente </span></span><code>NODE_ENV</code><span lang="pt"><span> para </span></span><code>'production'</code>.</p> +</div> + +<div class="note"> +<p><strong>Nota:</strong> <span id="result_box" lang="pt"><span>HTTP404 e outros códigos de status de "erro" não são tratados como erros.</span> <span>Se você quiser lidar com isso, você pode adicionar uma função de middleware para fazê-lo.</span> <span>Para mais informações, consulte as </span></span><a href="http://expressjs.com/en/starter/faq.html#how-do-i-handle-404-responses">FAQ</a>.</p> +</div> + +<p><span id="result_box" lang="pt"><span>Para obter mais informações, consulte </span></span><a href="http://expressjs.com/en/guide/error-handling.html">Gerenciamento de erros</a><span lang="pt"><span> (Express docs).</span></span></p> + +<h3 id="Usando_Banco_de_Dados">Usando Banco de Dados</h3> + +<p><span id="result_box" lang="pt"><span>Aplicativos Express podem usar qualquer mecanismo de banco de dados suportado pelo Node (o Express em si não define nenhum comportamento/requisitos adicionais específicos para gerenciamento de banco de dados).</span> <span>Existem muitas opções, incluindo PostgreSQL, MySQL, Redis, SQLite, MongoDB, etc.</span></span></p> + +<p><span id="result_box" lang="pt"><span>Para usá-los, você deve primeiro instalar o driver do banco de dados usando NPM.</span> <span>Por exemplo, para instalar o driver para o popular NoSQL MongoDB você usaria o comando:</span></span></p> + +<pre class="brush: bash notranslate"><code>$ npm install mongodb +</code></pre> + +<p><span id="result_box" lang="pt"><span>O próprio banco de dados pode ser instalado localmente ou em um servidor em nuvem.</span> <span>No seu código Express, você precisa do driver, conecte-se ao banco de dados e execute as operações criar, ler, atualizar e excluir (CRUD).</span> <span>O exemplo abaixo (da documentação Express) mostra como você pode encontrar registros de "mamíferos" usando MongoDB.</span></span></p> + +<pre class="brush: js notranslate">var MongoClient = require('mongodb').MongoClient; + +MongoClient.connect('mongodb://localhost:27017/animals', function(err, db) { + if (err) throw err; + + db.collection('mammals').find().toArray(function (err, result) { + if (err) throw err; + + console.log(result); + }); +});</pre> + +<p><span id="result_box" lang="pt"><span>Outra abordagem popular é acessar seu banco de dados indiretamente, através de um Object Relational Mapper ("ORM").</span> <span>Nesta abordagem, você define seus dados como "objetos" ou "modelos" e o ORM mapeia estes para o formato de banco de dados subjacente.</span> <span>Esta abordagem tem o benefício de que, como desenvolvedor, você pode continuar a pensar em termos de objetos JavaScript, em vez de semântica de banco de dados, e que existe um local óbvio para realizar a validação e verificação de dados recebidos.</span> <span>Falaremos mais sobre bancos de dados em um artigo posterior.</span></span></p> + +<p><span id="result_box" lang="pt"><span>Para obter mais informações, consulte </span></span><a href="https://expressjs.com/en/guide/database-integration.html">integração com banco de dados </a><span lang="pt"><span>(documentos express).</span></span></p> + +<h3 id="Renderizando_dados_views">Renderizando dados (views)</h3> + +<p><span id="result_box" lang="pt"><span>Os mecanismos de modelo (referidos como "view engines" por Express) permitem que você especifique a estrutura de um documento de saída em um modelo, usando marcadores de posição para os dados que serão preenchidos quando uma página for gerada.</span> <span>Os modelos geralmente são usados para criar HTML, mas também podem criar outros tipos de documentos.</span> <span>Express tem suporte para uma série de <a href="https://github.com/expressjs/express/wiki#template-engines">mecanismos de modelos</a>, e há uma comparação útil dos motores mais populares aqui: </span></span><a href="https://strongloop.com/strongblog/compare-javascript-templates-jade-mustache-dust/">Comparing JavaScript Templating Engines: Jade, Mustache, Dust and More</a>.</p> + +<p><span id="result_box" lang="pt"><span>No seu código de configurações do aplicativo você configurou o mecanismo do modelo para usar e o local onde Express deve procurar modelos usando as configurações 'visualizações' e 'visualizar mecanismos', conforme mostrado abaixo (você também terá que instalar o pacote que contém a biblioteca do modelo também</span> <span>!)</span></span></p> + +<pre class="brush: js notranslate">var express = require('express'); +var app = express(); + +// <span class="short_text" id="result_box" lang="pt"><span>Definir o diretório para conter os modelos ('views')</span></span> +app.set('views', path.join(__dirname, 'views')); + +<span id="result_box" lang="pt"><span>// Definir o motor de visualização para usar, neste caso 'some_template_engine_name'</span></span> +app.set('view engine', 'some_template_engine_name'); +</pre> + +<p><span id="result_box" lang="pt"><span>A aparência do modelo dependerá do mecanismo que você usa.</span> <span>Supondo que você tenha um arquivo de modelo chamado "índice. <Template_extension>" que contenha espaços reservados para variáveis de dados denominadas 'título' e 'mensagem', você chamaria </span></span><code><a href="http://expressjs.com/en/4x/api.html#res.render">Response.render()</a></code><span lang="pt"><span> em uma função de roteador de rotas para criar e enviar a resposta HTML</span> <span>:</span></span></p> + +<pre class="brush: js notranslate">app.get('/', function(req, res) { + res.render('index', { title: 'About dogs', message: 'Dogs rock!' }); +});</pre> + +<p><span id="result_box" lang="pt"><span>Para obter mais informações, consulte </span></span><a href="http://expressjs.com/en/guide/using-template-engines.html">usando motores de modelo com Express</a><span lang="pt"><span> (Express docs).</span></span></p> + +<h3 id="Estrutura_de_Arquivos">Estrutura de Arquivos</h3> + +<p><span id="result_box" lang="pt"><span>Express não faz suposições em termos de estrutura ou quais os componentes que você usa.</span> <span>Rotas, visualizações, arquivos estáticos e outra lógica específica da aplicação podem viver em qualquer número de arquivos com qualquer estrutura de diretório.</span> <span>Embora seja perfeitamente possível ter todo o aplicativo Express em um único arquivo, geralmente faz sentido dividir seu aplicativo em arquivos com base em função (por exemplo, gerenciamento de contas, blogs, fóruns de discussão) e domínio de problema arquitetônico (por exemplo, modelo, exibição ou controlador se</span> <span>você está usando uma </span></span><a href="/en-US/docs/Web/Apps/Fundamentals/Modern_web_app_architecture/MVC_architecture">arquitetura MVC</a><span lang="pt"><span>).</span></span></p> + +<p><span id="result_box" lang="pt"><span>Em um tópico posterior, usaremos o Express Application Generator, que cria um esqueleto de aplicativo modular que podemos estender facilmente para criar aplicativos da web.</span></span></p> + +<ul> +</ul> + +<h2 id="Sumário">Sumário</h2> + +<p><span id="result_box" lang="pt"><span>Parabéns, você completou o primeiro passo em sua viagem Express/Node!</span> <span>Agora você deve entender os principais benefícios do Express e Node, e aproximadamente o que as principais partes de um aplicativo Express podem ser (rotas, middleware, tratamento de erros e código de modelo).</span> <span>Por ser um framework não opinativo, o Express permite que você defina a maneira como essas partes e essas bibliotecas são integradas.</span></span></p> + +<p><span style="">Claro que Express é deliberadamente uma estrutura de aplicativos web muito leve, tanto seu benefício e potencial vem de bibliotecas e recursos de terceiros.</span><span style=""> </span><span style="">Examinaremos essa questão com mais detalhes nos próximos artigos.</span><span style=""> </span><span style="">No artigo a seguir, vamos analisar a criação de um ambiente de desenvolvimento de Node, para que você possa começar a ver algum código Express em ação.</span></p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://medium.com/@ramsunvtech/manage-multiple-node-versions-e3245d5ede44">Venkat.R - Manage Multiple Node versions</a></li> + <li><a href="https://nodejs.org/api/modules.html#modules_modules">Modules</a> (Node API docs)</li> + <li><a href="https://expressjs.com/">Express</a> (home page)</li> + <li><a href="http://expressjs.com/en/starter/basic-routing.html">Basic routing</a> (Express docs)</li> + <li><a href="http://expressjs.com/en/guide/routing.html">Routing guide</a> (Express docs)</li> + <li><a href="http://expressjs.com/en/guide/using-template-engines.html">Using template engines with Express</a> (Express docs)</li> + <li><a href="https://expressjs.com/en/guide/using-middleware.html">Using middleware</a> (Express docs)</li> + <li><a href="http://expressjs.com/en/guide/writing-middleware.html">Writing middleware for use in Express apps</a> (Express docs)</li> + <li><a href="https://expressjs.com/en/guide/database-integration.html">Database integration</a> (Express docs)</li> + <li><a href="Serving static files in Express">Serving static files in Express</a> (Express docs)</li> + <li><a href="http://expressjs.com/en/guide/error-handling.html">Error handling</a> (Express docs)</li> +</ul> + +<div>{{NextMenu("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs")}}</div> + +<h2 id="Próximos_módulos">Próximos módulos</h2> + +<ul> + <li><a href="/pt-BR/docs/Learn/Server-side/Express_Nodejs/Introduction">Introdução Express/Node </a>- Módulo Atual</li> + <li><a href="/pt-BR/docs/Learn/Server-side/Express_Nodejs/development_environment">Configurando um ambiente de desenvolvimento Node (Express)</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: C</a>riando um esqueleto de website</li> + <li><a href="/pt-BR/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Utilizando Banco de Dados (com Mongoose)</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: R</a>otas e Controladores</li> + <li><a href="/pt-BR/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li> + <li><a href="/pt-BR/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: </a>Trabalhando com formulários</li> + <li><a href="/pt-BR/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/express_nodejs/mongoose/index.html b/files/pt-br/learn/server-side/express_nodejs/mongoose/index.html new file mode 100644 index 0000000000..8d733ec077 --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/mongoose/index.html @@ -0,0 +1,838 @@ +--- +title: 'Tutorial Express Parte 3: Usando um banco de dados (com Mongoose)' +slug: Learn/Server-side/Express_Nodejs/mongoose +translation_of: Learn/Server-side/Express_Nodejs/mongoose +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs")}}</div> + +<p class="summary">Este artigo introduz brevemente bancos de dados e como usá-los com aplicativos Node/Express. Depois demonstra como podemos usar o <a href="http://mongoosejs.com/">Mongoose</a> para prover acesso ao banco de dados para o website <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">LocalLibrary</a>. Explica como object schema e modelos são declarados, os principais tipos de campos e validações básicas. Também demonstra brevemente algumas das muitas maneiras em que se pode acessar os dados do modelo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Tutorial Express Parte 2: Criando o esqueleto de um website</a></td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ser capaz de projetar e criar seus próprios modelos usando Mongoose.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_geral">Visão geral</h2> + +<p>A equipe da biblioteca usará o site da Biblioteca Local para gardar informações sobre livros e empréstimos, enquanto os membros da biblioteca irão utilizá-lo para navegar e pesquisar por livros, descobrir se há alguma cópia disponível, e então reservar ou emprestar eles. Para armazenar e obter informações eficientemente, nós guardaremos elas em um <em>banco de dados</em>.</p> + +<p>Aplicativos <em>Express</em> podem usar muitos bancos de dados diferentes, e existem várias abordagens que você pode usar para fazer operações de Criar, Ler, Atualizar e Apagar (CRUD, na sigla em inglês). Esse tutorial provê uma curta visão geral de algumas das opções disponíveis e então irá mostrar em detalhes os mecanismos particulares selecionados.</p> + +<h3 id="Quais_bancos_de_dados_eu_posso_usar">Quais bancos de dados eu posso usar?</h3> + +<p>Aplicativos <em>Express</em> podem usar qualquer banco de dados suportado pelo <em>Node </em>(O <em>Express</em> por si só não define nenhum requerimento ou comportamento adicional específico para gerenciamento de bancos de dados). Há <a href="https://expressjs.com/en/guide/database-integration.html">muitas<em> </em>opções populares</a>, incluindo PostgreSQL, MySQL, Redis, SQLite, and MongoDB.</p> + +<p>Quando escolher um banco de dados, você deveria considerar coisas como o tempo-para-produtividade/curva de aprendizado, performance, facilidade de replicação/backup, custo, suporte da comunidade, etc. Enquanto não existe o "melhor" banco de dados, praticamente qualquer uma das soluções populares devem ser mais do que aceitáveis para um site de tamanho pequeno a médio como o da nossa Biblioteca Local.</p> + +<p>Para mais informações sobre as opções veja <a href="https://expressjs.com/en/guide/database-integration.html">Integração com o Banco de dados</a> (documentação do Express).</p> + +<h3 id="Qual_o_melhor_jeito_de_interagir_com_um_banco_de_dados">Qual o melhor jeito de interagir com um banco de dados?</h3> + +<p>There are two approaches for interacting with a database: </p> + +<ul> + <li>Using the databases' native query language (e.g. SQL)</li> + <li>Using an Object Data Model ("ODM") / Object Relational Model ("ORM"). An ODM/ORM represents the website's data as JavaScript objects, which are then mapped to the underlying database. Some ORMs are tied to a specific database, while others provide a database-agnostic backend.</li> +</ul> + +<p>The very best <em>performance</em> can be gained by using SQL, or whatever query language is supported by the database. ODM's are often slower because they use translation code to map between objects and the database format, which may not use the most efficient database queries (this is particularly true if the ODM supports different database backends, and must make greater compromises in terms of what database features are supported).</p> + +<p>The benefit of using an ORM is that programmers can continue to think in terms of JavaScript objects rather than database semantics — this is particularly true if you need to work with different databases (on either the same or different websites). They also provide an obvious place to perform validation and checking of data.</p> + +<div class="note"> +<p><strong>Tip:</strong> Using ODM/ORMs often results in lower costs for development and maintenance! Unless you're very familiar with the native query language or performance is paramount, you should strongly consider using an ODM.</p> +</div> + +<h3 id="Qual_ORMODM_eu_devo_usar">Qual ORM/ODM eu devo usar?</h3> + +<p>There are many ODM/ORM solutions available on the NPM package manager site (check out the <a href="https://www.npmjs.com/browse/keyword/odm">odm</a> and <a href="https://www.npmjs.com/browse/keyword/orm">orm</a> tags for a subset!).</p> + +<p>A few solutions that were popular at the time of writing are:</p> + +<ul> + <li><a href="https://www.npmjs.com/package/mongoose">Mongoose</a>: Mongoose is a <a href="https://www.mongodb.org/">MongoDB</a> object modeling tool designed to work in an asynchronous environment.</li> + <li><a href="https://www.npmjs.com/package/waterline">Waterline</a>: An ORM extracted from the Express-based <a href="http://sailsjs.com/">Sails</a> web framework. It provides a uniform API for accessing numerous different databases, including Redis, MySQL, LDAP, MongoDB, and Postgres.</li> + <li><a href="https://www.npmjs.com/package/bookshelf">Bookshelf</a>: Features both promise-based and traditional callback interfaces, providing transaction support, eager/nested-eager relation loading, polymorphic associations, and support for one-to-one, one-to-many, and many-to-many relations. Works with PostgreSQL, MySQL, and SQLite3.</li> + <li><a href="https://www.npmjs.com/package/objection">Objection</a>: Makes it as easy as possible to use the full power of SQL and the underlying database engine (supports SQLite3, Postgres, and MySQL).</li> + <li><a href="https://www.npmjs.com/package/sequelize">Sequelize</a> is a promise-based ORM for Node.js and io.js. It supports the dialects PostgreSQL, MySQL, MariaDB, SQLite, and MSSQL and features solid transaction support, relations, read replication and more.</li> + <li><a href="https://node-orm.readthedocs.io/en/latest/">Node ORM2</a> is an Object Relationship Manager for NodeJS. It supports MySQL, SQLite, and Progress, helping to work with the database using an object-oriented approach.</li> + <li> + <p><a href="http://1602.github.io/jugglingdb/" rel="nofollow">JugglingDB</a> is cross-DB ORM for NodeJS, providing a common interface to access most popular database formats. Currently supporting MySQL, SQLite3, Postgres, MongoDB, Redis and js-memory-storage (self-written engine for test-usage only).</p> + </li> +</ul> + +<p>As a general rule, you should consider both the features provided and the "community activity" (downloads, contributions, bug reports, quality of documentation, etc.) when selecting a solution. At the time of writing Mongoose is by far the most popular ODM, and is a reasonable choice if you're using MongoDB for your database.</p> + +<h3 id="Usando_Mongoose_e_MongoDb_para_a_LocalLibrary">Usando Mongoose e MongoDb para a LocalLibrary</h3> + +<p>Para o exemplo da <em>Local Library</em> (e para o resto do tópico) nós iremos usar o <a href="https://www.npmjs.com/package/mongoose">Mongoose ODM</a> para acessar os dados da nossa aplicação. Mongoose funciona como uma interface para o <a href="https://www.mongodb.com/what-is-mongodb">MongoDB</a>, um banco de dados de código aberto e <a href="https://en.wikipedia.org/wiki/NoSQL">NoSQL</a> que usa um modelo de dados orientado a documentos. Uma “coleção” de “documentos”, em uma base de dados do MongoDB, <a href="https://docs.mongodb.com/manual/core/databases-and-collections/#collections">é semelhante</a> a uma “tabela” com “linhas” em uma base dados relacional.</p> + +<p>Esse ODM (Object Data Model) e banco de dados combinados são extremamente populares na comunidade do Node, particularmente porque os documentos armazenados e os métodos de consultas se parecem muito com JSON, que consequentemente são muito familiares aos desenvolvedores JavaScript.</p> + +<div class="note"> +<p><strong>Dica:</strong> Você não precisa conhecer o MongoDB antes de usar o Mongoose, apesar de que partes da <a href="http://mongoosejs.com/docs/guide.html">documentação do Mongoose</a> <em>são mais fáceis</em> de entender se você já está familiarizado com o MongoDB.</p> +</div> + +<p>O resto desse tutorial mostra como definir e acessar os modelos e schemas no Mongoose para o nosso website da <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">LocalLibrary</a>.</p> + +<h2 id="Projetando_os_modelos_da_aplicação_LocalLibrary">Projetando os modelos da aplicação LocalLibrary</h2> + + + +<p>Antes de pularmos de cabeça na codificação dos modelos, vale a pena pensar uns minutinhos sobre quais dados precisamos armazenar e o relacionamento entre diferentes objetos.</p> + +<p>Nós sabemos que precisamos armazenar informações sobre livros(título, resumo, autor, gênero, ISBN) e que nós podemos ter múltiplas cópias disponíveis (com ids globlamente únicos, status de disponibilidade, etc.). Nós também podemos armazenar mais informações sobre o autor do que apenas seu nome, e podem haver múltiplos autores com o mesmo nome ou um bem parecido. Nós queremos também ser capazes de ordernar informações baseadas no título do livro, autor, gênero e categoria.</p> + +<p>Ao estruturar seus modelos é sempre bom separar modelos para cada "objeto"(um grupo de informações relacionadas). Neste caso, os nossos objetos mais evidentes são os de livros (books), pedidos de livros (book instances), e autores (authors).</p> + +<p>Você pode usar também modelos para representar opções de listagens(por exemplo um menu drop-down com escolhas para o usuário), ao invés de implementar as escolhas diretamente em linhas de códigos dentro do seu website — isso é recomendado quando as escolhas não são conhecidas durante o desenvolvimento ou quando elas podem mudar. O candidato mais evidente para um modelo desse tipo é o de gênero (genre) de livros (por exemplo Ficção Ciêntífica, Poesia Clássica, etc.).</p> + +<p>Uma vez que nós decidimos nossos modelos e os seus atributos, nós precisamos pensar sobre o relacionamento entre eles.</p> + +<p>Com isso em mente, o diagrama UML a seguir mostra os modelos (as caixas) que iremos definir na nossa aplicação. Como discutido acima, criamos modelos para os livros ( com informações genéricas sobre o livro), pedidos de livros(status de cópias físicas de um livro específico disponíveis no sistema), e autor. E também decidimos ter um modelo para o gênero então esses valores poderão ser criados dinamicamente na aplicação. Outra decisão foi de não criarmos um modelo para <code>BookInstance:status </code> — nós deixaremos diretamente no código os valores aceitáveis para o status de pedidos porque nós não esperamos que eles mudem. Dentro de cada caixa, você pode ver o nome do modelo, o nome dos atributos e seus tipos, e também os métodos e seu tipo de retorno.</p> + +<p>O diagrama também mostra o relacionamento entre modelos, incluindo sua cardinalidade. A cardinalidade são os números no diagrama próximos das linhas que conectam as caixas mostrando os números (máximo e mínimo) de cada modelo que pode estar presente no relacionamento. Por exemplo, as linhas que conectam as caixas <code>Book</code>e <code>Genre</code> mostram que as duas coleções têm uma relação. Os números próximos ao modelo <code>Book</code> mostra que Genre pode ter zero ou mais Book (quantos você quiser), enquanto no outro fim da linha de conexão próximo a <code>Genre </code> mostra que ele pode ter zero ou mais livros associados.</p> + +<div class="note"> +<p><strong>Nota</strong>: Assim como discutido abaixo em <a href="#related_documents">Iniciando com Mongoose </a> muitas vezes é melhor ter o atributo que define a relação entre os documentos/modelos em apenas um dos modelos( você ainda pode encontrar o relacionamento reverso pesquisando o <code>_id</code> associado no outro modelo). Abaixo nós escolhemos definir o modelo Book Schema para armazenar o relacionamento entre Book/Genre e Book/Author, e definimos BookInstance Schema para armazenar o relacionamento entre Book/BookInstance. Esta escolha foi um tanto arbitrária — nós poderíamos igualmente ter declarado esses atributos em outro schema.</p> +</div> + +<p><img alt="Mongoose Library Model with correct cardinality" src="https://mdn.mozillademos.org/files/15645/Library%20Website%20-%20Mongoose_Express.png" style="height: 620px; width: 737px;"></p> + +<div class="note"> +<p><strong>Nota</strong>: A próxima seção fornece um guia explicando como os modelos são definidos e usados. Ao ler, considere como iremos construir cada um dos modelos no diagrama acima.</p> +</div> + +<h2 id="Iniciando_com_Mongoose">Iniciando com Mongoose</h2> + +<p>Esta seção fornece uma visão geral de como conectar o Mongoose a um banco de dados do MongoDB, como definir um schema e um modelo, e como fazer consultas básicas.</p> + +<div class="note"> +<p><strong>Nota:</strong> Esse guia é "bastante influenciado" pelo conteúdo encontrado no <a href="https://www.npmjs.com/package/mongoose">Mongoose quick start</a> do <em>npm</em> e pela <a href="http://mongoosejs.com/docs/guide.html">documentação oficial</a>.</p> +</div> + +<h3 id="Instalando_Mongoose_e_MongoDB">Instalando Mongoose e MongoDB</h3> + +<p>O Mongoose é instalado no seu projeto (<strong>package.json</strong>) assim como outra dependência qualquer — usando NPM. Para instalá-lo, use a seguinte linha de comando dentro da pasta do seu projeto:</p> + +<pre class="brush: bash">npm install mongoose +</pre> + +<p>Installing <em>Mongoose</em> adds all its dependencies, including the MongoDB database driver, but it does not install MongoDB itself. If you want to install a MongoDB server then you can <a href="https://www.mongodb.com/download-center">download installers from here</a> for various operating systems and install it locally. You can also use cloud-based MongoDB instances.</p> + +<div class="note"> +<p><strong>Note:</strong> For this tutorial, we'll be using the MongoDB Atlas cloud-based <em>database as a service</em> <a href="https://www.mongodb.com/cloud/atlas/pricing">free tier</a> to provide the database. This is suitable for development and makes sense for the tutorial because it makes "installation" operating system independent (database-as-a-service is also one approach you might well use for your production database).</p> +</div> + +<h3 id="Conectando_ao_MongoDB">Conectando ao MongoDB</h3> + +<p><em>Mongoose</em> requires a connection to a MongoDB database. You can <code>require()</code> and connect to a locally hosted database with <code>mongoose.connect()</code>, as shown below.</p> + +<pre class="brush: js">//Import the mongoose module +var mongoose = require('mongoose'); + +//Set up default mongoose connection +var mongoDB = 'mongodb://127.0.0.1/my_database'; +mongoose.connect(mongoDB, { useNewUrlParser: true }); + +//Get the default connection +var db = mongoose.connection; + +//Bind connection to error event (to get notification of connection errors) +db.on('error', console.error.bind(console, 'MongoDB connection error:'));</pre> + +<p>You can get the default <code>Connection</code> object with <code>mongoose.connection</code>. Once connected, the open event is fired on the <code>Connection</code> instance.</p> + +<div class="note"> +<p><strong>Tip:</strong> If you need to create additional connections you can use <code>mongoose.createConnection()</code>. This takes the same form of database URI (with host, database, port, options etc.) as <code>connect()</code> and returns a <code>Connection</code> object).</p> +</div> + +<h3 id="Definindo_e_criando_modelos">Definindo e criando modelos</h3> + +<p>Models are <em>defined </em>using the <code>Schema</code> interface. The Schema allows you to define the fields stored in each document along with their validation requirements and default values. In addition, you can define static and instance helper methods to make it easier to work with your data types, and also virtual properties that you can use like any other field, but which aren't actually stored in the database (we'll discuss a bit further below).</p> + +<p>Schemas are then "compiled" into models using the <code>mongoose.model()</code> method. Once you have a model you can use it to find, create, update, and delete objects of the given type.</p> + +<div class="note"> +<p><strong>Note:</strong> Each model maps to a <em>collection</em> of <em>documents</em> in the MongoDB database. The documents will contain the fields/schema types defined in the model <code>Schema</code>.</p> +</div> + +<h4 id="Defining_schemas">Defining schemas</h4> + +<p>The code fragment below shows how you might define a simple schema. First you <code>require()</code> mongoose, then use the Schema constructor to create a new schema instance, defining the various fields inside it in the constructor's object parameter.</p> + +<pre class="brush: js">//Require Mongoose +var mongoose = require('mongoose'); + +//Define a schema +var Schema = mongoose.Schema; + +var SomeModelSchema = new Schema({ + a_string: String, + a_date: Date +}); +</pre> + +<p>In the case above we just have two fields, a string and a date. In the next sections, we will show some of the other field types, validation, and other methods.</p> + +<h4 id="Criando_um_modelo">Criando um modelo</h4> + +<p>Models are created from schemas using the <code>mongoose.model()</code> method:</p> + +<pre class="brush: js">// Define schema +var Schema = mongoose.Schema; + +var SomeModelSchema = new Schema({ + a_string: String, + a_date: Date +}); + +<strong>// Compile model from schema +var SomeModel = mongoose.model('SomeModel', SomeModelSchema );</strong></pre> + +<p>The first argument is the singular name of the collection that will be created for your model (Mongoose will create the database collection for the above model <em>SomeModel</em> above), and the second argument is the schema you want to use in creating the model.</p> + +<div class="note"> +<p><strong>Note:</strong> Once you've defined your model classes you can use them to create, update, or delete records, and run queries to get all records or particular subsets of records. We'll show you how to do this in the <a href="#Using_models">Using models</a> section, and when we create our views.</p> +</div> + +<h4 id="Schema_types_fields">Schema types (fields)</h4> + +<p>A schema can have an arbitrary number of fields — each one represents a field in the documents stored in <em>MongoDB</em>. An example schema showing many of the common field types and how they are declared is shown below.</p> + +<pre class="brush: js">var schema = new Schema( +{ + name: <strong>String</strong>, + binary: <strong>Buffer</strong>, + living: <strong>Boolean</strong>, + updated: { type: <strong>Date</strong>, default: Date.now() }, + age: { type: <strong>Number</strong>, min: 18, max: 65, required: true }, + mixed: <strong>Schema.Types.Mixed</strong>, + _someId: <strong>Schema.Types.ObjectId</strong>, + array: <strong>[]</strong>, + ofString: [<strong>String</strong>], // You can also have an array of each of the other types too. + nested: { stuff: { type: <strong>String</strong>, lowercase: true, trim: true } } +})</pre> + +<p>Most of the <a href="http://mongoosejs.com/docs/schematypes.html">SchemaTypes</a> (the descriptors after “type:” or after field names) are self-explanatory. The exceptions are:</p> + +<ul> + <li><code>ObjectId</code>: Represents specific instances of a model in the database. For example, a book might use this to represent its author object. This will actually contain the unique ID (<code>_id</code>) for the specified object. We can use the <code>populate()</code> method to pull in the associated information when needed.</li> + <li><a href="http://mongoosejs.com/docs/schematypes.html#mixed">Mixed</a>: An arbitrary schema type.</li> + <li>[]: An array of items. You can perform JavaScript array operations on these models (push, pop, unshift, etc.). The examples above show an array of objects without a specified type and an array of <code>String</code> objects, but you can have an array of any type of object.</li> +</ul> + +<p>The code also shows both ways of declaring a field:</p> + +<ul> + <li>Field <em>name</em> and <em>type</em> as a key-value pair (i.e. as done with fields <code>name</code>, <code>binary </code>and <code>living</code>).</li> + <li>Field <em>name</em> followed by an object defining the <code>type</code>, and any other <em>options</em> for the field. Options include things like: + <ul> + <li>default values.</li> + <li>built-in validators (e.g. max/min values) and custom validation functions.</li> + <li>Whether the field is required</li> + <li>Whether <code>String</code> fields should automatically be set to lowercase, uppercase, or trimmed (e.g. <code>{ type: <strong>String</strong>, lowercase: true, trim: true }</code>)</li> + </ul> + </li> +</ul> + +<p>For more information about options see <a href="http://mongoosejs.com/docs/schematypes.html">SchemaTypes</a> (Mongoose docs).</p> + +<h4 id="Validação">Validação</h4> + +<p>Mongoose provides built-in and custom validators, and synchronous and asynchronous validators. It allows you to specify both the acceptable range or values and the error message for validation failure in all cases.</p> + +<p>The built-in validators include:</p> + +<ul> + <li>All <a href="http://mongoosejs.com/docs/schematypes.html">SchemaTypes</a> have the built-in <a href="http://mongoosejs.com/docs/api.html#schematype_SchemaType-required">required</a> validator. This is used to specify whether the field must be supplied in order to save a document.</li> + <li><a href="http://mongoosejs.com/docs/api.html#schema-number-js">Numbers</a> have <a href="http://mongoosejs.com/docs/api.html#schema_number_SchemaNumber-min">min</a> and <a href="http://mongoosejs.com/docs/api.html#schema_number_SchemaNumber-max">max</a> validators.</li> + <li><a href="http://mongoosejs.com/docs/api.html#schema-string-js">Strings</a> have: + <ul> + <li><a href="http://mongoosejs.com/docs/api.html#schema_string_SchemaString-enum">enum</a>: specifies the set of allowed values for the field.</li> + <li><a href="http://mongoosejs.com/docs/api.html#schema_string_SchemaString-match">match</a>: specifies a regular expression that the string must match.</li> + <li><a href="http://mongoosejs.com/docs/api.html#schema_string_SchemaString-maxlength">maxlength</a> and <a href="http://mongoosejs.com/docs/api.html#schema_string_SchemaString-minlength">minlength</a> for the string.</li> + </ul> + </li> +</ul> + +<p>The example below (slightly modified from the Mongoose documents) shows how you can specify some of the validator types and error messages:</p> + +<pre class="brush: js">var breakfastSchema = new Schema({ + eggs: { + type: Number, + min: [6, 'Too few eggs'], + max: 12, + required: [true, 'Why no eggs?'] + }, + drink: { + type: String, + enum: ['Coffee', 'Tea', 'Water',] + } +}); +</pre> + +<p>For complete information on field validation see <a href="http://mongoosejs.com/docs/validation.html">Validation</a> (Mongoose docs).</p> + +<h4 id="Propriedades_virtuais">Propriedades virtuais</h4> + +<p>Virtual properties are document properties that you can get and set but that do not get persisted to MongoDB. The getters are useful for formatting or combining fields, while setters are useful for de-composing a single value into multiple values for storage. The example in the documentation constructs (and deconstructs) a full name virtual property from a first and last name field, which is easier and cleaner than constructing a full name every time one is used in a template.</p> + +<div class="note"> +<p><strong>Note:</strong> We will use a virtual property in the library to define a unique URL for each model record using a path and the record's <code>_id</code> value.</p> +</div> + +<p>For more information see <a href="http://mongoosejs.com/docs/guide.html#virtuals">Virtuals</a> (Mongoose documentation).</p> + +<h4 id="Methods_and_query_helpers">Methods and query helpers</h4> + +<p>A schema can also have <a href="http://mongoosejs.com/docs/guide.html#methods">instance methods</a>, <a href="http://mongoosejs.com/docs/guide.html#statics">static methods</a>, and <a href="http://mongoosejs.com/docs/guide.html#query-helpers">query helpers</a>. The instance and static methods are similar, but with the obvious difference that an instance method is associated with a particular record and has access to the current object. Query helpers allow you to extend mongoose's <a href="http://mongoosejs.com/docs/queries.html">chainable query builder API</a> (for example, allowing you to add a query "byName" in addition to the <code>find()</code>, <code>findOne()</code> and <code>findById()</code> methods).</p> + +<h3 id="Usando_modelos">Usando modelos</h3> + +<p>Once you've created a schema you can use it to create models. The model represents a collection of documents in the database that you can search, while the model's instances represent individual documents that you can save and retrieve.</p> + +<p>We provide a brief overview below. For more information see: <a href="http://mongoosejs.com/docs/models.html">Models</a> (Mongoose docs).</p> + +<h4 id="Criando_e_modificando_documentos">Criando e modificando documentos</h4> + +<p>To create a record you can define an instance of the model and then call <code>save()</code>. The examples below assume SomeModel is a model (with a single field "name") that we have created from our schema.</p> + +<pre class="brush: js">// Create an instance of model SomeModel +var awesome_instance = new SomeModel({ name: 'awesome' }); + +// Save the new model instance, passing a callback +awesome_instance.save(function (err) { + if (err) return handleError(err); + // saved! +}); +</pre> + +<p>Creation of records (along with updates, deletes, and queries) are asynchronous operations — you supply a callback that is called when the operation completes. The API uses the error-first argument convention, so the first argument for the callback will always be an error value (or null). If the API returns some result, this will be provided as the second argument.</p> + +<p>You can also use <code>create()</code> to define the model instance at the same time as you save it. The callback will return an error for the first argument and the newly-created model instance for the second argument.</p> + +<pre class="brush: js">SomeModel.create({ name: 'also_awesome' }, function (err, awesome_instance) { + if (err) return handleError(err); + // saved! +});</pre> + +<p>Every model has an associated connection (this will be the default connection when you use <code>mongoose.model()</code>). You create a new connection and call <code>.model()</code> on it to create the documents on a different database.</p> + +<p>You can access the fields in this new record using the dot syntax, and change the values. You have to call <code>save()</code> or <code>update()</code> to store modified values back to the database.</p> + +<pre class="brush: js">// Access model field values using dot notation +console.log(awesome_instance.name); //should log 'also_awesome' + +// Change record by modifying the fields, then calling save(). +awesome_instance.name="New cool name"; +awesome_instance.save(function (err) { + if (err) return handleError(err); // saved! +}); +</pre> + +<h4 id="Pesquisando_por_registros">Pesquisando por registros</h4> + +<p>You can search for records using query methods, specifying the query conditions as a JSON document. The code fragment below shows how you might find all athletes in a database that play tennis, returning just the fields for athlete <em>name</em> and <em>age</em>. Here we just specify one matching field (sport) but you can add more criteria, specify regular expression criteria, or remove the conditions altogether to return all athletes.</p> + +<pre class="brush: js">var Athlete = mongoose.model('Athlete', yourSchema); + +// find all athletes who play tennis, selecting the 'name' and 'age' fields +Athlete.find({ 'sport': 'Tennis' }, 'name age', function (err, athletes) { + if (err) return handleError(err); + // 'athletes' contains the list of athletes that match the criteria. +})</pre> + +<p>If you specify a callback, as shown above, the query will execute immediately. The callback will be invoked when the search completes.</p> + +<div class="note"> +<p><strong>Note:</strong> All callbacks in Mongoose use the pattern <code>callback(error, result)</code>. If an error occurs executing the query, the <code>error</code> parameter will contain an error document and <code>result</code> will be null. If the query is successful, the <code>error</code> parameter will be null, and the <code>result</code> will be populated with the results of the query.</p> +</div> + +<div class="note"> +<p><strong>Note:</strong> It is important to remember that not finding any results is <strong>not an error</strong> for a search —but it may be a fail-case in the context of your application. If your application expects a search to find a value you can either check the result in the callback (<code>results==null</code>) or daisy chain the method <a href="https://mongoosejs.com/docs/api.html#query_Query-orFail">orFail()</a> on the query. </p> +</div> + +<p>If you don't specify a callback then the API will return a variable of type <a href="http://mongoosejs.com/docs/api.html#query-js">Query</a>. You can use this query object to build up your query and then execute it (with a callback) later using the <code>exec()</code> method.</p> + +<pre class="brush: js">// find all athletes that play tennis +var query = Athlete.find({ 'sport': 'Tennis' }); + +// selecting the 'name' and 'age' fields +query.select('name age'); + +// limit our results to 5 items +query.limit(5); + +// sort by age +query.sort({ age: -1 }); + +// execute the query at a later time +query.exec(function (err, athletes) { + if (err) return handleError(err); + // athletes contains an ordered list of 5 athletes who play Tennis +})</pre> + +<p>Above we've defined the query conditions in the <code>find()</code> method. We can also do this using a <code>where()</code> function, and we can chain all the parts of our query together using the dot operator (.) rather than adding them separately. The code fragment below is the same as our query above, with an additional condition for the age.</p> + +<pre class="brush: js">Athlete. + find(). + where('sport').equals('Tennis'). + where('age').gt(17).lt(50). //Additional where query + limit(5). + sort({ age: -1 }). + select('name age'). + exec(callback); // where callback is the name of our callback function.</pre> + +<p>The <a href="http://mongoosejs.com/docs/api.html#query_Query-find">find()</a> method gets all matching records, but often you just want to get one match. The following methods query for a single record:</p> + +<ul> + <li><code><a href="http://mongoosejs.com/docs/api.html#model_Model.findById">findById()</a></code>: Finds the document with the specified <code>id</code> (every document has a unique <code>id</code>).</li> + <li><code><a href="http://mongoosejs.com/docs/api.html#query_Query-findOne">findOne()</a></code>: Finds a single document that matches the specified criteria.</li> + <li><code><a href="http://mongoosejs.com/docs/api.html#model_Model.findByIdAndRemove">findByIdAndRemove()</a></code>, <code><a href="http://mongoosejs.com/docs/api.html#model_Model.findByIdAndUpdate">findByIdAndUpdate()</a></code>, <code><a href="http://mongoosejs.com/docs/api.html#query_Query-findOneAndRemove">findOneAndRemove()</a></code>, <code><a href="http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate">findOneAndUpdate()</a></code>: Finds a single document by <code>id</code> or criteria and either update or remove it. These are useful convenience functions for updating and removing records.</li> +</ul> + +<div class="note"> +<p><strong>Note:</strong> There is also a <code><a href="http://mongoosejs.com/docs/api.html#model_Model.count">count()</a></code> method that you can use to get the number of items that match conditions. This is useful if you want to perform a count without actually fetching the records.</p> +</div> + +<p>There is a lot more you can do with queries. For more information see: <a href="http://mongoosejs.com/docs/queries.html">Queries</a> (Mongoose docs).</p> + +<h4 id="Working_with_related_documents_—_population">Working with related documents — population</h4> + +<p>You can create references from one document/model instance to another using the <code>ObjectId</code> schema field, or from one document to many using an array of <code>ObjectIds</code>. The field stores the id of the related model. If you need the actual content of the associated document, you can use the <code><a href="http://mongoosejs.com/docs/api.html#query_Query-populate">populate()</a></code> method in a query to replace the id with the actual data.</p> + +<p>For example, the following schema defines authors and stories. Each author can have multiple stories, which we represent as an array of <code>ObjectId</code>. Each story can have a single author. The "ref" (highlighted in bold below) tells the schema which model can be assigned to this field.</p> + +<pre class="brush: js">var mongoose = require('mongoose') + , Schema = mongoose.Schema + +var authorSchema = Schema({ + name : String, + stories : [{ type: Schema.Types.ObjectId, <strong>ref</strong>: 'Story' }] +}); + +var storySchema = Schema({ + author : { type: Schema.Types.ObjectId, <strong>ref</strong>: 'Author' }, + title : String +}); + +var Story = mongoose.model('Story', storySchema); +var Author = mongoose.model('Author', authorSchema);</pre> + +<p>We can save our references to the related document by assigning the <code>_id</code> value. Below we create an author, then a story, and assign the author id to our stories author field.</p> + +<pre class="brush: js">var bob = new Author({ name: 'Bob Smith' }); + +bob.save(function (err) { + if (err) return handleError(err); + + //Bob now exists, so lets create a story + var story = new Story({ + title: "Bob goes sledding", + author: bob._id // assign the _id from the our author Bob. This ID is created by default! + }); + + story.save(function (err) { + if (err) return handleError(err); + // Bob now has his story + }); +});</pre> + +<p>Our story document now has an author referenced by the author document's ID. In order to get the author information in the story results we use <code>populate()</code>, as shown below.</p> + +<pre class="brush: js">Story +.findOne({ title: 'Bob goes sledding' }) +.populate('author') //This populates the author id with actual author information! +.exec(function (err, story) { + if (err) return handleError(err); + console.log('The author is %s', story.author.name); + // prints "The author is Bob Smith" +});</pre> + +<div class="note"> +<p><strong>Note:</strong> Astute readers will have noted that we added an author to our story, but we didn't do anything to add our story to our author's <code>stories</code> array. How then can we get all stories by a particular author? One way would be to add our author to the stories array, but this would result in us having two places where the information relating authors and stories needs to be maintained.</p> + +<p>A better way is to get the <code>_id</code> of our <em>author</em>, then use <code>find()</code> to search for this in the author field across all stories.</p> + +<pre class="brush: js">Story +.find({ author : bob._id }) +.exec(function (err, stories) { + if (err) return handleError(err); + // returns all stories that have Bob's id as their author. +}); +</pre> +</div> + +<p>This is almost everything you need to know about working with related items<em> for this tutorial</em>. For more detailed information see <a href="http://mongoosejs.com/docs/populate.html">Population</a> (Mongoose docs).</p> + +<h3 id="One_schemamodel_per_file">One schema/model per file</h3> + +<p>While you can create schemas and models using any file structure you like, we highly recommend defining each model schema in its own module (file), exporting the method to create the model. This is shown below:</p> + +<pre class="brush: js">// File: ./models/somemodel.js + +//Require Mongoose +var mongoose = require('mongoose'); + +//Define a schema +var Schema = mongoose.Schema; + +var SomeModelSchema = new Schema({ + a_string : String, + a_date : Date, +}); + +<strong>//Export function to create "SomeModel" model class +module.exports = mongoose.model('SomeModel', SomeModelSchema );</strong></pre> + +<p>You can then require and use the model immediately in other files. Below we show how you might use it to get all instances of the model.</p> + +<pre class="brush: js">//Create a SomeModel model just by requiring the module +var SomeModel = require('../models/somemodel') + +// Use the SomeModel object (model) to find all SomeModel records +SomeModel.find(callback_function);</pre> + +<h2 id="Configurando_o_banco_de_dados_MongoDB">Configurando o banco de dados MongoDB</h2> + +<p>Now that we understand something of what Mongoose can do and how we want to design our models, it's time to start work on the <em>LocalLibrary</em> website. The very first thing we want to do is set up a MongoDb database that we can use to store our library data.</p> + +<p>For this tutorial, we're going to use the <a href="https://www.mongodb.com/cloud/atlas">MongoDB Atlas</a> free cloud-hosted <a href="https://www.mongodb.com/cloud/atlas/pricing">sandbox</a> database. This database tier is not considered suitable for production websites because it has no redundancy, but it is great for development and prototyping. We're using it here because it is free and easy to set up, and because MongoDB Atlas is a popular <em>database as a service</em> vendor that you might reasonably choose for your production database (other popular choices at the time of writing include <a href="https://www.compose.com/">Compose</a>, <a href="https://scalegrid.io/pricing.html">ScaleGrid</a> and <a href="https://www.mongodb.com/cloud/atlas">ObjectRocket</a>).</p> + +<div class="note"> +<p><strong>Note:</strong> If you prefer you can set up a MongoDb database locally by downloading and installing the <a href="https://www.mongodb.com/download-center/community">appropriate binaries for your system</a>. The rest of the instructions in this article would be similar, except for the database URL you would specify when connecting.</p> +</div> + +<p>You will first need to <a href="https://www.mongodb.com/cloud/atlas/register">create an account</a> with MongoDB Atlas (this is free, and just requires that you enter basic contact details and acknowledge their terms of service). </p> + +<p>After logging in, you'll be taken to the <a href="https://cloud.mongodb.com/v2">home</a> screen:</p> + +<ol> + <li>Click <strong>Buid a Cluster</strong> button in the Clusters Overview section.<br> + <img alt="Create a cluster on MongoDB Atlas." src="https://mdn.mozillademos.org/files/16516/MongoDB_Atlas_-_CreateCluster.jpg" style="border-style: solid; border-width: 1px; height: 549px; width: 742px;"></li> + <li>This will open the <em>Create New Cluster</em> screen.<br> + <img alt="Choose a cloud provider when using MongoDB Atlas." src="https://mdn.mozillademos.org/files/16511/MongoDB_Atlas_-_ChooseProviderRegion.jpg" style="border-style: solid; border-width: 1px; height: 656px; width: 742px;"> + <ul> + <li>Select any provider from the <em>Cloud Provider & Region </em>section. Different providers offer different regions.</li> + <li>Select any region marked "FREE TIER AVAILABLE".</li> + <li>Click the <strong>Create Cluster</strong> button (creation of the cluster will take some minutes).</li> + </ul> + </li> + <li> + <p>You will return to the <em>Cluster Overview</em> screen.<br> + <img alt="Setup a collection on MongoDB Atlas." src="https://mdn.mozillademos.org/files/16517/MongoDB_Atlas_-_CreateCollection.jpg" style="border-style: solid; border-width: 1px; height: 399px; width: 742px;"></p> + + <ul> + <li> + <p>Click the <strong>Collections</strong> button.</p> + </li> + </ul> + </li> + <li>This will open the <em>Collections</em> section.<br> + <img alt="Create a database on MongoDB Atlas." src="https://mdn.mozillademos.org/files/16518/MongoDB_Atlas_-_CreateDatabase.jpg" style="border-style: solid; border-width: 1px; height: 412px; width: 742px;"> + <ul> + <li>Click the <strong>Create Database</strong> button.</li> + </ul> + </li> + <li>This will open the <em>Create Database</em> screen.<br> + <img alt="Details during database creation on MongoDB Atlas." src="https://mdn.mozillademos.org/files/16520/MongoDB_Atlas_-_DatabaseDetails.jpg" style="border-style: solid; border-width: 1px; height: 441px; width: 416px;"> + <ul> + <li>Enter the name for the new database as <code>local_library</code>.</li> + <li>Enter the name of the collection as <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">Collection0</span></font>.</li> + <li>Click the <strong>Create</strong> button to create the database.</li> + </ul> + </li> + <li>You will return to the Collection screen with your database created.<br> + <img alt="Database creation confirmation on MongoDB Atlas." src="https://mdn.mozillademos.org/files/16519/MongoDB_Atlas_-_DatabaseCreated.jpg" style="border-style: solid; border-width: 1px; height: 305px; width: 742px;"> + <ul> + <li>Click the <em>Overview</em> tab to return the cluster overview.</li> + </ul> + </li> + <li>From the Cluster0 Overview screen click the <strong>Connect</strong> button.<br> + <img alt="Configure a connection when after setting up a cluster in MongoDB Atlas." src="https://mdn.mozillademos.org/files/16512/MongoDB_Atlas_-_Connectbutton.jpg" style="border-style: solid; border-width: 1px; height: 308px; width: 742px;"></li> + <li>This will open the Connect to Cluster screen.<br> + <img alt="Setup a connection when using MongoDB Atlas." src="https://mdn.mozillademos.org/files/16513/MongoDB_Atlas_-_ConnectCluster.jpg" style="border-style: solid; border-width: 1px; height: 771px; width: 690px;"> + <ul> + <li>Click the <strong>Add a Different IP Address</strong> button, enter <code>0.0.0.0/0</code> for the IP Address and click <strong>Add IP Address</strong> button. + <div class="blockIndicator note"> + <p><strong>Note:</strong> It is a best practice to limit the IP addresses that can connect to your database and other resources. Here we allow a connection from anywhere because we don't know where the request will come from after deployment.</p> + </div> + </li> + <li>Enter a username and password and click <strong>Create MongoDB User</strong> button. + <div class="blockIndicator note"> + <p><strong>Note:</strong> Avoid using special characters in your MongoDB user password as mongoose may not parse the connection string properly.</p> + </div> + </li> + <li>If you have completed the 2 previous steps, the button <strong>Choose a connection method </strong>will turn green.</li> + <li>Click the <strong>Choose a connection method</strong> button.</li> + </ul> + </li> + <li>This will access the <em>Choose a connection</em> method tab.<br> + <img alt="Choose a connection type when connecting with MongoDB Atlas." src="https://mdn.mozillademos.org/files/16510/MongoDB_Atlas_-_ChooseAConnectionMethod.jpg" style="border-style: solid; border-width: 1px; height: 606px; width: 691px;"> + <ul> + <li>Click the <strong>Connect Your Application</strong> option.</li> + </ul> + </li> + <li>This will open the <em>Connect</em> screen.<br> + <img alt="Choose the Short SRV connection when settinup a connection on MongoDB Atalas." src="https://mdn.mozillademos.org/files/16514/MongoDB_Atlas_-_ConnectForShortSRV.jpg" style="border-style: solid; border-width: 1px; height: 604px; width: 693px;"> + <ul> + <li>Click the <strong>Short SRV connection string</strong> option to copy the connection string.</li> + </ul> + </li> + <li>This will open the connection string URL.<br> + <img alt="Copy the Short SRV connection string when setting up a connection on MongoDB Atlas" src="https://mdn.mozillademos.org/files/16515/MongoDB_Atlas_-_CopyShortSRV.jpg" style="border-style: solid; border-width: 1px; height: 741px; width: 690px;"> + <ul> + <li>Choose <strong>Copy</strong> button to copy the string.</li> + <li>Save this string somewhere safe.</li> + <li>Update the password with your users password.</li> + <li>Replace test with <code>local_library</code>.</li> + </ul> + </li> +</ol> + +<p>You have now created the database, and have an URL (with username and password) that can be used to access it. This will look something like: <code>mongodb+srv://your_user_name:your_password@cluster0-mbdj7.mongodb.net/local_library?retryWrites=true</code></p> + +<h2 id="Instalando_Mongoose">Instalando Mongoose</h2> + +<p>Open a command prompt and navigate to the directory where you created your <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">skeleton Local Library website</a>. Enter the following command to install Mongoose (and its dependencies) and add it to your <strong>package.json</strong> file, unless you have already done so when reading the <a href="#Installing_Mongoose_and_MongoDB">Mongoose Primer</a> above.</p> + +<pre class="brush: bash">npm install mongoose +</pre> + +<h2 id="Conectando_ao_MongoDB_2">Conectando ao MongoDB</h2> + +<p>Open <strong>/app.js</strong> (in the root of your project) and copy the following text below where you declare the <em>Express application object</em> (after the line <code>var app = express();</code>). Replace the database url string ('<em>insert_your_database_url_here</em>') with the location URL representing your own database (i.e. using the information from <em>mongoDB Atlas</em>).</p> + +<pre class="brush: js">//Set up mongoose connection +var mongoose = require('mongoose'); +var mongoDB = '<em>insert_your_database_url_here</em>'; +mongoose.connect(mongoDB, { useNewUrlParser: true }); +var db = mongoose.connection; +db.on('error', console.error.bind(console, 'MongoDB connection error:'));</pre> + +<p>As discussed <a href="#Connecting_to_MongoDB">in the Mongoose primer above</a>, this code creates the default connection to the database and binds to the error event (so that errors will be printed to the console). </p> + +<h2 id="Defining_the_LocalLibrary_Schema">Defining the LocalLibrary Schema</h2> + +<p>We will define a separate module for each model, as <a href="#One_schemamodel_per_file">discussed above</a>. Start by creating a folder for our models in the project root (<strong>/models</strong>) and then create separate files for each of the models:</p> + +<pre>/express-locallibrary-tutorial //the project root + <strong>/models</strong> + <strong>author.js</strong> + <strong>book.js</strong> + <strong>bookinstance.js</strong> + <strong>genre.js</strong> +</pre> + +<h3 id="Author_model">Author model</h3> + +<p>Copy the <code>Author</code> schema code shown below and paste it into your <strong>./models/author.js</strong> file. The scheme defines an author has having <code>String</code> SchemaTypes for the first and family names, that are required and have a maximum of 100 characters, and <code>Date</code> fields for the date of birth and death.</p> + +<pre class="brush: js">var mongoose = require('mongoose'); + +var Schema = mongoose.Schema; + +var AuthorSchema = new Schema( + { + first_name: {type: String, required: true, max: 100}, + family_name: {type: String, required: true, max: 100}, + date_of_birth: {type: Date}, + date_of_death: {type: Date}, + } +); + +<strong>// Virtual for author's full name +AuthorSchema +.virtual('name') +.get(function () { + return this.family_name + ', ' + this.first_name; +}); + +// Virtual for author's lifespan +AuthorSchema +</strong>.virtual('lifespan') +.get(function () { + return (this.date_of_death.getYear() - this.date_of_birth.getYear()).toString(); +}); + +// Virtual for author's URL +AuthorSchema +.virtual('url') +.get(function () { + return '/catalog/author/' + this._id; +}); + +//Export model +module.exports = mongoose.model('Author', AuthorSchema); + +</pre> + +<p>We've also declared a <a href="#Virtual_properties">virtual</a> for the AuthorSchema named "url" that returns the absolute URL required to get a particular instance of the model — we'll use the property in our templates whenever we need to get a link to a particular author.</p> + +<div class="note"> +<p><strong>Note:</strong> Declaring our URLs as a virtual in the schema is a good idea because then the URL for an item only ever needs to be changed in one place.<br> + At this point, a link using this URL wouldn't work, because we haven't got any routes handling code for individual model instances. We'll set those up in a later article!</p> +</div> + +<p>At the end of the module, we export the model.</p> + +<h3 id="Book_model">Book model</h3> + +<p>Copy the <code>Book</code> schema code shown below and paste it into your <strong>./models/book.js</strong> file. Most of this is similar to the author model — we've declared a schema with a number of string fields and a virtual for getting the URL of specific book records, and we've exported the model.</p> + +<pre class="brush: js">var mongoose = require('mongoose'); + +var Schema = mongoose.Schema; + +var BookSchema = new Schema( + { + title: {type: String, required: true}, + <strong> author: {type: Schema.Types.ObjectId, ref: 'Author', required: true},</strong> + summary: {type: String, required: true}, + isbn: {type: String, required: true}, + <strong> genre: [{type: Schema.Types.ObjectId, ref: 'Genre'}]</strong> + } +); + +// Virtual for book's URL +BookSchema +.virtual('url') +.get(function () { + return '/catalog/book/' + this._id; +}); + +//Export model +module.exports = mongoose.model('Book', BookSchema); +</pre> + +<p>The main difference here is that we've created two references to other models:</p> + +<ul> + <li>author is a reference to a single <code>Author</code> model object, and is required.</li> + <li>genre is a reference to an array of <code>Genre</code> model objects. We haven't declared this object yet!</li> +</ul> + +<h3 id="BookInstance_model">BookInstance model</h3> + +<p>Finally, copy the <code>BookInstance</code> schema code shown below and paste it into your <strong>./models/bookinstance.js</strong> file. The <code>BookInstance</code> represents a specific copy of a book that someone might borrow and includes information about whether the copy is available or on what date it is expected back, "imprint" or version details.</p> + +<pre class="brush: js">var mongoose = require('mongoose'); + +var Schema = mongoose.Schema; + +var BookInstanceSchema = new Schema( + { + book: { type: Schema.Types.ObjectId, ref: 'Book', required: true }, //reference to the associated book + imprint: {type: String, required: true}, + status: {type: String, required: true, <strong>enum: ['Available', 'Maintenance', 'Loaned', 'Reserved']</strong>, <strong>default: 'Maintenance'</strong>}, + due_back: {type: Date, <strong>default: Date.now</strong>} + } +); + +// Virtual for bookinstance's URL +BookInstanceSchema +.virtual('url') +.get(function () { + return '/catalog/bookinstance/' + this._id; +}); + +//Export model +module.exports = mongoose.model('BookInstance', BookInstanceSchema);</pre> + +<p>The new things we show here are the field options:</p> + +<ul> + <li><code>enum</code>: This allows us to set the allowed values of a string. In this case, we use it to specify the availability status of our books (using an enum means that we can prevent mis-spellings and arbitrary values for our status)</li> + <li><code>default</code>: We use default to set the default status for newly created bookinstances to maintenance and the default <code>due_back</code> date to <code>now</code> (note how you can call the Date function when setting the date!)</li> +</ul> + +<p>Everything else should be familiar from our previous schema.</p> + +<h3 id="Genre_model_-_challenge!">Genre model - challenge!</h3> + +<p>Open your <strong>./models/genre.js</strong> file and create a schema for storing genres (the category of book, e.g. whether it is fiction or non-fiction, romance or military history, etc).</p> + +<p>The definition will be very similar to the other models:</p> + +<ul> + <li>The model should have a <code>String</code> SchemaType called <code>name</code> to describe the genre.</li> + <li>This name should be required and have between 3 and 100 characters.</li> + <li>Declare a <a href="#Virtual_properties">virtual</a> for the genre's URL, named <code>url</code>.</li> + <li>Export the model.</li> +</ul> + +<h2 id="Testando_—_criando_alguns_itens">Testando — criando alguns itens</h2> + +<p>That's it. We now have all models for the site set up!</p> + +<p>In order to test the models (and to create some example books and other items that we can use in our next articles) we'll now run an <em>independent</em> script to create items of each type:</p> + +<ol> + <li>Download (or otherwise create) the file <a href="https://raw.githubusercontent.com/hamishwillee/express-locallibrary-tutorial/master/populatedb.js">populatedb.js</a> inside your <em>express-locallibrary-tutorial</em> directory (in the same level as <code>package.json</code>). + + <div class="note"> + <p><strong>Note:</strong> You don't need to know how <a href="https://raw.githubusercontent.com/hamishwillee/express-locallibrary-tutorial/master/populatedb.js">populatedb.js</a> works; it just adds sample data into the database.</p> + </div> + </li> + <li>Enter the following commands in the project root to install the <em>async</em> module that is required by the script (we'll discuss this in later tutorials, ) + <pre class="brush: bash">npm install async</pre> + </li> + <li>Run the script using node in your command prompt, passing in the URL of your <em>MongoDB</em> database (the same one you replaced the <em>insert_your_database_url_here </em>placeholder with, inside <code>app.js</code> earlier): + <pre class="brush: bash">node populatedb <your mongodb url></pre> + + <div class="blockIndicator note"> + <p><strong>Note for Windows operating system users</strong>: If the above command results in the error <code>DeprecationWarning: current URL string parser is deprecated</code>, change the <code>mongoose.connect(mongoDB);</code> line in <code>populatedb.js</code> file with <code>mongoose.connect(mongoDB, { useNewUrlParser:true });</code></p> + </div> + </li> + <li>The script should run through to completion, displaying items as it creates them in the terminal.</li> +</ol> + +<div class="note"> +<p><strong>Tip:</strong> Go to your database on mongoDB Atlas (in the <em>Collections</em> tab). You should now be able to drill down into individual collections of Books, Authors, Genres and BookInstances, and check out individual documents.</p> +</div> + +<h2 id="Resumo">Resumo</h2> + +<p>In this article, we've learned a bit about databases and ORMs on Node/Express, and a lot about how Mongoose schema and models are defined. We then used this information to design and implement <code>Book</code>, <code>BookInstance</code>, <code>Author</code> and <code>Genre</code> models for the <em>LocalLibrary</em> website.</p> + +<p>Last of all we tested our models by creating a number of instances (using a standalone script). In the next article we'll look at creating some pages to display these objects.</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="https://expressjs.com/en/guide/database-integration.html">Database integration</a> (Express docs)</li> + <li><a href="http://mongoosejs.com/">Mongoose website</a> (Mongoose docs)</li> + <li><a href="http://mongoosejs.com/docs/guide.html">Mongoose Guide</a> (Mongoose docs)</li> + <li><a href="http://mongoosejs.com/docs/validation.html">Validation</a> (Mongoose docs)</li> + <li><a href="http://mongoosejs.com/docs/schematypes.html">Schema Types</a> (Mongoose docs)</li> + <li><a href="http://mongoosejs.com/docs/models.html">Models</a> (Mongoose docs)</li> + <li><a href="http://mongoosejs.com/docs/queries.html">Queries</a> (Mongoose docs)</li> + <li><a href="http://mongoosejs.com/docs/populate.html">Population</a> (Mongoose docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introduction</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Setting up a Node (Express) development environment</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/express_nodejs/skeleton_website/index.html b/files/pt-br/learn/server-side/express_nodejs/skeleton_website/index.html new file mode 100644 index 0000000000..c6cc459141 --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/skeleton_website/index.html @@ -0,0 +1,509 @@ +--- +title: 'Express Tutorial Parte 2: Criando a estrutura do website' +slug: Learn/Server-side/Express_Nodejs/skeleton_website +translation_of: Learn/Server-side/Express_Nodejs/skeleton_website +--- +<div>{{LearnSidebar}}</div> + +<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs")}}</p> + +<p class="summary">Neste segundo <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial</a> , mostrará como criar a estrutura do website que depois você poderá colocar <em>templates,</em> chamadas de banco de dados ou rotas específicas.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Preparar o ambiente de desenvolvimento do Node </a>. Revise o Tutorial Express.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Iniciar nosso website usando o "<em>Express Application Generator"</em>.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_Geral">Visão Geral</h2> + +<p>Nesse artigo mostraremos como criar a estrutura do website usando a ferramenta "<a href="https://expressjs.com/en/starter/generator.html">Express Application Generator</a> ". Neste caso, usaremos a ferramenta para criar o framework para nosso <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">website "LocalLibrary" </a>, tpara o qual adicionaremos mais tarde todo o outro código necessário para o site. O processo é extremamente simples, com apenas a requisição de invocar o "Generator" na linha de comando com um novo nome de projeto, e, se quiser, especificar o <em>template </em>do site e o gerador de CSS. </p> + +<p><span style="line-height: 1.5;">As seguintes sessões mostrará como chamar o "Application Generator", e prover uma pequena explicação sobre as diferentes opções de CSS. Também aprenderemos como a estrutura do site é definida. No final, será mostrado como podemos rodar o site para ver se funciona.</span></p> + +<div class="note"> +<p><span style="line-height: 1.5;"><strong>Nota</strong>: O "<em>Express Application Generator"</em> não é o único gerador para as aplicações do Express, e o projeto gerado não é a única maneira viável de estruturar seus arquivos e diretórios. O site gerado, entretanto, tem um estrutura modular que é fácil de extender e ser entendida. Para aprender melhor sobre a aplicação do "<em>minimal</em> Express", veja <a href="https://expressjs.com/en/starter/hello-world.html">Exemplo"Hello world" </a>.</span></p> +</div> + +<h2 id="Usando_o_Application_Generator">Usando o "Application Generator"</h2> + +<p>Você já deve ter instalado o gerador como requisito.Como um lembrete rápido, você instala a ferramenta de gerador em todo o site usando o Gerenciador de pacotes NPM, como mostrado:</p> + +<pre class="brush: bash"><code>npm install express-generator -g</code></pre> + +<p>O gerador tem algumas opções que podem ser visualizadas usando o comando <code>--help</code> (or <code>-h</code>):</p> + +<pre class="brush: bash">> express --help + + Usage: express [options] [dir] + + + Options: + + --version output the version number + -e, --ejs add ejs engine support + --pug add pug engine support + --hbs add handlebars engine support + -H, --hogan add hogan.js engine support + -v, --view <engine> add view <engine> support (dust|ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade) + --no-view use static html instead of view engine + -c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css) + --git add .gitignore + -f, --force force on non-empty directory + -h, --help output usage information +</pre> + +<p>Você pode simplesmente especificar <code>express</code> para criar um projeto dentro do diretório atual usando <em>Jade</em> view e CSS simples (se você especificar um nome de diretório, o projeto será criado em uma subpasta com esse nome).</p> + +<pre class="brush: bash"><code>express</code></pre> + +<p>Também pode ser escolhido um "view" (<em>template)</em> usando<code>--view</code> e/ou um gerador de CSS usando <code>--css</code>.</p> + +<div class="note"> +<p><strong>Nota:</strong> As outras opções para escolher os mecanismos de modelo (e.g. <code>--hogan</code>, <code>--ejs</code>, <code>--hbs</code> etc.) são preteridas. Use <code>--view</code> (ou<code> -v</code>)!</p> +</div> + +<h3 id="Qual_engine_de_view_devo_usar">Qual <em>engine</em> de "view" devo usar?</h3> + +<p>The <em>Express Application Generator</em> allows you to configure a number of popular view/templating engines, including <a href="https://www.npmjs.com/package/ejs">EJS</a>, <a href="http://github.com/donpark/hbs">Hbs</a>, <a href="https://pugjs.org/api/getting-started.html">Pug</a> (Jade), <a href="https://www.npmjs.com/package/twig">Twig</a>, and <a href="https://www.npmjs.com/package/vash">Vash</a>, although it chooses Jade by default if you don't specify a view option. Express itself can also support a large number of other templating languages <a href="https://github.com/expressjs/express/wiki#template-engines">out of the box</a>.</p> + +<div class="note"> +<p><strong>Note:</strong> If you want to use a template engine that isn't supported by the generator then see <a href="https://expressjs.com/en/guide/using-template-engines.html">Using template engines with Express</a> (Express docs) and the documentation for your target view engine.</p> +</div> + +<p>Generally speaking, you should select a templating engine that delivers all the functionality you need and allows you to be productive sooner — or in other words, in the same way that you choose any other component! Some of the things to consider when comparing template engines:</p> + +<ul> + <li>Time to productivity — If your team already has experience with a templating language then it is likely they will be productive faster using that language. If not, then you should consider the relative learning curve for candidate templating engines.</li> + <li>Popularity and activity — Review the popularity of the engine and whether it has an active community. It is important to be able to get support for the engine when you have problems over the lifetime of the website.</li> + <li>Style — Some template engines use specific markup to indicate inserted content within "ordinary" HTML, while others construct the HTML using a different syntax (for example, using indentation and block names).</li> + <li>Performance/rendering time.</li> + <li>Features — you should consider whether the engines you look at have the following features available: + <ul> + <li>Layout inheritance: Allows you to define a base template and then "inherit" just the parts of it that you want to be different for a particular page. This is typically a better approach than building templates by including a number of required components or building a template from scratch each time.</li> + <li>"Include" support: Allows you to build up templates by including other templates.</li> + <li>Concise variable and loop control syntax.</li> + <li>Ability to filter variable values at template level (e.g. making variables upper-case, or formatting a date value).</li> + <li>Ability to generate output formats other than HTML (e.g. JSON or XML).</li> + <li>Support for asynchronous operations and streaming.</li> + <li>Can be used on the client as well as the server. If a templating engine can be used on the client this allows the possibility of serving data and having all or most of the rendering done client-side.</li> + </ul> + </li> +</ul> + +<div class="note"> +<p><strong>Tip:</strong> There are many resources on the Internet to help you compare the different options!</p> +</div> + +<p>For this project, we'll use the <a href="https://pugjs.org/api/getting-started.html">Pug</a> templating engine (this is the recently-renamed Jade engine), as this is one of the most popular Express/JavaScript templating languages and is supported out of the box by the generator.</p> + +<h3 id="What_CSS_stylesheet_engine_should_I_use">What CSS stylesheet engine should I use?</h3> + +<p>The <em>Express Application Generator</em> allows you to create a project that is configured to use the most common CSS stylesheet engines: <a href="http://lesscss.org/">LESS</a>, <a href="http://sass-lang.com/">SASS</a>, <a href="http://compass-style.org/">Compass</a>, <a href="http://stylus-lang.com/">Stylus</a>.</p> + +<div class="note"> +<p><strong>Note: </strong>CSS has some limitations that make certain tasks difficult. CSS stylesheet engines allow you to use more powerful syntax for defining your CSS and then compile the definition into plain-old CSS for browsers to use.</p> +</div> + +<p>As with templating engines, you should use the stylesheet engine that will allow your team to be most productive. For this project, we'll use the ordinary CSS (the default) as our CSS requirements are not sufficiently complicated to justify using anything else.</p> + +<h3 id="What_database_should_I_use">What database should I use?</h3> + +<p>The generated code doesn't use/include any databases. <em>Express</em> apps can use any <a href="https://expressjs.com/en/guide/database-integration.html">database mechanism</a> supported by <em>Node</em> (<em>Express</em> itself doesn't define any specific additional behavior/requirements for database management).</p> + +<p>We'll discuss how to integrate with a database in a later article.</p> + +<h2 id="Creating_the_project">Creating the project</h2> + +<p>For the sample <em>Local Library</em> app we're going to build, we'll create a project named <em>express-locallibrary-tutorial </em>using the <em>Pug</em> template library and no CSS stylesheet engine.</p> + +<p>First, navigate to where you want to create the project and then run the <em>Express Application Generator</em> in the command prompt as shown:</p> + +<pre class="brush: bash">express express-locallibrary-tutorial --view=pug +</pre> + +<p>The generator will create (and list) the project's files.</p> + +<pre class="brush: bash"> create : express-locallibrary-tutorial\ + create : express-locallibrary-tutorial\public\ + create : express-locallibrary-tutorial\public\javascripts\ + create : express-locallibrary-tutorial\public\images\ + create : express-locallibrary-tutorial\public\stylesheets\ + create : express-locallibrary-tutorial\public\stylesheets\style.css + create : express-locallibrary-tutorial\routes\ + create : express-locallibrary-tutorial\routes\index.js + create : express-locallibrary-tutorial\routes\users.js + create : express-locallibrary-tutorial\views\ + create : express-locallibrary-tutorial\views\error.pug + create : express-locallibrary-tutorial\views\index.pug + create : express-locallibrary-tutorial\views\layout.pug + create : express-locallibrary-tutorial\app.js + create : express-locallibrary-tutorial\package.json + create : express-locallibrary-tutorial\bin\ + create : express-locallibrary-tutorial\bin\www + + change directory: + > cd express-locallibrary-tutorial + + install dependencies: + > npm install + + run the app: + > SET DEBUG=express-locallibrary-tutorial:* & npm start</pre> + +<p>At the end of the output, the generator provides instructions on how you install the dependencies (as listed in the <strong>package.json</strong> file) and then how to run the application (the instructions above are for Windows; on Linux/macOS they will be slightly different).</p> + +<div class="blockIndicator note"> +<p><strong>Note:</strong> When using Windows, the && and & assumes you are using the Command Prompt. If you are using the new default PowerShell terminal do not concatenate the commands with && and &. Instead set the DEBUG environment variable with $ENV:DEBUG = "express-locallibrary-tutorial:*";. The npm start can be followed by the npm start. </p> +</div> + +<h2 id="Running_the_skeleton_website">Running the skeleton website</h2> + +<p>At this point, we have a complete skeleton project. The website doesn't actually <em>do</em> very much yet, but it's worth running it to show how it works.</p> + +<ol> + <li>First, install the dependencies (the <code>install</code> command will fetch all the dependency packages listed in the project's<strong> package.json</strong> file). + + <pre class="brush: bash">cd express-locallibrary-tutorial +npm install</pre> + </li> + <li>Then run the application. + <ul> + <li>On Windows, use this command: + <pre class="brush: bash">SET DEBUG=express-locallibrary-tutorial:* & npm start</pre> + </li> + <li>On macOS or Linux, use this command: + <pre class="brush: bash">DEBUG=express-locallibrary-tutorial:* npm start +</pre> + </li> + </ul> + </li> + <li>Then load <a href="http://localhost:3000/">http://localhost:3000/</a> in your browser to access the app.</li> +</ol> + +<p>You should see a browser page that looks like this:</p> + +<p><img alt="Browser for default Express app generator website" src="https://mdn.mozillademos.org/files/14375/ExpressGeneratorSkeletonWebsite.png" style="display: block; height: 403px; margin: 0px auto; width: 576px;"></p> + +<p>You have a working Express application, serving itself to <em>localhost:3000</em>.</p> + +<div class="note"> +<p><strong>Note:</strong> You could also start the app just using the <code>npm start</code> command. Specifying the DEBUG variable as shown enables console logging/debugging. For example, when you visit the above page you'll see debug output like this:</p> + +<pre class="brush: bash">>SET DEBUG=express-locallibrary-tutorial:* & npm start + +> express-locallibrary-tutorial@0.0.0 start D:\github\mdn\test\exprgen\express-locallibrary-tutorial +> node ./bin/www + + express-locallibrary-tutorial:server Listening on port 3000 +0ms +GET / 304 490.296 ms - - +GET /stylesheets/style.css 200 4.886 ms - 111 +</pre> +</div> + +<h2 id="Enable_server_restart_on_file_changes">Enable server restart on file changes</h2> + +<p>Any changes you make to your Express website are currently not visible until you restart the server. It quickly becomes very irritating to have to stop and restart your server every time you make a change, so it is worth taking the time to automate restarting the server when needed.</p> + +<p>One of the easiest such tools for this purpose is <a href="https://github.com/remy/nodemon">nodemon</a>. This is usually installed globally (as it is a "tool"), but here we'll install and use it locally as a <em>developer dependency</em>, so that any developers working with the project get it automatically when they install the application. Use the following command in the root directory for the skeleton project:</p> + +<pre class="brush: bash">npm install --save-dev nodemon</pre> + +<p>If you still choose to install <a href="https://github.com/remy/nodemon">nodemon</a> globally to your machine, and not only to your project's <strong>package.json</strong> file:</p> + +<pre class="brush: bash">npm install -g nodemon</pre> + +<p>If you open your project's <strong>package.json</strong> file you'll now see a new section with this dependency:</p> + +<pre class="brush: json"> "devDependencies": { + "nodemon": "^1.18.10" +} +</pre> + +<p>Because the tool isn't installed globally we can't launch it from the command line (unless we add it to the path) but we can call it from an NPM script because NPM knows all about the installed packages. Find the the <code>scripts</code> section of your package.json. Initially, it will contain one line, which begins with <code>"start"</code>. Update it by putting a comma at the end of that line, and adding the <code>"devstart"</code> line seen below:</p> + +<pre class="brush: json"> "scripts": { + "start": "node ./bin/www"<strong>,</strong> +<strong> "devstart": "nodemon ./bin/www"</strong> + }, +</pre> + +<p>We can now start the server in almost exactly the same way as previously, but with the <code>devstart</code> command specified:</p> + +<ul> + <li>On Windows, use this command: + <pre class="brush: bash">SET DEBUG=express-locallibrary-tutorial:* & npm <strong>run devstart</strong></pre> + </li> + <li>On macOS or Linux, use this command: + <pre class="brush: bash">DEBUG=express-locallibrary-tutorial:* npm <strong>run devstart</strong> +</pre> + </li> +</ul> + +<div class="note"> +<p><strong>Note:</strong> Now if you edit any file in the project the server will restart (or you can restart it by typing <code>rs</code> on the command prompt at any time). You will still need to reload the browser to refresh the page.</p> + +<p>We now have to call "<code>npm run <em><scriptname></em></code>" rather than just <code>npm start</code>, because "start" is actually an NPM command that is mapped to the named script. We could have replaced the command in the <em>start</em> script but we only want to use <em>nodemon</em> during development, so it makes sense to create a new script command.</p> +</div> + +<h2 id="The_generated_project">The generated project</h2> + +<p>Let's now take a look at the project we just created.</p> + +<h3 id="Directory_structure">Directory structure</h3> + +<p>The generated project, now that you have installed dependencies, has the following file structure (files are the items <strong>not</strong> prefixed with "/"). The <strong>package.json</strong> file defines the application dependencies and other information. It also defines a startup script that will call the application entry point, the JavaScript file <strong>/bin/www</strong>. This sets up some of the application error handling and then loads <strong>app.js</strong> to do the rest of the work. The app routes are stored in separate modules under the <strong>routes/</strong> directory. The templates are stored under the /<strong>views</strong> directory.</p> + +<pre>/express-locallibrary-tutorial + <strong>app.js</strong> + /bin + <strong>www</strong> + <strong>package.json</strong> + <strong>package-lock.json</strong> + /node_modules + [about 6700 subdirectories and files] + /public + /images + /javascripts + /stylesheets + <strong>style.css</strong> + /routes + <strong>index.js</strong> + <strong>users.js</strong> + /views + <strong>error.pug</strong> + <strong>index.pug</strong> + <strong>layout.pug</strong> + +</pre> + +<p>The following sections describe the files in a little more detail.</p> + +<h3 id="package.json">package.json</h3> + +<p>The <strong>package.json </strong>file defines the application dependencies and other information:</p> + +<pre class="brush: json">{ + "name": "express-locallibrary-tutorial", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www", + "devstart": "nodemon ./bin/www" + }, + "dependencies": { + "cookie-parser": "~1.4.3", + "debug": "~2.6.9", + "express": "~4.16.0", + "http-errors": "~1.6.2", + "morgan": "~1.9.0", + "pug": "2.0.0-beta11" + }, + "devDependencies": { + "nodemon": "^1.18.10" + } +} +</pre> + +<p>The dependencies include the <em>express</em> package and the package for our selected view engine (<em>pug</em>). In addition, we have the following packages that are useful in many web applications:</p> + +<ul> + <li><a href="https://www.npmjs.com/package/cookie-parser">cookie-parser</a>: Used to parse the cookie header and populate <code>req.cookies</code> (essentially provides a convenient method for accessing cookie information).</li> + <li><a href="https://www.npmjs.com/package/debug">debug</a>: A tiny node debugging utility modeled after node core's debugging technique.</li> + <li><a href="https://www.npmjs.com/package/morgan">morgan</a>: An HTTP request logger middleware for node.</li> + <li><a href="https://www.npmjs.com/package/http-errors">http-errors</a>: Create HTTP errors where needed (for express error handling).</li> +</ul> + +<p>The scripts section defines a "<em>start</em>" script, which is what we are invoking when we call <code>npm start</code> to start the server. From the script definition, you can see that this actually starts the JavaScript file <strong>./bin/www</strong> with <em>node</em>. It also defines a "<em>devstart</em>" script, which we invoke when calling <code>npm run devstart</code> instead. This starts the same <strong>./bin/www</strong> file, but with <em>nodemon</em> rather than <em>node</em>.</p> + +<pre class="brush: json"> "scripts": { + "start": "node ./bin/www", + "devstart": "nodemon ./bin/www" + }, +</pre> + +<h3 id="www_file">www file</h3> + +<p>The file <strong>/bin/www</strong> is the application entry point! The very first thing this does is <code>require()</code> the "real" application entry point (<strong>app.js</strong>, in the project root) that sets up and returns the <code><a href="http://expressjs.com/en/api.html">express()</a></code> application object.</p> + +<pre class="brush: js">#!/usr/bin/env node + +/** + * Module dependencies. + */ + +<strong>var app = require('../app');</strong> +</pre> + +<div class="note"> +<p><strong>Note:</strong> <code>require()</code> is a global node function that is used to import modules into the current file. Here we specify <strong>app.js</strong> module using a relative path and omitting the optional (.<strong>js</strong>) file extension.</p> +</div> + +<p>The remainder of the code in this file sets up a node HTTP server with <code>app</code> set to a specific port (defined in an environment variable or 3000 if the variable isn't defined), and starts listening and reporting server errors and connections. For now you don't really need to know anything else about the code (everything in this file is "boilerplate"), but feel free to review it if you're interested.</p> + +<h3 id="app.js">app.js</h3> + +<p>This file creates an <code>express</code> application object (named <code>app</code>, by convention), sets up the application with various settings and middleware, and then exports the app from the module. The code below shows just the parts of the file that create and export the app object:</p> + +<pre class="brush: js"><code>var express = require('express'); +var app = express(); +... +</code>module.exports = app; +</pre> + +<p>Back in the <strong>www</strong> entry point file above, it is this <code>module.exports</code> object that is supplied to the caller when this file is imported.</p> + +<p>Let's work through the <strong>app.js</strong> file in detail. First, we import some useful node libraries into the file using <code>require()</code>, including http-errors, <em>express</em>, <em>morgan</em> and <em>cookie-parser</em> that we previously downloaded for our application using NPM; and <em>path</em>, which is a core Node library for parsing file and directory paths.</p> + +<pre class="brush: js">var createError = require('http-errors'); +var express = require('express'); +var path = require('path'); +var cookieParser = require('cookie-parser'); +var logger = require('morgan'); +</pre> + +<p>Then we <code>require()</code> modules from our routes directory. These modules/files contain code for handling particular sets of related "routes" (URL paths). When we extend the skeleton application, for example to list all books in the library, we will add a new file for dealing with book-related routes.</p> + +<pre class="brush: js">var indexRouter = require('./routes/index'); +var usersRouter = require('./routes/users'); +</pre> + +<div class="note"> +<p><strong>Note:</strong> At this point, we have just <em>imported</em> the module; we haven't actually used its routes yet (this happens just a little bit further down the file).</p> +</div> + +<p>Next, we create the <code>app</code> object using our imported <em>express</em> module, and then use it to set up the view (template) engine. There are two parts to setting up the engine. First, we set the '<code>views</code>' value to specify the folder where the templates will be stored (in this case the subfolder <strong>/views</strong>). Then we set the '<code>view engine</code>' value to specify the template library (in this case "pug").</p> + +<pre class="brush: js">var app = express(); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'pug'); +</pre> + +<p>The next set of functions call <code>app.use()</code> to add the <em>middleware</em> libraries into the request handling chain. In addition to the 3rd party libraries we imported previously, we use the <code>express.static</code> middleware to get <em>Express</em> to serve all the static files in the <strong>/public</strong> directory in the project root.</p> + +<pre class="brush: js">app.use(logger('dev')); +app.use(express.json()); +app.use(express.urlencoded({ extended: false })); +app.use(cookieParser()); +<strong>app.use(express.static(path.join(__dirname, 'public')));</strong> +</pre> + +<p>Now that all the other middleware is set up, we add our (previously imported) route-handling code to the request handling chain. The imported code will define particular routes for the different <em>parts</em> of the site:</p> + +<pre class="brush: js">app.use('/', indexRouter); +app.use('/users', usersRouter); +</pre> + +<div class="note"> +<p><strong>Note:</strong> The paths specified above ('/' and '<code>/users'</code>) are treated as a prefix to routes defined in the imported files. So for example, if the imported <strong>users</strong> module defines a route for <code>/profile</code>, you would access that route at <code>/users/profile</code>. We'll talk more about routes in a later article.</p> +</div> + +<p id="error_handling">The last middleware in the file adds handler methods for errors and HTTP 404 responses.</p> + +<pre class="brush: js">// catch 404 and forward to error handler +app.use(function(req, res, next) { + next(createError(404)); +}); + +// error handler +app.use(function(err, req, res, next) { + // set locals, only providing error in development + res.locals.message = err.message; + res.locals.error = req.app.get('env') === 'development' ? err : {}; + + // render the error page + res.status(err.status || 500); + res.render('error'); +}); +</pre> + +<p>The Express application object (app) is now fully configured. The last step is to add it to the module exports (this is what allows it to be imported by <strong>/bin/www</strong>).</p> + +<pre class="brush: js">module.exports = app;</pre> + +<h3 id="Routes">Routes</h3> + +<p>The route file <strong>/routes/users.js</strong> is shown below (route files share a similar structure, so we don't need to also show <strong>index.js</strong>). First, it loads the <em>express</em> module and uses it to get an <code>express.Router</code> object. Then it specifies a route on that object and lastly exports the router from the module (this is what allows the file to be imported into <strong>app.js</strong>).</p> + +<pre class="brush: js">var express = require('express'); +var router = express.Router(); + +/* GET users listing. */ +<strong>router.get('/', function(req, res, next) { + res.send('respond with a resource');</strong> +}); + +module.exports = router; +</pre> + +<p>The route defines a callback that will be invoked whenever an HTTP <code>GET</code> request with the correct pattern is detected. The matching pattern is the route specified when the module is imported ('<code>/users</code>') plus whatever is defined in this file ('<code>/</code>'). In other words, this route will be used when an URL of <code>/users/</code> is received.</p> + +<div class="note"> +<p><strong>Tip:</strong> Try this out by running the server with node and visiting the URL in your browser: <a href="http://localhost:3000/users/">http://localhost:3000/users/</a>. You should see a message: 'respond with a resource'.</p> +</div> + +<p>One thing of interest above is that the callback function has the third argument '<code>next</code>', and is hence a middleware function rather than a simple route callback. While the code doesn't currently use the <code>next</code> argument, it may be useful in the future if you want to add multiple route handlers to the <code>'/'</code> route path.</p> + +<h3 id="Views_(templates)">Views (templates)</h3> + +<p>The views (templates) are stored in the <strong>/views</strong> directory (as specified in <strong>app.js</strong>) and are given the file extension <strong>.pug</strong>. The method <code><a href="http://expressjs.com/en/4x/api.html#res.render">Response.render()</a></code> is used to render a specified template along with the values of named variables passed in an object, and then send the result as a response. In the code below from <strong>/routes/index.js</strong> you can see how that route renders a response using the template "index" passing the template variable "title".</p> + +<pre class="brush: js">/* GET home page. */ +router.get('/', function(req, res, next) { + res.render('index', { title: 'Express' }); +}); +</pre> + +<p>The corresponding template for the above route is given below (<strong>index.pug</strong>). We'll talk more about the syntax later. All you need to know for now is that the <code>title</code> variable (with value <code>'Express'</code>) is inserted where specified in the template.</p> + +<pre>extends layout + +block content + h1= title + p Welcome to #{title} +</pre> + +<h2 id="Challenge_yourself">Challenge yourself</h2> + +<p>Create a new route in <strong>/routes/users.js</strong> that will display the text "<em>You're so cool"</em> at URL <code>/users/cool/</code>. Test it by running the server and visiting <a href="http://localhost:3000/users/cool/">http://localhost:3000/users/cool/</a> in your browser</p> + +<ul> +</ul> + +<h2 id="Summary">Summary</h2> + +<p>You have now created a skeleton website project for the <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Local Library</a> and verified that it runs using <em>node</em>. Most importantly, you also understand how the project is structured, so you have a good idea where we need to make changes to add routes and views for our local library.</p> + +<p>Next, we'll start modifying the skeleton so that it works as a library website.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://expressjs.com/en/starter/generator.html">Express application generator</a> (Express docs)</li> + <li><a href="https://expressjs.com/en/guide/using-template-engines.html">Using template engines with Express</a> (Express docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introduction</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Setting up a Node (Express) development environment</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/express_nodejs/tutorial_local_library_website/index.html b/files/pt-br/learn/server-side/express_nodejs/tutorial_local_library_website/index.html new file mode 100644 index 0000000000..718e207e86 --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/tutorial_local_library_website/index.html @@ -0,0 +1,93 @@ +--- +title: 'Express: Tutorial para criar o site de uma Biblioteca Local' +slug: Learn/Server-side/Express_Nodejs/Tutorial_local_library_website +tags: + - Express + - Iniciante + - Introdução + - Node + - desenvolvimento-web + - nodejs + - server-side +translation_of: Learn/Server-side/Express_Nodejs/Tutorial_local_library_website +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs")}}</div> + +<p class="summary">Este artigo tem como objetivo explicar o que você vai aprender ao longo dos próximo tutoriais e dar uma visão geral do projeto que vamos desenvolver: um site de "local library" (Biblioteca Local, em tradução livre).</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Leia a <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Express_Nodejs/Introdu%C3%A7%C3%A3o">Indrodução ao Express</a>. Para os próximos artigos, você também precisa ler <a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Express_Nodejs/ambiente_de_desenvolvimento">Conhecendo Node como ambiente de desenvolvimento</a>. </td> + </tr> + <tr> + <th scope="row">Objetivos:</th> + <td>Apresentar a aplicação que será desenvolvida ao longo deste tutorial e permitir aos leitores entender quais tópicos serão abordados.</td> + </tr> + </tbody> +</table> + +<h2 id="Visão_Geral">Visão Geral</h2> + +<p>Bem-vindo ao tutorial MDN "Express: Tutorial para criar o site de uma Biblioteca Local", no qual vamos desenvolver um website para gerenciar o catálogo de uma biblioteca. </p> + +<p>Neste passo a passo você vai: </p> + +<ul> + <li>Usar a ferramenta <em>Express Aplication Generator (Gerador de Aplicações Express) </em>para<em> </em>criar a estrutura do site e da aplicação. </li> + <li>Iniciar e encerrar o Web Server do Node.</li> + <li>Usar um banco de dados para armazenar os dados de sua aplicação.</li> + <li>Criar caminhos para a requisição de diferentes informações e templates ("views") para renderizar os dados em arquivos HTML no browser.</li> + <li>Trabalhar com formulários.</li> + <li>Subir sua aplicação para o ambiente de produção (deploy).</li> +</ul> + +<p>Alguns dos itens acima você já conhecebe bem, outros você sabe apenas um pouco. Não se preocupe. Ao final do tutorial, você saberá o sucifiente para desenvolver, por conta própria, um simples app Express.</p> + +<h2 id="O_site_da_Biblioteca_Local">O site da Biblioteca Local</h2> + +<p><em>LocalLibrary</em> ou Biblioteca Local é o nome do website que vamos criar durante os tutoriais. O objetivo do site é prover um catálogo para uma pequena biblioteca, onde usuários podem pesquisar livros disponíveis e gerenciar suas contas. </p> + +<p>Esse exemplo foi escolhido cuidadosamente. Isso porque para construir a "biblioteca" vamos utilizar recursos básicos e fundamentais do Express, além de funcionalidades e conceitos que você poderá aplicar em qualquer outro website:</p> + +<ul> + <li>Em nossos primeiros artigos vamos criar uma biblioteca virtual na qual os usuários poderão procurar quais livros estão disponíveis para empréstimo. Tal funcionalidade nos exigirá entender operações padrões em sites web, como leituras e visualizações de conteúdos registrados em banco de dados.</li> + <li>Durante nosso trabalho, o exemplo da biblioteca se estenderá naturalmente para mais funcionalidades e informações disponíveis na biblioteca. Por exemplo: permitir que novos livros sejam adicionados aos catálogos. Somente essa <em>feature</em> nos permitirá aprender sobre o uso de formulários e autenticação de usuários.</li> +</ul> + +<p>Apesar de ser um exemplo bem extenso, nossa Biblioteca Local apresentará o mínimo de informações para ajudar você a entender e se desenvolver melhor no uso do Express. A aplicação terá informações sobre livros, cópias de livros, autores e outras informações-chave. Nós não vamos, no entanto, armazenar informações sobre outros itens que a biblioteca pode emprestar e nem vamos oferecer a infraestrutura necessária para suportar os serviços de uma biblioteca grande (de verdade).</p> + +<h2 id="Estou_perdido_onde_encontro_o_código-fonte">Estou perdido, onde encontro o código-fonte?</h2> + +<p>Com o avanço nos tutoriais, forneceremos trechos de códigos para você copiar e colar. Você também receberá trechos apenas com códigos iniciais para completá-los e aprimorá-los por conta própria.</p> + +<p>Dica: Em vez de simplesmente copiar e colar todos os códigos, a sugestão é digitá-los. Isso ajuda você a se familiarizar com a sintaxe, melhorando o nível de aprendizado.</p> + +<p>Se ficar perdido no meio do caminho, fique calmo. Você pode acessar o código inteiro pelo<a href="https://github.com/mdn/express-locallibrary-tutorial"> Github</a>.</p> + +<div class="note"> +<p><strong>Nota:</strong> As versões específicas do Node, Express e outros módulos que adotados no tutorial estão listados no arquivo <a href="https://github.com/mdn/express-locallibrary-tutorial/blob/master/package.json">package.json</a>.</p> +</div> + +<h2 id="Sumário">Sumário</h2> + +<p>Agora que você entedeu o que é o site "Biblioteca Local " e o que vamos aprender ao longo do projeto, é hora de criar nossa estrutura de pastas e arquivos.</p> + +<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Express_Nodejs/Introdu%C3%A7%C3%A3o">Indrodução ao Express</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Express_Nodejs/ambiente_de_desenvolvimento">Conhecendo Node como ambiente de desenvolvimento</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/first_steps/client-server_overview/index.html b/files/pt-br/learn/server-side/first_steps/client-server_overview/index.html new file mode 100644 index 0000000000..57dd82946d --- /dev/null +++ b/files/pt-br/learn/server-side/first_steps/client-server_overview/index.html @@ -0,0 +1,333 @@ +--- +title: Visão geral do cliente-servidor +slug: Learn/Server-side/First_steps/Client-Server_overview +tags: + - Desenvolvimento Web + - Iniciante + - servidores + - site dinâmico + - site estatico +translation_of: Learn/Server-side/First_steps/Client-Server_overview +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/First_steps/Introduction", "Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}</div> + +<p class="summary">Agora que você conhece o propósito e os benefícios potenciais da programação do lado do servidor, examinaremos em detalhes o que acontece quando um servidor recebe uma "solicitação dinâmica" de um navegador. Como a maioria dos códigos do lado servidor do site lida com solicitações e respostas de maneiras semelhantes, isso o ajudará a entender o que você precisa fazer ao escrever a maior parte do seu próprio código.</p> + +<p class="summary"></p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré requisitos:</th> + <td>Conhecimento básico em informática. Uma compreensão básica do que é um servidor web.</td> + </tr> + <tr> + <th scope="row">Objetivos:</th> + <td>Entender as interações entre cliente e servidor em um website dinâmico e, em particular, quais operações precisam ser realizadas pelo código no servidor.</td> + </tr> + </tbody> +</table> + +<p>Não há código real em discussão porque ainda não escolhemos um framework web para escrever nosso código. No entanto essa discussão é muito relevante, porque o comportamento descrito deve ser implementado pelo seu código no servidor, independentemente de qual linguagem de programação ou framework web você escolha.</p> + +<h2 id="Web_servers_e_HTTP_uma_introdução">Web servers e HTTP (uma introdução)</h2> + +<p>Navegadores Web se comunicam com <a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_web_server">servidores Web</a> usando o <strong>H</strong>yper<strong>T</strong>ext<strong>T</strong>ransfer <strong>P</strong>rotocol (<a href="https://wiki.developer.mozilla.org/en-US/docs/Web/HTTP">HTTP</a>). Quando você clica em um link em uma página web, envia um formulário, ou faz uma pesquisa, o browser envia uma Requisição HTTP para o servidor.</p> + +<p>A requisição inclui:</p> + +<ul> + <li>Uma URL que identifica o servidor e o recurso de destino(e.g. por exemplo, um arquivo HTML, um determinado ponto de dados no servidor ou uma ferramenta a ser executada).</li> + <li>Um método que define a ação necessária(por exemplo, para obter um arquivo ou para salvar ou atualizar alguns dados). Os diferentes métodos e suas ações associadas estão listados abaixo : + <ul> + <li><code>GET</code>: Obtenha um recurso específico(por exemplo, um arquivo contendo informações sobre um produto ou uma lista de produtos) .</li> + <li><code>POST</code>: Crie um novo recurso(por exemplo, adicione um novo artigo a uma wiki, adicione um novo contato a um banco de dados e entre outros) .</li> + <li><code>HEAD</code>: Obtenha as informações de metadados sobre um recurso específico, sem obter o corpo, como o GET faria. Você pode, por exemplo, usar uma solicitação HEAD para descobrir a última vez que um recurso foi atualizado e, em seguida, usar a solicitação GET(mais "CARA") para baixar o recurso se ele tiver sido alterado.</li> + <li><code>PUT</code>: Atualize um recurso existente(ou crie um novo se ele não existir).</li> + <li><code>DELETE</code>: Apague um recurso específico.</li> + <li><code>TRACE</code>, <code>OPTIONS</code>, <code>CONNECT</code>, <code>PATCH</code>: Esses métodos são para tarefas menos comuns/avançadas, não os cobriremos por aqui.</li> + </ul> + </li> + <li>Informações adicionais podem ser codificadas com a solicitação(por exemplo, dados de formulário HTML). As informações podem ser codificadas como : + <ul> + <li>Paramêtros de URL : Solicitações <code>GET</code> codificam dados na URL enviada ao servidor, adicionando pares de nome/valor ao final dela— por exemplo, <code>http://mysite.com<strong>?name=Fred&age=11</strong></code>. Você sempre tem um ponto de interrogação (<code>?</code>) separando o resto da URL dos paramêtros de URL, um sinal de igual (<code>=</code>) separando cada nome de seu valor associado , e um "E" comercial (<code>&</code>) separando cada par. Os paramêtros URL são inerentemente inseguros, pois podem ser alterados pelos usuários e reenviados. Como resultado, os parâmetros de URL/ solicitações GET não são usados para solicitações que atualizam dados no servidor.</li> + <li><code>POST</code> data(dados de postagem). As solicitações POST adicionam novos recursos, cujos dados são codificados no corpo da solicitação.</li> + <li>Cookies do lado do cliente. Os cookies contêm dados de sessão sobre o cliente, incluindo chaves que o servidor pode usar para determinar seu status de login e permissões aos recursos.</li> + </ul> + </li> +</ul> + +<p>Os servidores da web aguardam as mensagens de solicitação do cliente, processam-nas quando chegam e respondem ao navegador da web com uma mensagem de resposta HTTP. A resposta contém( <a href="/en-US/docs/Web/HTTP/Status">HTTP Response status code</a>) um código de status de resposta HTTP que indica se a solicitação foi bem sucedida ou não (e.g. "<code>200 OK</code>" para sucesso, "<code>404 Not Found</code>" se o recurso não puder ser encontrado, "<code>403 Forbidden</code>" se o usuário não estiver autorizado para ver o recurso, etc). O corpo de uma resposta bem sucedida a uma solicitação <code>GET</code> conteria o recurso solicitado.</p> + +<p>Quando uma página HTML é retornada, ela é processada pelo navegador da web. Como parte do processamento, o navegador pode descobrir links para outros recursos (por exemplo, uma página HTML geralmente faz referência a páginas JavaScript e CSS) e enviará solicitações HTTP separadas para baixar esses arquivos.</p> + +<p>Os sites estáticos e dinâmicos (discutidos nas seções a seguir) usam exatamente o mesmo protocolo / padrões de comunicação.</p> + +<h3 id="Exemplo_de_requisiçãoresposta_GET">Exemplo de requisição/resposta GET</h3> + +<p>Você pode fazer uma simples requisição GET clicando em um link ou buscando em um site (como uma simples ferramenta de pesquisa). Por exemplo, a requisição HTTP enviada quando você realiza uma busa na MDN pelo termo "cliente servidor visão geral" será muito parecido com o texto mostrado abaixo (não será identico porque partes da mensagem depente de seu navegador/configuração.</p> + +<div class="note"> +<p>O formato das mensagens HTTP é definido em um "padrão da web" (<a href="http://www.rfc-editor.org/rfc/rfc7230.txt">RFC7230</a>). Você não precisa saber esse nível de detalhe, mas pelo menos agora você sabe de onde vem tudo isso.</p> +</div> + +<h4 id="A_requisição">A requisição</h4> + +<p>Cada linha da solicitação contém informações sobre ela. A primeira parte é chamada de <strong>header</strong>, e contém informações úteis sobre o pedido, Da mesma forma que um <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">HTML head</a> contém informações úteis sobre um documento HTML(mas não o conteúdo real em si, que está no corpo):</p> + +<pre class="notranslate">GET https://developer.mozilla.org/en-US/search?q=client+server+overview&topic=apps&topic=html&topic=css&topic=js&topic=api&topic=webdev HTTP/1.1 +Host: developer.mozilla.org +Connection: keep-alive +Pragma: no-cache +Cache-Control: no-cache +Upgrade-Insecure-Requests: 1 +User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 +Referer: https://developer.mozilla.org/en-US/ +Accept-Encoding: gzip, deflate, sdch, br +<code>Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7</code> +Accept-Language: en-US,en;q=0.8,es;q=0.6 +Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; csrftoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT; dwf_section_edit=False; dwf_sg_task_completion=False; _gat=1; _ga=GA1.2.1688886003.1471911953; ffo=true +</pre> + +<p>A primeira e a segunda linhas contêm a maioria das informações sobre as quais falamos acima:</p> + +<ul> + <li>O tipo de requisição (<code>GET</code>).</li> + <li>A URL do recurso de destino (<code>/en-US/search</code>).</li> + <li>Os parâmetros de URL (<code>q=client%2Bserver%2Boverview&topic=apps&topic=html&topic=css&topic=js&topic=api&topic=webdev</code>).</li> + <li>O site de destino(developer.mozilla.org).</li> + <li>O final da primeira linha inclui uma string curta que identifica a versão e especifica o protocolo (<code>HTTP/1.1</code>).</li> +</ul> + +<p>A linha final contém informações sobre os cookies do lado do cliente - você pode ver neste caso que o cookie inclui um id para gerenciar as sessões (<code>Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; ...</code>).</p> + +<p>As linhas restantes contêm informações sobre o navegador usado e o tipo de respostas que ele pode manipular. Por exemplo, você pode ver aqui que:</p> + +<ul> + <li>Meu navegador(<code>User-Agent</code>) é o Mozilla Firefox (<code>Mozilla/5.0</code>).</li> + <li>Pode aceitar informações comprimidas gzip(<code>Accept-Encoding: gzip</code>).</li> + <li>Pode aceitar o conjunto específico de caracteres (<code>Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7</code>) e idiomas (<code>Accept-Language: de,en;q=0.7,en-us;q=0.3</code>).</li> + <li>The <code>Referer</code> line indica o endereço da página web que continha o link para este recurso (i.e. a origem da requisição, <code>https://developer.mozilla.org/en-US/</code>).</li> +</ul> + +<p>As solicitações HTTP também podem ter um corpo, mas está vazio neste caso</p> + +<h4 id="A_resposta">A resposta</h4> + +<p>A primeira parte da resposta para esta solicitação é mostrada abaixo. O header(cabeçalho) contém informações, como as seguintes:</p> + +<ul> + <li>A primeira linha contém o código de resposta <code>200 OK</code>, o que nos diz que a solicitação foi bem sucedida.</li> + <li>Podemos ver que a resposta é <code>text/html</code> formatada (<code>Content-Type</code>).</li> + <li>Também podemos ver que ele usa o conjunto de caracteres UTF-8 (<code>Content-Type: text/html; charset=utf-8</code>).</li> + <li>O head também nos diz o quão grande é (<code>Content-Length: 41823</code>).</li> +</ul> + +<p>No final da mensagem vemos o conteúdo do corpo( <strong>body</strong> content) — que contém o HTML real retornado pela solicitação.</p> + +<pre class="brush: html notranslate">HTTP/1.1 200 OK +Server: Apache +X-Backend-Server: developer1.webapp.scl3.mozilla.com +Vary: Accept,Cookie, Accept-Encoding +Content-Type: text/html; charset=utf-8 +Date: Wed, 07 Sep 2016 00:11:31 GMT +Keep-Alive: timeout=5, max=999 +Connection: Keep-Alive +X-Frame-Options: DENY +Allow: GET +X-Cache-Info: caching +Content-Length: 41823 + + + +<!DOCTYPE html> +<html lang="en-US" dir="ltr" class="redesign no-js" data-ffo-opensanslight=false data-ffo-opensans=false > +<head prefix="og: http://ogp.me/ns#"> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=Edge"> + <script>(function(d) { d.className = d.className.replace(/\bno-js/, ''); })(document.documentElement);</script> + ... +</pre> + +<p>O restante do header da resposta inclui informações sobre a resposta (por exemplo, quando ela foi gerada), o servidor e como ele espera que o navegador manipule a página(e.g. A linha <code>X-Frame-Options: DENY</code> diz ao navegador para não permitir que esta página seja incorporada em outros sites {{htmlelement("iframe")}} ).</p> + +<h3 id="Exemplo_de_requestsolicitaçãoresponseresposta_POST">Exemplo de request(solicitação)/response(resposta) POST</h3> + +<p>Um HTTP <code>POST</code> é feito quando você envia um formulário contendo informações a serem salvas no servidor.</p> + +<h4 id="A_requisição_2">A requisição</h4> + +<p>O texto abaixo mostra a solicitação HTTP feita quando um usuário envia novos detalhes de perfil neste site. O formato de requisição é quase o mesmo que o exemplo de solicitação <code>GET</code> mostrado anteriormente, embora a primeira linha reconheça esta solicitação como um <code>POST</code>. </p> + +<pre class="brush: html notranslate">POST https://developer.mozilla.org/en-US/profiles/hamishwillee/edit HTTP/1.1 +Host: developer.mozilla.org +Connection: keep-alive +Content-Length: 432 +Pragma: no-cache +Cache-Control: no-cache +Origin: https://developer.mozilla.org +Upgrade-Insecure-Requests: 1 +User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 +Content-Type: application/x-www-form-urlencoded +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 +Referer: https://developer.mozilla.org/en-US/profiles/hamishwillee/edit +Accept-Encoding: gzip, deflate, br +Accept-Language: en-US,en;q=0.8,es;q=0.6 +Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; _gat=1; csrftoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT; dwf_section_edit=False; dwf_sg_task_completion=False; _ga=GA1.2.1688886003.1471911953; ffo=true + +csrfmiddlewaretoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT&user-username=hamishwillee&user-fullname=Hamish+Willee&user-title=&user-organization=&user-location=Australia&user-locale=en-US&user-timezone=Australia%2FMelbourne&user-irc_nickname=&user-interests=&user-expertise=&user-twitter_url=&user-stackoverflow_url=&user-linkedin_url=&user-mozillians_url=&user-facebook_url=</pre> + +<p>A principal diferença é que o URL não possui parâmetros. Como você pode ver, as informações do formulário são codificadas no corpo da solicitação (por exemplo, o novo nome completo do usuário é definido usando: <code>&user-fullname=Hamish+Willee</code>).</p> + +<h4 id="A_resposta_2">A resposta</h4> + +<p>A resposta de solicitação é mostrada abaixo. O código de status "<code>302 Found</code>" diz ao navegador que a postagem foi bem sucedida, e que deve emitir uma segunda solicitação HTTP para carregar a página especificada no campo determinado( <code>Location</code> field). As informações são semelhantes às da resposta a uma solicitação <code>GET</code> .</p> + +<pre class="brush: html notranslate">HTTP/1.1 302 FOUND +Server: Apache +X-Backend-Server: developer3.webapp.scl3.mozilla.com +Vary: Cookie +Vary: Accept-Encoding +Content-Type: text/html; charset=utf-8 +Date: Wed, 07 Sep 2016 00:38:13 GMT +Location: https://developer.mozilla.org/en-US/profiles/hamishwillee +Keep-Alive: timeout=5, max=1000 +Connection: Keep-Alive +X-Frame-Options: DENY +X-Cache-Info: not cacheable; request wasn't a GET or HEAD +Content-Length: 0 +</pre> + +<div class="note"> +<p><strong>Note</strong>: As respostas e solicitações HTTP mostradas nesse exemplo foram capturadas utilizando o aplicativo <a href="https://www.telerik.com/download/fiddler">Fiddler</a> , mas você pode obter informações semelhantes utilizando web sniffers (e.g. <a href="http://websniffer.cc/">Websniffer</a>) ou extensões de navegador como o <a href="https://addons.mozilla.org/en-US/firefox/addon/httpfox/">HttpFox</a>. Você pode tentar isso sozinho. Use qualquer uma das ferramentas vinculadas e navegue por um site e edite as informações de perfil para ver os diferentes tipos de solicitações e respostas. A maioria dos navegadores possuem ferramentas que monitoram solicitações de rede(por exemplo, a ferramenta <a href="/en-US/docs/Tools/Network_Monitor">Network Monitor</a> no Firefox).</p> +</div> + +<h2 id="Sites_estáticos">Sites estáticos</h2> + +<p dir="ltr" id="tw-target-text">Um site estático é aquele que retorna o mesmo conteúdo codificado do servidor sempre que um recurso específico é solicitado. Por exemplo, se você tiver uma página sobre um produto em <code>/static/myproduct1.html</code>, esta mesma página será devolvida a todos os usuários. Se você adicionar outro produto semelhante ao seu site, você precisará adicionar outra página (e.g. <code>myproduct2.html</code>) e assim por diante. Isso pode começar a ficar realmente ineficiente - o que acontece quando você chega a milhares de páginas de produtos? Você repetiria muitos códigos em cada página (o modelo básico de página, estrutura, etc.) e, se quisesse alterar qualquer coisa na estrutura da página - como adicionar uma nova seção de "produtos relacionados", por exemplo -, tem que mudar cada página individualmente.</p> + +<div class="note"> +<p><strong>Note</strong>: Os sites estáticos são excelentes quando você tem um pequeno número de páginas e deseja enviar o mesmo conteúdo para todos os usuários. No entanto, eles podem ter um custo significativo para manter à medida que o número de páginas aumenta.</p> +</div> + +<p>Vamos recapitular como isso funciona, olhando novamente para o diagrama de arquitetura de site estático que vimos no último artigo.</p> + +<p><img alt="A simplified diagram of a static web server." src="https://mdn.mozillademos.org/files/13841/Basic%20Static%20App%20Server.png"></p> + +<p>Quando o usuário deseja navegar em uma página, O navegador envia uma solicitação HTTP <code>GET</code> especificando o URL dessa página HTML. O servidor recupera o documento solicitado de seu sistema de arquivos e retorna uma resposta HTTP contendo o documento e um <a href="/en-US/docs/Web/HTTP/Status">HTTP Response status code</a> de "<code>200 OK</code>" (indicando). O servidor pode retornar um diferente código de status, por exemplo "<code>404 Not Found</code>" se o arquivo não estiver presente no servidor, ou "<code>301 Moved Permanently</code>" se o arquivo existe, mas foi redirecionado para um local diferente.</p> + +<p>O servidor de um site estático sempre precisará processar solicitações GET, porque o servidor não armazena nenhum dado modificável. Ele também não altera suas respostas com base nos dados de solicitação HTTP (por exemplo, parâmetros de URL ou cookies).</p> + +<p>No entanto, entender como os sites estáticos funcionam é útil ao aprender a programação do lado do servidor, porque os sites dinâmicos lidam com solicitações de arquivos estáticos (CSS, JavaScript, imagens estáticas etc.) exatamente da mesma maneira.</p> + +<h2 id="Sites_dinâmicos">Sites dinâmicos</h2> + +<p>Um site dinâmico é aquele que pode gerar e retornar conteúdo com base no URL e nos dados de solicitação específicos (em vez de sempre retornar o mesmo arquivo embutido em código para um URL específico). Usando o exemplo de um site de produto, o servidor armazenaria "dados" do produto em um banco de dados em vez de arquivos HTML individuais. Ao receber uma solicitação HTTP <code>GET</code> para o produto , o servidor determina o ID do produto, busca os dados do banco de dados e, em seguida, constrói a página HTML para a resposta inserindo os dados em um modelo HTML. Isso tem grandes vantagens em relação a um site estático:</p> + +<p>O uso de um banco de dados permite que as informações do produto sejam armazenadas com eficiência de uma forma facilmente extensível, modificável e pesquisável</p> + +<p>O uso de modelos HTML torna muito fácil alterar a estrutura HTML, porque isso só precisa ser feito em um lugar, em um único modelo, e não em potencialmente milhares de páginas estáticas.</p> + +<h3 id="Anatomia_de_uma_solicitação_dinâmica">Anatomia de uma solicitação dinâmica</h3> + +<p dir="ltr" id="tw-target-text">Esta seção fornece uma visão geral passo a passo da solicitação HTTP "dinâmica" e do ciclo de resposta, com base no que vimos no último artigo com muito mais detalhes. Para "manter as coisas reais", usaremos o contexto de um site de gerente de equipe esportiva, onde um treinador pode selecionar o nome e o tamanho da equipe em um formulário HTML e receber uma sugestão de "melhor escalação" para o próximo jogo.</p> + +<p>O diagrama abaixo mostra os principais elementos do site do "treinador de equipe", juntamente com rótulos numerados para a sequência de operações quando o treinador acessa sua lista de "melhores equipes". As partes do site que o tornam dinâmico são o Web application(é assim que nos referiremos ao código do lado do servidor que processa solicitações HTTP e retorna respostas HTTP), o Banco de Dados, que contém informações sobre jogadores, times, treinadores e seus relacionamentos e os modelos HTML.</p> + +<p><img alt="This is a diagram of a simple web server with step numbers for each of step of the client-server interaction." src="https://mdn.mozillademos.org/files/13829/Web%20Application%20with%20HTML%20and%20Steps.png" style="height: 584px; width: 1226px;"></p> + +<p dir="ltr" id="tw-target-text">Após o treinador enviar o formulário com o nome da equipe e número de jogadores, a sequência de operações é:</p> + +<ol> + <li>O navegador cria uma solicitação HTTP <code>GET</code> para o servidor usando a URL base para o recurso(<code>/best</code>) e codifica o número do time e do jogador como parâmetros de URL (e.g. <code>/best?team=my_team_name&show=11)</code> ou como parte do padrão de URL (e.g. <code>/best/my_team_name/11/</code>). A solicitação <code>GET</code>é usada porque a solicitação está apenas buscando dados (não modificando dados).</li> + <li>O servidor da Web detecta que a solicitação é "dinâmica" e a encaminha ao Web application para o processamento (o servidor da Web determina como lidar com URLs diferentes com base nas regras de correspondência de padrões definidas em sua configuração).</li> + <li>O <em>Web Application</em> identifica que a intenção da solicitação é obter a "lista da melhor equipe" com base no URL<span>(</span><code>/best/</code><span>)</span>e descobre o nome da equipe necessária e o número de jogadores no URL. O Web application então obtém as informações necessárias do banco de dados (usando parâmetros "internos" adicionais para definir quais jogadores são os "melhores" e, possivelmente, também obtendo a identidade do treinador conectado a partir de um cookie do lado do cliente).</li> + <li>O Web application cria dinamicamente uma página HTML colocando os dados (do banco de dados) em espaços reservados dentro de um modelo HTML.</li> + <li> + <p dir="ltr" id="tw-target-text">O Web application retorna o HTML gerado para o navegador da Web (por meio do servidor da Web), junto com um código de status HTTP de 200 ("sucesso"). Se alguma coisa impedir que o HTML seja retornado, o Web application retornará outro código - por exemplo, "404" para indicar que a equipe não existe.</p> + </li> + <li>O navegador da Web começará a processar o HTML retornado, enviando solicitações separadas para obter qualquer outro arquivo CSS ou JavaScript ao qual faça referência (consulte a etapa 7).</li> + <li>O servidor da Web carrega arquivos estáticos do sistema de arquivos e os retorna ao navegador diretamente (novamente, o tratamento correto do arquivo é baseado nas regras de configuração e correspondência de padrão de URL).</li> +</ol> + +<p dir="ltr" id="tw-target-text">Uma operação para atualizar um registro no banco de dados seria tratada de forma semelhante, exceto que, como qualquer atualização de banco de dados, a solicitação HTTP do navegador deve ser codificada como uma solicitação <code>POST</code>. </p> + +<h3 id="Fazendo_outro_trabalho">Fazendo outro trabalho</h3> + +<p>O trabalho de um Web application é receber solicitações HTTP e retornar respostas HTTP. Embora interagir com um banco de dados para obter ou atualizar informações sejam tarefas muito comuns, o código pode fazer outras coisas ao mesmo tempo ou não interagir com um banco de dados.</p> + +<p dir="ltr" id="tw-target-text">Um bom exemplo de uma tarefa adicional que um Web application pode realizar seria enviar um e-mail aos usuários para confirmar seu registro no site. O site também pode realizar registro ou outras operações.</p> + +<h3 id="Retornando_algo_diferente_de_HTML">Retornando algo diferente de HTML</h3> + +<p dir="ltr" id="tw-target-text">O código do site do lado do servidor não precisa retornar snippets / arquivos HTML na resposta. Em vez disso, ele pode criar e retornar dinamicamente outros tipos de arquivos (texto, PDF, CSV, etc.) ou mesmo dados (JSON, XML, etc.).</p> + +<p>A ideia de retornar dados a um navegador da web para que ele possa atualizar dinamicamente seu próprio conteúdo ({{glossary("AJAX")}}) já existe há um bom tempo. Mais recentemente, os "aplicativos de página única" se tornaram populares, em que todo o site é escrito com um único arquivo HTML que é atualizado dinamicamente quando necessário. Os sites criados com esse estilo de aplicativo geram muitos custos computacionais do servidor para o navegador da web e podem resultar em sites que parecem se comportar muito mais como aplicativos nativos (altamente responsivos etc.).</p> + +<h2 id="Web_frameworks_simplificam_a_programação_da_Web_do_lado_do_servidor"><br> + Web frameworks simplificam a programação da Web do lado do servidor</h2> + +<p dir="ltr" id="tw-target-text">Os frameworks web do lado do servidor tornam a escrita de código para lidar com as operações descritas acima muito mais fácil.</p> + +<p dir="ltr" id="tw-target-text">Uma das operações mais importantes que eles executam é fornecer mecanismos simples para mapear URLs de diferentes recursos / páginas para funções de manipulador específicas. Isso torna mais fácil manter o código associado a cada tipo de recurso separado. Também traz benefícios em termos de manutenção, pois você pode alterar a URL usada para entregar um determinado recurso em um único local, sem ter que alterar a função do manipulador.</p> + +<p>Por exemplo, considere o seguinte código Django (Python) que mapeia dois padrões de URL para duas funções de visualização. O primeiro padrão garante que uma solicitação HTTP com um URL de recurso de <code>/best</code> será passado para uma função chamada <code>index()</code> no módulo <code>views</code>. Uma solicitação que tem o padrão "<code>/best/junior</code>", será passada para a fução view <code>junior()</code> .</p> + +<pre class="brush: python notranslate"># file: best/urls.py +# + +from django.conf.urls import url + +from . import views + +urlpatterns = [ + # example: /best/ + url(r'^$', views.index), + # example: /best/junior/ + url(r'^junior/$', views.junior), +]</pre> + +<div class="note"> +<p><strong>Nota </strong>: Os primeiros parâmetros da função <code>url()</code> pode parecer um pouco estranho (e.g. <code>r'^junior/$'</code>) porque eles usam uma técnica de correspondência de padrões chamada "expressões regulares"(RegEx, or RE). Você não precisa saber como as expressões regulares funcionam neste ponto, a não ser que elas nos permitam combinar padrões na URL (em vez dos valores codificados acima) e usá-los como parâmetros em nossas funções de visualização. Por exemplo, um RegEx realmente simples pode dizer "corresponde a uma única letra maiúscula, seguida por entre 4 e 7 letras minúsculas."</p> +</div> + +<p>O framework web também torna mais fácil para uma função de visualização buscar informações do banco de dados. A estrutura de nossos dados é definida em modelos, que são classes Python que definem os campos a serem armazenados no banco de dados subjacente. Se tivermos um modelo denominado Team com um campo de "team_type", então podemos usar uma sintaxe de consulta simples para recuperar todas as equipes que possuem um tipo específico.</p> + +<p>O exemplo abaixo obtém uma lista de todas as equipes que têm o exato (diferencia maiúsculas de minúsculas) <code>team_type</code> de "junior" —Observe o formato field name (<code>team_type</code>) seguido por sublinhado duplo e, em seguida, o tipo de correspondência a usar (neste caso <code>exact</code>). Existem muitos outros tipos de casos e podemos conectá-los em cadeia. Também podemos controlar a ordem e o número de resultados retornados.</p> + +<pre class="brush: python notranslate">#best/views.py + +from django.shortcuts import render + +from .models import Team + + +def junior(request): + list_teams = Team.objects.filter(team_type__exact="junior") + context = {'list': list_teams} + return render(request, 'best/index.html', context) +</pre> + +<p><code><font face="Arial, x-locale-body, sans-serif"><span style="background-color: #ffffff;">Depois da função </span></font>junior()</code> obter a lista de junior teams, é chamada a função <code>render()</code> , passando o original <code>HttpRequest</code>, um modelo HTML e um objeto de "contexto" que define as informações a serem incluídas no modelo. A função <code>render()</code> é uma função de conveniência que gera HTML usando um contexto e um modelo HTML e o retorna em um objeto <code>HttpResponse</code> .</p> + +<p dir="ltr" id="tw-target-text">Obviamente, os frameworks da Web podem ajudá-lo em muitas outras tarefas. Discutiremos muitos outros benefícios e algumas opções populares de estrutura da web no próximo artigo.</p> + +<h2 id="Resumo">Resumo</h2> + +<p dir="ltr" id="tw-target-text">Neste ponto, você deve ter uma boa visão geral das operações que o código do lado do servidor deve realizar e conhecer algumas das maneiras pelas quais uma framework Web do lado do servidor pode tornar isso mais fácil.</p> + +<p dir="ltr" id="tw-target-text">Em um módulo a seguir, vamos ajudá-lo a escolher o melhor Web Framework para seu primeiro site.</p> + +<p>{{PreviousMenuNext("Learn/Server-side/First_steps/Introduction", "Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Introduction">Introduction to the server side</a></li> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Client-Server_overview">Client-Server overview</a></li> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Web_frameworks">Server-side web frameworks</a></li> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Website_security">Website security</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/first_steps/index.html b/files/pt-br/learn/server-side/first_steps/index.html new file mode 100644 index 0000000000..fface84a77 --- /dev/null +++ b/files/pt-br/learn/server-side/first_steps/index.html @@ -0,0 +1,57 @@ +--- +title: Primeiros passos programando o site no servidor +slug: Learn/Server-side/First_steps +tags: + - Beginner + - CodingScripting + - Guide + - Intro + - Landing + - Learn + - NeedsTranslation + - Server-side programming + - TopicStub +translation_of: Learn/Server-side/First_steps +--- +<div>{{LearnSidebar}}</div> + +<p>Neste módulo nós iremos responder uma pergunta fundamental sobre programção server-side —"O que é?","Quão diferente é da programação client-side?", e "Por que é tão útil?".</p> + +<p>Em seguida vamos fornecer uma visão geral de alguns dos mais populares server-side web framworks juntamente com orientações sobre como selecionar o mais adequado framwork para criar seu primeiro website.</p> + +<p>Por fim, fornecemos um artigo introdutório de alto nível sobre segurança do servidor da web</p> + +<p>Finalmente,nós iremos fornecer uma introdução de alto nível. </p> + +<h2 id="Pré-requisitos">Pré-requisitos</h2> + +<p>Antes de começarmos este módulo,você não precisa ter nenhum conhecimento de programação server-side,ou mesmo qualquer outro tipo de programção.</p> + +<p>Entretanto,você precisa saber como a web funciona.Nós recomendamos que você leia primeiro os seguintes tópicos:</p> + +<ul> + <li>O que é um servidor?</li> + <li>Qual o software eu preciso para construir um website?</li> + <li>Como eu faço o upload de arquivos para um webserver?</li> +</ul> + +<p>Com o entendimento básico disso, você estará pronto para trabalhar nos módulos desta seção.</p> + +<h2 id="Guias">Guias</h2> + +<dl> + <dt> Introdução ao serve-side</dt> + <dd>Bem-vindo ao curso para iniciante de programação server-side do MDN! Neste primeiro artigo, examinaremos a programação server-side de alto nível, respondendo a perguntas como "O que é?", "Como ela difere da programação do lado do cliente?" E "Por que é tão útil?". Depois de ler este artigo, você entenderá o poder adicional disponível para sites por meio de codificação server-side.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/First_steps/Client-Server_overview">Visão geral do cliente-servidor</a></dt> + <dd>Agora que você conhece a finalidade e os benefícios potenciais da programação server-side , examinaremos em detalhes o que acontece quando um servidor recebe uma "solicitação dinâmica" de um navegador. Como o código server-side da maioria dos sites lida com solicitações e respostas de maneira semelhante, isso ajudará você a entender o que precisa fazer ao escrever seu próprio código.</dd> + <dt>Framework <a href="/en-US/docs/Learn/Server-side/First_steps/Web_frameworks"> server-side</a></dt> + <dd>No último artigo foi mostrado o que uma aplicação server-side precisa fazer para responder as solicitações de um navegador da web. Agora mostramos como as estruturas da Web podem simplificar essas tarefas e ajudá-lo a escolher o framework para seu primeiro aplicativo da Web server-side.</dd> + <dt>Segurança do website</dt> + <dd>A segurança do website exige vigilância em todos os aspectos,do desenvolvimento ao uso. Este artigo introdutório não fará de você um guru em segurança de website, mas ajudará você a entender quais as primeiras medidas importantes que você deve tomar para proteger seu aplicativo da Web contra as ameaças mais comuns.</dd> +</dl> + +<h2 id="Avaliação">Avaliação</h2> + + + +<p>Este módulo de "visão geral" não tem nenhuma avaliação porque ainda não mostramos nenhum código. Esperamos que, a esta altura, você tenha um bom entendimento dos tipos de funcionalidade que pode oferecer usando a programação do lado do servidor e que tenha tomado uma decisão sobre qual estrutura da web do lado do servidor usará para criar seu primeiro site.</p> diff --git a/files/pt-br/learn/server-side/first_steps/introdução/index.html b/files/pt-br/learn/server-side/first_steps/introdução/index.html new file mode 100644 index 0000000000..e5cc0b991c --- /dev/null +++ b/files/pt-br/learn/server-side/first_steps/introdução/index.html @@ -0,0 +1,237 @@ +--- +title: Introdução ao lado servidor +slug: Learn/Server-side/First_steps/Introdução +tags: + - Desenvolvimento Web + - Iniciante + - Introdução + - Programação + - Programação do lado do servidor + - Servidor + - programação do lado do cliente +translation_of: Learn/Server-side/First_steps/Introduction +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps")}}</div> + +<p dir="ltr" id="tw-target-text">Bem-vindo ao curso de programação do lado do servidor para iniciantes do MDN! Neste primeiro artigo, examinamos a programação do lado do servidor de um alto nível, respondendo a perguntas como "o que é?", "Como ela difere da programação do lado do cliente?" E "por que é tão útil?" . Depois de ler este artigo, você entenderá o poder adicional disponível para sites por meio da codificação do lado do servidor.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos :</th> + <td>Conhecimento básico de informática. Uma compreensão básica do que é um servidor web</td> + </tr> + <tr> + <th scope="row"> + <p>Objetivo :</p> + </th> + <td>Ganhar familiaridade com o que é programação do lado do servidor, o que ela pode fazer e como ela difere da programação do lado do cliente.</td> + </tr> + </tbody> +</table> + +<p dir="ltr" id="tw-target-text">A maioria dos sites de grande escala usa código do lado do servidor para exibir dinamicamente diferentes dados quando necessário, geralmente retirados de um banco de dados armazenado em um servidor e enviados ao cliente para serem exibidos por meio de algum código (por exemplo, HTML e JavaScript).</p> + +<p>Talvez o benefício mais significativo do código do lado do servidor seja que ele permite personalizar o conteúdo do site para usuários individuais. Os sites dinâmicos podem destacar o conteúdo que é mais relevante com base nas preferências e hábitos do usuário. Ele também pode tornar os sites mais fáceis de usar, armazenando preferências e informações pessoais - por exemplo, reutilizando os detalhes armazenados do cartão de crédito para agilizar os pagamentos subsequentes.</p> + +<p>Pode até permitir a interação com os usuários do site, enviando notificações e atualizações por e-mail ou por outros canais. Todos esses recursos permitem um envolvimento muito mais profundo com os usuários.</p> + +<p>No mundo moderno do desenvolvimento web, aprender sobre desenvolvimento do lado do servidor é extremamente recomendado.</p> + +<h2 id="O_que_é_programação_de_site_do_lado_do_servidor">O que é programação de site do lado do servidor ?</h2> + +<p>Navegadores comunicam-se com <a href="/en-US/docs/Learn/Common_questions/What_is_a_web_server">web servers</a> utilizando o <strong>H</strong>yper<strong>T</strong>ext <strong>T</strong>ransfer <strong>P</strong>rotocol ({{glossary("HTTP")}}). Quando você clica em um link em uma página da web, envia um formulário ou faz uma pesquisa, uma <strong>HTTP request(solicitação HTTP)</strong> é enviada do seu navegador para o servidor de destino.</p> + +<p dir="ltr" id="tw-target-text">A solicitação inclui uma URL que identifica o recurso afetado, um método que define a ação necessária (por exemplo, para obter, excluir ou postar o recurso) e pode incluir informações adicionais codificadas em parâmetros de URL(Os pares field-value(campo-valor) são enviados por meio de uma <a href="https://en.wikipedia.org/wiki/Query_string">query string</a>), como dados POST (dados enviados pelo método <a href="/en-US/docs/Web/HTTP/Methods/POST">HTTP POST </a>), ou em associado {{glossary("Cookie", "cookies")}} .</p> + +<p>Os servidores da web esperam por mensagens de solicitação do cliente, processam-nas quando chegam e respondem ao navegador da web com uma mensagem <strong>HTTP response</strong> . A resposta contém uma linha de status indicando se a solicitação foi bem-sucedida ou não (e.g. "HTTP/1.1 200 OK" for success). </p> + +<p dir="ltr" id="tw-target-text">O corpo de uma resposta bem-sucedida a uma solicitação conteria o recurso solicitado (por exemplo, uma nova página HTML ou uma imagem, etc ...), que poderia então ser exibido pelo navegador.</p> + +<h3 id="Sites_estáticos">Sites estáticos</h3> + +<p>O diagrama abaixo mostra uma arquitetura básica de servidor da web para um site estático (um site estático é aquele que retorna o mesmo conteúdo embutido em código do servidor sempre que um determinado recurso é solicitado). Quando um usuário deseja navegar para uma página, o navegador envia uma solicitação HTTP "GET" especificando seu URL.</p> + +<p>O servidor recupera o documento solicitado de seu sistema de arquivos e retorna uma resposta HTTP contendo o documento e um <a href="/en-US/docs/Web/HTTP/Status#Successful_responses">success status</a> (geralmente, 200 OK). Se o arquivo não puder ser recuperado por algum motivo, um status de erro será retornado(Veja <a href="/en-US/docs/Web/HTTP/Status#Client_error_responses">client error responses</a> e <a href="/en-US/docs/Web/HTTP/Status#Server_error_responses">server error responses</a>).</p> + +<p><img alt="A simplified diagram of a static web server." src="https://mdn.mozillademos.org/files/13841/Basic%20Static%20App%20Server.png" style="height: 223px; width: 800px;"></p> + +<h3 id="Sites_dinâmicos">Sites dinâmicos</h3> + +<p>Um site dinâmico é aquele em que parte do conteúdo da resposta é gerado dinamicamente, apenas quando necessário. Em um site dinâmico, as páginas HTML são normalmente criadas inserindo dados de um banco de dados em espaços reservados em modelos HTML (essa é uma maneira muito mais eficiente de armazenar grandes quantidades de conteúdo do que usar sites estáticos). </p> + +<p>Um site dinâmico pode retornar dados diferentes para um URL com base nas informações fornecidas pelo usuário ou preferências armazenadas e pode realizar outras operações como parte do retorno de uma resposta (e.g. enviando notificações).</p> + +<p>A maior parte do código para oferecer suporte a um site dinâmico deve ser executado no servidor. A criação desse código é denominado "<strong>server-side programming</strong>" (ou às vezes "<strong>back-end scripting</strong>").</p> + +<p>O diagrama abaixo mostra uma arquitetura simples para um site dinâmico. Como no diagrama anterior, os navegadores enviam solicitações HTTP para o servidor, então o servidor processa as solicitações e retorna as respostas HTTP apropriadas.</p> + +<p>As solicitações de recursos estáticos são tratadas da mesma maneira que para sites estáticos (recursos estáticos são quaisquer arquivos que não mudam - normalmente: CSS, JavaScript, imagens, arquivos PDF pré-criados etc.).</p> + +<p><img alt="A simplified diagram of a web server that uses server-side programming to get information from a database and construct HTML from templates. This is the same diagram as is in the Client-Server overview." src="https://mdn.mozillademos.org/files/13839/Web%20Application%20with%20HTML%20and%20Steps.png"></p> + +<p>As solicitações de recursos dinâmicos são encaminhadas (2) para o código do lado do servidor (mostrado no diagrama como uma web application). Para "solicitações dinâmicas", o servidor interpreta a solicitação, lê as informações necessárias do banco de dados (3), combina os dados recuperados com modelos HTML (4) e envia de volta uma resposta contendo o HTML gerado (5,6).</p> + +<div> +<h2 id="A_programação_do_lado_do_servidor_e_do_lado_cliente_são_iguais">A programação do lado do servidor e do lado cliente são iguais ?</h2> +</div> + +<p>Vamos agora voltar nossa atenção para o código envolvido na programação do lado do servidor e do lado do cliente. Em cada caso, o código é significativamente diferente:</p> + +<ul> + <li>Eles têm objetivos e propósitos diferentes.</li> + <li>Eles geralmente não usam as mesmas linguagens de programação (exceto JavaScript, que pode ser utilizado tanto no lado do servidor quanto no lado do cliente).</li> + <li>Eles são executados em diferentes ambientes do sistema operacional.</li> +</ul> + +<p>O código em execução no navegador é conhecido como <strong>client-side code </strong>e se preocupa principalmente em melhorar a aparência e o comportamento de uma página da web renderizada. Isso inclui selecionar e definir o estilo dos componentes da IU, criação de layouts, navegação, validação de formulário etc. Por outro lado, a programação do site do lado do servidor envolve principalmente a escolha de qual conteúdo é retornado ao navegador em resposta às solicitações. O código do lado do servidor lida com tarefas como validação de dados e solicitações enviadas, usando bancos de dados para armazenar e recuperar dados e enviar os dados corretos para o cliente conforme necessário.</p> + +<p>O código do lado do cliente é geralmente escrito em <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a>, e <a href="/en-US/docs/Learn/JavaScript">JavaScript</a> — ele é executado dentro de um navegador da web e tem pouco ou nenhum acesso ao sistema operacional subjacente (incluindo acesso limitado ao sistema de arquivos)</p> + +<p>Os desenvolvedores da Web não podem controlar qual navegador cada usuário pode estar usando para visualizar um site - os navegadores fornecem níveis inconsistentes de compatibilidade com recursos de código do lado do cliente, e parte do desafio da programação do lado do cliente é lidar com as diferenças no suporte do navegador de maneira elegante.</p> + +<p>O código do lado do servidor pode ser escrito algumas linguagens de programação - exemplos de linguagens da web do lado do servidor populares incluem PHP, Python, Ruby, C # e NodeJS (JavaScript). O código do lado do servidor tem acesso total ao sistema operacional do servidor e o desenvolvedor pode escolher qual linguagem de programação (e versão específica) deseja usar.</p> + +<p>Desenvolvedores geralmente escrevem seus códigos utilizando <strong>web frameworks</strong>. Frameworks Web são coleções de funções, objetos, regras e outras construções de código projetadas para resolver problemas comuns, acelerar o desenvolvimento e simplificar os diferentes tipos de tarefas enfrentadas em um domínio específico.</p> + +<p>Novamente, embora o código do lado do cliente e do servidor usem frameworks, os domínios são muito diferentes e, portanto, os frameworks também são. Os frameworks web do lado do cliente simplificam as tarefas de layout e apresentação, enquanto os frameworks web do lado do servidor fornecem muitas funcionalidades de servidor da web "comuns" que você mesmo poderia ter que implementar (por exemplo, suporte para sessões, suporte para usuários e autenticação, fácil acesso ao banco de dados, bibliotecas de modelos, etc.).</p> + +<div class="note"> +<p><strong>Nota </strong>: Os frameworks do lado do cliente costumam ser usados para ajudar a acelerar o desenvolvimento do código do lado do cliente, mas você também pode escolher escrever todo o código manualmente; na verdade, escrever seu código manualmente pode ser mais rápido e eficiente se você precisar apenas de uma IU de site da Web pequena e simples.</p> + +<p>Em contraste, você quase nunca pensaria em escrever o componente do lado do servidor de um web application sem um framework - implementar um recurso vital como um servidor HTTP é realmente difícil de fazer do zero em, digamos, Python, mas frameworks web em Python como Django fornecem essa ferramenta , junto com outras ferramentas muito úteis.</p> +</div> + +<div> +<h2 id="O_que_você_pode_fazer_no_lado_do_servidor">O que você pode fazer no lado do servidor ?</h2> + +<p dir="ltr" id="tw-target-text">A programação do lado do servidor é muito útil porque nos permite fornecer com eficiência informações personalizadas para usuários individuais e, assim, criar uma experiência de usuário muito melhor.</p> +</div> + +<p>Empresas como a Amazon usam programação do lado do servidor para construir resultados de pesquisa de produtos, fazer sugestões de produtos direcionados com base nas preferências do cliente e hábitos de compra anteriores, simplificar as compras, etc.</p> + +<p>Os bancos usam a programação do lado do servidor para armazenar informações de contas e permitir que apenas usuários autorizados visualizem e façam transações. Outros serviços como Facebook, Twitter, Instagram e Wikipedia usam programação do lado do servidor para destacar, compartilhar e controlar o acesso ao conteúdo .</p> + +<p>Alguns dos usos e benefícios comuns da programação do lado do servidor estão listados abaixo. Você notará que há alguma sobreposição!</p> + +<h3 id="Armazenamento_eficiente_e_entrega_de_informações">Armazenamento eficiente e entrega de informações</h3> + +<p>Imagine quantos produtos estão disponíveis na Amazon e quantas postagens foram escritas no Facebook? Criar uma página estática separada para cada produto ou postagem seria completamente impraticável.</p> + +<p>A programação do lado do servidor nos permite, em vez disso, armazenar as informações em um banco de dados e construir e retornar dinamicamente HTML e outros tipos de arquivos (por exemplo, PDFs, imagens, etc.). Também é possível simplesmente retornar dados ({{glossary("JSON")}}, {{glossary("XML")}}, etc.) para renderização por frameworks web do lado do cliente apropriados (isso reduz a carga de processamento em um servidor e a quantidade de dados que precisa ser enviada).</p> + +<p>O servidor não se limita a enviar informações de bancos de dados e pode, alternativamente, retornar o resultado de ferramentas de software ou dados de serviços de comunicação. O conteúdo pode até ser direcionado para o tipo de dispositivo que o cliente está recebendo.</p> + +<p>Como as informações estão em um banco de dados, elas também podem ser mais facilmente compartilhadas e atualizadas com outros sistemas de negócios (por exemplo, quando os produtos são vendidos online ou em uma loja, a loja pode atualizar seu banco de dados de estoque).</p> + +<div class="note"> +<p><strong>Nota </strong>: Sua imaginação não precisa trabalhar muito para ver os benefícios do código do lado do servidor para armazenamento e entrega eficientes de informações:</p> + +<ol> + <li>Vá em <a href="https://www.amazon.com">Amazon</a> ou em outro site comercial.</li> + <li>Pesquise várias palavras-chave e observe como a estrutura da página não muda, embora os resultados mudem.</li> + <li>Abra dois ou três produtos diferentes. Observe novamente como eles têm uma estrutura e layout comuns, mas o conteúdo de diferentes produtos foi retirado do banco de dados.</li> +</ol> + +<p>Para um termo de pesquisa comum ("peixe", digamos), você pode ver literalmente milhões de valores retornados. O uso de um banco de dados permite que sejam armazenados e compartilhados de forma eficiente, além de permitir que a apresentação das informações seja controlada em um só lugar.</p> +</div> + +<h3 id="Experiência_de_usuário_personalizada">Experiência de usuário personalizada</h3> + +<p>Os servidores podem armazenar e usar informações sobre clientes para fornecer uma experiência de usuário conveniente e personalizada. Por exemplo, muitos sites armazenam cartões de crédito para que os detalhes não tenham que ser inseridos novamente. Sites como o Google Maps podem usar locais salvos ou atuais para fornecer informações de rota e pesquisar o histórico de viagens para destacar empresas locais nos resultados de pesquisa.</p> + +<p>Uma análise mais profunda dos hábitos do usuário pode ser usada para antecipar seus interesses e personalizar ainda mais as respostas e notificações, por exemplo, fornecendo uma lista de locais visitados anteriormente ou que você pode querer ver em um mapa.</p> + +<div class="note"> +<p><strong>Nota: </strong><a href="https://maps.google.com/">Google Maps</a> salva sua pesquisa e histórico de visitas. Locais visitados ou pesquisados com frequência são destacados mais do que outros.</p> + +<p>Os resultados de pesquisa do Google são otimizados com base em pesquisas anteriores.</p> + +<ol> + <li> Vá em <a href="https:\\google.com">Google search</a>.</li> + <li> Pesquise por "futeboll".</li> + <li>Agora tente digitar "favorito" na caixa de pesquisa e observe as previsões de pesquisa do preenchimento automático.</li> +</ol> + +<p>Coincidência ? Nada!</p> +</div> + +<h3 id="Acesso_controlado_ao_conteúdo">Acesso controlado ao conteúdo</h3> + +<p>A programação do lado do servidor permite que os sites restrinjam o acesso a usuários autorizados e forneçam apenas as informações que um usuário tem permissão para ver.</p> + +<p>Exemplos do mundo real, incluem :</p> + +<ul> + <li>Redes sociais como o Facebook permitem que os usuários controlem totalmente seus próprios dados, mas apenas permitem que seus amigos os visualizem ou comentem. O usuário determina quem pode ver seus dados e, por extensão, quais dados aparecem em seu feed - a autorização é uma parte central da experiência do usuário!</li> + <li> + <p>O site em que você está agora controla o acesso ao conteúdo: os artigos são visíveis para todos, mas apenas os usuários que efetuaram login podem editá-los. Para tentar fazer isso, clique no botão Editar no topo desta página - se você estiver conectado, será exibida a visualização de edição; se você não estiver logado, será direcionado para a página de inscrição.</p> + </li> +</ul> + +<div class="note"> +<p><strong>Nota </strong>: Considere outros exemplos reais em que o acesso ao conteúdo é controlado. Por exemplo, o que você pode ver se acessar o site online do seu banco? Faça login em sua conta - quais informações adicionais você pode ver e modificar? Quais informações você pode ver que somente o banco pode alterar?</p> +</div> + +<h3 id="Sessão_de_armazenamento_informações_de_estado">Sessão de armazenamento / informações de estado</h3> + +<p>A programação do lado do servidor permite que os desenvolvedores façam uso de sessões - basicamente, um mecanismo que permite a um servidor armazenar informações sobre o usuário atual de um site e enviar diferentes respostas com base nessas informações.</p> + +<p>Isso permite, por exemplo, que um site saiba que um usuário fez login anteriormente e exiba links para seus e-mails ou histórico de pedidos, ou talvez salve o estado de um jogo simples para que o usuário possa ir a um site novamente e continuar onde eles deixaram.</p> + +<div class="note"> +<p><strong>Note</strong>:Visite um site de jornal que tem um modelo de assinatura e abra várias guias (por exemplo, The Age). Continue a visitar o site por algumas horas / dias. Eventualmente, você começará a ser redirecionado para páginas que explicam como se inscrever e não conseguirá acessar os artigos. Essas informações são um exemplo de informações de sessão armazenadas em cookies.</p> +</div> + +<h3 id="Notificações_e_comunicação">Notificações e comunicação</h3> + +<p>Os servidores podem enviar notificações gerais ou específicas do usuário por meio do próprio site ou por e-mail, SMS, mensagens instantâneas, conversas por vídeo ou outros serviços de comunicação.</p> + +<p>Alguns exemplos, incluem :</p> + +<ul> + <li>Facebook e Twitter enviam e-mails e mensagens SMS para notificá-lo de novas comunicações.</li> + <li>A Amazon envia regularmente e-mails de produtos que sugerem produtos semelhantes aos já comprados ou vistos nos quais você possa estar interessado.</li> + <li>Um servidor da web pode enviar mensagens de aviso aos administradores do site alertando-os sobre a memória insuficiente no servidor ou atividade suspeita do usuário.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: O tipo mais comum de notificação é uma "confirmação de registro". Escolha quase todos os grandes sites de seu interesse (Google, Amazon, Instagram, etc.) e crie uma nova conta usando seu endereço de e-mail. Em breve, você receberá um e-mail confirmando seu registro ou solicitando confirmação para ativar sua conta.</p> +</div> + +<h3 id="Análise_de_dados">Análise de dados</h3> + +<p>Um site pode coletar muitos dados sobre os usuários: o que procuram, o que compram, o que recomendam, quanto tempo permanecem em cada página. A programação do lado do servidor pode ser usada para refinar as respostas com base na análise desses dados.</p> + +<p>Por exemplo, Amazon e Google anunciam produtos com base em pesquisas anteriores (e compras).</p> + +<div class="note"> +<p><strong>Nota</strong>:Se você é um usuário do Facebook, vá para o seu feed principal e veja o fluxo de postagens. Observe como algumas das postagens estão fora da ordem numérica - em particular, as postagens com mais "curtidas" geralmente estão no topo da lista do que as postagens mais recentes.</p> + +<p>Observe também que tipo de anúncio está sendo mostrado - você pode ver anúncios de coisas que já viu em outros sites. O algoritmo do Facebook para destacar conteúdo e publicidade pode ser um pouco misterioso, mas é claro que depende de seus gostos e hábitos de visualização!</p> +</div> + +<h2 id="Resumo">Resumo</h2> + +<p>Parabéns, você chegou ao final do primeiro artigo sobre programação do lado do servidor.</p> + +<p>Agora você aprendeu que o código do lado do servidor é executado em um servidor da web e que sua função principal é controlar quais informações são enviadas ao usuário (enquanto o código do lado do cliente lida principalmente com a estrutura e apresentação desses dados para o usuário) .</p> + +<p>Você também deve entender que é útil porque nos permite criar sites que fornecem informações sob medida para usuários individuais de forma eficiente e têm uma boa ideia de algumas das coisas que você pode fazer quando for um programador do lado do servidor.</p> + +<p>Por último, você deve entender que o código do lado do servidor pode ser escrito em várias linguagens de programação e que você deve usar um framewoek web para tornar todo o processo mais fácil.</p> + +<p>Em um artigo futuro, ajudaremos você a escolher o melhor framework web para seu primeiro site. Aqui, vamos levá-lo pelas principais interações cliente-servidor com um pouco mais de detalhes.</p> + +<p>{{NextMenu("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps")}}</p> + +<h2 id="Nesse_módulo">Nesse módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Introduction">Introduction to the server side</a></li> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Client-Server_overview">Client-Server overview</a></li> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Web_frameworks">Server-side web frameworks</a></li> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Website_security">Website security</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/first_steps/seguranca_site/index.html b/files/pt-br/learn/server-side/first_steps/seguranca_site/index.html new file mode 100644 index 0000000000..12a11cf641 --- /dev/null +++ b/files/pt-br/learn/server-side/first_steps/seguranca_site/index.html @@ -0,0 +1,175 @@ +--- +title: Segurança em aplicação web +slug: Learn/Server-side/First_steps/Seguranca_site +tags: + - Aprendizagem + - Guía + - Iniciante + - Introdução + - Programação do server + - Segurança + - Segurança em aplicações web + - Segurança web +translation_of: Learn/Server-side/First_steps/Website_security +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}</div> + +<p class="summary">A segurança do site requer vigilância em todos os aspectos do design e uso do site. Este artigo introdutório não fará de você um guru da segurança de sites, mas ajudará a entender de onde vem as ameaças e o que você pode fazer para proteger sua aplicação web contra os ataques mais comuns.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimento básico em informática.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender as ameaças mais comuns à segurança de aplicações web e o que você pode fazer para reduzir o risco de invasão do site.</td> + </tr> + </tbody> +</table> + +<h2 id="O_que_é_segurança_no_site">O que é segurança no site?</h2> + +<p>A Internet é um lugar perigoso! Com grande regularidade, ouvimos sobre a indisponibilidade de sites devido a ataques de negação de serviço ou a exibição de informações modificadas (e muitas vezes prejudiciais) em suas páginas iniciais. Em outros casos de alto perfil, milhões de senhas, endereços de email e detalhes de cartão de crédito foram vazados para o domínio público, expondo os usuários do site a vergonha pessoal e risco financeiro.</p> + +<p>O objetivo da segurança do site é impedir esse (ou qualquer) tipo de ataque. A definição mais formal de segurança do site é o ato ou prática de proteger sites contra acesso, uso, modificação, destruição ou interrupção não autorizados.</p> + +<p>A segurança efetiva do site requer um esforço de design em todo o site: em sua aplicação web, na configuração do servidor da web, em suas políticas para criar e renovar senhas e no código do cliente. Embora tudo isso pareça muito ameaçador, a boa notícia é que, se você estiver usando <em>framework </em>(uma estrutura da web) no servidor, é provável que ele habilitará "por padrão" mecanismos de defesa robustos e bem pensados contra vários ataques mais comuns. Outros ataques podem ser mitigados através da configuração do servidor da web, por exemplo, ativando o HTTPS. Por fim, existem ferramentas de scanner de vulnerabilidades disponíveis publicamente que podem ajudá-lo a descobrir se você cometeu algum erro óbvio.</p> + +<p>O restante deste artigo fornece mais detalhes sobre algumas ameaças comuns e algumas das etapas simples que você pode executar para proteger seu site.</p> + +<div class="note"> +<p><strong>Nota</strong>: Este é um tópico introdutório projetado para ajudá-lo a começar a pensar na segurança do site, mas não é exaustivo.</p> +</div> + +<h2 id="Ameaças_à_segurança_do_site">Ameaças à segurança do site</h2> + +<p>Esta seção lista apenas algumas das ameaças mais comuns do site e como elas são mitigadas. Enquanto você lê, observe como as ameaças são mais bem-sucedidas quando a aplicação web confia ou <em>não é paranóico o suficiente</em> sobre os dados provenientes do navegador.</p> + +<h3 id="Cross-Site_Scripting_XSS">Cross-Site Scripting (XSS)</h3> + +<p>XSS é um termo usado para descrever uma classe de ataques que permitem que um invasor injete scripts do lado do cliente <em>através </em>do site nos navegadores de outros usuários. Como o código injetado chega ao navegador a partir do site, o código é <em>confiável </em>e pode fazer coisas como enviar o cookie de autorização do site do usuário ao invasor. Quando o invasor possui o cookie, ele pode fazer login em um site como se fosse o usuário e fazer tudo que o usário pode, como acessar os detalhes do cartão de crédito, ver detalhes do contato ou alterar senhas.</p> + +<div class="note"> +<p><strong>Nota</strong>: As vulnerabilidades XSS têm sido historicamente mais comuns do que qualquer outro tipo de ameaça à segurança.</p> +</div> + +<p>As vulnerabilidades do XSS são divididas em <em>refletidas </em>e <em>persistentes</em>, de acordo como o site retorna os scripts injetados para um navegador.</p> + +<ul> + <li>Uma vulnerabilidade XSS <em>refletida </em>ocorre quando o conteúdo do usuário passado para o servidor é retornado <em>imediatamente </em>e <em>não é modificado</em> para exibição no navegador. Quaisquer scripts no conteúdo original do usuário serão executados quando a nova página for carregada. Por exemplo, considere uma função de pesquisa no site em que os termos de pesquisa são codificados como parâmetros de URL e esses termos são exibidos junto com os resultados. Um invasor pode construir um link de pesquisa que contenha um script malicioso como parâmetro (por exemplo, <code>http://sitedecompra.com?q=produto<script%20src="http://sitedomal.com/trapaca.js"></code>) e enviar por e-mail para outro usuário. Se o usuário alvo clicar nesse "link interessante", o script será executado quando os resultados da pesquisa forem exibidos. Conforme discutido anteriormente, isso fornece ao invasor todas as informações necessárias para entrar no site como usuário alvo, potencialmente fazendo compras como o usuário ou compartilhando suas informações de contato.</li> + <li> Uma vulnerabilidade <em>persistente </em>do XSS ocorre quando o script mal-intencionado é armazenado no site e posteriormente exibido novamente sem modificação para que outros usuários executem sem querer. Por exemplo, um quadro de discussão que aceita comentários que contêm HTML não modificado pode armazenar um script mal-intencionado de um invasor. Quando os comentários são exibidos, o script é executado e pode enviar ao invasor as informações necessárias para acessar a conta do usuário. Esse tipo de ataque é extremamente popular e poderoso, porque o invasor pode até não ter nenhum envolvimento direto com as vítimas.</li> +</ul> + +<p>Embora os dados das solicitações <code>POST</code> ou <code>GET</code> sejam a fonte mais comum de vulnerabilidades XSS, qualquer dado do navegador é potencialmente vulnerável, como dados de cookies renderizados pelo navegador ou arquivos de usuário que são carregados e exibidos.</p> + +<p>A melhor defesa contra as vulnerabilidades do XSS é remover ou desativar qualquer marcação que possa conter instruções para executar o código. Para HTML, isso inclui elementos, como <code><script></code>, <code><object></code>, <code><embed></code> e <code><link></code> .</p> + +<p>O processo de modificação de dados do usuário para que não possa ser usado para executar scripts ou afetar a execução do código do servidor é conhecido como limpeza de entrada. Muitas estruturas da Web limpam automaticamente a entrada do usuário de formulários HTML por padrão.</p> + +<h3 id="Injeção_de_SQL">Injeção de SQL</h3> + +<p>As vulnerabilidades de injeção de SQL permitem que usuários mal-intencionados executem código SQL arbitrário em um banco de dados, permitindo que os dados sejam acessados, modificados ou excluídos, independentemente das permissões do usuário. Um ataque de injeção bem-sucedido pode falsificar identidades, criar novas identidades com direitos de administração, acessar todos os dados no servidor ou destruir/modificar os dados para torná-los inutilizáveis.</p> + +<p>Os tipos de injeção SQL incluem injeção SQL baseada em erro, injeção SQL baseada em erros booleanos e injeção SQL baseada em tempo.</p> + +<p>Esta vulnerabilidade está presente se a entrada do usuário que é passada para uma instrução SQL subjacente puder alterar o significado da instrução. Por exemplo, o código a seguir tem como objetivo listar todos os usuários com um nome específico (<code>nomeUsuario)</code> fornecido a partir de um formulário HTML:</p> + +<pre class="brush: sql">statement = "SELECT * FROM usuarios WHERE name = '" + <strong>nomeUsuario</strong> + "';"</pre> + +<p>Se o usuário especificar um nome real, a instrução funcionará como pretendido. No entanto, um usuário mal-intencionado pode alterar completamente o comportamento dessa instrução SQL para a nova instrução no exemplo a seguir, simplesmente especificando o texto em negrito para o <code>nomeUsuario.</code></p> + +<pre class="brush: sql">SELECT * FROM usuarios WHERE name = '<strong>a';DROP TABLE usuarios; SELECT * FROM userinfo WHERE 't' = 't</strong>'; +</pre> + +<p>A instrução modificada cria uma instrução SQL válida que exclui a tabela de <code>usuarios</code> e seleciona todos os dados da tabela <code>userinfo</code> (que revela as informações de cada usuário). Isso funciona porque a primeira parte do texto injetado ( <code>a';</code>) completa a declaração original.</p> + +<p>Para evitar esse tipo de ataque, você deve garantir que os dados do usuário passados para uma consulta SQL não possam alterar a natureza da consulta. Uma maneira de fazer isso é utilizar '<a href="https://pt.wikipedia.org/wiki/Caractere_de_escape">escape</a>' em todos os caracteres na entrada do usuário que tenham um significado especial no SQL.</p> + +<div class="note"> +<p><strong>Nota</strong>: A instrução SQL trata o caractere <strong>'</strong> como o início e o final de uma cadeia de caracteres literal. Ao colocar uma barra invertida na frente desse caractere (<strong>\'</strong>), "escapamos" do símbolo e dizemos ao SQL para tratá-lo como um caractere (apenas uma parte da string).</p> +</div> + +<p>Na declaração a seguir, escapamos o caractere <strong>'</strong>. O SQL agora interpretará o nome como toda a string em negrito (que é um nome muito estranho, mas não prejudicial).</p> + +<pre class="brush: sql">SELECT * FROM usarios WHERE name = '<strong>a\';DROP TABLE usuarios; SELECT * FROM userinfo WHERE \'t\' = \'t'</strong>; + +</pre> + +<p><em>Frameworks web</em> geralmente cuidam do caractere que está escapando para você. O Django, por exemplo, garante que todos os dados do usuário passados para os conjuntos de consultas (consultas de modelo) sejam escapados.</p> + +<div class="note"> +<p><strong>Nota</strong>: Esta seção baseia-se fortemente nas informações da <a href="https://en.wikipedia.org/wiki/SQL_injection">Wikipedia</a>.</p> +</div> + +<h3 id="Cross-Site_Request_Forgery_CSRF">Cross-Site Request Forgery (CSRF)</h3> + +<p>Os ataques de CSRF permitem que um usuário mal-intencionado execute ações usando as credenciais de outro usuário sem o conhecimento ou consentimento desse usuário.</p> + +<p>Esse tipo de ataque é melhor explicado por exemplo. John é um usuário mal-intencionado que sabe que um site específico permite que usuários conectados enviem dinheiro para uma conta especificada usando uma solicitação HTTP <code>POST</code> que inclui o nome da conta e uma quantia em dinheiro. John cria um formulário que inclui seus dados bancários e uma quantia de dinheiro como campos ocultos e o envia por e-mail a outros usuários do site (com o botão <em>Enviar</em>, disfarçado como um link para um site "fique rico rapidamente").</p> + +<p>Se um usuário clicar no botão enviar, uma solicitação HTTP <code>POST</code> será enviada ao servidor contendo os detalhes da transação e quaisquer cookies do lado do cliente que o navegador associou ao site (adicionar cookies do site associados a solicitações é um comportamento normal do navegador). O servidor irá verificar os cookies e usá-los para determinar se o usuário está ou não conectado e tem permissão para fazer a transação.</p> + +<p>O resultado é que qualquer usuário que clicar no botão <em>Enviar </em>enquanto estiver conectado ao site de negociação fará a transação. John fica rico.</p> + +<div class="note"> +<p><strong>Nota</strong>: O truque aqui é que John não precisa ter acesso aos cookies do usuário (ou credenciais de acesso). O navegador do usuário armazena essas informações e as inclui automaticamente em todas as solicitações ao servidor associado.</p> +</div> + +<p>Uma maneira de impedir esse tipo de ataque é o servidor exigir que as solicitações <code>POST</code> incluam um segredo gerado pelo site específico do usuário. O segredo seria fornecido pelo servidor ao enviar o formulário da web usado para fazer transferências. Essa abordagem impede John de criar seu próprio formulário, uma vez que ele precisaria conhecer o segredo que o servidor está fornecendo ao usuário. Mesmo se descobrisse o segredo e criasse um formulário para um usuário específico, ele não seria mais capaz de usar o mesmo formulário para atacar todos os usuários.</p> + +<p><em>Frameworks web</em> geralmente incluem esses mecanismos de prevenção para CSRF.</p> + +<h3 id="Outras_ameaças">Outras ameaças</h3> + +<p>Outros ataques e vulnerabilidades comuns incluem:</p> + +<ul> + <li><em><a href="https://www.owasp.org/index.php/Clickjacking">Clickjacking</a></em>. Nesse ataque, um usuário mal-intencionado seqüestra cliques destinados a um site de nível superior visível e os direciona para uma página oculta abaixo. Essa técnica pode ser usada, por exemplo, para exibir um site bancário legítimo, mas capturar as credenciais de logon em um invisível controlado pelo invasor. O clickjacking também pode ser usado para fazer com que o usuário clique em um botão em um site visível, mas, ao fazer isso, clique inconscientemente em um botão completamente diferente. Como defesa, seu site pode impedir que ele seja incorporado em um iframe em outro site, definindo os cabeçalhos HTTP apropriados.</li> + <li><a href="https://pt.wikipedia.org/wiki/Ataque_de_nega%C3%A7%C3%A3o_de_servi%C3%A7o">Negação de Serviço</a> (DoS, em inglês). O DoS geralmente é atingido inundando um site de destino com solicitações falsas para que o acesso a um site seja interrompido por usuários legítimos. As solicitações podem ser simplesmente numerosas ou podem consumir grandes quantidades de recursos individualmente (por exemplo, leituras lentas ou upload de arquivos grandes). As defesas de DoS geralmente funcionam identificando e bloqueando o tráfego "ruim" e permitindo a passagem de mensagens legítimas. Essas defesas geralmente estão localizadas antes ou no servidor da web (elas não fazem parte da própria aplicação web).</li> + <li><em><a href="https://en.wikipedia.org/wiki/Directory_traversal_attack">Directory Traversal</a> </em> (arquivo e divulgação). Nesse ataque, um usuário mal-intencionado tenta acessar partes do sistema de arquivos do servidor da web que ele não deve acessar. Essa vulnerabilidade ocorre quando o usuário consegue passar nomes de arquivos que incluem caracteres de navegação do sistema de arquivos (por exemplo, <code>../../</code>). A solução é limpar a entrada antes de usá-la.</li> + <li><a href="/pt-BR/docs/">Inclusão de arquivo</a>. Nesse ataque, um usuário pode especificar um arquivo "não intencional" para exibição ou execução nos dados passados para o servidor. Quando carregado, esse arquivo pode ser executado no servidor da web ou no lado do cliente (levando a um ataque XSS). A solução é limpar a entrada antes de usá-la.</li> + <li><a href="/pt-BR/docs/">Injeção de comando</a>. Os ataques de injeção de comando permitem que um usuário mal-intencionado execute comandos arbitrários do sistema no sistema operacional host. A solução é limpar a entrada do usuário antes que ela possa ser usada nas chamadas do sistema.</li> +</ul> + +<p>Para obter uma lista abrangente das ameaças à segurança do site, consulte <a href="/pt-BR/docs/">Categoria: explorações de segurança da Web </a>(Wikipedia) e <a href="/pt-BR/docs/">Categoria: Ataque</a> (Projeto de Segurança para Aplicações Web Abertos).</p> + +<h2 id="Algumas_mensagens-chave">Algumas mensagens-chave</h2> + +<p>Quase todas as explorações de segurança nas seções anteriores são bem-sucedidas quando a aplicação web confia nos dados do navegador. Tudo o que você fizer para melhorar a segurança do seu site, você deve limpar todos os dados originados pelo usuário antes de serem exibidos no navegador, usados em consultas SQL ou passados para um sistema operacional ou para uma chamada do sistema de arquivos.</p> + +<div class="warning"> +<p>Importante: A lição mais importante que você pode aprender sobre segurança do site é nunca confiar nos dados do navegador. Isso inclui, mas não se limita a dados nos parâmetros de URL de solicitações <code>GET</code>, <code>POST</code>, cabeçalhos HTTP, cookies e arquivos enviados por usuários. Sempre verifique e limpe todos os dados recebidos. Sempre assuma o pior.</p> +</div> + +<p>Uma série de outras etapas concretas que você pode executar são:</p> + +<ul> + <li>Use um gerenciamento de senhas mais eficaz. Incentive senhas fortes que são alteradas regularmente. Considere a autenticação de dois fatores para o seu site, para que, além de uma senha, o usuário insira outro código de autenticação (geralmente um código fornecido com algum hardware físico que somente o usuário terá, como um código em um SMS enviado para seu telefone).</li> + <li>Configure seu servidor da web para usar <a href="/pt-BR/docs/">HTTPS </a>e <a href="/pt-BR/docs/">HTTP Strict Transport Security</a> (HSTS). O HTTPS criptografa os dados enviados entre seu cliente e servidor. Isso garante que credenciais de login, cookies, dados de solicitações <code>POST</code> e informações de cabeçalho não estejam facilmente disponíveis para os invasores.</li> + <li>Acompanhe as ameaças mais populares (<a href="/pt-BR/docs/">a lista atual do OWASP está aqui</a>) e resolva as vulnerabilidades mais comuns primeiro.</li> + <li>Use as <a href="https://www.owasp.org/index.php/Category:Vulnerability_Scanning_Tools">ferramentas de verificação de vulnerabilidades</a> para executar testes de segurança automatizados em seu site. Posteriormente, seu site bem-sucedido também poderá encontrar bugs oferecendo uma recompensa de bugs, <a href="https://www.mozilla.org/en-US/security/bug-bounty/faq-webapp/">como a Mozilla faz aqui</a>.</li> + <li>Armazene e exiba apenas os dados necessários. Por exemplo, se seus usuários precisam armazenar informações confidenciais, como detalhes do cartão de crédito, exiba apenas o número do cartão suficiente para que possa ser identificado pelo usuário e não o suficiente para que possa ser copiado por um invasor e usado em outro site. O padrão mais comum no momento é exibir apenas os últimos 4 dígitos de um número de cartão de crédito.</li> +</ul> + +<p><em>Frameworks web</em> podem ajudar a mitigar muitas das vulnerabilidades mais comuns.</p> + +<h2 id="Resumo">Resumo</h2> + +<p>Este artigo explicou o conceito de segurança na web e algumas das ameaças mais comuns contra as quais o site deve tentar se proteger. Mais importante, você deve entender que uma aplicação web não pode confiar em nenhum dado do navegador. Todos os dados do usuário devem ser limpos antes de serem exibidos ou usados em consultas SQL e chamadas do sistema de arquivos.</p> + +<p>Com este artigo, você chegou ao final <a href="https://wiki.developer.mozilla.org/pt-BR/docs/Learn/Server-side/First_steps">deste módulo</a>, abordando seus primeiros passos na programação de sites em relação ao servidor. Esperamos que você tenha gostado de aprender esses conceitos fundamentais e agora esteja pronto para selecionar um <em>Framework web</em> e iniciar a programação.</p> + +<p>{{PreviousMenu("Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Introduction">Introduction to the server side</a></li> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Client-Server_overview">Client-Server overview</a></li> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Web_frameworks">Server-side web frameworks</a></li> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Website_security">Website security</a></li> +</ul> diff --git a/files/pt-br/learn/server-side/index.html b/files/pt-br/learn/server-side/index.html new file mode 100644 index 0000000000..2c7759aa89 --- /dev/null +++ b/files/pt-br/learn/server-side/index.html @@ -0,0 +1,52 @@ +--- +title: Programação de site do lado do servidor +slug: Learn/Server-side +tags: + - Beginner + - CodingScripting + - Intro + - Landing + - Learn + - NeedsTranslation + - Server + - Server-side programming + - Topic + - TopicStub +translation_of: Learn/Server-side +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">O tópico de <em><strong>Websites Dinâmicos - Programação do lado do servidor</strong></em> é uma série de módulos que mostram como criar sites dinâmicos; sites que fornecem informações personalizadas em resposta a solicitações HTTP. Os módulos fornecem uma introdução genérica à programação do lado do servidor, juntamente com guias específicos de nível iniciante sobre como usar os frameworks web Django (Python) e Express (Node.js / JavaScript) para criar aplicativos básicos.</p> + +<p>A maioria dos principais sites utilizam algum tipo de tecnologia do lado do servidor para exibir dinamicamente dados diferentes conforme necessário. Por exemplo, imagine quantos produtos estão disponíveis na Amazon e imagine quantos posts foram escritos no Facebook? Exibir tudo isso usando páginas estáticas completamente diferentes seria completamente ineficiente, então, em vez disso, esses sites exibem modelos estáticos (construídos usando <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a>, e <a href="/en-US/docs/Learn/JavaScript">JavaScript</a>), e então atualizam dinamicamente os dados exibidos dentro desses modelos quando necessário, por exemplo, quando você quiser ver um produto diferente na Amazon.</p> + +<p>No mundo moderno do desenvolvimento web, aprender sobre o desenvolvimento do lado do servidor é altamente recomendado.</p> + +<h2 id="Caminho_de_aprendizagem">Caminho de aprendizagem</h2> + +<p>Começar a usar a programação do lado do servidor geralmente é mais fácil do que com o desenvolvimento do lado do cliente, porque sites dinâmicos tendem a executar muitas operações similares (recuperando dados de um banco de dados e exibindo-os em uma página, validando dados inseridos pelo usuário e salvando-os em um banco de dados, verificando permissões de usuários e registrando usuários, etc.) e são construídos usando estruturas da Web que facilitam essas e outras operações comuns de servidor da Web.</p> + +<p>Um conhecimento básico de conceitos de programação (ou de uma linguagem de programação específica) é útil, mas não essencial. Semelhantemente, a especialização em codificação do lado do cliente não é necessária, mas um conhecimento básico ajudará você a trabalhar melhor com os desenvolvedores criando seu "front end" da Web do lado do cliente.</p> + +<p>Você precisará entender "como a web funciona". Recomendamos que você leia primeiro os seguintes tópicos:</p> + +<ul> + <li><a href="/en-US/docs/Learn/Common_questions/What_is_a_web_server">O que é um servidor web?</a></li> + <li><a href="/en-US/docs/Learn/Common_questions/What_software_do_I_need">Qual software eu preciso para construir um website?</a></li> + <li><a href="/en-US/docs/Learn/Common_questions/Upload_files_to_a_web_server">Como você faz o upload de arquivos para um servidor web?</a></li> +</ul> + +<p>Com essa compreensão básica, você estará pronto para percorrer os módulos desta seção.</p> + +<h2 id="Modulos">Modulos</h2> + +<p>Este tópico contém os seguintes módulos. Você deve começar com o primeiro módulo e depois seguir para um dos módulos seguintes, que mostram como trabalhar com duas linguagens do lado do servidor muito populares usando estruturas da Web apropriadas.</p> + +<dl> + <dt><a href="/en-US/docs/Learn/Server-side/First_steps">Primeiros passos de programação do site do lado do servidor</a></dt> + <dd>Este módulo fornece informações agnósticas sobre a tecnologia do servidor sobre programação de sites do lado do servidor, incluindo respostas a perguntas fundamentais de programação do lado do servidor — "o que é isso", "como ela difere da programação do lado do cliente", e "porque é tão útil" — e uma visão geral de alguns dos mais populares frameworks do lado do servidor e orientações sobre como selecionar o mais adequado para o seu site. Por fim, fornecemos uma seção introdutória sobre segurança do servidor da web.</dd> + <dt><a href="/pt-BR/docs/Learn/Server-side/Django">Framework Web Django (Python)</a></dt> + <dd>O Django é um framework web do lado do servidor extremamente popular e cheio de recursos, escrito em Python. O módulo explica por que o Django é uma estrutura de servidor da Web tão boa, como configurar um ambiente de desenvolvimento e como executar tarefas comuns com ele.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs">Framework Web Express (Node.js/JavaScript)</a></dt> + <dd>O Express é um framwork web popular, escrito em JavaScript e hospedado no ambiente de tempo de execução node.js. O módulo explica alguns dos principais benefícios dessa estrutura, como configurar seu ambiente de desenvolvimento e como executar tarefas comuns de desenvolvimento e implantação da web.</dd> +</dl> diff --git a/files/pt-br/learn/tools_and_testing/client-side_javascript_frameworks/comecando_com_react/index.html b/files/pt-br/learn/tools_and_testing/client-side_javascript_frameworks/comecando_com_react/index.html new file mode 100644 index 0000000000..5c1798518d --- /dev/null +++ b/files/pt-br/learn/tools_and_testing/client-side_javascript_frameworks/comecando_com_react/index.html @@ -0,0 +1,461 @@ +--- +title: Começando com React +slug: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Comecando_com_React +translation_of: >- + Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}</div> + +<p class="summary">Neste artigo mostraremos como dizer Olá para o React. Descobriremos um pouco sobre e os casos de usos, configurar uma Reac toolchain no computador localmente, e criar e usar um app simples como partida, aprendendo um pouco sobre como o processo de React funciona.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td> + <p>Familiaridade com <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a>, e linguagem <a href="/en-US/docs/Learn/JavaScript">JavaScript</a>, conhecimento de <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line">terminal/linha de comandos.</a></p> + + <p>React usa a sintaxe HTML-in-JavaScript com o nome JSX (JavaScript e XML). Familiaridade em ambos HTML e JavaScript ajudará aprender JSX, e identificar melhor se os erros na sua aplicação estão relacionado ao JavaScript ou na parte especifíca do React.</p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Configurar um ambiente local de desenvolvimento React, criar o primeiro app e entender o básico de como as coisas funcionam.</td> + </tr> + </tbody> +</table> + +<h2 id="Olá_React">Olá, React</h2> + +<p>Segundo seu slogan oficial, <a href="https://reactjs.org/">React</a> é uma biblioteca para construção de interfaces de usuário. React não é um framework – nem mesmo é exclusivo para web. É utilizado com outras bibliotecas para renderização em certos ambientes. Por exemplo, <a href="https://reactnative.dev/">React Native</a> pode ser usado para construção de aplicativos móveis; <a href="https://facebook.github.io/react-360/">React 360</a> pode ser usado para construir aplicações de realidade virtual; e muitas outras possibilidades.</p> + +<p>Para construir para web, desenvolvedores usam React em conjunto com <a href="https://reactjs.org/docs/react-dom.html">ReactDOM</a>. React e ReactDOM são frequentemente discutidos nos mesmos espaços e utlizados para resolver os mesmos problemas como outros arcabouços(frameworks). Quando referimos React como "arcabouço"(framework) estamos trabalhando com o termo/entendimento coloquial.</p> + +<p>A meta primária do React é minimizar os erros que ocorrem quando os desenvolvedores estão construindo UIs(User Interface). Isto é devido ao uso de componentes - autocontidos, partes lógicas de códigos que descrevem uma parte da interface do usuário. Estes componentes são adicionados para criar uma UI completa e o React concentra muito do trabalho de renderizar, proporcionando que se concentre no projeto de UI.</p> + +<h2 id="Casos_de_uso">Casos de uso</h2> + +<p>Diferente de outros frameworks comentados neste módulo, React não implementa regras restritas no código como convenções ou organizações de arquivos. Isto permite que times criem convenções próprias que melhor se adequem e para adotar o React do jeito que desejar. React pode manusear um botão único, poucas partes da interface ou a interface inteira de um app.</p> + +<p>Enquanto React pode ser utilizado por <a href="https://reactjs.org/docs/add-react-to-a-website.html">pequenos pedaços de interface</a> e não "cai" em uma aplicação com uma biblioteca como jQuery ou até mesmo como um framework como Vue - é mais acessível quando você constrói todo o app com React.</p> + +<p>Além disso, muitos dos beneficios da experiencias de desenvolvimento de uma aplicação React, tais como escrever interfaces com JSX, requerem um processo de compilação. Adicionar um compilador como o Babel em um website faz o código funcionar lentamente, então os desenvolvedores geralmente configuram algumas ferramentas para fazer compilações em etapas. React, sem duvídas, tem um grande ecossistema de ferramentas, mas isso pode ser aprendido.</p> + +<p>Este artigo será focado no caso de uso do React para renderizar toda a interface do usuario de um aplicativo, usando ferramentas fornecidas pelo prórpio <a href="https://create-react-app.dev/">create-react-app</a> do Facebook.</p> + +<h2 id="Como_React_usa_Javascript">Como React usa Javascript?</h2> + +<p>React utiliza características de Javascript moderno para muitos de seus padrões. O maior desvio do React para o JavaScript dá-se pela utilização sintaxe<a href="https://reactjs.org/docs/introducing-jsx.html"> JSX</a>. O JSX estende a sintaxe padrão do Javascript hablitando-o a utilizar código similar a HTML que pode viver lado a lado ao JSX. Por exemplo:</p> + +<pre class="brush: js notranslate">const heading = <h1> Mozilla Developer Network</h1>;</pre> + +<p>A constante <em>heading </em>acima é conhecida como uma <strong>expressão JSX. </strong>React pode utilizá-la para renderizar a <em>tag </em><code><a href="/en-US/docs/Web/HTML/Element/Heading_Elements"><h1> </a></code>em nosso aplicativo.</p> + +<p>Suponha que quiséssemos conter nosso cabeçalho em uma tag <code><a href="/en-US/docs/Web/HTML/Element/header"><header></a></code>, por razões semânticas? A aproximação em JSX permite-nos aninhar nossos elementos dentro uns dos outros, do mesmo jeito que fazemos com o HTML:</p> + +<pre class="brush: js notranslate">const header = ( + <header> + <h1>Mozilla Developer Network</h1> + </header> +);</pre> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: Os parenteses no recorte de código anterior não são exclusivos ao JSX e não têm nenhum efeito na sua aplicação. Eles estão lá para sinalizar para você (e seu computador) que as múltiplas linhas de código dentro do mesmo são parte da mesma expressão. Você poderia muito bem escrever a expressão do cabeçalho do seguinte jeito:</p> + +<pre class="brush: js notranslate">const header = <header> + <h1>Mozilla Developer Network</h1> +</header></pre> + +<p>Entretanto, isso é meio estranho, porquê a tag <code><a href="/en-US/docs/Web/HTML/Element/header"><header></a></code> que inicia a expressão não está alinhada na mesma posição que sua tag de fechamento correspondente.</p> +</div> + +<p>Claro, seu navegador não é capaz de ler o JSX sem alguma ajuda. Quando compilado (utilizando uma ferramenta como <a href="https://babeljs.io/">Babel</a> ou <a href="https://parceljs.org/">Parcel </a>), nossa expressão de cabeçalho ficaria assim:</p> + +<pre class="brush: js notranslate">const header = React.createElement("header", null, + React.createElement("h1", null, "Mozilla Developer Network") +);</pre> + +<p>É <em>possível </em>pular o processo de compilação e utilizar <code><a href="https://reactjs.org/docs/react-api.html#createelement">React.createElement() </a></code>para escrever sua UI você mesmo. Ao fazer isso, entretanto, você perde o benefício declarativo do JSX, e seu código torna-se mais difícil de ler. Compilação é um passo adicional no processo de desenvolvimento, porém muitos desenvolvedores na comunidade do React acham que a legibilidade do JSX vale a pena. Ainda mais, ferramentas populares fazem a parte de compilar JSX-para-Javascript parte do próprio processo de configuração. Você não vai ter que configurar a compilação você mesmo, a não ser que você queira.</p> + +<p>Por conta do JSX ser uma mistura de HTML e Javascript, muitos desenvolvedores acham o JSX intuitivo. Outros dizem que a natureza mista torna o mesmo mais confuso. Entretanto, assim que você estiver confortável com o JSX, este irá permitir que você construa interfaces de usuários mais rapidamente e intuitivamente, e permitirá que outros melhor entendam seu código com apenas algumas olhadas.</p> + +<p>Para ler mais sobre o JSX, confira este artigo do time do React, <a href="https://reactjs.org/docs/jsx-in-depth.html">JSX In Depth</a>.</p> + +<h2 id="Configurando_seu_primeiro_app_React">Configurando seu primeiro app React</h2> + +<p>Existem muitos jeitos de utilizar o React, mas nós iremos utilizar a ferramenta de interface da linha de comando (ILC), <em>create-react-app</em>, como mencionado anteriormente, que acelera o processo de desenvolvimento da aplicação em React instalando alguns pacotes e criando alguns arquivos para você, lidando com os processos de automação mencionados acima.</p> + +<p>É possível <a href="https://reactjs.org/docs/add-react-to-a-website.html">adicionar React á um website sem create-react-app</a> copiando alguns elementos <code><a href="/en-US/docs/Web/HTML/Element/script"><script> </a></code>em um arquivo HTML, mas o a interface de linha de comando <em>create-react-app </em>é um ponto de partida comum para aplicações em React. Utilizar-lo vai permitir que você passe mais tempo construindo seu aplicativo e menos tempo incomodando-se com configurações.</p> + +<h3 id="Requisitos">Requisitos</h3> + +<p>Para começar a utilizar o <em>create-react-app, </em>você precisa ter o <a href="https://nodejs.org/en/">Node.js </a>instalado. É recomendado que você utilize a versão com suporte de longa data (SLT). <em>Node </em>inclui o <em>npm </em>(o gerenciador de pacotes node), e o <em>npx </em>(o executador de pacotes do node).</p> + +<p>Você também pode utilizar o gerenciador de pacotes <em>Yarn </em>como uma alternativa, mas nós iremos assumir que você está utilizando o <em>npm </em>para esta série de tutoriais. Veja <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management"> Gerenciador de pacotes - básico </a>para mais informações sobre o <em>npm </em>ou o <em>Yarn</em>.</p> + +<p>Se você está utilizando o Windows, você vai precisar instalar alguns softwares adicionais para que você tenha as mesmas capacidades de um terminal Unix/macOS e utilizar os comandos de terminal que serão mencionados neste tutorial. <strong>Gitbash </strong>(que vem junto como parte do pacote de ferramentas <a href="https://gitforwindows.org/"> Git para o Windows </a>) ou o <a href="https://docs.microsoft.com/en-us/windows/wsl/about"> subsistema Windows para Linux </a>(<strong>WSL</strong>) ambos são adequados. Veja o <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line">Curso intensivo - Linha de comando </a>para mais informações sobre estes e sobre comandos de terminal no geral.<br> + </p> + +<p>Mantenha em mente também que React e ReactDOM produzem aplicativos que funcionam apenas em navegadores consideravelmente modernos, IE9+ (Internet Explorer 9) com o auxílio de alguns <em><a href="https://en.wikipedia.org/wiki/Polyfill_(programming)">polyfills</a>. </em>É recomendado que você utilize um navegador moderno com o Firefox, Safari ou Chrome enquanto estiver trabalhando nestes tutoriais.</p> + +<p>Veja também os seguintes artigos para mais informações:</p> + +<ul> + <li><a href="https://nodejs.org/en/knowledge/getting-started/npm/what-is-npm/">"O que é NPM" no NodeJS.org</a></li> + <li><a href="https://blog.npmjs.org/post/162869356040/introducing-npx-an-npm-package-runner">"Introdução ao NPX" no blog npm</a></li> + <li><a href="https://create-react-app.dev/">Documentação do create-react-app</a></li> +</ul> + +<h3 id="Inicializando_seu_app">Inicializando seu app</h3> + +<p>O <em>create-react-app </em>leva apenas um argumento: o nome que você quer dar ao seu aplicativo. <em>create-react-app </em>utiliza este nome para criar uma nova pasta, e então cria os arquivos necessários para o funcionamento do seu aplicativo dentro desta pasta. Certifique-se de utilizar o comando <code>cd</code> até o local em seu computador que você deseja que seu aplicativo viva dentro de seu disco rígido, feito isso, utilize o seguinte comando em seu terminal:</p> + +<pre class="brush: bash notranslate">npx create-react-app moz-todo-react</pre> + +<p>Isto criará a pasta <code>moz-todo-react</code>, e também faz mais algumas coisas dentro desta:</p> + +<ul> + <li>Instala alguns pacotes <em>npm </em>essenciais para a funcionalidade do app.</li> + <li>Escreve scripts para iniciar e servir a aplicação.</li> + <li>Cria a estrutura de arquivos e pastas que define a arquitetura básica do aplicativo.</li> + <li>Inicializa o diretório como um <em>repositório git</em>, se você tem o <em>git </em>instalado em seu computador.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Se você tem o gerenciador de pacotes <em>Yarn</em> instalado, <em>create-react-app </em>vai utilizá-lo por padrão em vez de utilizar o<em> npm</em>. Se você tem ambos gerenciadores de pacotes instalados e explicitamente quer utilizar o NPM, você pode adicionar a opção <code>--use-npm</code> quando você executar o <em>create-react-app</em>:</p> + +<pre class="brush: bash notranslate">npx create-react-app moz-todo-react --use-npm</pre> +</div> + +<p><em>create-react-app </em>vai mostrar várias mensagens em seu terminal enquanto ele trabalha; isto é normal! Isso pode levar alguns minutos, agora pode ser uma boa hora para ir preparar uma xícara de chá.</p> + +<p>Quando o processo finalizar, dê um <code>cd</code> para dentro da pasta <code>moz-todo-react </code>e execute o comando <code>npm start</code>. Os scripts instalados pelo <em>create-react-app </em>vão começar a serem servidos em um servidor local, no endereço <em>localhost:3000, </em>e abrirão o aplicativo em uma nova aba em seu navegador. Seu navegador vai mostrar algo como isto:</p> + +<p><img alt="Screenshot of Firefox MacOS, open to localhost:3000, showing the default create-react-app application" src="https://mdn.mozillademos.org/files/17203/default-create-react-app.png" style="border-style: solid; border-width: 1px; height: 980px; width: 1600px;"></p> + +<h3 id="Estrutura_da_aplicação">Estrutura da aplicação</h3> + +<p><em>create-react-app </em>dá para você tudo que você precisa para desenvolver uma aplicação React. A estrutura inicial do arquivo vai ficar assim:</p> + +<pre class="notranslate">moz-todo-react +├── README.md +├── node_modules +├── package.json +├── package-lock.json +├── .gitignore +├── public +│ ├── favicon.ico +│ ├── index.html +│ └── manifest.json +└── src + ├── App.css + ├── App.js + ├── App.test.js + ├── index.css + ├── index.js + ├── logo.svg + └── serviceWorker.js</pre> + +<p>A pasta <code>src </code>é onde nós iremos ficar a maior parte do nosso tempo, é onde o código fonte da nossa aplicação vive.</p> + +<p>A pasta <code>public </code>contém arquivos que serão lidos pelo navegador enquanto você desenvolve o aplicativo; o mais importante de todos estes arquivos é o <code>index.html</code>. O React irá injetar seu código neste arquivo para que seu navegador possa executá-lo. Existem outras marcações que ajudam o <em>create-react-app </em>a funcionar, então cuidado para não editar estas, a não ser que você saiba o que você está fazendo. Você é encorajado a mudar o texto dentro do elemento <code><a href="/en-US/docs/Web/HTML/Element/title"><title> </a></code>neste arquivo, esta mudança irá refletir no título de sua aplicação. Títulos de páginas precisos são importante para acessibilidade!</p> + +<p>A pasta <code>public </code>também será publicada quando você construir e lançar uma versão de produção de seu aplicativo. Nós não cobriremos <em>lançamento </em>(deploy) de aplicações neste tutorial, entretanto você provavelmente conseguirá implementar uma solução similar para isso descrito em nosso tutorial <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Deployment">Lançando nosso app</a>.</p> + +<p>O arquivo <code>package.json </code>contém informação sobre nosso projeto que o Node.js/npm use para manté-lo organizado. Esse arquivo não é exclusivo para aplicações em React; o <em>create-react-app </em>simplesmente encarregasse de popular este. Você não precisa entender este arquivo para completar este tutorial, entretanto, se você estiver interessado em aprender mais sobre este, você pode ler <a href="https://nodejs.org/en/knowledge/getting-started/npm/what-is-the-file-package-json/">O que é o arquivo 'package.json'? no NodeJS.org</a>; nós também falamos sobre ele no nosso tutorial <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management">Básico sobre gerenciamento de pacotes.</a></p> + +<h2 id="Explorando_seu_primeiro_componente_React_—_<App>">Explorando seu primeiro componente React — <code><App/></code></h2> + +<p>No React, um <strong>componente </strong>é um módulo reutilizável que renderiza parte de nosso aplicativo. Estas partes podem ser grandes ou pequenas, mas elas geralmente são claramente definidas: elas servem um único propósito, um propósito óbvio.</p> + +<p>Vamos o arquivo <code>src/App.js</code> dado que nosso navegador está nos instigando a editá-lo. Esse arquivo contém nosso primeiro componente, <code>App</code>, e algumas outras linhas de código.</p> + +<pre class="brush: js notranslate">import React from 'react'; +import logo from './logo.svg'; +import './App.css'; + +function App() { + return ( + <div className="App"> + <header className="App-header"> + <img src={logo} className="App-logo" alt="logo" /> + <p> + Edit <code>src/App.js</code> and save to reload. + </p> + <a + className="App-link" + href="https://reactjs.org" + target="_blank" + rel="noopener noreferrer" + > + Learn React + </a> + </header> + </div> + ); +} +export default App;</pre> + +<p>O arquivo <code>App.js</code> consiste de três partes principais: algumas declarações de <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/import">import </a></code>no topo, o componente <code>App </code>no meio, e uma declaração de <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/export">export </a></code>na parte de baixo. A maioria dos componentes React segue este padrão.</p> + +<h3 id="Declarações_de_import">Declarações de <em>import</em></h3> + +<p>As declaração de <code>import </code>no topo de nosso arquivo <code>App.js</code> nos permitem utilizar código que foi definido em outro lugar fora de nosso arquivo. Vamos dar uma olhada nestas declarações mais de perto.</p> + +<pre class="brush: js notranslate">import React from 'react'; +import logo from './logo.svg'; +import './App.css';</pre> + +<p>A primeira declaração importa a própria biblioteca React mesmo. Por conta do React transformar o JSX que nós escrevemos em declarações de <code>React.createElement()</code>, todos componentes React devem importar o módulo <code>React</code>. Se você pular este passo, sua aplicação irá resultar em um erro.</p> + +<p>A segunda declaração importa um logo de <code>.'/logo.svg</code>. Note que o <code>./</code> no começo do caminho e a extensão <code>.svg</code> no final — estes nos falam que o arquivo é local e que não é um arquivo de Javascript. De fato, o arquivo <code>logo.svg</code> vive em nossa pasta base.</p> + +<p>Nós não escrevemos um caminho ou extensão quando importando o módulo <code>React </code>— este não é um arquivo local; em vez disso, este é listado como uma dependência em nosso arquivo <code>package.json</code>. Tome cuidado com esta distinção enquanto você trabalha nesta lição!</p> + +<p>A terceira declaração importa o CSS relacionado ao nosso componente App. Note que não existe um nome de variável e também não há a diretriz <code>from</code>. Essa declaração de <em>import </em>em particular não é nativa à sintaxe de módulos do Javascript — esta vem do <em>Webpack</em>, a ferramenta que o aplicativo <em>create-react-app </em>utiliza para agrupar todos nosso arquivos de Javascript e servi-los ao navegador.</p> + +<h3 id="O_componente_App">O componente <code>App</code></h3> + +<p>Depois dos <em>imports, </em>nós temos uma função chamada <code>App</code>. Enquanto a maior parte da nossa comunidade Javascript prefere nomes utilizando o padrão <em>camel-case </em>como <code>helloWorld</code>, os componentes React utilizam o padrão de formatação para variáveis em <em>pascal-case, </em>como <code>HelloWorld</code>, para ficar claro que um dado elemento JSX é um componente React e não apenas uma <em>tag </em>de HTML comum. Se você mudasse o nome da função <code>App </code>para <code>app </code>o seu navegador iria mostrar um erro.</p> + +<p>Vamos dar uma olhada em App mais de perto.</p> + +<pre class="brush: js notranslate">function App() { + return ( + <div className="App"> + <header className="App-header"> + <img src={logo} className="App-logo" alt="logo" /> + <p> + Edit <code>src/App.js</code> and save to reload. + </p> + <a + className="App-link" + href="https://reactjs.org" + target="_blank" + rel="noopener noreferrer" + > + Learn React + </a> + </header> + </div> + ); +}</pre> + +<p>A função <code>App</code> retrona uma expressão JSX. Essa expressão define o que, no fim, o seu navegador irá renderizar para o DOM.</p> + +<p>Alguns elementos na expressão têm atributos, que são escritos assim como no HTML, seguindo o seguinte padrão de <code>atributo="valor"</code>. Na linha 3, a tag <code><a href="/en-US/docs/Web/HTML/Element/div"><div> </a></code>de abertaura tem o atributo <em><code>className</code></em>. Isso é o mesmo que o atributo <code><a href="/en-US/docs/Web/HTML/Global_attributes/class">class</a> </code>no HTML, porém por conta do JSX ser Javascript, nós não podemos utilizar a palavra <code>class</code> - esta é reservada, isso quer dizer que o Javascript já utiliza-a para um propósito específico e causaria problemas no nosso código inseri-lá aqui. Alguns outros atributos de HTML são escritos diferentes em JSX em comparação com o HTML, pela mesma razão. Nós falaremos sobre estes quando encontrarmos os mesmos.</p> + +<p>Tome um momento para mudar a <em>tag </em><code><a href="/en-US/docs/Web/HTML/Element/p"><p></a> </code>na linha 6 para que esta diga "Hello, world!", e então salve o arquivo. Você irá notar que esta mudança é imediatamente refletida e renderiza no servidor de desenvolvimento executando em <code>http://localhost:3000</code> em seu navegador. Agora delete a <em>tag </em><code><a href="/en-US/docs/Web/HTML/Element/a"><a></a></code> e salve; o link <em>"Learn React" </em>vai desaparecer.</p> + +<p>Seu componente <code>App </code>deve estar assim agora:</p> + +<pre class="brush: js notranslate">function App() { + return ( + <div className="App"> + <header className="App-header"> + <img src={logo} className="App-logo" alt="logo" /> + <p> + Hello, World! + </p> + </header> + </div> + ); +}</pre> + +<h3 id="Declarações_export">Declarações <em>export</em></h3> + +<p>Bem no final do seu arquivo <code>App.js</code>, a declaração <code>export default App</code> faz com que seu componente <code>App</code> esteja disponível para outros módulos.</p> + +<h2 id="Interrogando_o_index">Interrogando o <em>index</em></h2> + +<p>Vamos abrir <code>src/index.js</code>, porque é onde nosso componente <code>App </code>está sendo utilizado. Esse arquivo é o ponto de entrada para nosso aplicativo, e inicialmente parece-se assim:</p> + +<pre class="brush: js notranslate">import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; +import * as serviceWorker from './serviceWorker'; + +ReactDOM.render(<App />, document.getElementById('root')); + +// If you want your app to work offline and load faster, you can change +// unregister() to register() below. Note this comes with some pitfalls. +// Learn more about service workers: https://bit.ly/CRA-PWA +serviceWorker.unregister();</pre> + +<p>Assim como em <code>App.js</code>, o arquivo começa importando todos os módulos de JS (Javascript) e outros recursos que precisa executar. <code>src/index.css </code>contém estilos globais (CSS) que são aplicados em todo nosso aplicativo. Nós podemos também ver nosso componente <code>App </code>importado aqui; este é disponibilizado para ser importado graças à declaração de <code>export</code> no final do nosso arquivo <code>App.js</code>.</p> + +<p>A linha 7 invoca a função <code>ReactDOM.render()</code> com dois argumentos:</p> + +<ul> + <li>O componente que queremos renderizar, <code><App /> </code>neste caso.</li> + <li>O elemento do DOM que queremos que nosso componente seja renderizado dentro, neste caso é o elemento com o ID de <code>root</code>. Se você olhar dentro de <code>public/index.html</code>, você verá que existe um elemento <code><div></code> logo ali dentro do elemento <code><body></code>.</li> +</ul> + +<p>Tudo isso diz para o React que nós queremos renderizar nossa aplicação React como o componente <code>App</code> como a raíz do app, ou o primeiro componente.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: No JSX, componentes React e elementos HTML precisam ser barras de fechamento. Escrever apenas <code><App></code> ou apenas <code><img></code> irá causar um erro.</p> +</div> + +<p><a href="/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers">Service workers</a> são pedaços interessantes de código que ajudam a perfomance da aplicação e permitem a utilização de algumas características de sua aplicação de web a funcionarem <em>offline</em>, porém estes não estão no escopo deste artigo. Você pode deletar a linha 5, como também as linhas 9 até a 12.</p> + +<p>Seu arquivo <code>index.js</code> final deve estar assim:</p> + +<pre class="brush: js notranslate">import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; + +ReactDOM.render(<App />, document.getElementById('root'));</pre> + +<h2 id="Variáveis_e_props">Variáveis e props</h2> + +<p>A seguir, nós usaremos algumas de nossas habilidades de JavaScript para ficarmos mais confortáveis editando componentes e trabalhando com dados no React. Nós falaremos sobre como variáveis são utilizadas dentro do JSX, introduziremos <em>props</em>, que são por si uma forma de passar dados para um componente (que então podem ser acessadas utilizando-se de variáveis).</p> + +<h3 id="Variáveis_no_JSX">Variáveis no JSX</h3> + +<p>De volta ao <code>App.js</code> vamos focar na linha 9:</p> + +<pre class="brush: js notranslate"><img src={logo} className="App-logo" alt="logo" /></pre> + +<p>Aqui, na <em>tag </em><code><img /> </code>o atributo <code>src</code> está entre chaves ( { } ). É assim que o JSX reconhece variáveis. React irá ver <code>{logo}</code>, saberá que você está referindo-se ao <em>import </em>do logo na linha 2 do nosso aplicativo, e então buscar o arquivo logo e renderizá-lo.</p> + +<p>Vamos tentar fazer uma variável própria. Antes da declaração de <em>return </em>de <code>App</code> adicione <code>const subject = 'React';</code>. Seu componente <code>App</code> deve estar assim agora:</p> + +<pre class="brush: js notranslate">function App() { + const subject = "React"; + return ( + <div className="App"> + <header className="App-header"> + <img src={logo} className="App-logo" alt="logo" /> + <p> + Hello, World! + </p> + </header> + </div> + ); +}</pre> + +<p>Muda a linha 8 para usar a nossa variável <code>subject</code> em vez da palavra "world", desta forma:</p> + +<pre class="brush: js notranslate">function App() { + const subject = "React"; + return ( + <div className="App"> + <header className="App-header"> + <img src={logo} className="App-logo" alt="logo" /> + <p> + Hello, {subject}! + </p> + </header> + </div> + ); +}</pre> + +<p>Quando você salvar, seu navegador deverá mostrar "Hello, React!", em vez de mostrar "Hello, world!"</p> + +<p>Variáveis são conveniente, mas esta que nós definimos não faz jus aos ótimos recursos do React. É aí que entram as <em>props</em>.</p> + +<h3 id="props_de_Componentes"><em>props </em>de Componentes</h3> + +<p>Uma <strong>prop</strong> é qualquer dado passado para um componente React. <em>Props</em> são escritos dentro de invocações de componentes e utilizam a mesma sintaxe que atributos de HTML - <code>prop="valor"</code>. Vamos abrir o <code>index.js</code> e dar à nossa invocação do <code><App/></code> nossa primeira <em>prop</em>.</p> + +<p>Adicione a <em>prop</em> <code>subject</code> para a invocação do componente <code><App/></code>, com o valor de <code>Clarice</code>. Quando você terminar, seu código deve estar assim:</p> + +<pre class="brush: js notranslate">ReactDOM.render(<App subject="Clarice" />, document.getElementById('root'));</pre> + +<p>De volta ao <code>App.js</code>, vamos revisitar a própria função App, que é lida da seuginte forma ( com a declaração de <code>return </code>encurtada, a fim de ser breve.)</p> + +<pre class="brush: js notranslate">function App() { + const subject = "React"; + return ( + // return statement + ); +}</pre> + +<p>Mude a definação da nossa função <code>App</code> para que aceite <code>props</code> como um parâmetro. Assim como qualquer outro parâmetro, você pode colocar <code>props</code> em um <code>console.log()</code> para ler o que este contém no console de seu navegador. Vá em frente e faça justamente isto depois da sua constante <code>subject</code> porém antes da sua declaração de <code>return</code>, da seguinte forma:</p> + +<pre class="brush: js notranslate">function App(props) { + const subject = "React"; + console.log(props); + return ( + // return statement + ); +}</pre> + +<p>Salve seu arquivo e dê uma olhada no console do navegador. Você deve ver algo assim nos <em>logs</em>:</p> + +<pre class="brush: js notranslate">Object { subject: "Clarice" }</pre> + +<p>A propriedade <code>subjet</code> deste objeto corresponde à <em>prop </em><code>subject</code> que nós adicionamos à nossa chamada do componente <code><App /> </code>, e a <em>string</em> <code>Clarice</code> corresponde ao seu valor. <em>props </em>de coponentes no React são sempre coletadas em objetos neste mesmo estilo.</p> + +<p>Agora que <code>subjet</code> é uma de nossas <em>props</em>, vamos utilizá-la em <code>App.js</code>. Mude a constante <code>subject</code> para que, em vez de ler a string que diz <code>React</code>, você está lendo o valor de <code>props.subject</code>. Você também pode deletar o <code>console.log()</code>, se você quiser.</p> + +<pre class="brush: js notranslate">function App(props) { + const subject = props.subject; + return ( + // return statement + ); +}</pre> + +<p>Quando você salvar o arquivo, o aplicativo agora deve dizer "Hello, Clarice!". Se você retornar ao <code>index.js</code>, editar o valor de <code>subject</code> e salvar, seu texto irá mudar.</p> + +<h2 id="Sumário">Sumário</h2> + +<p>Isto nos traz ao fim da nossa primeira olhada no React, incluindo como instalá-lo localmente, criando um aplicativo inicial e como os básicos funcionam. No próximo artigo nós começaremos construindo nossa primeira aplicação de verdade — uma lista de afazeres. Antes de fazermos isso, entretanto, vamos relembrar algumas coisas que aprendemos.</p> + +<p>No React</p> + +<ul> + <li>Componentes podem importar módulos que eles precisam e devem exportar a si mesmo no final de seus respectivos arquivos.</li> + <li>Componentes em forma de função são nomeados com <code>PascalCase</code>.</li> + <li>Você pode ler variáveis de JSX ao colocá-las entre chaves, da seguinte forma <code>{assim}</code>.</li> + <li>Alguns atributos de JSX são diferente dos atributos de HTML, isto é feito para que eles não entrem em conflito com palavras reservadas do JavaScript. Por exemplo. <code>class</code> no HTML transforma-se em <code>className</code> no JSX. Note que atributos com múltiplas palavras são escritos no padrão de formatação <em>camel-case</em>.</li> + <li><em>Props</em> são escritas bem como atributos dentro das invocações de componentes e são passadas para dentro de componentes.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction">Introdução a frameworks <em>client-side</em></a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features">Principais características de frameworks</a></li> + <li>React + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started">Começando com o React</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning">Começando nossa app de lista de afazares</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components">Componentizando nosso aplicativo React</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state">Interatividade no React: <em>events </em>e <em>state</em></a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_filtering_conditional_rendering">Interatividade no React: Editando, filtrando e renderização condicional</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility">Accessibilidade no React</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_resources">Recursos sobre React</a></li> + </ul> + </li> + <li>Ember + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_getting_started">Começando com o Ember</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_structure_componentization">Ember: estrutura de apps e componetização</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_interactivity_events_state">Interatividade no Ember: Events, classes e state</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_conditional_footer">Interatividade no Ember: Funcionalidade do rodapé e renderização condicional</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_routing">Roteamento no Ember</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources">Recursos sobre o Ember e problemas comuns</a></li> + </ul> + </li> + <li>Vue + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started">Começando com o Vue</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component">Criando nosso primeiro componente com o Vue</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists">Renderizando uma lista de componentes Vue</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models">Adicionando um novo formulário de afazeres: Events do Vue, métodos e models</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_styling">Estilizando componentes Vue com CSS</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_computed_properties">Utilizando propriedades computadas do Vue</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_conditional_rendering">Renderização condicional no Vue: Editando afazeres existentes</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_refs_focus_management">Gerenciamento de foco com Vue refs</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_resources">Recursos sobre Vue</a></li> + </ul> + </li> +</ul> diff --git a/files/pt-br/learn/tools_and_testing/client-side_javascript_frameworks/index.html b/files/pt-br/learn/tools_and_testing/client-side_javascript_frameworks/index.html new file mode 100644 index 0000000000..ba7a1cba3e --- /dev/null +++ b/files/pt-br/learn/tools_and_testing/client-side_javascript_frameworks/index.html @@ -0,0 +1,136 @@ +--- +title: Understanding client-side JavaScript frameworks +slug: Learn/Tools_and_testing/Client-side_JavaScript_frameworks +tags: + - Beginner + - Frameworks + - JavaScript + - Learn + - NeedsTranslation + - TopicStub + - client-side +translation_of: Learn/Tools_and_testing/Client-side_JavaScript_frameworks +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">As estruturas JavaScript são uma parte essencial do desenvolvimento front-end da Web moderna, que fornecem aos desenvolvedores ferramentas utilizadas e testadas para a criação de aplicativos Web interativos e escalonáveis. Muitas empresas modernas usam estruturas como parte padrão de suas ferramentas, portanto, muitos trabalhos de desenvolvimento front-end agora exigem experiência em estruturas.</p> + +<p class="summary"><span class="tlid-translation translation" lang="pt"><span class="alt-edited">Como um desenvolvedor front-end iniciante, pode ser difícil descobrir por onde começar ao aprender frameworks - com tantos frameworks diferentes para escolher, novos aparecem o tempo todo, geralmente funcionam de maneira semelhante, mas fazem algumas coisas de forma diferente, e há alguns cuidados específicos a serem seguidos ao se usar frameworks.</span></span></p> + +<p class="summary">Neste conjunto de artigos, nosso objetivo é fornecer um ponto de partida confortável para ajudá-lo a começar a aprender frameworks. Não pretendemos ensinar exaustivamente tudo o que você precisa saber sobre o React / ReactDOM, ou Vue, ou algum outro framework específico; os próprios documentos das equipes do framework já fazem esse trabalho. Em vez disso, queremos fazer backup e responder primeiro a perguntas mais fundamentais, como:</p> + +<ul> + <li class="summary">Por que devo usar um framework? Que problemas eles resolvem para mim?</li> + <li class="summary">Que perguntas devo fazer ao tentar escolher um framwork? Eu preciso mesmo usar um framework?</li> + <li class="summary">Quais recursos os frameworks têm? Como funcionam em geral e como as implementações dos frameworks desses recursos diferem?</li> + <li class="summary">Como se relacionam com JavaScript ou HTML "vanilla"?</li> +</ul> + +<p class="summary">Depois disso, forneceremos alguns tutoriais que abordam os fundamentos de alguns dos principais frameworks, que fornecem contexto e familiaridade suficientes para começar a se aprofundar mais. Queremos que avance e aprenda sobre estruturas de uma maneira pragmática que não se esqueça das melhores práticas fundamentais da plataforma da web, como acessibilidade.</p> + +<p class="summary"><strong><a href="https://wiki.developer.mozilla.org/pr-BR/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction">Comece agora, com "Introdução às estruturas do lado do cliente"</a></strong></p> + +<h2 id="Pré_-_requisitos">Pré - requisitos</h2> + +<p>Você deve aprender o básico das principais linguagens para web(<strong>HTML</strong>, <strong>CSS </strong> e principalmente <strong>Javascript</strong>) antes de estudar os frameworks voltados para client-side.Dessa forma, o seu código será mais rico e profissional, preparando você para lidar com problemas com mais confiança, resultado do bom entendimento sobre os recursos fundamentais dos frameworks que constroem as plataformas.</p> + +<h2 id="Guias_de_introdução">Guias de introdução</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction">1.trodução a frameworks para client-side</a></dt> + <dd>( begin our look at frameworks with a general overview of the area, looking at a brief history of JavaScript and frameworks, why frameworks exist and what they give us, how to start thinking about choosing a framework to learn, and what alternatives there are to client-side frameworks.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features">2.Principais recursos para frameworks</a></dt> + <dd>Each major JavaScript framework has a different approach to updating the DOM, handling browser events, and providing an enjoyable developer experience. This article will explore the main features of “the big 4” frameworks, looking at how frameworks tend to work from a high level and the differences between them.</dd> +</dl> + +<h2 id="React_tutorials">React tutorials</h2> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: React tutorials last tested in May 2020, with React/ReactDOM 16.13.1 and create-react-app 3.4.1.</p> + +<p>If you need to check your code against our version, you can find a finished version of the sample React app code in our <a href="https://github.com/mdn/todo-react">todo-react repository</a>. For a running live version, see <a href="https://mdn.github.io/todo-react-build/">https://mdn.github.io/todo-react-build/</a>.</p> +</div> + +<dl> + <dt><a href="c">1. </a><a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started">Começando com o React</a></dt> + <dd>In this article we will say hello to React. We'll discover a little bit of detail about its background and use cases, set up a basic React toolchain on our local computer, and create and play with a simple starter app, learning a bit about how React works in the process.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning">2. </a><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning">Começando com a nossa lista "to do" do React</a></dt> + <dd>Let's say that we’ve been tasked with creating a proof-of-concept in React – an app that allows users to add, edit, and delete tasks they want to work on, and also mark tasks as complete without deleting them. This article will walk you through putting the basic <code>App</code> component structure and styling in place, ready for individual component definition and interactivity, which we'll add later.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components">3. </a><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components">Componetizando o nosso app React</a></dt> + <dd>At this point, our app is a monolith. Before we can make it do things, we need to break it apart into manageable, descriptive components. React doesn’t have any hard rules for what is and isn’t a component – that’s up to you! In this article, we will show you a sensible way to break our app up into components.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state">4.</a> <a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state">Interatividade React : Eventos e estado</a></dt> + <dd>With our component plan worked out, it's now time to start updating our app from a completely static UI to one that actually allows us to interact and change things. In this article we'll do this, digging into events and state along the way.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_filtering_conditional_rendering">5. </a><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_filtering_conditional_rendering">Interatividade com o React : Editando, filltrando e renderizando</a></dt> + <dd>As we near the end of our React journey (for now at least), we'll add the finishing touches to the main areas of functionality in our Todo list app. This includes allowing you to edit existing tasks and filtering the list of tasks between all, completed, and incomplete tasks. We'll look at conditional UI rendering along the way.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility">6. </a><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility">Acessibilidade com o React</a></dt> + <dd>In our final tutorial article, we'll focus on (pun intended) accessibility, including focus management in React, which can improve usability and reduce confusion for both keyboard-only and screen reader users.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_resources">7. </a><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_resources">Recursos do React</a></dt> + <dd>Our final article provides you with a list of React resources that you can use to go further in your learning.</dd> +</dl> + +<h2 id="Ember_tutorials">Ember tutorials</h2> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: Ember tutorials last tested in May 2020, with Ember/Ember CLI version 3.18.0.</p> + +<p>If you need to check your code against our version, you can find a finished version of the sample Ember app code in the <a href="https://github.com/NullVoxPopuli/ember-todomvc-tutorial/tree/master/steps/00-finished-todomvc/todomvc">ember-todomvc-tutorial repository</a>. For a running live version, see <a href="https://nullvoxpopuli.github.io/ember-todomvc-tutorial/">https://nullvoxpopuli.github.io/ember-todomvc-tutorial/</a> (this also includes a few additional features not covered in the tutorial).</p> +</div> + +<dl> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_getting_started">1. Getting started with Ember</a></dt> + <dd>In our first Ember article we will look at how Ember works and what it's useful for, install the Ember toolchain locally, create a sample app, and then do some initial setup to get it ready for development.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_structure_componentization">2. Ember app structure and componentization</a></dt> + <dd>In this article we'll get right on with planning out the structure of our TodoMVC Ember app, adding in the HTML for it, and then breaking that HTML structure into components.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_interactivity_events_state">3. Ember interactivity: Events, classes and state</a></dt> + <dd>At this point we'll start adding some interactivity to our app, providing the ability to add and display new todo items. Along the way, we'll look at using events in Ember, creating component classes to contain JavaScript code to control interactive features, and setting up a service to keep track of the data state of our app.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_conditional_footer">4. Ember Interactivity: Footer functionality, conditional rendering</a></dt> + <dd>Now it's time to start tackling the footer functionality in our app. Here we'll get the todo counter to update to show the correct number of todos still to complete, and correctly apply styling to completed todos (i.e. where the checkbox has been checked). We'll also wire up our "Clear completed" button. Along the way, we'll learn about using conditional rendering in our templates.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_routing">5. Routing in Ember</a></dt> + <dd>In this article we learn about routing or URL-based filtering as it is sometimes referred to. We'll use it to provide a unique URL for each of the three todo views — "All", "Active", and "Completed".</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources">6. Ember resources and troubleshooting</a></dt> + <dd>Our final Ember article provides you with a list of resources that you can use to go further in your learning, plus some useful troubleshooting and other information.</dd> +</dl> + +<h2 id="Vue_tutorials">Vue tutorials</h2> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: Vue tutorials last tested in May 2020, with Vue 2.6.11.</p> + +<p>If you need to check your code against our version, you can find a finished version of the sample Vue app code in our <a href="https://github.com/mdn/todo-vue">todo-vue repository</a>. For a running live version, see <a href="https://mdn.github.io/todo-vue/dist/">https://mdn.github.io/todo-vue/dist/</a>.</p> +</div> + +<dl> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started">1. Getting started with Vue</a></dt> + <dd>Now let's introduce Vue, the third of our frameworks. In this article, we'll look at a little bit of Vue background, learn how to install it and create a new project, study the high-level structure of the whole project and an individual component, see how to run the project locally, and get it prepared to start building our example.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component">2. Creating our first Vue component</a></dt> + <dd>Now it's time to dive deeper into Vue, and create our own custom component — we'll start by creating a component to represent each item in the todo list. Along the way, we'll learn about a few important concepts such as calling components inside other components, passing data to them via props and saving data state.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists">3. Rendering a list of Vue components</a></dt> + <dd><span class="author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qoxwoxz78zz83zz84zz69z2z80zgwxsgnz83zfkt5e5tz70zz68zmsnjz122zz71z">At this point we've got a fully working component; we're now ready to add multiple <code>ToDoItem</code> components to our App. In this article we'll look at adding a set of todo item data to our <code>App.vue</code> component, which we'll then loop through and display inside <code>ToDoItem</code> components using the <code>v-for</code> directive. </span></dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models">4. Adding a new todo form: Vue events, methods, and models</a></dt> + <dd>We now have sample data in place and a loop that takes each bit of data and renders it inside a <code>ToDoItem</code> in our app. What we really need next is the ability to allow our users to enter their own todo items into the app, and for that, we'll need a text <code><input></code>, an event to fire when the data is submitted, a method to fire upon submission to add the data and rerender the list, and a model to control the data. This is what we'll cover in this article.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_styling">5. Styling Vue components with CSS</a></dt> + <dd>The time has finally come to make our app look a bit nicer. In this article, we'll explore the different ways of styling Vue components with CSS.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_computed_properties">6. Using Vue computed properties</a></dt> + <dd>In this article we'll add a counter that displays the number of completed todo items, using a feature of Vue called computed properties. These work similarly to methods but only re-run when one of their dependencies changes.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_conditional_rendering">7. Vue conditional rendering: editing existing todos</a></dt> + <dd>Now it is time to add one of the major parts of functionality that we're still missing — the ability to edit existing todo items. To do this, we will take advantage of Vue's conditional rendering capabilities — namely <code>v-if</code> and <code>v-else</code> — to allow us to toggle between the existing todo item view and an edit view where you can update todo item labels. We'll also look at adding functionality to delete todo items.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_refs_focus_management">8. Focus management with Vue refs</a></dt> + <dd>We are nearly done with Vue. The last bit of functionality to look at is focus management, or put another way, how we can improve our app's keyboard accessibility. We'll look at using Vue refs to handle this — an advanced feature that allows you to have direct access to the underlying DOM nodes below the virtual DOM, or direct access from one component to the internal DOM structure of a child component.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_resources">9. Vue resources</a></dt> + <dd>Now we'll round off our study of Vue by giving you a list of resources that you can use to go further in your learning, plus some other useful tips.</dd> +</dl> + +<h2 id="Which_frameworks_did_we_choose">Which frameworks did we choose?</h2> + +<p>We are publishing our initial set of articles with guides focusing on three of the major frameworks out there — React/ReactDOM, Ember, and Vue. There is a variety of reasons for this:</p> + +<ul> + <li>They are popular choices that will be around for a while — like with any software tool, it is good to stick with actively-developed choices that are likely to not be discontinued next week, and which will be desirable additions to your skill set when looking for a job.</li> + <li>They have strong communities and good documentation. It is very important to be able to get help with learning a complex subject, especially when you are just starting out.</li> + <li>We don't have the resources to cover <em>all</em> modern frameworks. That list would be very difficult to keep up-to-date anyway, as new ones appear all the time.</li> + <li>As a beginner, trying to choose what to focus on out of the huge number of choices available is a very real problem. Keeping the list short is therefore helpful.</li> +</ul> + +<p>We want to say this upfront — we've <strong>not</strong> chosen the frameworks we are focusing on because we think they are the best, or because we endorse them in any way. We just think they score highly on the above criteria.</p> + +<p>Note that we were hoping to have more frameworks included upon initial publication, but we decided to release the content and then add more framework guides later, rather than delay it longer. If your favourite framework is not represented in this content and you'd like to help change that, feel free to discuss it with us! Get in touch with us via <a href="https://wiki.mozilla.org/Matrix">Matrix</a>, or <a href="https://discourse.mozilla.org/c/mdn">Discourse</a>, or drop us a mail on the <a href="mailto:mdn-admins@mozilla.org">mdn-admins list</a>.</p> diff --git a/files/pt-br/learn/tools_and_testing/client-side_javascript_frameworks/vue_iniciando/index.html b/files/pt-br/learn/tools_and_testing/client-side_javascript_frameworks/vue_iniciando/index.html new file mode 100644 index 0000000000..607b876a2e --- /dev/null +++ b/files/pt-br/learn/tools_and_testing/client-side_javascript_frameworks/vue_iniciando/index.html @@ -0,0 +1,281 @@ +--- +title: Iniciando com Vue +slug: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_iniciando +translation_of: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}</div> + +<p class="summary">Agora vamos apresentar o Vue, o nosso terceiro frameworks. Neste artigo, examinaremos um pouco do histórico do Vue, aprenderemos como instalá-lo e criar um novo projeto, estudaremos a estrutura de alto nível de todo o projeto e um componente individual, veremos como executar o projeto localmente e o deixaremos preparado para começar a construir o nosso exemplo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td> + <p>Conhecimento com as liguagens <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a>, e <a href="/en-US/docs/Learn/JavaScript">JavaScript</a>, conhecimento do <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line">terminal/command line</a>.</p> + + <p>Os componentes do Vue são escritos como uma combinação de objetos JavaScript que gerenciam os dados do aplicativo e uma sintaxe de modelo baseada em HTML que é mapeada para a estrutura DOM subjacente. Para a instalação e para usar alguns dos recursos mais avançados do Vue (como simples Componentes de arquivo ou funções de renderização), você precisará de um terminal com node + npm instalados.</p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Para configurar um ambiente de desenvolvimento local do Vue, crie um aplicativo inicial e entenda o básico de como ele funciona.</td> + </tr> + </tbody> +</table> + +<h2 id="Um_Vue_mais_claro"><span class="tlid-translation translation" lang="pt"><span title="">Um Vue mais claro</span></span></h2> + +<p>O Vue é uma estrutura JavaScript moderna que fornece recursos úteis para aprimoramento progressivo - ao contrário de muitos outros frameworks, você pode usar o Vue para aprimorar o HTML existente. Isso permite que você use o Vue como um substituto para uma biblioteca como o <a href="https://wiki.developer.mozilla.org/en-US/docs/Glossary/jQuery">JQuery</a>.</p> + +<p>Dito isto, você também pode usar o Vue para escrever aplicativos de página única (Single Page Applications - SPAs) inteiros. Isso permite criar marcações gerenciadas inteiramente pelo Vue, o que pode melhorar a experiência e o desempenho do desenvolvedor ao lidar com aplicativos complexos. Também permite tirar proveito das bibliotecas para roteamento do lado do cliente (client-side) e gerenciamento de estado quando necessário. Além disso, o Vue adota uma abordagem "intermediária" das ferramentas, como roteamento do lado do cliente e gerenciamento de estado. Embora a equipe mantenedora do Vue sugira bibliotecas para essas funções, elas não são agrupadas diretamente no Vue. Isso permite que você selecione bibliotecas de gerenciamento de estado/roteamento diferentes, se elas se ajustarem melhor ao seu aplicativo.</p> + +<p>Além de permitir a integração progressiva do Vue em seus aplicativos, o Vue também fornece uma abordagem progressiva para escrever marcações. Como a maioria dos frameworks, o Vue permite criar blocos reutilizáveis de marcação por meio de componentes. Na maioria das vezes, os componentes do Vue são gravados usando uma sintaxe de modelo HTML especial. Quando você precisar de mais controle do que a sintaxe HTML permite, poderá escrever funções JSX ou JavaScript simples para definir seus componentes.</p> + +<p>À medida que você trabalha neste tutorial, convém manter o <a href="https://vuejs.org/v2/guide/">guia do Vue</a> e a <a href="https://vuejs.org/v2/api/">documentação da API</a> abertos em outras guias, para poder consultar um item se quiser obter mais informações sobre qualquer subtópico.<br> + Para uma boa comparação (mas potencialmente tendenciosa) entre o Vue e muitos outros frameworks, consulte <a href="https://vuejs.org/v2/guide/comparison.html">Vue Docs: Comparação com outros frameworks</a>.</p> + +<h2 id="Installation">Installation</h2> + +<p>To use Vue in an existing site, you can drop one of the following <code><a href="/en-US/docs/Web/HTML/Element/script"><script></a></code> elements onto a page. This allows you to start using Vue on existing sites, which is why Vue prides itself on being a progressive framework. This is a great option when migrating an existing project using a library like JQuery to Vue. With this method, you can use a lot of the core features of Vue, such as the attributes, custom components, and data-management.</p> + +<ul> + <li> + <p>Development Script (Unoptimized, but includes console warnings. Great for development</p> + + <pre class="brush: html"><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></pre> + </li> + <li> + <p>Production Script (Optimized version, minimal console warnings. It is recommended that you specify a version number when including Vue on your site so that any framework updates do not break your live site without you knowing.)</p> + + <pre class="brush: html"><script src="https://cdn.jsdelivr.net/npm/vue@2"></script></pre> + </li> +</ul> + +<p>However, this approach has some limitations. To build more complex apps, you’ll want to use the <a href="https://www.npmjs.com/package/vue">Vue NPM package</a>. This will let you use advanced features of Vue and take advantage of bundlers like WebPack. To make building apps with Vue easier, there is a CLI to streamline the development process. To use the npm package & the CLI you will need:</p> + +<ol> + <li>Node.js 8.11+ installed.</li> + <li>npm or yarn.</li> +</ol> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you don't have the above installed, find out <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line#Adding_powerups">more about installing npm and Node.js</a> here.</p> +</div> + +<p>To install the CLI, run the following command in your terminal:</p> + +<pre class="brush: bash">npm install --global @vue/cli</pre> + +<p>Or if you'd prefer to use yarn:</p> + +<pre class="brush: bash">yarn global add @vue/cli</pre> + +<p>Once installed, to initialize a new project you can then open a terminal in the directory you want to create the project in, and run <code>vue create <project-name></code>. The CLI will then give you a list of project configurations you can use. There are a few preset ones, and you can make your own. These options let you configure things like TypeScript, linting, vue-router, testing, and more.</p> + +<p>We’ll look at using this below.</p> + +<h2 id="Initializing_a_new_project">Initializing a new project</h2> + +<p>To explore various features of Vue, we will be building up a sample todo list app. We'll begin by using the Vue CLI to create a new app framework to build our app into. Follow the steps below:</p> + +<ol> + <li>In terminal, <code>cd</code> to where you'd like to create your sample app, then run <code>vue create moz-todo-vue</code>.</li> + <li>Use the arrow keys and <kbd>Enter</kbd> to select the "Manually select features" option.</li> + <li>The first menu you’ll be presented with allows you to choose which features you want to include in your project. Make sure that "Babel" and "Linter / Formatter" are selected. If they are not, use the arrow keys and the space bar to toggle them on. Once they are selected, press <kbd>Enter</kbd> to proceed.</li> + <li>Next you’ll select a config for the linter / formatter. Navigate to "Eslint with error prevention only" and hit <kbd>Enter</kbd> again. This will help us catch common errors, but not be overly opinionated.</li> + <li>Next you are asked to configure what kind of automated linting we want. Select "Lint on save". This will check for errors when we save a file inside the project. Hit <kbd>Enter</kbd> to continue.</li> + <li>Now, you will select how we want your config files to be managed. "In dedicated config files" will put your config settings for things like ESLint into their own, dedicated files. The other option, "In package.json", will put all of your config settings into the app's <code>package.json</code> file. Select "In dedicated config files" and push <kbd>Enter</kbd>.</li> + <li>Finally, you are asked if you want to save this as a preset for future options. This is entirely up to you. If you like these settings over the existing presets and want to use them again, type <kbd>y</kbd> , otherwise type <kbd>n</kbd>.</li> +</ol> + +<p>The CLI will now begin scaffolding out your project, and installing all of your dependencies.</p> + +<p>If you've never run the Vue CLI before, you'll get one more question — you'll be asked to choose a package manager. You can use the arrow keys to select which one you prefer. The Vue CLI will default to this package manager from now on. If you need to use a different package manager after this, you can pass in a flag <code>--packageManager=<package-manager></code>, when you run <code>vue create</code>. So if you wanted to create the <code>moz-todo-vue</code> project with npm and you'd previously chosen yarn, you’d run <code>vue create moz-todo-vue --packageManager=npm</code>.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: We've not gone over all of the options here, but you can <a href="https://cli.vuejs.org">find more information on the CLI</a> in the Vue docs.</p> +</div> + +<h2 id="Project_structure">Project structure</h2> + +<p>If everything went successfully, the CLI should have created a series of files and directories for your project. The most significant ones are as follows:</p> + +<ul> + <li><code>.eslintrc.js</code>: This is a config file for <a href="https://eslint.org/">eslint</a>. You can use this to manage your linting rules.</li> + <li><code>babel.config.js</code>: This is the config file for <a href="https://babeljs.io/">Babel</a>, which transforms modern JavaScript features being used in development code into older syntax that is more cross-browser compatible in production code. You can register additional babel plugins in this file.</li> + <li><code>.browserslistrc</code>: This is a config for <a href="https://github.com/browserslist/browserslist">Browserslist</a>. You can use this to control which browsers your tooling optimizes for.</li> + <li><code>public</code>: This directory contains static assets that are published, but not processed by <a href="https://webpack.js.org/">Webpack</a> during build (with one exception; <code>index.html</code> gets some processing). + <ul> + <li><code>favicon.ico</code>: This is the favicon for your app. Currently, it's the Vue logo.</li> + <li><code>index.html</code>: This is the template for your app. Your Vue app is run from this HTML page, and you can use lodash template syntax to interpolate values into it. + <div class="note"><strong>Note</strong>: this is not the template for managing the layout of your application — this template is for managing static HTML that sits outside of your Vue app. Editing this file typically only occurs in advanced use cases.</div> + </li> + </ul> + </li> + <li><code>src</code>: This directory contains the core of your Vue app. + <ul> + <li><code>main.js</code>: this is the entry point to your application. Currently, this file initializes your Vue application and signifies which HTML element in the <code>index.html</code> file your app should be attached to. This file is often where you register global components or additional Vue libraries.</li> + <li><code>App.vue</code>: this is the top-level component in your Vue app. See below for more explanation of Vue components.</li> + <li><code>components</code>: this directory is where you keep your components. Currently it just has one example component.</li> + <li><code>assets</code>: This directory is for storing static assets like CSS and images. Because these files are in the source directory, they can be processed by Webpack. This means you can use pre-processors like <a href="https://sass-lang.com/">Sass/SCSS</a> or <a href="https://stylus-lang.com/">Stylus</a>.</li> + </ul> + </li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: Depending on the options you select when creating a new project, there might be other directories present (for example, if you choose a router, you will also have a <code>views</code> directory).</p> +</div> + +<h2 id=".vue_files_single_file_components">.vue files (single file components)</h2> + +<p>Like in many front-end frameworks, components are a central part of building apps in Vue. These components let you break a large application into discrete building blocks that can be created and managed separately, and transfer data between each other as required. These small blocks can help you reason about and test your code.</p> + +<p>While some frameworks encourage you to separate your template, logic, and styling code into separate files, Vue takes the opposite approach. Using <a href="https://vuejs.org/v2/guide/single-file-components.html">Single File Components</a>, Vue lets you group your templates, corresponding script, and CSS all together in a single file ending in <code>.vue</code>. These files are processed by a JS build tool (such as Webpack), which means you can take advantage of build-time tooling in your project. This allows you to use tools like Babel, TypeScript, SCSS and more to create more sophisticated components.</p> + +<p>As a bonus, projects created with the Vue CLI are configured to use <code>.vue</code> files with Webpack out of the box. In fact, if you look inside the <code>src</code> folder in the project we created with the CLI, you'll see your first <code>.vue</code> file: <code>App.vue</code>.</p> + +<p>Let's explore this now.</p> + +<h3 id="App.vue">App.vue</h3> + +<p>Open your <code>App.vue</code> file — you’ll see that it has three parts: <code><template></code>, <code><script></code>, and <code><style></code>, which contain the component’s template, scripting, and styling information. All Single File Components share this same basic structure.</p> + +<p><code><template></code> contains all the markup structure and display logic of your component. Your template can contain any valid HTML, as well as some Vue-specific syntax that we'll cover later.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: By setting the <code>lang</code> attribute on the <code><template></code> tag, you can use Pug template syntax instead of standard HTML — <code><template lang="pug"></code>. We'll stick to standard HTML through this tutorial, but it is worth knowing that this is possible.</p> +</div> + +<p><code><script></code> contains all of the non-display logic of your component. Most importantly, your <code><script></code> tag needs to have a default exported JS object. This object is where you locally register components, define component inputs (props), handle local state, define methods, and more. Your build step will process this object and transform it (with your template) into a Vue component with a <code>render()</code> function.</p> + +<p>In the case of <code>App.vue</code>, our default export sets the name of the component to <code>app</code> and registers the <code>HelloWorld</code> component by adding it into the <code>components</code> property. When you register a component in this way, you're registering it locally. Locally registered components can only be used inside the components that register them, so you need to import and register them in every component file that uses them. This can be useful for bundle splitting/tree shaking since not every page in your app necessarily needs every component.</p> + +<pre class="brush: js">import HelloWorld from './components/HelloWorld.vue'; + +export default { + name: 'app', + components: { + //You can register components locally here. + HelloWorld + } +};</pre> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you want to use <a href="https://www.typescriptlang.org/">TypeScript</a> syntax, you need to set the <code>lang</code> attribute on the <code><script></code> tag to signify to the compiler that you're using TypeScript — <code><script lang="ts"></code>.</p> +</div> + +<p><code><style></code> is where you write your CSS for the component. If you add a <code>scoped</code> attribute — <code><style scoped></code> — Vue will scope the styles to the contents of your SFC. This works similar to CSS-in-JS solutions, but allows you to just write plain CSS.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you select a CSS pre-processor when creating the project via the CLI, you can add a <code>lang</code> attribute to the <code><style></code> tag so that the contents can be processed by Webpack at build time. For example, <code><style lang="scss"></code> will allow you to use SCSS syntax in your styling information.</p> +</div> + +<h2 id="Running_the_app_locally">Running the app locally</h2> + +<p>The Vue CLI comes with a built-in development server. This allows you to run your app locally so you can test it easily without needing to configure a server yourself. The CLI adds a <code>serve</code> command to the project’s <code>package.json</code> file as an npm script, so you can easily run it.</p> + +<p>In your terminal, try running <code>npm run serve</code> (or <code>yarn serve</code> if you prefer yarn). Your terminal should output something like the following:</p> + +<pre>INFO Starting development server... +98% after emitting CopyPlugin + + DONE Compiled successfully in 18121ms + + App running at: + - Local: <http://localhost:8080/> + - Network: <http://192.168.1.9:8080/> + + Note that the development build is not optimized. + To create a production build, run npm run build.</pre> + +<p>If you navigate to the “local” address in a new browser tab (this should be something like <code>http://localhost:8080</code> as stated above, but may vary based on your setup), you should see your app. Right now, it should contain a welcome message, a link to the Vue documentation, links to the plugins you added when you initialized the app with your CLI, and some other useful links to the Vue community and ecosystem.</p> + +<p><img alt="default vue app render, with vue logo, welcome message, and some documentation links" src="https://mdn.mozillademos.org/files/17240/vue-default-app.png" style="border-style: solid; border-width: 1px; height: 779px; width: 1600px;"></p> + +<h2 id="Making_a_couple_of_changes">Making a couple of changes</h2> + +<p>Let's make our first change to the app — we’ll delete the Vue logo. Open the <code>App.vue</code> file, and delete the <code><a href="/en-US/docs/Web/HTML/Element/img"><img></a></code> element from the template section:</p> + +<pre class="brush: html"><span class="author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z8h7gz67ziz76zcz77zz80zz71zncfz69zz69ziaz82zz71zz72zhz77zz122zz90z14mcyd"><img alt="Vue logo" src="./assets/logo.png"></span></pre> + +<p>If your server is still running, you should see the logo removed from the rendered site almost instantly. Let’s also remove the <code>HelloWorld</code> component from our template.</p> + +<p>First of all delete this line:</p> + +<pre class="brush: html"><HelloWorld msg="Welcome to Your Vue.js App"/></pre> + +<p>If you save your <code>App.vue</code> file now, the rendered app will throw an error because we’ve registered the component but are not using it. We also need to remove the lines from inside the <code><script></code> element that import and register the component:</p> + +<p>Delete these lines now:</p> + +<pre class="brush: js">import HelloWorld from './components/HelloWorld.vue'</pre> + +<pre class="brush: js">components: { + HelloWorld +}</pre> + +<p>Your rendered app should no longer show an error, just a blank page, as we currently have no visible content inside <code><template></code>.</p> + +<p>Let’s add a new <code><h1></code> inside <code><div id="app"></code>. Since we’re going to be creating a todo list app below, let's set our header text to "To-Do List". Add it like so:</p> + +<pre class="brush: html"><template> + <div id="app"> + <h1>To-Do List</h1> + </div> +</template></pre> + +<p><code>App.vue</code> will now show our heading, as you'd expect.</p> + +<h2 id="Summary">Summary</h2> + +<p>Let's leave this here for now. We've learnt about some of the ideas behind Vue, created some scaffolding for our example app to live inside, inspected it, and made a few preliminary changes.</p> + +<p>With a basic introduction out of the way, we'll now go further and build up our sample app, a basic Todo list application that allows us to store a list of items, check them off when done, and filter the list by all, complete, and incomplete todos.</p> + +<p>In the next article we'll build our first custom component, and look at some important concepts such as passing props into it and saving its data state.</p> + +<p>{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction">Introduction to client-side frameworks</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features">Framework main features</a></li> + <li>React + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started">Getting started with React</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning">Beginning our React todo list</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components">Componentizing our React app</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state">React interactivity: Events and state</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_filtering_conditional_rendering">React interactivity: Editing, filtering, conditional rendering</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility">Accessibility in React</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_resources">React resources</a></li> + </ul> + </li> + <li>Ember + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_getting_started">Getting started with Ember</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_structure_componentization">Ember app structure and componentization</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_interactivity_events_state">Ember interactivity: Events, classes and state</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_conditional_footer">Ember Interactivity: Footer functionality, conditional rendering</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_routing">Routing in Ember</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources">Ember resources and troubleshooting</a></li> + </ul> + </li> + <li>Vue + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started">Getting started with Vue</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component">Creating our first Vue component</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists">Rendering a list of Vue components</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models">Adding a new todo form: Vue events, methods, and models</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_styling">Styling Vue components with CSS</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_computed_properties">Using Vue computed properties</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_conditional_rendering">Vue conditional rendering: editing existing todos</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_refs_focus_management">Focus management with Vue refs</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_resources">Vue resources</a></li> + </ul> + </li> +</ul> diff --git a/files/pt-br/learn/tools_and_testing/cross_browser_testing/index.html b/files/pt-br/learn/tools_and_testing/cross_browser_testing/index.html new file mode 100644 index 0000000000..331e47b921 --- /dev/null +++ b/files/pt-br/learn/tools_and_testing/cross_browser_testing/index.html @@ -0,0 +1,49 @@ +--- +title: Cross Browser Teste +slug: Learn/Tools_and_testing/Cross_browser_testing +tags: + - Accessibility + - Automation + - Beginner + - CSS + - CodingScripting + - HTML + - JavaScript + - Landing + - Learn + - Module + - NeedsTranslation + - Testing + - Tools + - TopicStub + - cross browser +translation_of: Learn/Tools_and_testing/Cross_browser_testing +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">This module focuses on testing web projects across different browsers. We look at identifying your target audience (e.g. what users, browsers, and devices do you most need to worry about?), how to go about doing testing, the main issues that you'll face with different types of code and how to mitigate them, what tools are most useful in helping you test and fix problems, and how to use automation to speed up testing.</p> + +<h2 id="Prerequisites">Prerequisites</h2> + +<p>You should really learn the basics of the core <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a>, and <a href="/en-US/docs/Learn/JavaScript">JavaScript</a> languages first before attempting to use the tools detailed here.</p> + +<h2 id="Guides">Guides</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Introduction">Introduction to cross browser testing</a></dt> + <dd>This article starts the module off by providing an overview of the topic of cross browser testing, answering questions such as "what is cross browser testing?", "what are the most common types of problems you'll encounter?", and "what are the main approaches for testing, identifying, and fixing problems?"</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies">Strategies for carrying out testing</a></dt> + <dd>Next, we drill down into carrying out testing, looking at identifying a target audience (e.g. what browsers, devices, and other segments should you make sure are tested), low fi testing strategies (get yourself a range of devices and some virtual machines and do adhoc tests when needed), higher tech strategies (automation, using dedicated testing apps), and testing with user groups.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS">Handling common HTML and CSS problems</a></dt> + <dd>With the scene set, we'll now look specifically at the common cross browser problems you will come across in HTML and CSS code, and what tools can be used to prevent problems from happening, or fix problems that occur. This includes linting code, handing CSS prefixes, using browser dev tools to track down problems, using polyfills to add support into browsers, tackling responsive design problems, and more.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/JavaScript">Handling common JavaScript problems</a></dt> + <dd>Now we'll look at common cross browser JavaScript problems and how to fix them. This includes information on using browser dev tools to track down and fix problems, using polyfills and libraries to work around problems, getting modern JavaScript features working in older browsers, and more.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility">Handling common accessibility problems</a></dt> + <dd>Next we turn our attention to accessibility, providing information on common problems, how to do simple testing, and how to make use of auditing/automation tools for finding accessibility issues.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Feature_detection">Implementing feature detection</a></dt> + <dd>Feature detection involves working out whether a browser supports a certain block of code, and running different code dependent on whether it does (or doesn't), so that the browser can always provide a working experience rather crashing/erroring in some browsers. This article details how to write your own simple feature detection, how to use a library to speed up implementation, and native features for feature detection such as <code>@supports</code>.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Automated_testing">Introduction to automated testing</a></dt> + <dd>Manually running tests on several browsers and devices, several times per day, can get tedious and time consuming. To handle this efficiently, you should become familiar with automation tools. In this article we look at what is available, how to use task runners, and the basics of how to use commercial browser test automation apps such as Sauce Labs and Browser Stack.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment">Setting up your own test automation environment</a></dt> + <dd>In this article, we will teach you how to install your own automation environment and run your own tests using Selenium/WebDriver and a testing library such as selenium-webdriver for Node. We will also look at how to integrate your local testing environment with commercial apps like the ones discussed in the previous article.</dd> +</dl> diff --git a/files/pt-br/learn/tools_and_testing/cross_browser_testing/introduction/index.html b/files/pt-br/learn/tools_and_testing/cross_browser_testing/introduction/index.html new file mode 100644 index 0000000000..8999820e0b --- /dev/null +++ b/files/pt-br/learn/tools_and_testing/cross_browser_testing/introduction/index.html @@ -0,0 +1,201 @@ +--- +title: Introduction to cross browser testing +slug: Learn/Tools_and_testing/Cross_browser_testing/Introduction +translation_of: Learn/Tools_and_testing/Cross_browser_testing/Introduction +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies", "Learn/Tools_and_testing/Cross_browser_testing")}}</div> + +<p class="summary">This article starts the module off by providing an overview of the topic of (cross) browser testing, answering questions such as "what is cross browser testing?", "what are the most common types of problems you'll encounter?", and "what are the main approaches for testing, identifying, and fixing problems?"</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>Familiarity with the core <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a>, and <a href="/en-US/docs/Learn/JavaScript">JavaScript</a> languages.</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>To gain an understanding of the high-level concepts involved in cross browser testing.</td> + </tr> + </tbody> +</table> + +<h2 id="O_que_é_cross_browser_testing">O que é cross browser testing?</h2> + +<p>Cross browser testing é a prática de se assegurar de que os web sites e web apps que você cria funcionarão em um número aceitável de navegadores web. Como um desenvolvedor web, é de sua responsabilidade assegurar de não apenas fazer com que os seus projetos funcionem, mas também que funcionem para todos os usuários, não importa o navegador, dispositivo ou ferramentas auxiliares adicionais que eles estarão usando. Você deve pensar sobre:</p> + +<ul> + <li>Different browsers other than the one or two that you use regularly on your devices, including slightly older browsers that some people might still be using, which don't support all the latest, shiniest CSS and JavaScript features.</li> + <li>Different devices with different capabilities, from the latest greatest tablets and smartphones, through smart TVs, right down to cheap tablets and even older feature phones that may run browsers with limited capabilities.</li> + <li>People with disabilities, who use the Web with the aid of assistive technologies like screenreaders, or don't use a mouse (some people use only the keyboard).</li> +</ul> + +<p>Remember that you are not your users — just because your site works on your Macbook Pro or high-end Galaxy Nexus, doesn't mean it will work for all your users — there's a whole lot of testing to be done!</p> + +<div class="note"> +<p><strong>Note</strong>: <a href="https://hacks.mozilla.org/2016/07/make-the-web-work-for-everyone/">Make the web work for everyone</a> provides more useful perspective on the different browsers people use, their market share, and related cross browser compatibility issues.</p> +</div> + +<p>We should explain a few bits of terminology here. To start with, when we talk about sites "working cross browser", we are really saying that they should provide an acceptable user experience across different browsers. It is potentially OK for a site to not deliver the exact same experience on all browsers, as long as the core functionality is accessible in some way. On modern browsers you might get something animated, 3D and shiny, whereas on older browsers you might just get a flat graphic representing the same information. As long as the site owner is happy with this, then you have done your job.</p> + +<p>On the other hand, it is not OK for a site to work fine for sighted users, but be completely inaccessible for visually impaired users because their screen reader application can't read any of the information stored on it.</p> + +<p>Second, when we say "across an acceptable number of web browsers", we don't mean 100% of the browsers in the world — this is just about impossible. You can make some informed calls as to what browsers and devices your users will be using (as we'll discuss in the second article in the series — see <a href="https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies#Gotta_test_%27em_all">Gotta test 'em all?</a>), but you can't guarantee everything. As a web developer, you need to agree a range of browsers and devices that the code definitely needs to work on with the site owner, but beyond that, you need to code defensively to give other browsers the best chance possible of being able to use your content. This is one of the great challenges of web development.</p> + +<div class="note"> +<p><strong>Note</strong>: We'll cover defensive coding later in the module too.</p> +</div> + +<h2 id="Why_do_cross_browser_issues_occur">Why do cross browser issues occur?</h2> + +<p>There are many different reasons why cross browser issues occur, and note that here we are talking about issues where things behave different across different browsers / devices / browsing preferences. Before you even get to cross browser issues, you should have already fixed out bugs in your code (see <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">Debugging HTML</a>, <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Debugging_CSS">Debugging CSS</a>, and <a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong">What went wrong? Troubleshooting JavaScript</a> from previous topics to refresh your memory if needed).</p> + +<p>Cross browser issues commonly occur because:</p> + +<ul> + <li>sometimes browsers have bugs, or implement features differently. This situation is a lot less bad than it used to be; back when IE4 and Netscape 4 were competing to be the dominant browser in the 1990s, browser companies deliberately implemented things differently to each other to try to gain competitive advantage, which made life hell for developers. Browsers are much better at following standards these days, but differences and bugs still creep through sometimes.</li> + <li>some browsers may have different levels of support for technology features to others. This is inevitable when you are dealing with bleeding edge features that browsers are just getting round to implementing, or if you have to support really old browsers that are no longer being developed, which may have been frozen (i.e. no more new work done on them) a long time before a new feature was even invented. As an example, if you want to use cutting edge JavaScript features in your site, they might not work in older browsers. If you need to support older browsers, you might have to not use those, or convert your code to old fashioned syntax using some kind of cross-compiler where needed.</li> + <li>some devices may have constraints that cause a web site to run slowly, or display badly. For example, if a site has been designed to look nice on a desktop PC, it will probably look tiny and be hard to read on a mobile device. If your site includes a load of big animations, it might be ok on a high spec tablet, but might be sluggish or jerky on a low end device.</li> +</ul> + +<p>and more reasons besides.</p> + +<p>In later articles, we'll explore common cross browser problems, and look at solutions to those.</p> + +<h2 id="Workflows_for_cross_browser_testing">Workflows for cross browser testing</h2> + +<p>All of this cross browser testing business may sound time consuming and scary, but it needn't be — you just need to plan carefully for it, and make sure you do enough testing in the right places to make sure you don't run into unexpected problems. If you are working on a large project, you should be testing it regularly, to make sure that new features work for your target audience, and that new additions to the code don't break old features that were previously working.</p> + +<p>If you leave all the testing to the end of a project, any bugs you uncover will be a lot more expensive and time consuming to fix than if you uncover them and fix them as you go along.</p> + +<p>The workflow for testing and bug fixes on a project can be broken down into roughly the following four phases (this is only very rough — different people may do things quite differently to this):</p> + +<p><strong>Initial planning > Development > Testing/discovery > Fixes/iteration</strong></p> + +<p>Steps 2–4 will tend to be repeated as many times as necessary to get all of the implementation done. We will look at the different parts of the testing process in much greater detail in subsequent articles, but for now let's just summarize what may occur in each step.</p> + +<h3 id="Initial_planning">Initial planning</h3> + +<p>In the initial planning phase, you will probably have several planning meetings with the site owner/client (this might be your boss, or someone from an external company you are building a web site for), in which you determine exactly what the web site should be — what content and functionality should it have, what should it look like, etc. At this point you'll also want to know how much time you have to develop the site — what is their deadline, and how much are they going to pay you for your work? We won't go into much detail about this, but cross-browser issues can have a serious effect on such planning.</p> + +<p>Once you've got an idea of the required featureset, and what technologies you will likely build these features with, you should start exploring the target audience — what browsers, devices, etc. will the target audience for this site be using? The client might already have data about this from previous research they've done, e.g. from other web sites they own, or from previous versions of the web site you are now working on. If not, you will be able to get a good idea by looking at other sources, such as usage stats for competitors, or countries the site will be serving. You can also use a bit of intuition.</p> + +<p>So for example, you might be building an e-commerce site that serves customers in North America. the site should work entirely in the last few versions of the most popular desktop and mobile (iOS, Android, Windows phone) browsers — this should include Chrome (and Opera as it is based on the same rendering engine as Chrome), Firefox, IE/Edge, and Safari. It should also provide an acceptable experience on IE 8 and 9, and be accessible with WCAG AA compliance.</p> + +<p>Now you know your target testing platforms, you should go back and review the required featureset and what technologies you are going to use. For example, if the e-commerce site owner wants a WebGL-powered 3D tour of each product built into the product pages, they will need to accept that this just won't work in IE versions before 11. You'd have to agree to provide a version of the site without this feature to users of older IE versions.</p> + +<p>You should compile a list of the potential problem areas.</p> + +<div class="note"> +<p><strong>Note</strong>: You can find browser support information for technologies by looking up the different features on MDN — the site you're on! You should also consult <a href="http://caniuse.com/">caniuse.com</a>, for some further useful details.</p> +</div> + +<p>Once you've agreed on these details, you can go ahead and start developing the site.</p> + +<h3 id="Development">Development</h3> + +<p>Now on to the development of the site. You should split the different parts of the development into modules, for example you might split the different site areas up — home page, product page, shopping cart, payment workflow, etc. You might then further subdivide these — implement common site header and footer, implement product page detail view, implement persistent shopping cart widget, etc.</p> + +<p>There are multiple general strategies to cross browser development, for example:</p> + +<ul> + <li>Get all the functionality working as closely as possible in all target browsers. This may involve writing different code paths that reproduce functionality in different ways aimed at different browsers, or using a {{glossary("Polyfill")}} to mimic any missing support using JavaScript or other technologies, or using a library that allows you to write a single bit of code and then does different things in the background depending on what the browser supports.</li> + <li>Accept that some things aren't going to work the same on all browsers, and provide different (acceptable) solutions in browsers that don't support the full functionality. Sometimes this is inevitable due to device constraints — a cinema widescreen isn't going to give the same visual experience as a 4" mobile screen, regardless of how you program your site.</li> + <li>Accept that your site just isn't going to work in some older browsers, and move on. This is OK, provided your client/userbase is OK with it.</li> +</ul> + +<p>Normally your development will involve a combination of the above three approaches. The most important thing is that you test each small part before committing it — don't leave all the testing till the end!</p> + +<h3 id="Testingdiscovery">Testing/discovery</h3> + +<p>After each implementation phase, you will need to test the new functionality. To start with, you should make sure there are no general issues with your code that are stopping your feature from working:</p> + +<ol> + <li>Test it in a couple of stable browsers on your system, like Firefox, Safari, Chrome, or IE/Edge.</li> + <li>Do some low fi accessibility testing, such as trying to use your site with only the keyboard, or using your site via a screen reader to see if it is navigable.</li> + <li>Test on a mobile platform, such as Android or iOS.</li> +</ol> + +<p>At this point, fix any problems you find with your new code.</p> + +<p>Next, you should try expanding your list of test browsers to a full list of target audience browsers and start concentrating on weeding out cross browser issues (see the next article for more information on <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies#Gotta_test_%27em_all">determining your target browsers</a>). For example:</p> + +<ul> + <li>Try to test the latest change on all the modern desktop browsers you can — including Firefox, Chrome, Opera, IE, Edge, and Safari on desktop (Mac, Windows, and Linux, ideally).</li> + <li>Test it in common phone and tablet browsers (e.g. iOS Safari on iPhone/iPad, Chrome and Firefox on iPhone/iPad/Android),</li> + <li>Also do tests in any other browsers you have included inside your target list.</li> +</ul> + +<p>The most low fi option is to just do all the testing you can by yourself (pulling in team mates to help out if you are working in a team). You should try to test it on real physical devices where possible.</p> + +<p>If you haven't got the means to test all those different browser, operating system, and device combinations on physical hardware, you can also make use of emulators (emulate a device using software on your desktop computer) and virtual machines (software that allows you to emulate multiple operating system/software combinations on your desktop computer). This is a very popular choice, especially in some circumstances — for example, Windows doesn't let you have multiple versions of Windows installed simulataneously on the same machine, so using multiple virtual machines is often the only option here.</p> + +<p>Another option is user groups — using a group of people outside your development team to test your site. This could be a group of friends or family, a group of other employees, a class at a local university, or a professional user testing setup, where people are paid to test out your site and provide results.</p> + +<p>Finally, you can get smarter with your testing using auditing or automation tools; this is a sensible choice as your projects get bigger, as doing all this testing by hand can start to take a really long time. You can set up your own testing automation system (<a href="http://www.seleniumhq.org/">Selenium</a> being the popular app of choice) that could for example load your site in a number of different browsers, and:</p> + +<ul> + <li>see if a button click causes something to happen successfully (like for example, a map displaying), displaying the results once the tests are completed</li> + <li>take a screenshot of each, allowing you to see if a layout is consistent across the different browsers.</li> +</ul> + +<p>You can also go further than this, if wished. There are commercial tools available such as <a href="https://saucelabs.com/">Sauce Labs</a> and <a href="https://www.browserstack.com/">Browser Stack</a> that do this kind of thing for you, without you having to worry about the setup, if you wish to invest some money in your testing. It is also possible to set up an environment that automatically runs tests for you, and then only lets you check in your changes to the central code repository if the tests still pass.</p> + +<h4 id="Testing_on_prerelease_browsers">Testing on prerelease browsers</h4> + +<p>It is often a good idea to test on prerelease versions of browsers; see the following links:</p> + +<ul> + <li><a href="https://www.mozilla.org/en-US/firefox/developer/">Firefox Developer Edition</a></li> + <li><a href="https://insider.windows.com/">Edge Insider Preview</a></li> + <li><a href="https://developer.apple.com/safari/technology-preview/">Safari Technology Preview</a></li> + <li><a href="https://www.google.com/chrome/browser/canary.html">Chrome Canary</a></li> + <li><a href="http://www.opera.com/computer/beta">Opera Developer</a></li> +</ul> + +<p>This is especially prevalent if you are using very new technologies in your site, and you want to test against the latest implementations, or if you are coming across a bug in the latest release version of a browser, and you want to see if the browser's developers have fixed the bug in a newer version.</p> + +<h3 id="Fixesiteration">Fixes/iteration</h3> + +<p>Once you've discovered a bug, you need to try to fix it.</p> + +<p>The first thing to do is to narrow down where the bug occurs as much as possible. Get as much information as you can from the person reporting the bug — what platform(s), device(s), browser version(s), etc. Try it on similar configurations (e.g. the same browser version on different desktop platforms, or a few different versions of the same browser on the same platform) to see how widely the bug persists.</p> + +<p>It might not be your fault — if a bug exists in a browser, then hopefully the vendor will rapidly fix it. It might have already been fixed — for example if a bug is present in Firefox release 49, but it is no longer there in Firefox Nightly (version 52), then they have fixed it. If it is not fixed, then you may want to file a bug (see {{anch("Reporting bugs")}}, below).</p> + +<p>If it is your fault, you need to fix it! Finding out the cause of the bug involves the same strategy as any web development bug (again, see <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">Debugging HTML</a>, <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Debugging_CSS">Debugging CSS</a>, and <a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong">What went wrong? Troubleshooting JavaScript</a>). Once you've discovered what is causing your bug, you need to decide how to work around it in the particular browser it is causing problems in — you can't just change the problem code outright, as this may break the code in other browsers. The general approach is usually to fork the code in some way, for example use JavaScript feature detection code to detect situations in which a problem feature doesn't work, and run some different code in those cases that does work.</p> + +<p>Once a fix has been made, you'll want to repeat your testing process to make sure your fix is working OK, and hasn't caused the site to break in other places or in other browsers.</p> + +<h2 id="Reporting_bugs">Reporting bugs</h2> + +<p>Just to reiterate on what was said above, if you discover bugs in browsers, you should report them:</p> + +<ul> + <li><a href="https://bugzilla.mozilla.org/">Firefox Bugzilla</a></li> + <li><a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/">EdgeHTML issue tracker</a></li> + <li><a href="https://bugs.webkit.org/">Safari</a></li> + <li><a href="https://bugs.chromium.org/p/chromium/issues/list">Chrome</a></li> + <li><a href="https://bugs.opera.com/wizard/desktop">Opera</a></li> +</ul> + +<h2 id="Summary">Summary</h2> + +<p>This article should have given you a high-level understanding of the most important concepts you need to know about cross browser testing. Armed with this knowledge, you are now ready to move on and start learning about Cross browser testing strategies.</p> + +<p>{{NextMenu("Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies", "Learn/Tools_and_testing/Cross_browser_testing")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Introduction">Introduction to cross browser testing</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies">Strategies for carrying out testing</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS">Handling common HTML and CSS problems</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/JavaScript">Handling common JavaScript problems</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility">Handling common accessibility problems</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Feature_detection">Implementing feature detection</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Automated_testing">Introduction to automated testing</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment">Setting up your own test automation environment</a></li> +</ul> |