Chrysthian Simão
Desenvolvimento de projetos web
Cliente
(estamos aqui)
Servidor
É uma linguagem de marcação para apresentar conteúdo separado por <tags>.
Essas tags são simples e existem desde o início da internet, encapsuladas em arquivos com a extensão .html
Esse é um dos tipos de arquivo que trafegam pelo protocolo HTTP que é utilizado para montar a nossa página web.
Essas tags são organizadas numa estrutura de árvore chamada DOM (Document Object Model).
<html>
<head>
<title>My Title</title>
</head>
<body>
<h1>My Header</h1>
<a href="wwww.google.com">My Link</a>
</body>
</html>(esse arquivo está no repositório na pasta WebBasico)
Dar uma cara melhor para as coisas começou a fazer diferença, então entrou o CSS - Cascade Styling Sheets.
São marcações que alteram a aparências das páginas de acordo com critérios chamados "selectors".
Os selectors... selecionam os elementos das páginas que soincidem com os critérios definidos e aplicam as alterações necessárias.
As principais funções além de estilização são:
(esse arquivo está no repositório na pasta WebBasico/Nebula)
Não só de aparências, mas sentiu-se a necessidade de trazer funcionalidades as páginas web.
Então em meados de 1993 a Netscape fez a primeira versão da linguagem e lançou em 1994 no seu navegador.
Javascript é uma linguagem não tipada o que permite algumas... liberdades poéticas com tipagem e lógica de código num geral.
<link rel="stylesheet" href="styles.css">
<script src="script.js"></script>(esse arquivo está no repositório na pasta WebBasico/Template)
CSS
Javascript
Tags HTML, que incorporam a árvore do DOM
let y = true;
let x = false;
let z = null;
z = 3 > 2; // true
// resultados assumindo uma chamada
// a função teste(z) aqui do lado -->
z = y && x; //false
z = undefined; //false
z = null; //false
z = ""; //false
z = "bolovo"; //true
z = 0; //false
z = NaN; //false
z = 10; //true
z = {}; //true
z = []; //true
function teste( z ){
if( z ){
alert("true");
} else {
alert("false");
}
};Nada muito novo ali em cima, mas igualdade é uma coisa mais delicada!
let a = "Laranja";
let b = "Batata";
console.log(a > b); // true
console.log(a.localeCompare(b)); // -1
console.log(b.localeCompare(a)); // 1
console.log(a.localeCompare(a)); // 0let a = new Array(); //usamos um construtor para criar um array
let a = []; //também é um construtor válido
let cars = new Array("Fusca", "Palio", "BMW");
let cars = ["Fusca", "Palio", "BMW"];
let name = cars[0]; //'Fusca'
let x = cars.length; // obtem o número de elementos (3)
let y = cars.sort(); // ordenação nativa
let fruits = ["Banana", "Laranja", "Maçã", "Manga"];
fruits.push("Limão"); // adiciona um elemento ao array
fruits[fruits.length] = "Abacate"; // Também funcionalet wtf = [];
wtf["a"] = "abacate";
wtf[0]; // undefined
wtf["a"]; // 'abacate'
function mensagem( str ){
alert( str );
}
wtf["funcao"] = mensagem;
wtf["funcao"]("bolinho"); // que diabos!?Javascript usa ponteiros (ou referências de memória, como preferir). É um conceito importante para escrever um código otimizado.
Os ponteiros do Javascript funcionam da mesma forma que em Java com contagem de referência.
Assim como no Java, no JS tudo são ponteiros, a própria declaração de uma variável acontece da seguinte forma:
let a = [];let a = 2;
let b = a;
// Só há um espaço reservado em memória com o nosso objeto
// No entanto há duas referências ("a" e "b") para o mesmo
// endereço de memória
b = null;
// Isto faz com que a referência ao objeto da variável "b"
// deixe de existir mantendo apenas uma referência em "a"
a = null;
// Agora sem as duas referências o valor alocado em memória
// pode ser sinalizado para garbage collectionAlgumas coisas começam a fazer sentido agora como por exemplo, porque consideram o operador "new" computacionalmente caro, é porque ele aloca fisicamente memória.
Isso não é só sobre JS mas linguagens num geral.
Se a linguagem usa uma VM inteligente, ela gerencia a própria memória e consegue amenizar o impacto em tempo de execução.
Null e Undefined são coisas diferentes para a linguagem, mas são logicamente iguais (então por isso é comum confundir).
Uma variável declarada vazia, sem atribuição é undefined, porque nenhuma memória foi alocada para ela ainda.
Se a variável recebe a atribução de null, significa que ela continha algo e está pronta para ser coletada no Garbage Collector porque ela não será mais usada.
Math.sqrt(16); //4
Math.PI; //3.141592653589793
Math.cos(1); //0.5403023058681398
Math.ceil(1.2); //2
Math.floor(1.2); //1
Math.random(); //Um número aleatório entre 0 e 1
//esta função retorna um valor aleatório entre um mínimo e um máximo
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}<html>
<head>
<title>My Title</title>
</head>
<body>
<h1 id="header">My header</h1>
<a href="http://www.google.com.br" id="myLink">My link</a>
</body>
</html>
<script>
console.log( document.getElementById("myLink") );
</script>//Retorna uma lista de elementos com o nome de tag HTML fornecido.
document.getElementsByTagName();
function encontrarTagP() {
const all = document.getElementsByTagName('p');
let num = all.length;
alert('Existem ' + num + ' parágrafos neste documento');
}//Retorna uma lista de elementos com o nome de classe CSS fornecido.
document.getElementsByClassName();
<p class="test">hello</p>
<script>
let test = document.getElementsByClassName("test");
console.log(test);
</script>Tags HTML podem ser manipuladas normalmente com JS, é o uso mais comum da linguagem.
Atributos, valores e eventos podem ser manipulados programaticamente
<html>
<head>
<title>My Title</title>
</head>
<body>
<h1 id="header">My header</h1>
<a href="http://www.google.com.br" id="myLink">My link</a>
</body>
</html>
<script>
console.log( document.getElementById("myLink").href );
</script><html>
<head>
<title>My Title</title>
</head>
<body>
<h1 id="header">My header</h1>
<a href="http://www.google.com.br" id="myLink">My link</a><br>
<input type="button" value="Click me!"
onclick="exibirConsole()">
</body>
</html>
<script>
function exibirConsole(){
console.log( document.getElementById("myLink").href );
}
</script><html>
<body>
<h1 id="header">Você não clicou no botão</h1>
<input type="button" value="Clique em mim!" onclick="change()">
<script>
let count = 0;
function change(){
let element = document.getElementById("header");
count++;
element.innerHTML = "Você clicou no botão " + count + " vez(es)!";
console.log(window.count);
}
</script>
</body>
</html> Era uma vez o facebook... Eles tem uma aplicação de complexidade crescente que precisava de um controle adequado na exibição, sem que as coisas fossem complexas demais para gerenciar.
A partir daí os engenheiros criaram essa biblioteca, viram que ela era muito robusta, então disponibilizaram ela em código aberto para a comunidade.
Dezoito versões depois, cá estamos.
Um framework é um conjunto de ferramentas e bibliotecas que fornecem um conjunto de recursos e funcionalidades prontas para programadores.
Isso permite construir aplicativos mais rapidamente, com menos esforço e código, e com menores chances de erros.
Algumas pessoas dizem que o React não é um framework e sim uma biblioteca, porque o react te da ferramentas, mas você é livre pra usá-las como achar melhor.
É bom porque você pode fazer o que quiser
É ruim porque você pode fazer o que quiser!
Aplicações web ricas que precisam ser atualizadas em tempo real e que permita a criação de soluções escaláveis em times de qualquer tamanho.
A principal característica do React é permitir a criação de componentes reutilizáveis, como blocos de montar.
Estes componentes podem ser tão atômicos quanto necessário, de linhas e botões, até a páginas inteiras.
O que torna o React tão rãpido é o conceito introduzido pela lib, o Virtual DOM.
A árvore do DOM como vimos até agora é lenta demais para atualizações constantes.
Como o nome diz, é uma representação da árvore do DOM em memória, que uma vez atualizada é replicada inteira para o DOM final, sendo muito mais rápida porque acaba modificando somente o elemento necessário e não reconstruindo todos os nós.
É um motor de tempo de execução JavaScript de código aberto. Ele executa o código JavaScript fora de um navegador.
Como eu sei que instalou corretamente?
node --version
npm --version
npx --versionO NPM (Node Package Manager), é o gerenciador de pacotes do node, e permite baixar e gerenciar bibliotecas javascript.
React é uma delas, mas muitas outras bibliotecas podem ser instaladas através dessa ferramenta.
Hello React.js + TS
npx create-react-app my-app --template typescript
npm startlocalhost:3000
function MyButton() {
return (
<button>I'm a button</button>
);
}export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}JSX é uma extensão da linguagem JavaScript que é usada pelo React para criar interfaces de usuário.
Ele permite que você misture código JS com sintaxe de HTML, o que torna mais fácil escrever componentes de interface de usuário em um único arquivo de código.
Diferente do Angular, que traz lógica para o HTML, o React traz o HTML pra dentro do JS.
A variante do JSX para Typescript (que vamos usar) é TSX.
Single-page application é uma aplicação que carrega uma única página web, e então atualiza o conteúdo desse documento utilizando Javascript.
Da mesma forma que demonstramos que é possível trazer interação no exemplo de adivinhar a cor, React e outras bibliotecas e frameworks elevam isso trazendo estruturas mais complexas e otimizadas
Então como navegamos pela aplicação se quisermos mais do que... uma página?
Usamos o conceito de rotas, o JS toma controle do histórico de navegador para simular o comportamento, e dar a impressão de múltiplas páginas, mas no fim do dia é uma só, atualizada constantemente
Como estamos usando o React vanilla, temos que usar uma biblioteca externa para incluir e configurar rotas, alguns frameworks como o Next.js já tem configuradas as rotas no template padrão
npm install --save react-router-domAdicionamos bibliotecas ao projeto para não ser necessário fazer muitas coisas no braço, assim como C# tem o nuGet, o Java tem o Maven, o Node tem o NPM, e instalamos as bibliotecas por comandos node
import React from 'react';
export default function Simple() {
return (<div> Simples </div>)
}import React, { ReactElement } from 'react';
interface params {
name: string;
age?: number;
}
const SimpleWithParam = (values: params): ReactElement => {
return (<div> {values.name} </div>)
}
export default SimpleWithParam;import React from 'react';
interface params {
children: React.ReactNode
}
const SimpleWithChildren = (values: params)
: React.ReactElement => {
return (<div> {values.children} </div>)
}
export default SimpleWithChildren;import Simple from './components/Simple'
import SimpleWithChildren from './components/SimpleWithChildren'
import SimpleWithParam from './components/SimpleWithParam'
export default function Home() {
return (
<div>
<Simple />
<SimpleWithChildren>
<h1>Quero café</h1>
</SimpleWithChildren>
<SimpleWithParam name="Takoyaki" />
</div>
)
}
React é uma biblioteca que interpreta as páginas JSX/TSX transfere elas para o Virtual DOM, e este, atualiza o DOM do navegador.
Isso significa que o navegador não entende a sintaxe de um componente ou página React
Então algumas coisas precisam ser ligeiramente adaptadas, no caso do CSS, normalmente utilizamos o atributo class para aplicar um estilo CSS, mas essa é uma palavra reservada, então em TSX usamos className
Existem ferramentas para ajudar na responsividade (conteúdo adequado ao tamanho de tela), uma delas é utilizar media queries do CSS, isso permite que regras CSS sejam aplicadas conforme o tamanho da tela do navegador
@media (min-width: 640px) {
/*
aqui só será aplicado se a tela
tiver 640px ou MAIS
*/
}
@media (min-width:400px) and (max-width:900px) {
/* Não menor que 400px nem maior que 900px */
}Outra ferramenta é usar elementos com
display:flex
display:grid
React tem a sua forma de reagir a coisas que ocorrem na página, incluímos em nossos componentes algumas coisas específicas da biblioteca, chamados hooks
Por padrão, hooks são nomeados com o prefixo "use", como useState, useEffect, useMemo, useRouter etc...
useState é um comportamento adicionado aos nosso componentes que guarda... um estado próprio do componente, algo que só ele precisa saber.
const [count, setCount] = useState(0)Variável que guarda o valor
função pra alterar esse valor
chamada do hook + inicialização
Essa é a forma de reagir a aplicação, mudança do ciclo de vida do nosso componente (criação, montagem e desmontagem de acordo com o virtualDOM).
É uma função que vai ser chamada e fazer... alguma coisa quando um critério de execução acontecer
useEffect(
() => {
// executa o side effect / função
},
// array opcional de critérios para execução
[
// 0 ou mais critérios
]
)useEffect(() => {
// Executa toda vez que o componente for
// renderizado (mudou valor,
// desenhou um componente filho etc...)
});
useEffect(() => {
// Executa apenas uma vez
// quando o componente aprece
}, []);
useEffect(() => {
// Executa a primeira vez que renderizar
// E toda vez que "count" mudar de valor
}, [count, count2]);No fim só parece aplicar lógica com passos extras! (meme aqui)
Mas agora coloque em perpectiva que chamadas de APIs externas podem acontecer no useEffect
(Ex. apertei um botão para envio de um formulário, eu vou REAGIR a resposta)
Lembra da história do facebook com React?
Eles precisavam controlar não só o estado de cada componente, mas o estado da aplicação como um todo, para que cada componente reaja de acordo com as mudanças da aplicação.
Ex. Usuário logado, ele tem permissões a quais telas? qual o tema de cores ele escolheu, claro ou escuro?
Além do que, não era incomum componentes precisarem mandar informações para outros componentes, e aí, comofas?
Entrou em pauta o gerenciamento de estados da aplicação, pra não virar um macarrão de componetnes pasasndo informações de forma desorganizada, isso começou com uma tecnologia chamada Redux.
MAS para a sua sorte esse tipo de abordagem evoluiu pra alguns conceitos com uma curva de aprendizado mais amena.
É basicamente uma forma de armazenamento de variáveis e funções globais, que afeta a aplicação como um todo.
Uma alteração faz uma cascata de chamadas para quem está observando, é um design pattern chamado de observer
npm install zustandPrimeiro precisamos criar essa store
import { create } from "zustand"
// definição do meu estado global
interface DarkModeStore {
dark: boolean // variável
setDark: () => void // método pra alterar minha variável
}
//crio um estado baseado na minha interface
export const useDarkMode = create<DarkModeStore>()(
// inicializo as minhas variáveis e defino os comportamentos
(set) => ({
dark: true,
setDark: () => set((store) => ({ dark: !store.dark })),
})
)
Então acessamos ela de dentro dos componetentes
import { useDarkMode } from "../../store/darkModeStore"
const Window = (): ReactElement => {
const isDark = useDarkMode((state) => {
return state.dark
})
const backgorundColor = isDark ? "#0e4a66" : "#0e4aaa"
return (
<div className="window" style={{
background: backgorundColor,
}}>
</div>)
}Crie um projeto em React (pode usar meus templates) que tenha um componente que apresente um contador e um botão.
Quando eu no botão uma vez ele incrementa o valor em um.
Utilize o hook de useState
Agora crie um novo componente que faça o mesmo MAS usando uma store do zustand.
Coloque múltiplos componentes iguais na tela pra mostrar o estado global.
Mais algumas configurações para o nosso backend para habilitar comunicação com o frontend, no projeto C#, há um arquivo de configuração chamado launchSettings.json.
Através dele vamos configurar uma porta padrão para que a nossa aplicação rode.
Dentro desse arquivo mude as portas dos endereços listados para a porta que você deseja (por exemplo 4000)
Cross-Origin Resource Sharing, a sina dos frontends, o terror dos dev ops.
// nome arbitrário
var origins = "_origins";
builder.Services.AddCors(options =>
{
options.AddPolicy(name: origins,
policy =>
{
policy.WithOrigins("http://localhost:3000")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
WebApplication app = builder.Build();
app.UseCors(origins); useEffect(() => {
fetch('http://localhost:4000/api/icecream/getAll',
{method: "GET"})
.then((res) => res.json())
.then((data) => {
console.log(data);
})
}, [])Dentro do seu componente (por exemplo)
useEffect(() => {
if (!isDark) {
const data = {
id: "a2dcc71f-7705-4db6-8cf4-4f87994203b1",
name: "Framboesa",
}
fetch("http://localhost:4000/api/flavors", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
.then((res) => res.json())
.then((data) => {
console.log(data)
})
}
}, [isDark])