├── .gitignore
├── assets
├── vue2.png
├── Vuetify
│ ├── he4rt-logo.png
│ ├── O que e Vuetify
│ │ ├── project_plugin.png
│ │ ├── project_vue_cli.png
│ │ ├── project_vuetify.png
│ │ ├── project_dashboard.png
│ │ ├── project_helloworld.png
│ │ ├── create_project_details.png
│ │ ├── create_project_features.png
│ │ ├── create_project_preset.png
│ │ └── create_project_dependencies.png
│ └── Componentes
│ │ ├── component_header_final.png
│ │ ├── project_landing_page.png
│ │ └── component_header_location.png
├── Next
│ └── Vuetelemetry
│ │ └── util.png
├── Conceitos
│ ├── Diretivas
│ │ └── vfor1.png
│ ├── LifeCycleHooks
│ │ └── lifecyclehooks.png
│ └── Transições
│ │ └── simple_transition.png
├── Vue Router
│ ├── Navegação
│ │ └── login-page.png
│ ├── Rotas Filhas
│ │ └── dashboard-home.png
│ └── Iniciando com Vue Router
│ │ └── router-structure.png
├── Iniciando com Vue
│ ├── VueCLI
│ │ ├── vuecreate.png
│ │ ├── vuelocalhost.png
│ │ └── vueproject.png
│ └── Componentização
│ │ └── componentization.png
├── Vuex
│ └── Gerenciamento de Estado
│ │ ├── vuex.png
│ │ └── vuex_structure.png
└── Testes e Storybook
│ ├── Cypress no Vue
│ ├── e2e.png
│ └── e2e-tests.png
│ └── Storybook
│ └── storybook.png
├── docs
├── .vuepress
│ ├── public
│ │ └── favicon.ico
│ └── config.js
├── tutorial
│ ├── 9 - Next
│ │ ├── 11 - Obrigado.md
│ │ ├── 9 - Vuetelemetry.md
│ │ ├── 7 - Vite.md
│ │ ├── 10 - IonicVue.md
│ │ ├── 4 - Suspense.md
│ │ ├── 6 - Typescript.md
│ │ ├── 2 - Ecossistema.md
│ │ ├── 5 - JSX.md
│ │ ├── 8 - Pinia.md
│ │ ├── 3 - Hooks.md
│ │ └── 1 - API.md
│ ├── 8 - Ecossistema Vue
│ │ ├── 7 - Obrigado.md
│ │ ├── 2 - Gridsome.md
│ │ ├── 3 - VueNative.md
│ │ ├── 5 - Quasar.md
│ │ ├── 6 - Vuepress.md
│ │ ├── 1 - Nuxt.md
│ │ └── 4 - VueElectron.md
│ ├── 6-Bibliotecas Adicionais
│ │ ├── 6-VuePropertyDecorator.md
│ │ ├── 9-AntDesignVue.md
│ │ ├── 5-VueResource.md
│ │ ├── 4-VueDarkMode.md
│ │ ├── 7-VueFontAwesome.md
│ │ ├── 2-Vuei18n.md
│ │ ├── 3-VueAWN.md
│ │ ├── 8-VuexClassModules.md
│ │ └── 1-Vuelidate.md
│ ├── 1-Iniciando com Vue
│ │ ├── 0-Antes de começar.md
│ │ ├── 5-Componentização.md
│ │ ├── 2-VueCLI.md
│ │ ├── 1-O que e Vue.md
│ │ ├── 3-Estrutura do Projeto.md
│ │ └── 4-Fluxo e Props.md
│ ├── 3-Vuetify
│ │ ├── 4-Considerações.md
│ │ ├── 3-Customização.md
│ │ ├── 1-Iniciando com Vuetify.md
│ │ └── 2-Criando Componentes.md
│ ├── 7-Testes e Storybook
│ │ ├── 3-Storybook.md
│ │ ├── 2-Cypress no Vue.md
│ │ ├── 1-Jest no Vue.md
│ │ └── 4-Vitest.md
│ ├── 2-Conceitos
│ │ ├── 14-Considerações.md
│ │ ├── 11-Pre-Processadores.md
│ │ ├── 9-Keep Alive.md
│ │ ├── 5-Instância Vue.md
│ │ ├── 4-CSS.md
│ │ ├── 7-BusEvent.md
│ │ ├── 10-Mixins.md
│ │ ├── 6-LifeCycleHooks.md
│ │ ├── 3-Computed e Watch.md
│ │ ├── 8-Transições.md
│ │ ├── 2-Diretivas.md
│ │ ├── 1-Data, Methods e Modificadores.md
│ │ └── 13-SCSS-Avançado.md
│ ├── 5-Vuex
│ │ ├── 6-Getters.md
│ │ ├── 4-Actions.md
│ │ ├── 2-Iniciando com Vuex.md
│ │ ├── 7-Estrutura.md
│ │ ├── 8-Modules.md
│ │ ├── 5-Mutations.md
│ │ ├── 1-Gerenciamento de Estado.md
│ │ └── 3-State.md
│ └── 4-Vue Router
│ │ ├── 5-Transições no VueRouter.md
│ │ ├── 1-Iniciando com Vue Router.md
│ │ ├── 4-Guardas de Rota.md
│ │ ├── 3-Rotas Filhas.md
│ │ └── 2-Navegação.md
└── README.md
├── .editorconfig
├── generi.config.ts
├── package.json
├── REFERENCES.md
├── LICENSE
├── .github
└── workflows
│ └── action.yml
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | *.vue
3 | dist
4 | node_modules
--------------------------------------------------------------------------------
/assets/vue2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/vue2.png
--------------------------------------------------------------------------------
/assets/Vuetify/he4rt-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/he4rt-logo.png
--------------------------------------------------------------------------------
/assets/Next/Vuetelemetry/util.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Next/Vuetelemetry/util.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/docs/.vuepress/public/favicon.ico
--------------------------------------------------------------------------------
/assets/Conceitos/Diretivas/vfor1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Conceitos/Diretivas/vfor1.png
--------------------------------------------------------------------------------
/assets/Vue Router/Navegação/login-page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vue Router/Navegação/login-page.png
--------------------------------------------------------------------------------
/assets/Iniciando com Vue/VueCLI/vuecreate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Iniciando com Vue/VueCLI/vuecreate.png
--------------------------------------------------------------------------------
/assets/Vuex/Gerenciamento de Estado/vuex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuex/Gerenciamento de Estado/vuex.png
--------------------------------------------------------------------------------
/assets/Iniciando com Vue/VueCLI/vuelocalhost.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Iniciando com Vue/VueCLI/vuelocalhost.png
--------------------------------------------------------------------------------
/assets/Iniciando com Vue/VueCLI/vueproject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Iniciando com Vue/VueCLI/vueproject.png
--------------------------------------------------------------------------------
/assets/Testes e Storybook/Cypress no Vue/e2e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Testes e Storybook/Cypress no Vue/e2e.png
--------------------------------------------------------------------------------
/assets/Conceitos/LifeCycleHooks/lifecyclehooks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Conceitos/LifeCycleHooks/lifecyclehooks.png
--------------------------------------------------------------------------------
/assets/Conceitos/Transições/simple_transition.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Conceitos/Transições/simple_transition.png
--------------------------------------------------------------------------------
/assets/Testes e Storybook/Storybook/storybook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Testes e Storybook/Storybook/storybook.png
--------------------------------------------------------------------------------
/assets/Vue Router/Rotas Filhas/dashboard-home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vue Router/Rotas Filhas/dashboard-home.png
--------------------------------------------------------------------------------
/assets/Vuetify/O que e Vuetify/project_plugin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/O que e Vuetify/project_plugin.png
--------------------------------------------------------------------------------
/assets/Vuetify/O que e Vuetify/project_vue_cli.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/O que e Vuetify/project_vue_cli.png
--------------------------------------------------------------------------------
/assets/Vuetify/O que e Vuetify/project_vuetify.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/O que e Vuetify/project_vuetify.png
--------------------------------------------------------------------------------
/assets/Vuetify/Componentes/component_header_final.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/Componentes/component_header_final.png
--------------------------------------------------------------------------------
/assets/Vuetify/Componentes/project_landing_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/Componentes/project_landing_page.png
--------------------------------------------------------------------------------
/assets/Vuetify/O que e Vuetify/project_dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/O que e Vuetify/project_dashboard.png
--------------------------------------------------------------------------------
/assets/Vuetify/O que e Vuetify/project_helloworld.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/O que e Vuetify/project_helloworld.png
--------------------------------------------------------------------------------
/assets/Testes e Storybook/Cypress no Vue/e2e-tests.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Testes e Storybook/Cypress no Vue/e2e-tests.png
--------------------------------------------------------------------------------
/assets/Vuex/Gerenciamento de Estado/vuex_structure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuex/Gerenciamento de Estado/vuex_structure.png
--------------------------------------------------------------------------------
/assets/Vuetify/Componentes/component_header_location.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/Componentes/component_header_location.png
--------------------------------------------------------------------------------
/assets/Vuetify/O que e Vuetify/create_project_details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/O que e Vuetify/create_project_details.png
--------------------------------------------------------------------------------
/assets/Vuetify/O que e Vuetify/create_project_features.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/O que e Vuetify/create_project_features.png
--------------------------------------------------------------------------------
/assets/Vuetify/O que e Vuetify/create_project_preset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/O que e Vuetify/create_project_preset.png
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*.md]
4 | indent_style = space
5 | indent_size = 2
6 | charset = utf-8
7 | trim_trailing_whitespace = false
8 | insert_final_newline = false
--------------------------------------------------------------------------------
/assets/Iniciando com Vue/Componentização/componentization.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Iniciando com Vue/Componentização/componentization.png
--------------------------------------------------------------------------------
/assets/Vue Router/Iniciando com Vue Router/router-structure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vue Router/Iniciando com Vue Router/router-structure.png
--------------------------------------------------------------------------------
/assets/Vuetify/O que e Vuetify/create_project_dependencies.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/vue4noobs/HEAD/assets/Vuetify/O que e Vuetify/create_project_dependencies.png
--------------------------------------------------------------------------------
/generi.config.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | repository: "https://github.com/Novout/vue4noobs",
3 | silent: false,
4 | commits: "conventional-commits",
5 | tag: true,
6 | version: true,
7 | push: true,
8 | release: false,
9 | publish: false,
10 | exclude: [" typo"],
11 | prerelease: "beta",
12 | packagePath: "package.json",
13 | lernaPath: "lerna.json"
14 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "dev": "vuepress dev docs",
4 | "build": "vuepress build docs",
5 | "patch": "generi log patch",
6 | "minor": "generi log minor",
7 | "major": "generi log major"
8 | },
9 | "devDependencies": {
10 | "vuepress": "^1.5.0",
11 | "generi": "2.0.4"
12 | },
13 | "dependencies": {
14 | "vuepress-theme-yuu": "^2.3.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/docs/tutorial/9 - Next/11 - Obrigado.md:
--------------------------------------------------------------------------------
1 | # Obrigado
2 |
3 | Muito obrigado por concluir o curso! Com todo o conteúdo passado você tem muitas alternativas para aprimorar seu conhecimento utilizado **Vue 3.x**!
4 |
5 | Em caso de dúvidas ou sugestões, contate diretamente pelo discorda da [He4rt](discord.io/He4rt) ou pelo criadores:
6 |
7 | Giovane Cardoso - [Twitter](https://twitter.com/NovoutT) - novout@hotmail.com
8 |
9 | [Projeto final](https://github.com/Novout/vue4noobs-projeto)
10 |
11 | [Repositório atual](https://github.com/Novout/vue4noobs)
12 |
--------------------------------------------------------------------------------
/docs/tutorial/9 - Next/9 - Vuetelemetry.md:
--------------------------------------------------------------------------------
1 | # Vuetelemetry
2 |
3 | Desenvolvido pelo criador do `Nuxt.js`, o [Vuetelemetry](https://vuetelemetry.com/) foi desenvolvido para aprofundar os plugins de detecção de sites que usam `Vue`, mostrando detalhadamento o que foi utilizado.
4 |
5 | * Exemplo do próprio site do Vuetelemetry
6 |
7 |
8 |
9 |
10 |
11 | [Próxima Seção](./10%20-%20IonicVue.md)
12 |
--------------------------------------------------------------------------------
/docs/tutorial/8 - Ecossistema Vue/7 - Obrigado.md:
--------------------------------------------------------------------------------
1 | # Obrigado
2 |
3 | Muito obrigado por concluir o curso! Com todo o conteúdo passado você tem muitas alternativas para aprimorar seu conhecimento utilizado **Vue 2.x**!
4 |
5 | Em caso de dúvidas ou sugestões, contate diretamente pelo discorda da [He4rt](discord.io/He4rt) ou pelo criadores:
6 |
7 | Giovane Cardoso - [Twitter](https://twitter.com/NovoutT) - novout@hotmail.com.
8 |
9 | [Projeto final](https://github.com/Novout/vue4noobs-projeto)
10 |
11 | Se pretende continuar a dar uma olhada no Vue 3.x, clique [aqui](../9%20-%20Next/1%20-%20API.md)
12 |
--------------------------------------------------------------------------------
/docs/tutorial/8 - Ecossistema Vue/2 - Gridsome.md:
--------------------------------------------------------------------------------
1 | # Gridsome
2 |
3 | O [Gridsome](https://gridsome.org/docs/) é uma framework do **Vue** para construção de sites de forma rápida, sendo parecido em muitas partes com o **Gatsby** do **React**.
4 |
5 | ## Utilizando o Grisome
6 |
7 | `yarn global add @gridsome/cli`
8 |
9 | `gridsome create my-gridsome-site`
10 |
11 | ## Data
12 |
13 | O **Gridsome** utiliza o [GraphQL](https://gridsome.org/docs/data-layer/) para a importação de dados no seu projeto.
14 |
15 | Na próxima seção, iremos de mostrar o **VueNative**, uma forma de utilizar o **Vue** no **Mobile**, nos vemos lá!
16 |
17 | [Próxima Seção](./3%20-%20VueNative.md)
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | base: "/vue4noobs/",
3 | title: "Vue4noobs pela He4rt Developers",
4 | theme: "yuu",
5 | description: "Vue.js",
6 | head: [
7 | ["link", { rel: "icon", href: "/favicon.ico" }],
8 | ["meta", { name: 'google-site-verification', content: 'bmr3QFy052qbYVYRSuLrZrIpJPgIoLv2kIOXfdkwtkk' }],
9 | ],
10 | themeConfig: {
11 | yuu: {
12 | defaultDarkTheme: true,
13 | defaultColorTheme: "purple",
14 | },
15 | nav: [
16 | { text: "Home", link: "/" },
17 | { text: "Tutorial", link: "/tutorial/1-Iniciando%20com%20Vue/0-Antes%20de%20começar.html" },
18 | { text: "He4rt", link: "https://twitter.com/He4rtDevs" }
19 | ],
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/docs/tutorial/8 - Ecossistema Vue/3 - VueNative.md:
--------------------------------------------------------------------------------
1 | # VueNative
2 |
3 | O [VueNative](https://vue-native.io/) é uma estrutura para criar aplicativos móveis nativos entre plataformas usando JavaScript. Ele utiliza o próprio `react-native` por baixo dos panos para conseguirmos utilizar os componentes **Vue**.
4 |
5 | ## Instalação
6 |
7 | Recomendamos que leia a [documentação](https://vue-native.io/docs/installation.html) de instalação do **VueNative**.
8 |
9 | * O **VueNative** ainda está em desenvolvimento, falta amadurecimento da plataforma.
10 |
11 | * Também existe a opção do [VueNativeScript](https://nativescript-vue.org/) para o **mobile**.
12 |
13 | Na próxima seção iremos te mostrar como utilizar o **Vue** em conjunto com o **Electron**, nos vemos lá!
14 |
15 | [Próxima Seção](./4%20-%20VueElectron.md)
16 |
17 |
--------------------------------------------------------------------------------
/docs/tutorial/6-Bibliotecas Adicionais/6-VuePropertyDecorator.md:
--------------------------------------------------------------------------------
1 | # Vue Property Decorator
2 |
3 | No **Vue-CLI** é posível escolher a opção de usar o **Vue** com **Typescript**, e o [Property Decorator](https://github.com/kaorun343/vue-property-decorator) melhora esta experiência.
4 |
5 | Exemplo:
6 |
7 | ```ts
8 | import { Vue, Component, Emit } from 'vue-property-decorator';
9 |
10 | @Component
11 | export default class He4rtComponent extends Vue {
12 | he4rt = 'He4rt';
13 |
14 | @Emit()
15 | Dev() {
16 | this.he4rt += ' Developers';
17 | }
18 | };
19 | ```
20 |
21 | Saiba mais sobre o **Vue** com **Typescript** clicando [aqui](https://br.vuejs.org/v2/guide/typescript.html).
22 |
23 | Na próxima seção, iremos mostrar como utilizar o **awesome icons** no **Vue**, nos vemos lá!
24 |
25 | [Próxima Seção](./7-VueFontAwesome.md)
--------------------------------------------------------------------------------
/docs/tutorial/8 - Ecossistema Vue/5 - Quasar.md:
--------------------------------------------------------------------------------
1 | # Quasar
2 |
3 | O [Quasar](https://quasar.dev/) é um framework baseado em Vue.js que permite desenvolver rapidamente sites/aplicativos responsivos em vários formatos, ou seja, tanto aplicações Web quanto Mobile usando apenas uma ferramenta, seguindo os conceitos de [PWA](https://en.m.wikipedia.org/wiki/Progressive_web_application).
4 |
5 | ## Iniciando com Quasar
6 |
7 | Instalando o Quasar:
8 |
9 | ```bash
10 | yarn global add @quasar/cli
11 | ou
12 | npm install -g @quasar/cli
13 | ```
14 |
15 | Iniciando um Projeto:
16 |
17 | ```bash
18 | quasar create
19 | ```
20 |
21 | Comandos disponíveis no package.json:
22 |
23 | ```bash
24 | dev: quasar dev
25 | build: quasar build
26 | build:pwa: quasar build -m pwa
27 | ```
28 |
29 | [Próxima Seção](./6%20-%20Vuepress.md)
30 |
--------------------------------------------------------------------------------
/docs/tutorial/9 - Next/7 - Vite.md:
--------------------------------------------------------------------------------
1 | # Vite
2 |
3 | O [Vite](https://github.com/vitejs/vite) veio com a proposta de reduzir o tempo necessário para hot-reload, podendo utilizar tanto com Vue, como com Preact.js e React.js.
4 |
5 | ## Utilização
6 |
7 | ```sh
8 | yarn create vite-app
9 | cd
10 | yarn
11 | yarn dev
12 | ```
13 |
14 | React:
15 |
16 | `yarn create vite-app --template react`
17 |
18 | Preact:
19 |
20 | `yarn create vite-app --template preact`
21 |
22 | * Até o momento(17/12/2020), o Vite com JSX apresenta problemas, além de não ser totalmente compatível com algumas bibliotecas (Electron/Nuxt).
23 |
24 | ## Vitepress
25 |
26 | O [Vitepress](https://github.com/vuejs/vitepress) é a junção do já falado aqui no curso VuePress com o Vite, no momento estando em WIP.
27 |
28 | [Próxima Seção](./8%20-%20Pinia.md)
29 |
--------------------------------------------------------------------------------
/docs/tutorial/6-Bibliotecas Adicionais/9-AntDesignVue.md:
--------------------------------------------------------------------------------
1 | # Ant Design Vue
2 |
3 | [Ant](https://www.antdv.com/docs/vue/introduce/) é uma framework que possui componentes de alta qualidade para os seus projetos, sendo essa sua versão para o Vue, funcionando de uma forma diferente do [Vuetify](https://vuetifyjs.com/).
4 |
5 | Para instalar em um projeto já existente:
6 |
7 | `vue add ant-design`
8 |
9 | Para um novo projeto:
10 |
11 | `vue create antd-demo`
12 |
13 | Apenas instalar a dependência:
14 |
15 | `yarn add ant-design-vue`
16 |
17 | O Ant exige que se instale os componentes, vamos usar o exemplo utilizando o [Botão](https://www.antdv.com/components/button/):
18 |
19 | ```ts
20 | import { Button } from 'ant-design-vue';
21 | Vue.use(Button);
22 | ```
23 |
24 | Na próxima seção, iremos introduzir sobre como utilizar o **Jest** no **Vue**, te vemos lá!
25 |
26 | [Próxima Seção](../7-Testes%20e%20Storybook/1-Jest%20no%20Vue.md)
27 |
--------------------------------------------------------------------------------
/REFERENCES.md:
--------------------------------------------------------------------------------
1 | # Referencias para a construção das seções
2 |
3 | **O projeto utilizou estes links como auxilio para o desenvolvimento do curso, e não sua cópia.**
4 |
5 | - [LifeCycle](https://alligator.io/vuejs/component-lifecycle/)
6 | - [Load Error](https://alligator.io/vuejs/vue-async-components-load-error/)
7 | - [Class and Styles](https://vuejs.org/v2/guide/class-and-style.html)
8 | - [Async Components](https://vueschool.io/articles/vuejs-tutorials/async-vuejs-components)
9 | - [Mixins in Vue](https://levelup.gitconnected.com/how-to-use-mixins-in-vuejs-a40cc3fb4428)
10 | - [BusEvent](https://medium.com/@andrejsabrickis/https-medium-com-andrejsabrickis-create-simple-eventbus-to-communicate-between-vue-js-components-cdc11cd59860)
11 | - [Sass Guidelines](https://sass-guidelin.es/pt/) by *community*
12 | - [SCSS como você nunca viu](https://dev.to/deverebor/scss-como-voce-nunca-viu-1d99) by *@deverebor*
13 | - [Sass Basics](https://sass-lang.com/guide) by *Sass*
14 |
--------------------------------------------------------------------------------
/docs/tutorial/1-Iniciando com Vue/0-Antes de começar.md:
--------------------------------------------------------------------------------
1 | ## Antes de começar
2 |
3 | Bem-Vindo ao curso!Nosso objetivo é te oferecer todo o conteúdo introdutório para Vue em todos os aspectos possíveis.
4 |
5 | Para o curso, é necessario um bom conhecimento de HTML/CSS e especialmente JavaScript, devido ao fato do curso ser focado apenas na framework, e não na linguagem.
6 |
7 | Temas que serão abordados:
8 |
9 | - Vue
10 | - Vuetify
11 | - Vue Router
12 | - Vuex
13 | - Bibliotecas
14 | - Testes
15 | - Ecossistema
16 |
17 | Não se assuste, **depois de Vuex** não iremos aprofundar muito sobre as tecnologias, o intuito é você saber que aquilo existe no ecossistema Vue, dando uma noção geral para você conseguir se aprofundar no Vue :)
18 |
19 | ## Vue 3
20 |
21 | O curso foi feito para a versão 2.x, mas não se preocupe! o Vue 3 apenas acrescenta novos conteúdos, toda a base do vue continua sendo a mesma!
22 |
23 | [Ir para Próxima Seção](./1-O%20que%20e%20Vue.md)
24 |
--------------------------------------------------------------------------------
/docs/tutorial/3-Vuetify/4-Considerações.md:
--------------------------------------------------------------------------------
1 | # Considerações
2 |
3 | ## Projeto
4 |
5 | Todas as próximas seções de nosso curso será implementando conteúdo em nosso projeto:
6 |
7 | * VueRouter - Implementação das rotas e construção do formulário de login
8 |
9 | * Vuex - Gerenciamento de Estado nos permitindo a salvar dados do usuário para a aplicação
10 |
11 | * Bibliotecas Adicionais - Deixar a aplicação mais robusta e refinamentos gerais
12 |
13 | * Testes e Documentação - Relacionado ao projeto
14 |
15 | A Partir do **Nuxt** iremos mostrar outras tecnologias baseadas no **Vue**.
16 |
17 | ## Recomendações
18 |
19 | Explore os Componentes que o [Vuetify](https://vuetifyjs.com/pt-BR/components/cards/) dispoem, irão complementar e muito sua aplicação!
20 |
21 | ---
22 |
23 | Na próxima seção iremos iniciar com o **VueRouter** e já utilizando em nosso projetinho, nos vemos lá!
24 |
25 | [Próxima Seção](../4-Vue%20Router/1-Iniciando%20com%20Vue%20Router.md)
26 |
--------------------------------------------------------------------------------
/docs/tutorial/6-Bibliotecas Adicionais/5-VueResource.md:
--------------------------------------------------------------------------------
1 | # Vue Resource
2 |
3 | O **VueResource** é um http client para o **Vue**. Em uma das seções já mostramos em como configurar o **http** para utilizar junto com o **axios**, mas podemos usar o próprio **VueResource**
4 |
5 | Instalação: `yarn add vue-resource`
6 |
7 | ## Configuração
8 |
9 | ```ts
10 | new Vue({
11 | http: {
12 | root: '/root',
13 | headers: {
14 | Authorization: 'Bearer'.
15 | }.
16 | }.
17 | });
18 | ```
19 |
20 | ## Exemplo
21 |
22 | ```ts
23 | this.$http.get('/url')
24 | .then(res => {
25 |
26 | console.log(res.body());
27 | }, res => {
28 | console.error(err);
29 | }
30 | ```
31 |
32 | Para mais detalhes sobre o **VueLoader** clique [aqui](https://github.com/pagekit/vue-resource)
33 |
34 | Na próxima seção, iremos mostrar como utilizar o **TypeScript** no **Vue** com o auxílio do **PropertyDecorator**, nos vemos lá!
35 |
36 | [Próxima Seção](./6-VuePropertyDecorator.md)
--------------------------------------------------------------------------------
/docs/tutorial/6-Bibliotecas Adicionais/4-VueDarkMode.md:
--------------------------------------------------------------------------------
1 | # Vue Dark Mode
2 |
3 | O VueDarkMode é um conjunto de componentes projetados para facilitar a projeção de transiçõe sentre white mode e dark mode.
4 |
5 | ## Como instalar
6 |
7 | `yarn add @growthbunker/vuedarkmode`
8 |
9 | `./src/main.js`
10 |
11 | ```ts
12 | import Vue from "vue";
13 | import VueDarkMode from "@growthbunker/vuedarkmode";
14 |
15 | Vue.use(VueDarkMode);
16 | ```
17 |
18 | O **VueDarkMode** possui:
19 |
20 | - Alerts
21 | - Avatars
22 | - Badges
23 | - Buttons
24 | - Dividers
25 | - Headings
26 | - Icons
27 | - Progress Bar
28 | - Spinners
29 | - Toasts
30 | - Checkboxes
31 | - Images
32 | - Inputs
33 | - Numerics
34 | - Radios
35 | - Selects
36 | - Tabs
37 | - Textareas
38 | - Toggles
39 |
40 | Usando os **componentes*, basta passar as **propriedades** que estão na **documentação** de cada **componente**.
41 |
42 | Na próxima seção, iremos mostrar como utilizar o **VueResource**, te vemos lá!
43 |
44 | [Próxima Seção](./5-VueResource.md)
--------------------------------------------------------------------------------
/docs/tutorial/7-Testes e Storybook/3-Storybook.md:
--------------------------------------------------------------------------------
1 | # Storybook
2 |
3 | O [Storybook](https://storybook.js.org/) é uma ferramenta para o desenvolvimento de componentes de interface do usuário isolados para React, Vue e Angular. Torna a criação de UIs impressionantes organizada e eficiente.
4 |
5 | ## Utilizando no Vue
6 |
7 | Vamos utilizar o instalador global:
8 |
9 | `npx -p @storybook/cli sb init --type vue`
10 |
11 | Agora podemos criar nossas histórias em `./src/stories/**`
12 |
13 | Para rodar o **storybook**, usamos o comando `yarn storybook`
14 |
15 |
16 |
17 |
18 |
19 | * Não será explicado a sua utilização no projeto pois iria distânciar da ideia do 4noobs, apenas mostramos como utilizar no **Vue**, realmente recomendamos que dê uma lida sobre, pois pode ser muito **útil** para documentação de projetos.
20 |
21 | Na próxima seção, iremos começar a mostrar um pouco mais do **Ecossistema** do **Vue**, nos vemos lá!
22 |
23 | [Próxima Seção](../8%20-%20Ecossistema%20Vue/1%20-%20Nuxt.md)
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Giovane Cardoso
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/docs/tutorial/9 - Next/10 - IonicVue.md:
--------------------------------------------------------------------------------
1 | # Ionic Vue 3
2 |
3 | O [Ionic](https://ionicframework.com/docs/vue/overview) lançou uma versão compatível com o Vue 3, trazendo uma nova forma de criar aplicativos.
4 |
5 | ## Iniciando com Ionic Vue 3.x
6 |
7 | Primeiramente, precisamos instalar as dependência do Ionic:
8 |
9 | `yarn global add -g @ionic/cli@latest native-run cordova-res`
10 |
11 | ou
12 |
13 | `npm install -g @ionic/cli@latest native-run cordova-res`
14 |
15 | Para criar o nosso primeiro aplicatio, usamos:
16 |
17 | `ionic start heart-project tabs --type vue --capacitor`
18 |
19 | Devido ao [Capacitor](https://capacitorjs.com/), precisamos instalar os elementos para PWA:
20 |
21 | `yarn add install @ionic/pwa-elements`
22 |
23 | ou
24 |
25 | `npm install @ionic/pwa-elements`
26 |
27 | em nosso `main.ts`, adicionamos:
28 |
29 | ```ts
30 | import { defineCustomElements } from '@ionic/pwa-elements/loader';
31 |
32 | defineCustomElements(window);
33 | ```
34 |
35 | Agora só precisamos rodar:
36 |
37 | `ionic serve`
38 |
39 | * Plugins externos do Ionic funcionam da mesma forma com o Vue 3.x
40 |
41 | [Próxima Seção](./11%20-%20Obrigado.md)
42 |
--------------------------------------------------------------------------------
/.github/workflows/action.yml:
--------------------------------------------------------------------------------
1 |
2 | name: Deploy to GH-Pages
3 |
4 | on:
5 | push:
6 | branches: [ master, main ]
7 |
8 | permissions:
9 | contents: write
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 |
15 | strategy:
16 | matrix:
17 | node-version: [24.x]
18 |
19 | steps:
20 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
21 | - name: Install pnpm
22 | uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
23 | with:
24 | version: 10
25 | - name: Install Node.js
26 | uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
27 | with:
28 | node-version: ${{ matrix.node-version }}
29 | cache: 'pnpm'
30 |
31 | - name: Install Dependencies
32 | run: pnpm install
33 |
34 | - name: Run build
35 | run: pnpm run build
36 |
37 | - name: Deploy
38 | uses: JamesIves/github-pages-deploy-action@9d877eea73427180ae43cf98e8914934fe157a1a # v4.7.6
39 | with:
40 | folder: docs/.vuepress/dist
41 | clean: true
--------------------------------------------------------------------------------
/docs/tutorial/8 - Ecossistema Vue/6 - Vuepress.md:
--------------------------------------------------------------------------------
1 |
2 | # Vuepress
3 |
4 | A página que você está vendo o tutorial foi feita utilizando [Vuepress](https://vuepress.vuejs.org/), que é um gerador de página estática que utiliza [Markdown](https://pt.wikipedia.org/wiki/Markdown#:~:text=Markdown%20%C3%A9%20uma%20linguagem%20simples,seu%20texto%20em%20HTML%20v%C3%A1lido.)
5 |
6 | Para criarmos o nosso projeto, podemos utilizar o seguinte comando:
7 |
8 | `yarn create vuepress-site `
9 |
10 | Dessa forma, o nosso projeto já irá vir com o seguinte boilerplate:
11 |
12 | ```text
13 | .
14 | ├── docs
15 | | └── node_modules
16 | | └── src
17 | | | └── .vuepress
18 | | | └── config
19 | | | └── guide
20 | | | └── index.md
21 | | └── .gitignore
22 | | └── package.json
23 | | └── yarn.lock
24 | ```
25 |
26 | * Em .vuepress é aonde fica todas as configurações base do Vuepress.
27 |
28 | * Em config é aonde fica o markdown de configuração inicial da sidebar.
29 |
30 | * Em guide fica alguns auxilios para a utilização do vuepress
31 |
32 | * index.md é o markdown da página inicial que será renderizado
33 |
34 | Na próxima seção, temos agradecimentos especiais!
35 |
36 | [Próxima Seção](./7%20-%20Obrigado.md)
37 |
--------------------------------------------------------------------------------
/docs/tutorial/1-Iniciando com Vue/5-Componentização.md:
--------------------------------------------------------------------------------
1 | # Componentização
2 |
3 | Resumindo: `Se você está copiando código, falta componentização.`
4 |
5 | Agora falando um pouco mais sério:
6 |
7 | Um componente é algo que sozinho tem um sentido, ele pode ser único, ou um conjunto de vários outros components.Por exemplo, o cabeçalho de um site ele é unico, por mais que pode variar quando o usuario ta logado/deslogado, ele continua sendo um cabeçalho, então continua possuindo um único sentido.
8 |
9 | A vantagem da componentização é a reutilização de código e padronização, pois se for necessário alguma alteração no cabeçalho, por exemplo, não teremos que procurar todos os cabeçalhos na aplicação inteira.
10 |
11 | É comum que um aplicativo seja organizado em uma árvore de componentes aninhados de forma parecido com uma [Árvore](https://pt.wikibooks.org/wiki/Algoritmos_e_Estruturas_de_Dados/%C3%81rvore):
12 |
13 |
14 |
15 |
16 |
17 | Na próxima seção iremos iniciar o estudo dos conceitos do vue, mostrando as suas vantagens em relação ao VanillaJS.
18 |
19 | [Próxima Seção](../2-Conceitos/1-Data,%20Methods%20e%20Modificadores.md)
--------------------------------------------------------------------------------
/docs/tutorial/6-Bibliotecas Adicionais/7-VueFontAwesome.md:
--------------------------------------------------------------------------------
1 | # Vue Awesome Icons
2 |
3 | O [Vue FontAwesome](https://github.com/FortAwesome/vue-fontawesome) é o port do conhecido [FontAwesome](https://fontawesome.com/icons?d=gallery), assim conseguimos utilizar as fontes no **Vue**:
4 |
5 | ```ts
6 | yarn add @fortawesome/fontawesome-svg-core
7 | yarn add @fortawesome/free-solid-svg-icons
8 | yarn add @fortawesome/vue-fontawesome
9 | ```
10 |
11 | O exemplo recomendado:
12 |
13 | ```ts
14 | import Vue from 'vue';
15 | import { library } from '@fortawesome/fontawesome-svg-core';
16 | import { faUserSecret } from '@fortawesome/free-solid-svg-icons';
17 | import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
18 |
19 | library.add(faUserSecret);
20 |
21 | Vue.component('font-awesome-icon', FontAwesomeIcon);
22 | ```
23 |
24 | * Registrando o componente **font-awesome-icon** podemos usá-lo em nosso template:
25 |
26 | ```html
27 |
28 | ```
29 |
30 | * Para usar os ícones sem ser em usa versão default(solid), verifique a documentação.
31 |
32 | * Registre os ícones usando o `library.add(faIcone)`
33 |
34 | Na próxima seção, iremos introduzir sobre como utilizar o **Jest** no **Vue**, te vemos lá!
35 |
36 | [Próxima Seção](./8-VuexClassModules.md)
37 |
--------------------------------------------------------------------------------
/docs/tutorial/6-Bibliotecas Adicionais/2-Vuei18n.md:
--------------------------------------------------------------------------------
1 | # Vue i18n
2 |
3 | O [Vuei18n](https://kazupon.github.io/vue-i18n/) é um plugin para internacionalização que o **Vue** nos disponibiliza.
4 |
5 | ## Estrutura
6 |
7 | Todas as mensagens irão ficar em arquivos como **objetos literais**
8 |
9 | ```ts
10 | const messages = {
11 | en: {
12 | message: {
13 | hello: 'Hello'
14 | }
15 | },
16 | pt_BR: {
17 | message: {
18 | hello: 'Olá!'
19 | }
20 | }
21 | }
22 | ```
23 |
24 | E exibir no template como:
25 |
26 | ```ts
27 |
{{ $t('message.hello') }}
28 | ```
29 |
30 | Dessa forma, tudo oque for estático em nossa aplicação irá ser exibido a partir de um objeto, então:
31 |
32 | * É recomendável começar o projeto JÁ utilizando o i18n, pois para reestruturar tudo pode ser uma dor de cabeça
33 |
34 | * Mensagens em certas linguagens podem ficar muito grande ou muito pequeno do que o originalmente esperado.
35 |
36 | * Apenas utilize i18n se o seu projeto seja **REALMENTE** internacional, pois pode perder muito tempo no projeto sem necessidade.
37 |
38 | * NÃO iremos mostrar a aplicação do i18n no nosso projeto atual pois iria precisar refazer algumas coisas, o que quebraria a ideia do curso, mas fique á vontade para utilizá-lo!
39 |
40 | Na próxima seção iremos aplicar notificações com AWN, nos vemos lá!
41 |
42 | [Próxima Seção](./3-VueAWN.md)
--------------------------------------------------------------------------------
/docs/tutorial/3-Vuetify/3-Customização.md:
--------------------------------------------------------------------------------
1 | # Customização
2 |
3 | Vamos agora customizar o nosso **tema**, para conseguirmos seguir uma padronização.
4 |
5 | Quando instalamos o **Vuetify**, foi criado uma pasta **plugins** contendo o **vuetify.js**:
6 |
7 | ```ts
8 | import Vue from 'vue';
9 | import Vuetify from 'vuetify/lib';
10 |
11 | Vue.use(Vuetify);
12 |
13 | export default new Vuetify({
14 | });
15 | ```
16 |
17 | Dentro do **Vuetify** podemos passar configurações por padrão.
18 |
19 | Por exemplo, vamos passar o tema padrão para a aplicação:
20 |
21 | ```ts
22 | import Vue from 'vue';
23 | import Vuetify from 'vuetify/lib';
24 |
25 | Vue.use(Vuetify);
26 |
27 | export default new Vuetify({
28 | theme: {
29 | dark: true,
30 | },
31 | });
32 | ```
33 |
34 | ## Cores
35 |
36 | Podemos também customizar diretamente as **cores**:
37 |
38 | ```ts
39 | import Vue from 'vue';
40 | import Vuetify from 'vuetify/lib';
41 |
42 | Vue.use(Vuetify);
43 |
44 | export default new Vuetify({
45 | themes: {
46 | light: {
47 | primary: '#a142f5',
48 | secondary: '#f5f5f5',
49 | accent: '#c463e6',
50 | error: '#e66365',
51 | },
52 | },
53 | theme: {
54 | light: true,
55 | },
56 | });
57 | ```
58 |
59 | Dessa forma, podemos acessar as cores globais do **Vuetify** de uma forma já **definida**
60 |
61 | Na próxima seção iremos discutir um pouco sobre o que virá nas próximas seções, te vemos lá!
62 |
63 | [Próxima Seção](./4-Considerações.md)
--------------------------------------------------------------------------------
/docs/tutorial/2-Conceitos/14-Considerações.md:
--------------------------------------------------------------------------------
1 | # Considerações finais
2 |
3 | Obrigado mesmo por ter chegado até aqui! Com o conhecimento que passamos, ja é possível fazer muita coisa mesmo com o Vue, durante as próximas seções iremos explorar todo o ecossistema que o **Vue** nos forneçe!
4 |
5 | A partir de agora, começaremos um projeto aplicando bibliotecas do **Vue**, assim conseguindo explicar coisas na prática, além de exercitar os conceitos.
6 |
7 | Qualquer dúvida ou reportar algum problema sobre o curso, reporte diretamente no [repositório](https://github.com/Novout/vue4noobs). E se possível deixe uma estrela, foi realmente trabalhoso.
8 |
9 | ## Tópicos Adicionais
10 |
11 | Tópicos como **componentes assíncronos** e **manipulações de carregamento** não serão abordados pois o objetivo do curso é uma introdução ao vue mostrando todo o seu **ecossistema**, mas iremos deixar a seguir se desejar ler sobre estes tópicos:
12 | *
13 | [Componentes Assíncronos](https://vueschool.io/articles/vuejs-tutorials/async-vuejs-components/)
14 |
15 | [Manipulações de Carregamento](https://alligator.io/vuejs/vue-async-components-load-error/)
16 |
17 | * Infelizmente a maioria dos conteúdos de **Vue** ainda estão em inglês, e é exatamente o motivo para a existência deste mini-curso sendo o objetivo conseguir atingir novos entusiastas em **Vue**, então em um futuro poderemos ter tópicos mais específicos traduzidos(por exemplo, o novo Vue 3).
18 |
19 | [Próxima Seção](./../3-Vuetify/1-Iniciando%20com%20Vuetify.md)
--------------------------------------------------------------------------------
/docs/tutorial/5-Vuex/6-Getters.md:
--------------------------------------------------------------------------------
1 | # Getters
2 |
3 | Os **getters** funcionam da mesma forma que as **computeds**, e no nosso caso iremos usar para concatenar a string que será exibida no nosso `/dashboard`:
4 |
5 | ```ts
6 | import Vue from 'vue';
7 | import Vuex from 'vuex';
8 |
9 | Vue.use(Vuex);
10 |
11 | export default new Vuex.Store({
12 | state: {
13 | usuario: {
14 | conta: '',
15 | senha: '',
16 | },
17 | },
18 | actions: {
19 | usuarioLogado(context, usuario) {
20 | context.commit('usuarioLogado', usuario);
21 | },
22 | },
23 | mutations: {
24 | usuarioLogado(state, payload) {
25 | state.usuario = payload;
26 | },
27 | },
28 | getters: {
29 | usuarioBemVindo(state) {
30 | return `Olá ${state.usuario.conta}!`;
31 | },
32 | },
33 | modules: {
34 | },
35 | });
36 | ```
37 |
38 | Dessa forma, podemos utilizar o `usuarioBemVindo` no template:
39 |
40 | `./src/pages/Dashboard.vue`
41 |
42 | ```ts
43 |
44 |
45 | {{ usuarioBemVindo }}
46 | Drawer
47 |
48 |
49 |
50 | // ...
51 |
52 | import { mapGetters } from 'vuex';
53 |
54 | computed: {
55 | ...mapGetters(['usuarioBemVindo']),
56 | },
57 | ```
58 |
59 | * Trocamos o **mapState** por **mapGetters**
60 |
61 | Na próxima seção vamos mostrar como melhorar nossa estrutura, nos vemos lá!
62 |
63 | [Próxima Seção](./7-Estrutura.md)
--------------------------------------------------------------------------------
/docs/tutorial/2-Conceitos/11-Pre-Processadores.md:
--------------------------------------------------------------------------------
1 | # Pre-Processadores
2 |
3 | Nas seções de introdução, demos o exemplo que no **Vue** é possível utilizar pre-processadores de forma facilitada, agora iremos explicar como implementar:
4 |
5 | * Nas opções de criação do projeto manual usando o **VueCLI**, é possível adicionar os pre-processadores diretamente por lá.
6 |
7 | ## SCSS - SASS
8 |
9 | Vamos instalar primeiramente as dependências necessárias:
10 |
11 | ```zsh
12 | yarn add sass-loader sass --save-dev
13 | ```
14 |
15 | Dessa forma, podemos agora utilizar o sass:
16 |
17 | ```vue
18 |
21 | ```
22 |
23 | Para essa estilização se manter apenas no seu escopo, é necessário que você adicione o `scoped` no seu `style`:
24 |
25 | ```vue
26 |
29 | ```
30 |
31 | Dessa maneira o estilo que for escrito aqui não passara para outro componente.
32 |
33 | Caso a estilização do seu componente se torne grande ou você deseja organizar melhor seus estilos é possível criar um arquivo `.scss` adicionamos como dependência:
34 |
35 | ```vue
36 |
37 | ```
38 |
39 | ## PugJS
40 |
41 | ```zsh
42 | yarn add pug --save-dev
43 | ```
44 |
45 | ```html
46 |
47 | main
48 | h1 {{ hello }}
49 |
50 | ```
51 |
52 | Na próxima seção, iremos para as nossas considerações de tudo oque aprendemos sobre os conceitos base do **Vue**, te vemos lá!
53 |
54 | [Próxima Seção](./12-SCSS.md)
55 |
--------------------------------------------------------------------------------
/docs/tutorial/4-Vue Router/5-Transições no VueRouter.md:
--------------------------------------------------------------------------------
1 | # Transições no VueRouter
2 |
3 | O **VueRouter** aceita o componente **transition** nas rotas, dessa forma conseguimos fazer animações diretamente na **rota**
4 |
5 | ## VueRouter Principal
6 |
7 | Podemos adicionar um **transition** em nosso **App.js**, por exemplo:
8 |
9 | `./src/App.vue`
10 |
11 | ```html
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
31 | ```
32 |
33 | ## VueRouter do Dashboard
34 |
35 | Agora vamos implementar um efeito parecido nas rotas filhas de **dashboard**:
36 |
37 | ```html
38 |
39 |
40 |
41 |
42 |
43 |
44 |
60 | ```
61 |
62 | No próximo capítulo iremos inicializar com **Vuex**, explicando o fluxo e implementando uma simples autenticação, nos vemos lá!
63 |
64 | [Próxima Seção](../5-Vuex/1-Gerenciamento%20de%20Estado.md)
65 |
--------------------------------------------------------------------------------
/docs/tutorial/9 - Next/4 - Suspense.md:
--------------------------------------------------------------------------------
1 | # Suspense
2 |
3 | Suspense é um recurso utilizado no React.js, sendo um recurso especial assim como o `transition` e `transition-group`, seu objetivo é ser um watcher do componente e ter as informações de carregamento. Por mais que podemos monitorar a criação de um componente pelo retorno do setup() sem a necessidade de recursos adicionais, o Suspense vem para utilizar isso de uma forma elegante e que facilite para os desenvolvedores.
4 |
5 | ## Utilização
6 |
7 | ```html
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ```
19 |
20 | * De uma forma simples, o #default é o componente que será escutado e esperado em sua construção(finalização do hook onMounted), enquanto o #fallback é o componente que será carregado enquanto o `ComponenteEsperado` está sendo criado.
21 |
22 | * Se o componente esperado executar um erro, podemos capturar e tratar este erro:
23 |
24 | ```html
25 |
32 | ```
33 |
34 | Agora precisamos criar a action **USUARIO_LOGADO** em nossa **loja**:
35 |
36 | `./src/store/index.js`
37 |
38 | ```ts
39 | export default new Vuex.Store({
40 | // ...
41 | actions: {
42 | usuarioLogado(context, usuario) {
43 | context.commit('usuarioLogado', usuario);
44 | },
45 | },
46 | // ...
47 | });
48 | ```
49 |
50 | * O context terá tudo o que podemos precisar para executar na nossa action, no caso estamos utilizando o `commit` que irá mandar para nossa `mutation`.
51 |
52 | * O **usuario** é o que estamos recebendo do `dispatch`
53 |
54 | Podemos simplificar o uso também:
55 |
56 | ```ts
57 | export default new Vuex.Store({
58 | // ...
59 | actions: {
60 | usuarioLogado({ commit }, usuario) {
61 | commit('usuarioLogado', usuario);
62 | },
63 | },
64 | // ...
65 | });
66 | ```
67 |
68 | Na próxima seção iremos criar a nossa **mutation**, nos vemos lá!
69 |
70 | [Próxima Seção](./5-Mutations.md)
--------------------------------------------------------------------------------
/docs/tutorial/5-Vuex/2-Iniciando com Vuex.md:
--------------------------------------------------------------------------------
1 | # Iniciando com Vuex
2 |
3 | Primeiramente, vamos adicionar o **Vuex** em nossa aplicação:
4 |
5 | `vue add vuex`
6 |
7 | * Usando o CLI do **Vue**, ele já ira estruturar o **Vuex**
8 |
9 | Na pasta gerada `./src/store.js`, podemos ver como ficou nossa **loja**:
10 |
11 | ```ts
12 | import Vue from 'vue';
13 | import Vuex from 'vuex';
14 |
15 | Vue.use(Vuex);
16 |
17 | export default new Vuex.Store({
18 | state: {
19 | },
20 | mutations: {
21 | },
22 | actions: {
23 | },
24 | modules: {
25 | },
26 | });
27 | ```
28 |
29 | * Iniciamente na aplicação, iremos seguir este **padrão** de estrutura, mas no final da nossa seção do **Vuex** iremos apresentar **alternativas** mais robustas.
30 |
31 | O **Vuex** não restringe a estrutura do seu código, sendo possível implementar qualquer tipo de estrutura necessária. Em vez disso, ele impõe um conjunto de princípios recomendados para projetos de médio-grande porte:
32 |
33 | * O estado do nível do aplicativo é centralizado no store.
34 |
35 | * A única maneira de mudar o estado é confirmando (ou fazendo commit das) mutações, que são transações **síncronas**.
36 |
37 | * Os getters nos permitem uma facilidade muito grande para a formatação de conteúdos do **estado** no template.
38 |
39 | * A lógica assíncrona deve ser encapsulada e pode ser composta com ações, e podem ser feitas apenas nas **actions**.
40 |
41 | * Se o arquivo da loja for muito grande, basta começar a dividir as actions, mutations e getters em arquivos separados, podendo utilizar operadores de desconstrução do **JavaScript** sem problemas.
42 |
43 | Na próxima seção, iremos mostrar formas diferentes de implementar os **estados** em nossas aplicações, nos vemos lá!
44 |
45 | [Próxima Seção](./3-State.md)
--------------------------------------------------------------------------------
/docs/tutorial/9 - Next/6 - Typescript.md:
--------------------------------------------------------------------------------
1 | # Typescript
2 |
3 | Uma dos pontos bastante criticados do Vue 2.x é a falta de suporte direto ao Typescript, onde a utilização de classes com `vuex-class-modules` e `vue-class-components` era necessária, agora temos opções adicionais, principalmente devido ao Vue 3.x ser escrito no próprio Typescript.
4 |
5 | ## Configuração
6 |
7 | Se estiver utilizando o Vue-CLI, utilizamos o comando `vue add typescript` em um projeto já existente, e agora podemos utilizar como `
72 | ```
73 |
74 | * Iremos ensinar a como configurar o **axios** e até mesmo usar o **http** padrão do **Vue**, não se preocupe.
75 |
76 | Na próxima seção, iremos introduzir o conteúdo sobre **Getters**, nos vemos lá!
77 |
78 | [Próxima Seção](./6-Getters.md)
--------------------------------------------------------------------------------
/docs/tutorial/2-Conceitos/4-CSS.md:
--------------------------------------------------------------------------------
1 | ## CSS
2 |
3 | O **CSS** no **Vue** não se diferencia muito do **CSS** utilizado normalmente, apenas com algumas modificações.
4 |
5 | ## Scoped
6 |
7 | Quando uma tag `
18 |
19 |
20 |
21 |
He4rt Developers
22 |
23 |
24 | ```
25 |
26 | Dessa forma, irá ser feito um "hash" do componente para o **DOM final** (ou seja, depois de ser transformado pelo **Virtual DOM**).
27 |
28 | Exemplo:
29 |
30 | ```css
31 | .container[data-v-f84hf]
32 | ```
33 |
34 | * Você consegue observar isso facilmente olhando o html final no console de desenvolvedor.
35 |
36 | ## Module
37 |
38 | Módulos CSS é um sistema para modularização e composição de CSS no **Vue**. O **vue-loader** fornece integração de alto nível com módulos CSS como uma alternativa para parecida com a de escopos **CSS**.
39 |
40 | ```html
41 |
49 |
50 |
51 |
52 |
He4rt Developers
53 |
54 |
55 | ```
56 |
57 | Por conta da propriedade ser computada, é possível utilizar usando o **v-bind**
58 |
59 | ```html
60 |
63 | ```
64 |
65 | ## Estilos anexados
66 |
67 | Existe outras formas de utilziar o **v-bind** para anexar nossos estilos:
68 |
69 | Objeto:
70 |
71 | ```html
72 |
73 |
74 |
75 |
76 |
85 | ```
86 |
87 | Array(mostrado anteriormente em **module**):
88 |
89 | ```html
90 |
91 | ```
92 |
93 | Valores múltiplos(Vue v2.3.0+):
94 |
95 | ```html
96 |
97 | ```
98 |
99 | [Próxima Seção](./5-Instância%20Vue.md)
--------------------------------------------------------------------------------
/docs/tutorial/1-Iniciando com Vue/1-O que e Vue.md:
--------------------------------------------------------------------------------
1 | # Vue
2 |
3 | Sejam bem vindos ao paper de Vue da [He4rt Developers](discord.io/He4rt), aqui nós iremos dar uma introdução ao framework **Vue**, mostrando todo o seu conceito e mostrando como utilizar de maneira efetiva.
4 |
5 | O **Vue**(se pronuncia **view**) é um framework para a construção de sites de forma progressiva, sendo diferente de outros tipo de estrutura monolítica. O ecossistema do **Vue** é extenso possibilitando ao desenvolvedor construir aplicações Frontend Web.
6 |
7 | ## Comunidade
8 |
9 | A comunidade do **Vue** vem crescendo cada vez mais, iremos estar disponibilizando alguns links da comunidade para auxiliar seu estudo sobre a framework.
10 |
11 | [Fórum](https://forum.vuejs.org)
12 |
13 | [VueJSBrasil](http://vuejs-brasil.com.br/)
14 |
15 | [VueSchool](https://vueschool.io/)
16 |
17 | [VueMastery](https://www.vuemastery.com)
18 |
19 | [MadeWithVue](https://madewithvuejs.com)
20 |
21 | [LearnVue](https://twitter.com/LearnVuejs2)
22 |
23 | ## SPA(Single Page Aplication)
24 |
25 | Significa que no **Vue** teremos uma aplicação web completa acontecendo em uma única página sem a necessidade de recarregar a página. O **Vue** também possui **SSR(Server Side Render)** com o **Nuxt** e aplicações **PWA** com o **Quasar**, mas neste início vamos focar apenas no **SPA** e apresentar alternativas futuramente.
26 |
27 | Utilizando este conceito conseguimos construir aplicações frontend de forma robusta e escalável.
28 |
29 | ## Virtual DOM
30 |
31 | Virtual DOM é um framework para manipulação do DOM(Document Object Model) que é utilizado pelo **Vue**, ele faz uma representação do DOM real na linguagem JavaScript, ou seja, o DOM verdadeiro é gerado a partir do DOM Virtual.Por conta disso, o **Vue** utiliza o **vue-loader** para fazer todo o ciclo do Virtual DOM e conseguir transformar no DOM final.
32 |
33 | ## VueLoader
34 |
35 | O **vue-loader** irá analisar o arquivo, pegar cada bloco de linguagem e montá-lo de volta em um módulo CommonJs cujo module.exports seja um objeto de opções do componente **Vue.js**.
36 |
37 | Para manipular, o **Vue** utiliza um sistema de componentes com a extensão **.vue**. O arquivo é um formato de arquivo personalizado que usa a sintaxe parecido com o HTML para descrever um componente Vue. Cada arquivo é dividido em três partes: `,
49 |
50 |
55 | ```
56 |
57 | [Próxima Seção](./2-VueCLI.md)
58 |
--------------------------------------------------------------------------------
/docs/tutorial/1-Iniciando com Vue/3-Estrutura do Projeto.md:
--------------------------------------------------------------------------------
1 | # Estrutura do Projeto
2 |
3 | Agora iremos explicar sobre cada arquivo que contém no projeto. Se você optou pela opção **default**, os arquivos serão os seguintes:
4 |
5 | ```
6 | .
7 | ├── node_modules # Dependências do projeto
8 | ├── public # Todos os arquivos públicos do projeto
9 | | └── favicon.icon # Ícone do projeto
10 | | └── index.html # HTML principal da aplicação
11 | ├── src # Pasta source do projeto
12 | | └── assets # Todos os assets do projetos
13 | | └── components # Componentes do vue
14 | | └── App.vue # Componente principal da aplicação
15 | | └── main.js # Arquivo de montagem do componente
16 | ├── .gigignore # Arquivos que vão ser ignorados pelo Git
17 | ├── babel.config.js # Configurações do babel
18 | ├── package.json # Settings do projeto
19 | ├── yarn.lock # Se estiver usando yarn
20 | ```
21 |
22 | ## public/favicon.icon
23 |
24 | Ícone do seu site.
25 |
26 | ## public/index.html
27 |
28 | É a onde o virtual DOM irá transformar no DOM final, anexando no html.
29 |
30 | ## src/assets/**
31 |
32 | Todas as imagenss e presets serão guardados aqui.
33 |
34 | ## src/components/**
35 |
36 | Todos os componentes da aplicação ficarão aqui, as **rotas** normalmente ficam em uma pasta **pages** ou **views**, iremos abordar isso futuramente.
37 |
38 | ## src/App.vue
39 |
40 | O componente base da aplicação. Normalmente, a rota inicial de nosso projeto terá o conteúdo neste Arquivo, pois é ele que sera o "intermediador" principal da aplicação.
41 |
42 | * Quando usarmos o [VueRouter](https://router.vuejs.org/) este arquivo vira o **view-router** principal. Sobre o **VueRouter**, recomendamos estar sobre apenas quando acabar sobre o básico do **Vue** para não confundir conceitos.
43 |
44 | ## src/main.js
45 |
46 | Arquivo de entrada principal, criando a [Instância](https://br.vuejs.org/v2/guide/instance.html) do **Vue** e anexando na div que possui o id **app**, que fica no **public/index.html**.
47 |
48 | * Todas as bibliotecas poderão ser anexadas antes da criação da instância(new Vue) neste arquivo.
49 |
50 | ## babel.config.js
51 |
52 | O [babel](https://babeljs.io/) é um transcompilador de JavaScript para converter códigos ES6+, assim mecanismos mais antigos conseguindo executar o código.
53 |
54 | Na próxima seção irá ser explicado como está o fluxo inicial da aplicação e introduzindo o conceito de **props**.
55 |
56 | [Próxima Seção](./4-Fluxo%20e%20Props.md)
--------------------------------------------------------------------------------
/docs/tutorial/9 - Next/2 - Ecossistema.md:
--------------------------------------------------------------------------------
1 | # Ecossistema
2 |
3 | Vamos demonstrar as mudanças que ocorreram nas novas versões do Vue-Router e Vuex!
4 |
5 | ## Vue-Router
6 |
7 | Tivemos uma mudança na estrutura de base no novo [VueRouter](https://github.com/vuejs/vue-router-next) para utilizar a base:
8 |
9 | ```ts
10 | import { createRouter, createWebHistory } from "vue-router";
11 |
12 | const routes = [
13 | {
14 | path: "/",
15 | name: "Home",
16 | component: () => import("@/views/Home.vue")
17 | }
18 | ];
19 |
20 | const router = createRouter({
21 | history: createWebHistory(process.env.BASE_URL),
22 | routes
23 | });
24 |
25 | export default router;
26 | ```
27 |
28 | * Utilizamos `createRouter` e passamos um objeto com opções, no caso agora o `history` precisamos passar `createWebHistory` para utilizarmos o modo `history`. Temos outras opções como `createHashHistory` para usar no modo hash ou o `createMemoryHistory` para SSR.
29 |
30 | * Se estiver utilizando ``, necessita esperar o router ficar pronto para criar a instância. Utilize `router.isReady().then(() => app.mount('#app'))` por exemplo.
31 |
32 | Temos o `useRouter` para conseguirmos utilizar as coisas do router no setup:
33 |
34 | ```ts
35 | import { useRouter } from 'vue-router';
36 |
37 | const router = useRouter();
38 | router.push({ name: 'he4rt' }));
39 | ```
40 |
41 | Podemos agora criar rotas nos próprios componentes, por mais que seja um uso bem específico é uma adição muito válida:
42 |
43 | ```ts
44 | import { defineComponent } from 'vue';
45 | import { useRouter } from 'vue-router';
46 |
47 | const router = useRouter();
48 |
49 | const createRoute = id => {
50 | router.addRoute({
51 | path: `/he4rt/${id}`,
52 | name: `he4rt-${id}`,
53 | component: () => import('@/views/He4rt.vue');
54 | });
55 | }
56 | ```
57 |
58 | As guardas de rota tiveram uma mudança em seu retorno, agora retornam o valor primeiramente do que o `next()`. No exemplo abaixo, podemos determinar se a rota será renderizada ou não apenas pelo retorno do booleano:
59 |
60 | ```ts
61 | router.beforeEach(() => booleanAuthenticated);
62 | ```
63 |
64 | ### Pinia
65 |
66 | O [Pinia](https://pinia.vuejs.org/) é sucessor do [Vuex 4](https://github.com/vuejs/vuex) e trouxe uma nova perspectiva:
67 |
68 | ```ts
69 | // stores/counter.ts
70 | import { defineStore } from 'pinia'
71 |
72 | export const useCounterStore = defineStore('counter', {
73 | state: () => {
74 | return { count: 0 }
75 | },
76 | actions: {
77 | increment() {
78 | this.count++
79 | },
80 | },
81 | })
82 |
83 | //...
84 |
85 | const COUNTER = useCounterStore()
86 | console.log(COUNTER.count)
87 | ```
88 |
89 | [Próxima Seção](./3%20-%20Hooks.md)
90 |
--------------------------------------------------------------------------------
/docs/tutorial/2-Conceitos/7-BusEvent.md:
--------------------------------------------------------------------------------
1 | # BusEvent
2 |
3 | Dependendo da situação exige a necessidade de uma solução rápida e fácil para transmitir dados entre os componentes do **Vue**.
4 |
5 | Existe o [Vuex](https://vuex.vuejs.org/) para gerenciamento centralizado do estado. Assim, pode fornecer ao aplicativo uma única fonte de verdade.
6 |
7 | Mas para um aplicativo com arquitetura simples, basta comunicar-se entre componentes usando eventos. Para isso, podemos criar uma solução rápida e implementar o **EventBus**. Ele nos permite emitir um evento em um componente filho para outro componente filho(ambos possuindo o mesmo pai).
8 |
9 | Primeiro de tudo, precisamos de um mecanismo para transferir eventos entre componentes. Devido à simplicidade do **Vue**, ele nos permite criar uma nova **instância** com facilidade:
10 |
11 | ```ts
12 | // ./src/event-bus.js
13 | import Vue from 'vue';
14 |
15 | const EventBus = new Vue();
16 |
17 | export default EventBus;
18 | ```
19 |
20 | Aqui temos um componente que importa o Vue e o EventBus. Quando o método **emitirEvento** do componente é chamado, ele emite um novo evento chamado **FORMULARIO** e passa uma carga útil junto com ele.
21 |
22 | ```ts
23 | // primeiro-componente.js
24 | import Vue from 'vue';
25 | import EventBus from './event-bus';
26 |
27 | Vue.component('primeiro-componente', {
28 | ...
29 | methods: {
30 | emitirEvento() {
31 | EventBus.$emit('FORMULARIO', {
32 | nome: 'João',
33 | email: 'joao@hotmail.com'
34 | });
35 | }
36 | }
37 | });
38 | ```
39 |
40 | * O exemplo acima funcionaria normalmente em um **.vue**.
41 |
42 | Em outro componente, podemos registrar um ouvinte que escuta o evento **FORMULARIO** a ser transportado usando o EventBus. Assim que o evento aparecer, podemos executar o JavaScript com o payLoad recebido como argumento.
43 |
44 | ```ts
45 | // segundo-componente.js
46 | import Vue from 'vue';
47 | import EventBus from './event-bus';
48 | Vue.component('segundo-componente', {
49 | ...
50 | mounted () {
51 | EventBus.$on('FORMULARIO', payload => {
52 | console.log(payload.nome, payload.email);
53 | });
54 | }
55 | });
56 | ```
57 |
58 | E pronto! Dessa forma conseguimos comunicar dois componentes filhos se a necessidade de **anexar** o fluxo de ambos os componentes.
59 |
60 | Para anexar os componentes:
61 |
62 | ```ts
63 |
74 | ```
75 |
76 | Na próxima seção iremos de apresentar as transições, te vemos lá!
77 |
78 | [Próxima Seção](./8-Transições.md)
79 |
80 |
--------------------------------------------------------------------------------
/docs/tutorial/9 - Next/5 - JSX.md:
--------------------------------------------------------------------------------
1 | # JSX
2 |
3 | Um recurso que já existia no Vue 2.x, agora podemos de uma forma mais complementada em utilizar o tão famoso [JSX](https://github.com/vuejs/jsx-next), onde instânciamos um `defineComponent` e executamos o template dentro do próprio componente.
4 |
5 | ## Instalação
6 |
7 | Execute o comando:
8 |
9 | `npm install @vue/babel-plugin-jsx -D`
10 |
11 | e no seu .babelrc na raíz do projeto:
12 |
13 | ```tsx
14 | {
15 | "plugins": ["@vue/babel-plugin-jsx"]
16 | }
17 | ```
18 |
19 | * Também podemos utilizar o JSX com Typescript(TSX)
20 |
21 | Exemplo básico:
22 |
23 | ```tsx
24 | import { defineComponent } from "vue";
25 |
26 | export default defineComponent({
27 | name: "App",
28 | render() {
29 | return (
30 | <>
31 |
32 | >
33 | )
34 | }
35 | });
36 | ```
37 |
38 | Podemos utilizar diretamente pelo retorno do setup():
39 |
40 | ```tsx
41 | import { defineComponent } from "vue";
42 |
43 | export default defineComponent({
44 | name: "App",
45 | setup() {
46 | return () => (
47 | <>
48 |
49 | >
50 | )
51 | }
52 | });
53 | ```
54 |
55 | ## Diretivas e Modificadores
56 |
57 | Podemos utilizar diretamente pelo retorno do setup():
58 |
59 | ```tsx
60 | import { ref, defineComponent } from "vue";
61 |
62 | export default defineComponent({
63 | name: "App",
64 | setup() {
65 | let show = ref(false);
66 |
67 | const toggleBestGroup = () => show.value = !show.value;
68 |
69 | return () => (
70 | <>
71 |
72 | Olá He4rt!
73 | >
74 | )
75 | }
76 | });
77 | ```
78 |
79 | * Utilizando o V-Model:
80 |
81 | ```tsx
82 | import { ref, defineComponent } from "vue";
83 |
84 | export default defineComponent({
85 | name: "App",
86 | setup() {
87 | let text = ref("");
88 |
89 | return () => (
90 | <>
91 |
92 | {text}
93 | >
94 | )
95 | }
96 | });
97 | ```
98 |
99 | ## Usando Componentes
100 |
101 | Não precisamos importar os componentes com `components: {...}`, podendo utilizar diretamente:
102 |
103 | ```tsx
104 | import { ref, defineComponent } from "vue";
105 | //...
106 | const Header = defineComponent({...});
107 | //...
108 | const Content = defineComponent({...});
109 | //...
110 | export default defineComponent({
111 | name: "App",
112 | setup() {
113 | return () => (
114 | <>
115 |
116 |
117 | >
118 | )
119 | }
120 | });
121 | ```
122 |
123 | [Próxima Seção](./6%20-%20Typescript.md)
124 |
--------------------------------------------------------------------------------
/docs/tutorial/2-Conceitos/10-Mixins.md:
--------------------------------------------------------------------------------
1 | # Mixins
2 |
3 | Quando o seu projeto Vue começar a crescer, você pode copiar e colar os mesmos dados, métodos e observadores repetidamente, se tiver componentes semelhantes. Esse tipo de ideia "quebra" a componentização que uma framework oferece, por isso **mixins** são úteis. Claro, você pode escrever todos esses **arquivos separados** como um único componente e usar adereços para tentar personalizá-los, mas o uso desses adereços pode facilmente ficar **confuso**.
4 |
5 | Incrivelmente existe muitos códigos que ainda são feito com o famoso ctrc + ctrv de um componente a outro, então **recomendamos fortemente** o seu aprendizado com mixins para melhor utilização da framework.
6 |
7 | Felizmente, os **Mixins** do **Vue** são bem simples de se usar (assim como a maioria das coisas no **Vue** comparando com outras frameworks).O componente terá acesso a todas as opções no mixin como se fosse declarado no próprio componente.
8 |
9 | ```ts
10 | // arquivo mixin.js
11 | export default {
12 | data () {
13 | idade: 18
14 | },
15 | created() {
16 | console.log('Mixin existe!');
17 | },
18 | methods: {
19 | mostrarIdade() {
20 | console.log('Agora printando de uma função do mixin!');
21 | }
22 | }
23 | }
24 |
25 | // arquivo main.js
26 | import mixin from './mixin.js'
27 |
28 | new Vue({
29 | mixins: [mixin],
30 | created() {
31 | console.log(this.$data);
32 | this.mostrarIdade();
33 | }
34 | });
35 | // "Mixin existe!"
36 | // { idade: 18 }
37 | // "Agora printando de uma função do mixin!"
38 | ```
39 |
40 | Dessa forma, temos acesso ao mixin apenas pelo **$data**, evitando problemas com declarações no próprio componente que está utilizando o **mixin**.
41 |
42 | ```ts
43 | // mixin.js file
44 | export default {
45 | data () {
46 | return {
47 | title: 'pertenco ao mixin'
48 | }
49 | }
50 | }
51 | // -----------------------------------------------------------
52 |
53 | // main.js file
54 | import mixin from './mixin.js';
55 | export default {
56 | mixins: [mixin],
57 | data() {
58 | return {
59 | title: '>NÃO< estou no mixin'
60 | }
61 | },
62 | created() {
63 | console.log(this.title);
64 | }
65 | }
66 | // => ">NÃO< pertenco ao mixin"
67 | ```
68 |
69 | # Mixins Globais
70 |
71 | Podemos criar mixins globais utilizando o **Vue.mixin**:
72 |
73 | ```ts
74 | // irá jogar o 'importante' para as opções
75 | Vue.mixin({
76 | created() {
77 | const importante = this.$options.importante;
78 | if (importante) {
79 | console.log(importante);
80 | }
81 | }
82 | })
83 |
84 | new Vue({
85 | importante: 'he4rt'
86 | });
87 | // "he4rt"
88 | ```
89 |
90 | * Quando for criar mixins globais, tome muito cuidado pelo fato de ser algo global que estará na instância sempre.
91 |
92 | Na próxima seção, iremos ensinar a como utilizar os pre-processadores no **Vue**.
93 |
94 | [Próxima Seção](./11-Pre-Processadores.md)
95 |
--------------------------------------------------------------------------------
/docs/tutorial/9 - Next/8 - Pinia.md:
--------------------------------------------------------------------------------
1 | # Pinia
2 |
3 | [Pinia](https://github.com/posva/pinia) é um gerenciador de estado que já existia para Vue 2.x, feito pelo mesmo criador do `VueRouter`, com o objetivo de trazer um gerenciador de fácil utilizar e reaproveitação, seguindo alguns padrões do `Vuex`.
4 |
5 | ## Utilização
6 |
7 | Execute o comando:
8 |
9 | `yarn add pinia@next`
10 |
11 | no main.js:
12 |
13 | ```ts
14 | import { createPinia } from 'pinia';
15 |
16 | app.use(createPinia());// sintaxe diferente de outras bibliotecas
17 | ```
18 |
19 | Agora, vamos criar nossa primeira loja:
20 |
21 | ```ts
22 | // ./src/store/default
23 | import { defineStore } from 'pinia';
24 |
25 | export const useDefaultStore = defineStore({
26 | id: 'default',
27 | state: () => ({
28 | counter: 0,
29 | }),
30 | getters: {
31 | boostedCount() {
32 | return this.counter + Math.floor(Math.random() * 10);
33 | },
34 | // Um getter dentro do outro
35 | boostedCountPlusPlus() {
36 | return this.boostedCount + Math.floor(Math.random() * 10);
37 | }
38 | },
39 | actions: {
40 | reset() {
41 | this.counter = 0
42 | },
43 | },
44 | })
45 | ```
46 |
47 | * Não temos `mutation` no Pinia, já que podemos mutar diretamente nosso state.
48 |
49 | * Diferente do Vuex, não precisamos centralizar nossas lojas, podendo utilizá-las diretamente nos nossos componentes.
50 |
51 | * Cada loja é separada, mas podemos interligá-las normalmente.
52 |
53 | * Usamos a nova sintaxe de Hook's:
54 |
55 | ```ts
56 | import { useDefaultStore } from '@/store/default'
57 |
58 | export default defineComponent({
59 | setup() {
60 | const main = useDefaultStore() // instanciando a loja
61 |
62 | main.counter++; // mutando diretamente a loja antes de retornar ao template, para mutar mais de uma variável utilizamos o main.$patch({ ... })
63 |
64 | return {
65 | // retornando o state inteiro
66 | main,
67 | // apenas a um único elemento do state
68 | state: computed(() => main.counter),
69 | // apenas a um específico getter
70 | boosted: computed(() => main.boostedCountPlusPlus),
71 | }
72 | },
73 | })
74 | ```
75 |
76 | ## Interligando Lojas
77 |
78 | Podemos interligar as lojas de uma maneira muito fácil:
79 |
80 | ```ts
81 | import { defineStore } from 'pinia';
82 | import { useUserStore } from './user';
83 | import { useHe4rtStore } from './heart';
84 |
85 | export const useMainStore = defineStore({
86 | id: 'main',
87 | getters: {
88 | member() {
89 | const user = useUserStore();
90 | const heart = useHe4rtStore();
91 |
92 | return `${user.name} é membro da ${heart.fullName}!`
93 | },
94 | },
95 | })
96 | ```
97 |
98 | * O Pinia ainda está em alpha(17/12/2020), não recomendados para utilizar em produção.
99 |
100 | [Próxima Seção](./9%20-%20Vuetelemetry.md)
101 |
--------------------------------------------------------------------------------
/docs/tutorial/8 - Ecossistema Vue/1 - Nuxt.md:
--------------------------------------------------------------------------------
1 | # Nuxt
2 |
3 | O [Nuxt](https://nuxtjs.org/) é uma framework **progressiva** para o **Vue**. Além de perfomático e modular ele permite o **SSR**(também é possível utilizar SPA com o Nuxt).Ele também já possui integrado o **VueRouter** e o **Vuex** com um funcionamento próprio.
4 |
5 | ## Criando Projeto
6 |
7 | Criar uma projeto **Nuxt** é bem facil, apenas utilizamos o **NPX**:
8 |
9 | `npx create-nuxt-app `
10 |
11 | * As configurações base, como `head`, `plugins` e opções gerais ficam em `nuxt.config.js` na raiz do projeto.
12 |
13 | ## Rotas
14 |
15 | O **Nuxt** gera **automaticamente** as **rotas**, dependendo da estrutura utilizada:
16 |
17 | pages/
18 | |>produto/
19 | |> _id.vue
20 | |> index.vue
21 |
22 | Será convertido para:
23 |
24 | ```ts
25 | router: {
26 | routes: [
27 | {
28 | name: 'index',
29 | path: '/',
30 | component: 'pages/index.vue'
31 | },
32 | {
33 | name: 'produto',
34 | path: '/produto',
35 | component: 'pages/user/index.vue'
36 | },
37 | {
38 | name: 'produto_id',
39 | path: '/produto/:id',
40 | component: 'pages/produto/_id.vue'
41 | }
42 | ]
43 | }
44 | ```
45 |
46 | ## Plugins
47 |
48 | Para adicionar **bibliotecas externas** no **Nuxt**, podemos usar a pasta **plugins** e configurar o **nuxt.config.js**
49 |
50 | ```ts
51 | import Vue from 'vue'
52 | import VueLib from 'vue-lib'
53 |
54 | Vue.use(VueLib)
55 | ```
56 |
57 | ```ts
58 | export default {
59 | plugins: ['~/plugins/vue-lib']
60 | }
61 | ```
62 |
63 | ## Store
64 |
65 | O Nuxt muda a forma de como utilizar o **Vuex**, mapeando os arquivos dentro da pasta **store**:
66 |
67 | `store/index.js`
68 |
69 | ```ts
70 | export const state = () => ({
71 | grupo: "He4rt";
72 | })
73 |
74 | export const mutations = {
75 | add(state) {
76 | state.grupo += " Developers"
77 | }
78 | }
79 | ```
80 |
81 | Para criar módulos, utilizamos `store/.js`:
82 |
83 | `store/game.js`
84 |
85 | ```ts
86 | export const state = () => ({
87 | players: []
88 | })
89 | ```
90 |
91 | É a mesma coisa que:
92 |
93 | ```ts
94 | new Vuex.Store({
95 | modules: {
96 | game: {
97 | namespaced: true,
98 | state: () => ({
99 | players: []
100 | })
101 | }
102 | }
103 | })
104 | ```
105 |
106 | ## Geração Estática
107 |
108 | Para gerarmos páginas estáticas com o **Nuxt**, executamos os seguintes passos:
109 |
110 | 1: Utilize a versão 2.14.0 ou maior
111 | 2: Coloque `target: "static"` em `nuxt.config.js`
112 | 3: Executa o comando `nuxt generate`
113 |
114 | Na próxima seção, iremos te apresentar o **Gridsome**, um gerador de **paginas estáticas**, nos vemos lá!
115 |
116 | ## Modulos
117 |
118 | O Nuxt possui um próprio site que exibe os [módulos feitos para nuxt](https://modules.nuxtjs.org/), onde conseguimos encontrar com facilidade integrações prontas com o Nuxt.js
119 |
120 | [Próxima Seção](./2%20-%20Gridsome.md)
121 |
--------------------------------------------------------------------------------
/docs/tutorial/7-Testes e Storybook/2-Cypress no Vue.md:
--------------------------------------------------------------------------------
1 | # Cypress no Vue
2 |
3 | O Cypress é uma ferramente para testes e2e, dessa forma não precisamos "testar na mão", porquê não ter esses testes documentados? Dessa forma conseguimos evitar imprevistos em nossas aplicações frontend.
4 |
5 | * O **Vue** tambem possui suporte para o [NightWatch](https://nightwatchjs.org/)
6 |
7 | Para adicionar o [Cypress](https://www.cypress.io/) em nosso projeto, iremos usar o seguinte comando:
8 |
9 | `vue add @vue/e2e-cypress`
10 |
11 | Os arquivos gerados:
12 |
13 | `cypress.json`
14 |
15 | Entrypoint para os testes
16 |
17 | `./tests/e2e/specs/`
18 |
19 | Onde ficará nossos testes
20 |
21 | `./tests/e2e/specs/index.js`
22 |
23 | ```ts
24 | describe('My First Test', () => {
25 | it('Visits the app root url', () => {
26 | cy.visit('/');
27 | cy.contains('h1', 'Welcome to Your Vue.js App');
28 | });
29 | });
30 | ```
31 |
32 | * Neste teste, é visitado a rota `/` procurando pelo h1 que contén `Welcome to Your Vue.js App`.
33 |
34 | * Renomeie o teste de `test.js` para `landing.js`.
35 |
36 | Agora vamos reformular para a nossa página:
37 |
38 | ```ts
39 | describe('Página Inicial', () => {
40 | it('Visitando a página inicial', () => {
41 | cy.visit('/');
42 | cy.contains('span', 'Pela: He4rt Developers');
43 | });
44 | it('Indo para o repositório', () => {
45 | cy.visit('/');
46 | cy.contains('Repositório').click();
47 | });
48 | it('Indo para o discord da He4rt', () => {
49 | cy.visit('/');
50 | cy.contains('He4rt Discord').click();
51 | });
52 | });
53 | ```
54 |
55 | * O primeiro verifica se o span no site possui o conteúdo `Pela: He4rt Developers`.
56 |
57 | * O segundo verifica se o botão Repositório existe e abre.
58 |
59 | * O terceiro verifica se o botão He4rt Discord existe e abre.
60 |
61 | Agora vamos criar o `register.js`, com o seguinte:
62 |
63 | ```ts
64 | describe('Registrar', () => {
65 | it('Criando conta', () => {
66 | cy.visit('/register');
67 | cy.get('.conta').type('novout@hotmail.com');
68 | cy.get('.senha').type('123456789');
69 | cy.get('.repetirSenha').type('123456789');
70 | cy.contains('Entrar').click();
71 | cy.contains('Olá novout@hotmail.com');
72 | });
73 | });
74 | ```
75 |
76 | * O Cypress irá colocar os dados necessários e entrar no dashboard
77 |
78 | Após rodarmos o comando `yarn test:e2e`, abrirá a segunte tela:
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | * Para executar os testes basta clicar no nome deles ou em **Rodar todos os testes**.
89 |
90 | * O **Cypress** tem muitos recursos disponíveis, recomendamos muito que dê uma olhada na [documentação](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Cypress-Can-Be-Simple-Sometimes).
91 |
92 | Na próxima seção, iremos mostrar como configurar o **Storybook** em nosso projeto, nos vemos lá!
93 |
94 | [Próxima Seção](./3-Storybook.md)
--------------------------------------------------------------------------------
/docs/tutorial/4-Vue Router/1-Iniciando com Vue Router.md:
--------------------------------------------------------------------------------
1 | # Iniciando com Vue Router
2 |
3 | **VueRouter** é o **router** oficial do **VueJS**, Por isso ele se integra profundamente ao núcleo do **Vue**. para facilitar a criação de aplicativos de página única com o **Vue**. Características incluem:
4 |
5 | * Rotas aninhadas
6 | * Configuração modular de roteador baseada em componente
7 | * Parâmetros de rota, consulta
8 | * Integração com efeitos de transição
9 | * Controle de navegação refinado
10 | * Links com classes CSS ativas automáticas
11 | * Modo de histórico HTML5 ou modo de hash, com fallback automático no IE9
12 | * Comportamento de rolagem personalizável
13 |
14 | ## Adicionando ao Projeto
15 |
16 | Primeiramente, iremos instalar a dependência do **vue-router**.
17 |
18 | `yarn add vue-router`
19 |
20 | Criamos um arquivo `vuerouter.js` em `./src/plugins/vuerouter.js'` e adicionamos o seguinte:
21 |
22 | `./src/plugins/vuerouter.js`
23 |
24 | ```ts
25 | import Vue from 'vue';
26 | import VueRouter from 'vue-router';
27 | import routes from '@/routes.js';
28 |
29 | Vue.use(VueRouter);
30 |
31 | export default new VueRouter({
32 | mode: 'history',
33 | routes,
34 | });
35 | ```
36 |
37 | * Estamos exportando o **VueRouter**, contendo nossas rotas e no modo [history](https://router.vuejs.org/guide/essentials/history-mode.html#example-server-configurations).
38 |
39 | Agora vamos importar em nosso `main.js`.
40 |
41 | ```ts
42 | // ...
43 | import router from '@/plugins/vuerouter.js';
44 | // ...
45 | const app = new Vue({
46 | router
47 | }).$mount('#app');
48 | ```
49 |
50 | Não acabamos ainda, vamos criar o arquivo `routes.js` na raiz do `src` que é a onde ficará a declaração de nossas rotas.
51 |
52 | `./src/routes.js`
53 |
54 | ```ts
55 | import Home from './pages/Home.vue';
56 |
57 | export default [
58 | {
59 | path: '/',
60 | component: Home,
61 | },
62 | {
63 | path: '*',
64 | redirect: '/',
65 | },
66 | ];
67 | ```
68 |
69 | * Se ele não encontrar a rota '/', irá para a genérica '*', que no caso dá um redirect para o próprio '/', isso será util quando tivermos mais rotas no projeto.
70 |
71 | * Também seria possível criar um componente **Error.vue** por exemplo, e colocar no lugar do **redirect**.
72 |
73 | * Você pode utilizar RegEx no `path`.
74 |
75 | Vamos transferir o nosso conteúdo de `App.vue` para `./src/pages/Home.vue`.
76 |
77 | * Renomeie o import do **Header**:
78 |
79 | `./src/pages/Home.vue`
80 |
81 | ```ts
82 | import Header from '../components/header/Header.vue';
83 | ```
84 |
85 | E o novo conteúdo de `./src/App.vue` será:
86 |
87 | ```ts
88 |
89 |
90 |
91 |
92 |
95 | ```
96 |
97 | * O **router-view** é o que irá exibir a rota em que estamos, no caso '/' irá exibir a rota **Home** neste **router-view**.
98 |
99 | A estrutura final ficou a seguinte:
100 |
101 |
102 |
103 |
104 |
105 | Na próxima seção, iremos criar o nosso formulário de login, e a rota que ela irá redireciar, assim ensinando um pouco sobre **Navegação**, nos veremos lá!
106 |
107 | [Próxima Seção](./2-Navegação.md)
--------------------------------------------------------------------------------
/docs/tutorial/5-Vuex/1-Gerenciamento de Estado.md:
--------------------------------------------------------------------------------
1 | # Gerenciamento de Estado
2 |
3 | Agora vamos introduzir sobre o **Vuex**, o **gerenciador de estado** do **Vue**. O **Vuex** pode ser relacionado com o **Redux**, mas possuem diferenças cruciais.
4 |
5 | Ele é um padrão de gerenciamento de estado + biblioteca para a. Ele serve como uma loja centralizada para todos os componentes em uma aplicação, com regras garantindo que o estado só possa ser mutado de forma previsível. Ou seja, dessa forma conseguimos salvar dados temporários que podem ser úteis ao longo da aplicação. Por exemplo, o id de um usuário ou produto, que precisamos consultar em vários componentes diferentes!
6 |
7 | ## Fluxo
8 |
9 |
10 |
11 |
12 |
13 | Todo o **Vuex** funciona em torno deste ciclo, mas, oque É esse ciclo você me pergunta:
14 |
15 | ## Vue Components
16 |
17 | Seria todos os nossos componentes **.vue**, seja ela **propriedade** ou **page** o **vuex** irá realizar uma série de ações até chegar novamente no nosso componente.
18 |
19 | Para mandar uma ação para o **vuex**, usamos o **dispatch**, que irá conter o nome para onde queremos mandar, e como segundo parâmetro o conteúdo.
20 |
21 | Exemplo:
22 |
23 | `dispatch('nome_da_action', { hello: world });`
24 |
25 | Podemos enviar o que quisermos, como objetos, booleanos, etc. **NÃO** recomendamos mandar **templates**.
26 |
27 | ## Action
28 |
29 | As actions é a onde o **dispatch** irá enviar o conteúdo. As actions servem para realizar código **assíncrono** no **Vuex**.
30 |
31 | Em caso de não ter necessidade de realizar código assíncrono, podemos apenas enviar o conteúdo diretamente para a **Mutation**.
32 |
33 | Depois de executarmos o que for preciso, vamos **commitar** para a **Mutation**, como o próprio nome sugere, ele que irá **mutar** o estado.
34 |
35 | Exemplo:
36 |
37 | `commit('nome_da_mutation', objeto);`
38 |
39 | * Para mandar para uma **action** usamos o **dispatch** e para uma **mutation** usamos o **commit**, possuem nomes diferentes exatamente para não confundir o desenvolvedor.
40 |
41 | ## Mutations
42 |
43 | Na **mutation**, teremos acesso ao **estado** do **Vuex**, assim conseguindo **mutar**. Iremos explicar detalhadamente na seção de **Mutations**.
44 |
45 | ## State
46 |
47 | Aqui é a onde estará os nossos estados, por exemplo:
48 |
49 | ```ts
50 | state: {
51 | contador: 0
52 | }
53 | ```
54 |
55 | * Apenas isso? Sim!
56 |
57 | ## Getters
58 |
59 | Os **getters** funcionam com a mesma lógia das **computeds**, podemos fazer uma **cópia** do estado para modificação sem a **mutação** do **estado**
60 |
61 | ## Estrutura da Loja
62 |
63 | A estrutura de nossa loja é bem simples, nada distante do que já vimos no **Vue**:
64 |
65 | **Vue**
66 |
67 | ```ts
68 | new Vue({
69 | data: {
70 |
71 | },
72 | methods: {
73 |
74 | },
75 | computed: {
76 |
77 | },
78 | });
79 | ```
80 |
81 | **Vuex**
82 |
83 | ```ts
84 | new Vuex.Store({
85 | state: {
86 |
87 | },
88 | mutations: {
89 |
90 | },
91 | actions: {
92 |
93 | },
94 | getters: {
95 |
96 | },
97 | });
98 | ```
99 |
100 | * O **Vuex** **NÃO** irá substituir a estrutura dos componentes do **Vue**, é recomendável só utilizar o **Vuex** quando realmente necessitamos acessar um mesmo **conteúdo** em várias partes diferentes da **aplicação**.
101 |
102 | Na próxima seção, iremos implementar a **loja** em nosso projeto atual, nos vemos lá!
103 |
104 | [Próxima Seção](./2-Iniciando%20com%20Vuex.md)
--------------------------------------------------------------------------------
/docs/tutorial/9 - Next/3 - Hooks.md:
--------------------------------------------------------------------------------
1 | # Hooks
2 |
3 | Os Hooks que já tiveram uma participação no Vue 2.x e agora devido a nova composição da API sendo integrado diretamente, é uma forma de reaproveitar código, substituindo os antigos mixins.
4 |
5 | Inspirado nos Hooks do React.js, todas as lib's compatíveis com o Vue 3.x veem com a mesma base padronização a utilizar de bibliotecas.
6 |
7 | Já mostramos os hooks padrões, como a nova forma de utilizar os `LifeCycleHooks`, mas agora também podemos criar os nossos próprios.
8 |
9 | ## Nova Sintaxe
10 |
11 | Diferente do Vue 2.x em que utilizamos o `this.*` para acessar os plugins internos, agora nos importamos separadamente e instânciamos o que queremos:
12 |
13 | ```ts
14 | import { onBeforeDestroy } from 'vue';
15 | import { useRouter } from 'vue-router';
16 |
17 | const router = useRouter(); // instanciação do router
18 |
19 | onBeforeDestroy(() => { // life cycle hook
20 | router.push('/');
21 | })
22 | ```
23 |
24 | * Além de utilizaremos apenas o que precisamos, a grande vantagem de utilizar hook's é que podemos criar a nossa lógica de forma separada, sem ser dependente do template.
25 |
26 | ## Hooks Próprios
27 |
28 | Podemos separar por arquivos a nossa lógica, assim conseguindo criar uma estrutura interessante nos nossos projetos:
29 |
30 | ```ts
31 | // './src/use/state.js'
32 | import { reactive } from 'vue';
33 |
34 | export const useState = () => {
35 | const state = reactive({
36 | value: 0
37 | });
38 |
39 | return state
40 | }
41 | // ./src/pages/home.vue
42 | import { useState } from '@/use/state';
43 |
44 | const state = useState()
45 | ```
46 |
47 | * Uma grande vantagem dos hook's é que o nosso código fica menos poluido do que utilizar `this.*` sempre que queremos acessar um prototype.
48 |
49 | * Em hook's assíncronos, recomendamos que tenha cuidado pois o componente não vai ser criado até a instância do setup() ser retornada, ou seja, se a promise não retornar, o componente vai ficar eternamente carregando.
50 |
51 | * Podemos criar arquivos de hook's extensos e com qualquer recurso que o vue nos disponibiliza:
52 |
53 | ```ts
54 | import { ref, reactive, UnwrapRef } from 'vue';
55 |
56 | // Simulando React hook utilizando a Api de Composição do Vue em Typescript
57 |
58 | const useStateObject = (entryObj: T) => {
59 | const obj = reactive(entryObj); // criando o objeto reativo
60 | const set = (valueObj: T) => { // percorrendo todas as chaves da tupla para mutar uma por uma
61 | Object.entries(valueObj).forEach(([key, val]) => {
62 | obj[key] = val;
63 | });
64 | };
65 |
66 | return [obj, set];
67 | }
68 |
69 |
70 | export const useState = (entryValue: T) => {
71 | if (typeof entryValue === 'object') { // se for um objeto, iremos utilizar outra lógica
72 | return useStateObject(entryValue);
73 | }
74 | const state = ref(entryValue); // referência criada
75 | const set = (value: T) => { // mutando a referência
76 | state.value = value as UnwrapRef;
77 | };
78 |
79 | return [state, set];
80 | };
81 | ```
82 |
83 | ```ts
84 |
85 |
86 |
87 |
88 |
94 | ```
95 |
96 | * Não é um exemplo útil na prática, já que podemos mutar o `count` diretamente pelo template, sem a necessidade do `setCount`, usamos apenas para fins didáticos.
97 |
98 | ## VueUse
99 |
100 | Recentemente atuailizado para uma versão compatível com o Vue 3.x, temos uma gama de hook's já prontos para utilizar em nosso projeto com o [VueUse](https://github.com/antfu/vueuse)
101 |
102 | ```ts
103 | import { useMouse } from '@vueuse/core';
104 |
105 | const { x, y } = useMouse(); // posição do cursor
106 | ```
107 |
108 | * Recomendamos fortemente que dê uma olhada nesta lib, pois possui muitos recursos comuns e que podem te "salvar" em um futuro projeto.
109 |
110 | [Próxima Seção](./4%20-%20Suspense.md)
111 |
--------------------------------------------------------------------------------
/docs/tutorial/5-Vuex/3-State.md:
--------------------------------------------------------------------------------
1 | # States
2 |
3 | Agora, vamos implementar o objeto **usuario**, para conseguirmos ter todos os dados sem precisar requisitar novamente a **API**.
4 |
5 | Primeiramente, vamos criar em nosso estado:
6 |
7 | ```ts
8 | import Vue from 'vue';
9 | import Vuex from 'vuex';
10 |
11 | Vue.use(Vuex);
12 |
13 | export default new Vuex.Store({
14 | state: {
15 | usuario: {
16 | conta: '',
17 | senha: '',
18 | },
19 | },
20 | mutations: {
21 | },
22 | actions: {
23 | },
24 | modules: {
25 | },
26 | });
27 | ```
28 |
29 | * O estado do **Vuex** é criado **junto** com o que será montado na instância, no nosso caso **App.js**, então é possivel requisitar o localStorage diretamente, por exemplo:
30 |
31 | ```ts
32 | import Vue from 'vue';
33 | import Vuex from 'vuex';
34 |
35 | Vue.use(Vuex);
36 |
37 | export default new Vuex.Store({
38 | state: {
39 | autenticado: localStorage.getItem('AUTENTICADO') || '',
40 | },
41 | });
42 | ```
43 |
44 | ## mapState
45 |
46 | Para conseguirmos acessar no template, iremos utilizar o **mapState**:
47 |
48 | ```ts
49 | import { mapState } from 'vuex';
50 |
51 | export default {
52 | // ...
53 | computed: {
54 | ...mapState(['usuario']);
55 | },
56 | };
57 | ```
58 |
59 | * Estamos desconstruindo para conseguirmos utilizar outros conteúdos na nossa **computed**
60 |
61 | * o **mapState** precisa ficar na **computed** para que quando o valor que está no **store** for mudado, o **mapState** consiga escutar a alteração e exibir em tempo real no template.
62 |
63 | ## Aplicando no Projeto
64 |
65 | Em nossa aplicação, iremos retirar o nosso localStorage com os dados do usuário e substituir para o nosso usuário do estado:
66 |
67 | `./src/pages/Login.vue`
68 |
69 | ```ts
70 |
88 | ```
89 |
90 | `./src/pages/Dashboard.vue`
91 |
92 | ```ts
93 |
94 |
95 | Olá {{ usuario.conta }}!
96 | Drawer
97 |
98 |
99 |
100 |
150 | ```
151 |
152 | * Vamos exibir agora no template pelo `usuario.conta` e não por `conta`
153 |
154 | Podemos buscar outros conteúdos que estão no estado, por exemplo:
155 |
156 | ```ts
157 | computed: {
158 | ...mapState([
159 | 'a'
160 | 'b',
161 | 'c',
162 | ]),
163 | },
164 | ```
165 | Na próxima seção iremos implementar o **dispatch** no Login, nos vemos lá!
166 |
167 | [Próxima Seção](./4-Actions.md)
168 |
169 |
170 |
--------------------------------------------------------------------------------
/docs/tutorial/7-Testes e Storybook/1-Jest no Vue.md:
--------------------------------------------------------------------------------
1 | # Jest no Vue
2 |
3 | O Vue-Tests-Utils é uma coleção de ferramentas do **Vue** para **testes**.
4 |
5 | Ele possui disponível os seguintes comandos:
6 |
7 | ```bash
8 | # unit testing
9 | vue add @vue/unit-jest
10 |
11 | # or:
12 | vue add @vue/unit-mocha
13 |
14 | # end-to-end
15 | vue add @vue/e2e-cypress
16 |
17 | # or:
18 | vue add @vue/e2e-nightwatch
19 | ```
20 |
21 | ## Jest
22 |
23 | O [Jest](https://jestjs.io/pt-BR/) é um poderoso Framework de Testes em JavaScript com um foco na simplicidade. Pelo VueCLI o **Jest** já vem configurado, assim sendo temos que apenas escrever os testes!
24 |
25 | ## Adicionando no Projeto
26 |
27 | Vamos utilizar o comando:
28 |
29 | `vue add @vue/unit-jest`
30 |
31 | Os arquivos gerados são:
32 |
33 | `jest.config.js`
34 |
35 | É na onde está o nosso preset do **JestVue**
36 |
37 | `./tests`
38 |
39 | É a onde ficará nossos testes do **Jest**
40 |
41 | `./tests/unit/example.spec.js`
42 |
43 | Todo arquivo de teste possui **spec.js**, para o **Jest** entender quais são os arquivos de **testes**.
44 |
45 | ```ts
46 | import { shallowMount } from '@vue/test-utils';
47 | import HelloWorld from '@/components/HelloWorld.vue';
48 |
49 | describe('HelloWorld.vue', () => {
50 | it('renders props.msg when passed', () => {
51 | const msg = 'new message';
52 | const wrapper = shallowMount(HelloWorld, {
53 | propsData: { msg },
54 | });
55 | expect(wrapper.text()).toMatch(msg);
56 | });
57 | });
58 | ```
59 |
60 | Esse teste gerado é o **default**, no caso ele **monta** o componente que deletamos no ínicio do nosso projeto, o *HelloWorld**, passa uma **propriedade** por padrão, no caso **msg**, e **espera**(expect) encontrar esse texto no **componente**.
61 |
62 | * No nosso curso, iremos apenas mostrar como realizar testes no **Vue**, e não todo o **conceito** envolvido.Se quiser ler mais sobre, clique [aqui](https://medium.com/trainingcenter/uma-vis%C3%A3o-geral-de-testes-em-javascript-em-2018-8484154caf63).
63 |
64 | ## Criando testes
65 |
66 | Primeiramente vamos renomear nosso arquivo para `Home.spec.js` e substituir seu conteúdo para:
67 |
68 | ```ts
69 | import Vue from 'vue';
70 | import Vuetify from 'vuetify';
71 | import { shallowMount, createLocalVue } from '@vue/test-utils';
72 | import Home from '@/pages/Home.vue';
73 |
74 | Vue.use(Vuetify); // Dessa forma, o nosso localVue irá conter o Vuetify
75 |
76 | describe('Home', () => {
77 | const localVue = createLocalVue();
78 |
79 | const wrapper = shallowMount(Home, {
80 | localVue,
81 | });
82 |
83 | it('home existe', () => {
84 | expect(wrapper.isVueInstance()).toBe(true);
85 | });
86 | });
87 | ```
88 |
89 | * Para rodar os testes, utiliza o comando `yarn test:unit`
90 |
91 | * Criando o localVue podemos anexar as outras bibliotecas de nossa aplicação nos testes.
92 |
93 | * Nesse caso, temos um teste simples se o componente é uma instância **Vue**.
94 |
95 | * Sempre que o seu componente tiver bibliotecas externas, (Vue i18n, por exemplo), pesquise sobre como realizer os **mocks**.
96 |
97 | * Você támbem pode fazer um **setup.js** com as configurações dos **testes**.
98 |
99 | * É possível procurar as classes **css** com o **jest**, não dependendo do nome do **componente**.
100 |
101 | Vamos fazer outros testes agora, um pouco mais elaborados:
102 |
103 | ## Header pertence ao componente
104 |
105 | ```ts
106 | it('header.vue está no componente', () => {
107 | expect(wrapper.find('.header-stub').exists());
108 | });
109 | ```
110 |
111 | * Todo componente que está dentro de outro nos testes **sem ser montado** possui o final **-stub**.
112 |
113 | * Nesse teste, estamos apenas verificando se o **Header** é um componente de **Home**
114 |
115 | ## Texto do Vue4Noobs
116 |
117 | ```ts
118 | it('Vue4Noobs está sendo exibido', () => {
119 | const noobs = wrapper.find('p').text();
120 | expect(noobs).toBe('Vue4Noobs');
121 | });
122 | ```
123 |
124 | * Estamos esperando que o conteúdo da tag **p** seja **Vue4Noobs**.
125 |
126 | Na próxima seção, iremos mostrar como utilizar o **Cypress** no **Vue**, nos vemos lá!
127 |
128 | [Próxima Seção](./2-Cypress%20no%20Vue.md)
129 |
130 |
--------------------------------------------------------------------------------
/docs/tutorial/4-Vue Router/4-Guardas de Rota.md:
--------------------------------------------------------------------------------
1 | # Guardas de Rota
2 |
3 | O guarda de rota irá verificar alguma condição quando alguem entrar ou sair da rota, assim podemos garantir a segurança destas.
4 |
5 | ## Guardas Globais
6 |
7 | Primeiramente, vamos setar uma nova chave no localStorage:
8 |
9 | `./src/pages/Login.vue`
10 |
11 | ```ts
12 |
34 | ```
35 |
36 | Adicionando o **AUTENTICADO**, podemos usá-lo para verificação.
37 |
38 | Agora vamos utilizar o **beforeEnter** nas **rotas** para fazer uma verificação **ANTES** do usuário poder acessar a rota, ou seja, antes do **created()** ser executado.
39 |
40 | O **beforeRouter** e **afterRouter** possuem três parâmetros por padrão: to, from e next. to e from são as referência da rota de onde está vindo(from) e para onde está indo(to). o **next** é a condição se o redirecionamento da rota continuará ou não.
41 |
42 | `./src/routes.js`
43 |
44 | ```ts
45 | import Home from './pages/Home.vue';
46 | import Login from './pages/Login.vue';
47 | import Dashboard from './pages/Dashboard.vue';
48 |
49 | import DashboardHome from './components/dashboard/DashboardHome.vue';
50 |
51 | export default [
52 | {
53 | path: '/dashboard',
54 | component: Dashboard,
55 | beforeEnter: (to, from, next) => {
56 | if (localStorage.getItem('AUTENTICADO')) {
57 | next();
58 | } else {
59 | next({
60 | path: '/',
61 | });
62 | }
63 | },
64 | children: [
65 | { path: '/', component: DashboardHome },
66 | ],
67 | },
68 | ];
69 | ```
70 |
71 | Dessa forma, se acessarmos sem estar com autenticado, iremos ser redireciados **ANTES** de entrar na rota, evitando problemas.
72 |
73 | * Essa é uma forma simples, o correto seria armazenar o booleano em um gerenciador de estado(Vuex) e verificar a entrada e saida de todas as rotas, vamos falar um pouco sobre quando chegarmos nas seções do Vuex.
74 |
75 | ## VueRouter Multiguard
76 |
77 | Também podemos criar grupos de autenticação:
78 |
79 | Adicionamos um novo package: `yarn add vue-router-multiguard`
80 |
81 | E aplicamos no router:
82 |
83 | ```ts
84 | import multiguard from 'vue-router-multiguard';
85 |
86 | import Home from './pages/Home.vue';
87 | import Login from './pages/Login.vue';
88 | import Dashboard from './pages/Dashboard.vue';
89 |
90 | import DashboardHome from './components/dashboard/DashboardHome.vue';
91 |
92 | const logado = (to, from, next) => {
93 | if (localStorage.getItem('AUTENTICADO')) {
94 | next();
95 | } else {
96 | next({
97 | path: '/',
98 | });
99 | }
100 | };
101 |
102 | const deslogado = (to, from, next) => {
103 | if (!localStorage.getItem('AUTENTICADO')) {
104 | next();
105 | } else {
106 | next({
107 | path: '/dashboard',
108 | });
109 | }
110 | };
111 |
112 | export default [
113 | {
114 | path: '/login',
115 | component: Login,
116 | beforeEnter: multiguard([deslogado]),
117 | },
118 | {
119 | path: '/dashboard',
120 | component: Dashboard,
121 | beforeEnter: multiguard([logado]),
122 | children: [
123 | { path: '/', component: DashboardHome },
124 | ],
125 | },
126 | ];
127 | ```
128 |
129 | * Adicionamos o **deslogado**, pois dessa forma o usuário que já esta na aplicação não consigo acessar o login novamente.
130 |
131 | * Futuramente iremos implementar a mesma lógica no **Header** para não exibir as opções de **entrar** e **registrar**, e sim para ir no **dashboard**.
132 |
133 | Dessa forma podemos fazer vários tipos e reaproveitar verificações.
134 |
135 | Na próxima seção iremos explicar um pouco sobre transições em rotas, estaremos te esperando!
136 |
137 | [Próxima Seção](./5-Transições%20no%20VueRouter.md)
138 |
--------------------------------------------------------------------------------
/docs/tutorial/8 - Ecossistema Vue/4 - VueElectron.md:
--------------------------------------------------------------------------------
1 | # Vue-Electron Boilerplate
2 |
3 | O [VueElectron](https://github.com/SimulatedGREG/electron-vue) é um boilerplate configurado para utilizar o **Vue** junto com o [Electron](https://www.electronjs.org/).
4 |
5 | ## Instalação
6 |
7 | ```bash
8 | yarn global add vue-cli
9 | vue init simulatedgreg/electron-vue seu-projeto
10 | ```
11 |
12 | * Até a data quando essa seção foi feita(10/04/2020), o **Vuex** ainda não está funcionando em conjunto com o **VueElectron**.
13 |
14 | * Recomendamos que estude sobre o **Electron** para o maior aproveitamento da plataforma.
15 |
16 | ## vue-cli-electron-builder
17 |
18 | O Boilerplate acima está desatualizado e não é mais mantido, então recomendamos utilizar o [VueCli](https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/) para usar o electron.
19 |
20 | A sua utilização é bem simples, em um projeto já existênte execute o comando:
21 |
22 | `vue add electron-builder`
23 |
24 | Dessa forma, já ira ser criado o `background.js` que é o ponto de criação da interface inicial do electron
25 |
26 | * Podemos utilizar qualquer plugin externo como **vue-router**, **vuex**, **vuetify** e outros normalmente, diferente do boilerplate mostrado anteriormente.
27 |
28 | * Para utilizar os renders em conjunto com a instância vue, recomendamos que olhe a [documentação](https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/configuration.html#webpack-configuration) para a sua implementação.
29 |
30 | * O [Electron](https://www.electronjs.org/) por mais que seja sem dúvidas uma das tecnologias desktop de mais fácil implementação(se for comparado com as opções do C++) ainda sim exige um estudo a parte, a sua documentação é bem completa e possui diversos exemplos para seus recursos.
31 |
32 | O electron-builder já vem com algumas definições de reconhecimento de sistemas e de privilégios, mas o que recomendamos dar uma olhada a fundo é nisso daqui:
33 |
34 | ```ts
35 | function createWindow() {
36 | win = new BrowserWindow({
37 | width: 800,
38 | height: 600,
39 | webPreferences: {
40 | nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION
41 | }
42 | })
43 |
44 | if (process.env.WEBPACK_DEV_SERVER_URL) {
45 |
46 | win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
47 | if (!process.env.IS_TEST) win.webContents.openDevTools()
48 | } else {
49 | createProtocol('app')
50 |
51 | win.loadURL('app://./index.html')
52 | }
53 |
54 | win.on('closed', () => {
55 | win = null
56 | })
57 | }
58 | ```
59 |
60 | O `win` será a nossa janela inicial, onde **BrowserWindow** é um componente do electron, e dentro das opções definimos a altura, largura e preferências da janela(no caso, a integração com o node para conseguirmos usar recursos internos, como o fs por exemplo).
61 |
62 | * As opções adicionais do BrowserWindow estão disponíveis [aqui](https://www.electronjs.org/docs/api/browser-window).
63 |
64 | A condição seguinte é relacionada ao modo desenvolvedor(ou não), carregando a URL de nosso html base que está em `./public/index.html`.
65 |
66 | * Podemos chamar o electron normalmente dentro do `` dos componentes do Vue e utilizar com os métodos, computed's normalmente, exemplo:
67 |
68 | ```ts
69 | ...
70 |
25 | ```
26 |
27 | * Os **hooks** tem o funcionamento parecido com um **método**.
28 |
29 | ## Created
30 |
31 | No hook criado, agora temos acesso aos dados reativos e os eventos. Os modelos e o DOM virtual **ainda** não foram montados ou renderizados.
32 |
33 | ```ts
34 |
47 | ```
48 |
49 | ## Mount
50 |
51 | Hooks de montagem são geralmente os ganchos mais usados(não necessariamente da forma correta). Eles permitem que você acesse seu componente imediatamente antes e após a primeira renderização. No entanto, eles não são executados durante a renderização no servidor.
52 |
53 | O Mount é util quando precisa acessar ou modificar o **DOM** do seu componente **imediatamente** antes ou depois da renderização inicial.
54 |
55 | POR FAVOR(Sério mesmo): Se você precisa buscar alguns dados para o seu componente na inicialização utilize o **created** para isso, especialmente se você precisar desses dados durante a renderização no servidor(por exemplo, exibir dados em um dashboard).
56 |
57 | A diferença do **beforeMount** e **mounted** é que temos acesso total ao elemento nativo(new Vue()), sendo **mounted** o hook mais utilizado, geralmente usado para motificar o **DOM**.
58 |
59 | ```ts
60 |
70 | ```
71 |
72 | ## Re-render com UpdateHook
73 |
74 | Os ganchos de atualização são chamados sempre que uma propriedade **reativa** usada por seu componente é **alterada**, ou qualquer outra coisa faz com que seja renderizada novamente. Dessa forma conseguimos trabalhar ao ciclo de **computer-render** do seu componente.
75 |
76 | ```ts
77 |
96 | ```
97 |
98 | ## Destroy
99 |
100 | Quando você alcança o gancho destruído, vai restar pouca coisa em seu componente. Tudo o que foi anexado a ela já foi destruído, mas você pode usar o gancho destruído para fazer alguma limpeza necessária.
101 |
102 | ```ts
103 |
110 | ```
111 |
112 | ## Outros Hook's
113 |
114 | Existem outros dois ganchos: **activated** e **deactivated**. Estes são para componentes keep-alive, que será abordado futuramente em nosso paper.
115 |
116 | Na próxima seção iremos abordar sobre o **BusEvent**, uma forma para conseguirmos transitar dados de componentes filhos mantendo a persistência dos dados, nos vemos lá!
117 |
118 | [Próxima Seção](./7-BusEvent.md)
119 |
--------------------------------------------------------------------------------
/docs/tutorial/2-Conceitos/3-Computed e Watch.md:
--------------------------------------------------------------------------------
1 | # Computed
2 |
3 | As **expressões** no template são muito convenientes, mas são destinadas a operações simples. Colocar muita lógica em seus modelos pode torná-los inchados e difíceis de manter. Por exemplo:
4 |
5 | ```html
6 |
7 | {{ message.toLowerCase().split('').reverse().join('') }}
8 |
9 | ```
10 |
11 | Neste ponto, o modelo **não** é mais simples e declarativo. Você precisa examiná-lo por um segundo antes de perceber que ele exibe a mensagem ao contrário. O problema é agravado quando você deseja incluir a mensagem invertida em seu modelo mais de uma vez.
12 |
13 | É por isso que, para qualquer lógica complexa, você deve usar uma **propriedade computada**(computed properties):
14 |
15 | ```ts
16 |
17 |
18 |
Mensagem inicial: "{{ hello }}"
19 |
Mensagem computada: "{{ helloInvertido }}"
20 |
21 |
22 |
23 |
24 |
38 | ```
39 |
40 | O **Vue** está ciente de que **vm.helloInvertido** depende de **vm.hello**, portanto, ele atualizará todas as ligações que dependem de **vm.helloInvertido** quando o **vm.hello** for alterado. E a melhor parte é que criamos esse relacionamento de dependência declarativamente: a função getter acaba não tem efeitos colaterais, o que facilita a compreensão.
41 |
42 | ---
43 |
44 | ## Computed x Methods
45 |
46 |
47 | Em vez de uma propriedade computada, podemos definir a mesma função no formato de um **method**. Para o resultado final, as duas abordagens são exatamente iguais. No entanto, a diferença é que as propriedades calculadas são armazenadas em cache com base em suas dependências reativas. Uma propriedade computada somente reavaliará quando algumas de suas dependências reativas forem alteradas.
48 |
49 | Isso significa que, enquanto a mensagem não tiver sido alterada, o acesso múltiplo à propriedade computada reversedMessage retornará imediatamente o resultado calculado anteriormente sem precisar executar a função novamente.
50 |
51 | ```html
52 |
53 |
54 |
55 |
56 |
57 |
71 | ```
72 |
73 | Também podemos usar **methods** dentro de **computeds** normalmente:
74 |
75 | ```html
76 |
77 |
78 |
82 | {{ validacao }}
83 |
84 |
85 |
86 |
87 |
109 | ```
110 |
111 | ---
112 |
113 | Podemos usar as **computeds** em conjunto com o **v-bind**, além de outras **diretivas**:
114 |
115 | ```html
116 |
117 |
118 |
119 |
120 |
121 |
172 | ```
173 |
174 | * Os **Watchers** são recomendados para usar quando a necessidade de utilizar código **assíncrono** e quando não há necessidade de **retorno**.
175 |
176 | Na próxima seção iremos abordar o funcionamento do **CSS** no **Vue**, te vemos lá!
177 |
178 | [Próxima Seção](./4-CSS.md)
--------------------------------------------------------------------------------
/docs/tutorial/9 - Next/1 - API.md:
--------------------------------------------------------------------------------
1 | # Vue 3
2 |
3 | O [Novo Vue](https://github.com/vuejs/vue-next) e mais conhecido como Vue 3.x vem com a proposta de agregar maior flexibilidade e utilidades gerais aos projetos Vue, sem mudar drasticamente o Vue.
4 |
5 | ## Iniciando no Vue com Vite
6 |
7 | Use `pnpm create vite my-vue-app --template vue`
8 |
9 | ### Construção da Instância
10 |
11 | O nosso querido `main.js` possui diferenças:
12 |
13 | ```ts
14 | import { createApp } from 'vue';
15 | import App from './App.vue';
16 |
17 | createApp(App).mount('#app');
18 | ```
19 |
20 | Agora utilizamos o `createApp` para criar a nossa instância, ao invés do `new Vue`
21 |
22 | Para acrescentar dependências, utilizamos:
23 |
24 | ```ts
25 | // Exemplo utilizando vuex e vue-router
26 | import { createApp } from "vue";
27 | import App from "./App.vue";
28 | import router from "./router";
29 | import store from "./store";
30 |
31 | const app = createApp(App);
32 |
33 | app.use(store);
34 | app.use(router);
35 |
36 | app.mount("#app");
37 | ```
38 |
39 | ## API de Composição
40 |
41 | A API de composição é um conjunto de funções aditivas que permite uma melhor utilização em componentes. Veio com a proposta de acrescentar a experiência principalmente em projetos grandes, que exige uma modularidade e flexibilidade dos componentes maior.
42 |
43 | A medida que os projetos de Vue 2.x vão aumentando, cada vez mais fica complicado de entender os grandes arquivos .vue do projeto, além da falta de formas de extrair a lógica entre vários componentes devido a limitação dos mixins.
44 |
45 | ### Estado Reativo
46 |
47 | ```html
48 |
49 |
52 |
53 |
54 |
63 | ```
64 |
65 | * Utilizamos o ref para criar uma referência do `text`, e retornamos o estado.
66 |
67 | * Diferente do Vue 2.x, não temos necessidade de utilizar o `this.**`.
68 |
69 | O setup recebe dois argumentos:
70 |
71 | ```ts
72 | setup(props, context) {
73 | console.log(props);
74 | console.log(context);
75 | }
76 | ```
77 |
78 | Podemos também formar grupos de objetos com o `reactive`(anterior no Vue 2.x como Vue.observable)
79 |
80 | ```html
81 |
93 | ```
94 |
95 | ### Computed
96 |
97 | ```html
98 |
99 |
102 |
103 |
104 |
115 | ```
116 |
117 | ### watch
118 |
119 | Mantendo a sintaxe parecido com o Vue 2.x, o primeiro parâmetro é o que será escutado e o segundo um callback com a execução da lógica, recebendo o novo valor como parâmetro do callback:
120 |
121 | ```html
122 |
148 | ```
149 |
150 | ### LifeCycleHooks
151 |
152 | Temos os mesmos life cycles, só que agora na API:
153 |
154 | ```ts
155 |
184 |
185 |
186 |
187 |
{{ error.statusCode }}
188 | Go back home
189 |
190 |
191 | ```
192 |
193 | * Se quiser se aprofundar na API, recomendamos a [documentação](https://composition-api.vuejs.org/#summary).
194 |
195 | Na próxima seção iremos mostrar algumas mudanças para utilizar as lib's no Vue 3.x
196 |
197 | [Próxima Seção](./2%20-%20Ecossistema.md)
198 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Tutorial De Vue para iniciantes em frameworks JavaScript.
121 |
--------------------------------------------------------------------------------
/docs/tutorial/3-Vuetify/1-Iniciando com Vuetify.md:
--------------------------------------------------------------------------------
1 | # O que e Vuetify
2 |
3 | [Vuetify](https://vuetifyjs.com/pt-BR/) é uma Biblioteca Vue UI com Material Components para a sua aplicação, tirando a necessidade de conhecimentos sobre UI.
4 |
5 | ## Instalação
6 |
7 | Lembra do começo do nosso curso que usamos o **Vue-CLI** para criar nosso projeto? Iremos utilizar novamente ele!
8 |
9 | Estando em um diretório para criar o projeto, execute o comando `vue ui` para iniciar a UI. Na outra vez fizemos por comando, agora quero te mostrar como fazer isso diretamente da UI.
10 |
11 | * Para adicionar uma biblioteca em um projeto existente, podemos usar o add: `vue add vuetify`
12 |
13 | Irá aparecer esta tela:
14 |
15 |
16 |
17 |
18 |
19 | Crie o projeto com o nome de sua **preferência** e clique em **Next**.
20 |
21 | Na próxima tela selecione a opção **Manual** e de **Next**.
22 |
23 |
24 |
25 |
26 |
27 | Vamos deixar selecionado o **Babel** e o **Linter** no momento e de **Next**.
28 |
29 | * No nosso tutorial, foi usado o preset do airbnb `@vue/eslint-config-airbnb`
30 |
31 | Na próxima tela, escolha as suas preferências de linter, e depois de **Next**.
32 |
33 | Após avançar, você terá a opção de **salvar seu preset**:
34 |
35 |
36 |
37 |
38 |
39 | Depois se salvar(ou não) seu preset, o vue começará a carregar as depedências (aka yarn install / npm run install).
40 |
41 |
42 |
43 |
44 |
45 | Após isso, teremos o **dashboard** principal do ui:
46 |
47 |
48 |
49 |
50 |
51 | ## Adicionando Vuetify
52 |
53 | Para conseguirmos adicionar o **Vuetify**, iremos em **Plugin**, e no canto superior direito em **Add Plugin**
54 |
55 |
56 |
57 |
58 |
59 | Procuramos por **Vuetify**, clicamos e depois em `Install vue-cli-plugin-vuetify`
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Escolha a opção padrão e espere instalar.
70 |
71 | Agora podemos executar o comando **yarn serve** em nosso projeto, e acesse o localhost que será exibido:
72 |
73 |
74 |
75 |
76 |
77 | ## Estrutura
78 |
79 | Vamos dar uma olhada no `./src/App.vue`. De início parece ser algo muito complicado mas entendendo o que cada componente está fazendo irá facilitar a compreensão:
80 |
81 | O nosso componente está envolvido com o container *v-app* e possui dois filhos:
82 |
83 | **v-app-bar** que é o nosso header que está na aplicação.
84 |
85 | **v-container** que está carregando o componente **HelloWorld**, que está centralizado no meio de nossa aplicação.
86 |
87 | ## Header
88 |
89 | Vamos pegar só o header para analizar:
90 |
91 | ```html
92 |
97 |
98 |
106 |
107 |
115 |
116 |
117 |
118 |
119 |
124 | Latest Release
125 | mdi-open-in-new
126 |
127 |
128 | ```
129 |
130 | Temos a **div** que junta tanto o **icon** quanto o nome do **Vuetify**, dessa forma estando ao lado **esquerdo** do header**.
131 |
132 | o **v-spacer** separa a nossa **div** e o **v-btn**, mantendo cada um de um lado diferente.
133 |
134 | o **v-btn** leva a página de últimos lançamentos do **Vuetify**, tendo em seu conteúdo o ícone e a descrição do **v-btn**.
135 |
136 | ## HelloWorld
137 |
138 | Não temos nada muito diferente do que já estamos acostumados, o funcionamento dos **v-row** e **v-col** é muito parecido com o display **grid** de nosso querido CSS, iremos também abordar sobre este sistema do **Vuetify** na próxima seção.
139 |
140 | * Recomendamos **>MUITO<** que explore a [documentação](https://vuetifyjs.com/pt-BR/getting-started/quick-start/) do **Vuetify**, pois ele possui uma gama muito vasta que pode resolver um problema específico seu.Felizmente muito conteúdo da documentação do **Vuetify** possui tradução para PT-BR!
141 |
142 | Nas próximas seções do **Vuetify**, iremos ensinar a como extrair o conteúdo dessa framework UI.
143 |
144 | [Próxima Seção](./2-Criando%20Componentes.md)
145 |
--------------------------------------------------------------------------------
/docs/tutorial/2-Conceitos/8-Transições.md:
--------------------------------------------------------------------------------
1 | # Transições
2 |
3 | As transições não servem apenas para adicionar um toque bonito ao seu aplicativo(juro). Uma boa transição pode ser a diferença entre um usuário se inscrever, fazer uma compra ou sair completamente do site.
4 |
5 | O Vue.js oferece várias maneiras de animar seu aplicativo, incluindo transições e animações CSS, e usando JavaScript para manipular o DOM durante ganchos de transição. Você pode até conectar-se a bibliotecas de terceiros, como [GSAP](https://greensock.com/gsap/) ou [VelocityJS](http://velocityjs.org/).
6 |
7 | Uma transição ocorre quando um elemento passa de A para B. Eles estão entre dois estágios: do **estado inicial** (A) ao **estado final** (B). Eles funcionam muito bem para coisas como passar o mouse sobre links e botões ou adicionar um novo item a uma lista. O principal objetivo das transições é criar uma demonstração natural de que algo mudou. Um bom **exemplo** de uma transição no mundo real seria **portas automáticas**. Eles **começam fechados** e quando você pisa na frente deles, eles **passam** automaticamente para o estado **aberto**.
8 |
9 | ## Elementos de Transição
10 |
11 | O **Vue** possui o elemento `` que facilita o manuseio de animações JavaScript, animações CSS e demais transições em seus elementos ou componentes.
12 | No caso de transições CSS, o elemento `` cuida da aplicação e da não aplicação de classes. Tudo o que você precisa fazer é definir a aparência do elemento durante a transição.
13 | Ele age como qualquer outro componente do Vue.js e você pode usar as mesmas diretivas como **v-if e **v-show**.
14 |
15 | Para isso, o **Vue** usa **classes de transição** padrões para facilitar(talvez nem tanto) o manuseio de todo o estado da transição.
16 |
17 | * Exemplo de uma transição simples que envolve a opacidade do elemento:
18 |
19 |
20 |
21 |
22 |
23 | O *-active é na onde definimos o **tempo de transição** da nossa transição, e nas pontas o **estado** que irá ocorrer no começo ou no fim.
24 |
25 | ## Transições CSS
26 |
27 | Iremos agora mostrar um exemplo na prática usando as **transições**:
28 |
29 | ```ts
30 |
31 |
32 |
33 |
34 |
Oiiiiiiiiiiiiiiiiiiiii
35 |
36 |
37 |
38 |
39 |
48 |
49 |
59 | ```
60 |
61 | * Podemos criar nossos próprios nomes para as transições, no caso atribuimos o name="opacity", assim o **vue-loader** irá pesquisar a tag `opacity-**` para carregar as classes na transição.
62 |
63 | * Como no nosso exemplo tanto a entrada quanto a saida possuem a mesma lógica, podemos economizar código juntando em um mesmo escopo.
64 |
65 | * Nesse caso, omitimos o estado inicial do componente, pois se não colocarmos o **Vue** considera o estado inicial dos atributos, no caso por padrão temos a opacidade em 1.
66 |
67 | ## Animações
68 |
69 | Assim como as transições, podemos usar **animações** de uma forma parecido em nossos componentes **transition**:
70 |
71 | ```ts
72 |
73 |
74 |
75 |
76 |
Oiiiiiiiiiiiiiiiiiiiii
77 |
78 |
79 |
80 |
81 |
90 |
91 |
109 | ```
110 |
111 | ## Out-in
112 |
113 | Utilizando o **Out-in**, podemos **esperar** a transição de um componente, assim evitando **mutações** inesperadas(na verdade, esperadas) no template:
114 |
115 | ```ts
116 |
117 | ...
118 |
119 | ```
120 |
121 | ## Transições entre componentes
122 |
123 | ```ts
124 |
125 |
126 |
127 | ```
128 |
129 | * O **component** irá buscar o nome **componente** nos componentes que estão registrados na instância.
130 |
131 | ## Transição em grupos
132 |
133 | Quando temos mais de um elemento dentro de um **transition**(no caso mais que 1 elemento filho na transição), temos que usar o **transition-group**:
134 |
135 | ```ts
136 |
137 |
138 | {{ item }}
139 |
140 |
141 | ```
142 |
143 | * No caso **item** irá assumir a tag **p** passada no **transition-group**.
144 |
145 | ## Move
146 |
147 | Usando o **move** é aplicado diretamente um evento de transição a uma lista que possui elementos sendo alterados.
148 | ```css
149 | .classe-move {
150 | transition: transform 1s;
151 | }
152 | ```
153 |
154 | ## Transições em methods
155 |
156 | Podemos anexar transições em nosso template:
157 |
158 | ```ts
159 | @before-enter="beforeEnter"
160 | // ou
161 | v-on:before-enter="beforeEnter"
162 | methods: {
163 | beforeEnter(el) {
164 | el.style.opacity = 0
165 | el.style.height = 0
166 | }
167 | }
168 | ```
169 |
170 | Te esperamos na próxima seção, falaremos sobre o **Keep Alive** e como ele pode ser útil, nos vemos lá!
171 |
172 | [Próxima Seção](./9-Keep%20Alive.md)
--------------------------------------------------------------------------------
/docs/tutorial/6-Bibliotecas Adicionais/1-Vuelidate.md:
--------------------------------------------------------------------------------
1 | # Vuelidate
2 |
3 | **Vuelidate** é uma biblioteca para validação dos dados de entrada **v-model**
4 |
5 | Com ele, conseguimos fazer validação de formulários de uma forma intuitiva.
6 |
7 | ## Adicionando no Projeto
8 |
9 | `yarn add vuelidate`
10 |
11 | Agora utilizando o `Vue.use()` iremos registrar nossa **biblioteca**:
12 |
13 | `./src/main.js`
14 |
15 | ```ts
16 | import Vue from 'vue';
17 | import Vuelidate from 'vuelidate';
18 | import App from './App.vue';
19 | import vuetify from './plugins/vuetify';
20 | import router from './plugins/vuerouter';
21 | import store from './store';
22 |
23 | Vue.config.productionTip = false;
24 |
25 | Vue.use(Vuelidate);
26 |
27 | new Vue({
28 | vuetify,
29 | router,
30 | store,
31 | render: (h) => h(App),
32 | }).$mount('#app');
33 | ```
34 |
35 | * O **Vuelidate** não tem necessidade de registrar dentro da instância **Vue**, igual o **Vuetify**, **VueRouter** e **Vuex**.
36 |
37 | Antes de aplicar as validações no formulário de login, vamos fazer o formulário de registrar!
38 |
39 | ``./src/routes.js`
40 |
41 | ```ts
42 | import Register from './pages/Register.vue';
43 | // ...
44 | {
45 | path: '/register',
46 | component: Register,
47 | beforeEnter: multiguard([deslogado]),
48 | },
49 | // ...
50 | ```
51 |
52 | `./src/pages/Register.vue`
53 |
54 | ```ts
55 |
56 |
57 |
58 |
62 |
66 |
71 |
72 |
77 | Cadastre sua Conta!
78 |
79 |
80 |
81 |
88 |
95 |
102 |
103 |
104 |
105 | Já possui uma conta? Clique
106 |
107 |
110 | aqui
111 |
112 |
113 |
114 |
115 | Entrar
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
144 | ```
145 |
146 | Bem parecido com o nosso **Login**, agora vamos aplicar o **Vuelidate**
147 |
148 | ## Validators
149 |
150 | O **Vuelidate** trabalha com **validators**, ele irá **escutar** toda alteração no **v-model** e retornando **true** ou *false** dependendo do que estiver como **condição** nos **validators**
151 |
152 | Vamos fazer o nosso **validator** do **Register.vue**:
153 |
154 | ```ts
155 |
198 | ```
199 |
200 | * Importamos os **validators**.
201 |
202 | * Colocamos o tipo de validação.
203 |
204 | * Verificamos se o formulário é válido no **enviarFormulario()**.
205 |
206 | * Também podemos utilizar as validações em nosso template:
207 |
208 | ```html
209 |
210 |
Digite a senha!
211 |
212 | ```
213 |
214 | Recomendamos FORTEMENTE que olhe a documentação do [Vuelidate](https://vuelidate.js.org/#sub-form-submission).
215 |
216 | Na próxima seção iremos apresentar a forma de fazer **internacionalização** no **Vue**!
217 |
218 | [Próxima Seção](./2-Vuei18n.md)
219 |
--------------------------------------------------------------------------------
/docs/tutorial/2-Conceitos/2-Diretivas.md:
--------------------------------------------------------------------------------
1 | # Diretivas
2 |
3 | Todas as **diretivas** do vue possuem o **v-**, como por exemplo os já ensinados **v-bind** e **v-on**, e nesta seção iremos introduzar novas diretivas para ajudar o seu desenvolvimento.
4 |
5 | ## V-IF
6 |
7 | Ele possui um funcionamento bem simples: analiza a condição imposta ou variavel e em caso de **true** exibe no template, e em caso de **false** ele não exibe.
8 |
9 | Exemplo:
10 |
11 | ```html
12 |
13 |
14 |
1
15 |
2
16 |
3
17 |
18 |
19 |
20 |
29 | ```
30 |
31 | Neste caso o **v-if** está atribuindo ao estado **mostrar** a sua condição, e por **mostrar** ser um booleano verdade ele será exibido ao template, mas:
32 |
33 | ```html
34 |
35 |
36 |
1
37 |
2
38 |
3
39 |
40 |
41 |
42 |
51 | ```
52 |
53 | Nessa situação, todo o **section**, **INCLUINDO** os conteúdos filhos **NÃO** serão exibidos no DOM
54 |
55 | Por exemplo:
56 |
57 | ```html
58 |
59 |
60 |
1
61 |
2
62 |
3
63 |
64 |
65 |
66 |
75 | ```
76 |
77 | Apenas um item(p) está sendo atribuido a condição, então em caso de mudanças no estado de **mostrar** apenas **p** sofrerá mutação.
78 |
79 | ---
80 |
81 | Podemos encadear condições, parecido com a sintaxe de algumas linguagens como **C** e ao próprio **JavaScript**
82 |
83 | ```html
84 |
85 |
86 |
1
87 |
2
88 |
3
89 |
90 |
91 |
92 |
101 | ```
102 |
103 | Também temos o **v-else-if**, mas iremos mudar um pouco a estrutura do código para ter sentido:
104 |
105 | ```html
106 |
107 |
108 |
Carlos
109 |
João
110 |
José
111 |
112 |
113 |
114 |
123 | ```
124 |
125 | ---
126 |
127 | ## V-FOR
128 |
129 | O **v-for** não é nada mais nada menos que um **forEach**,ou seja, ele percorre um array inteiro que é atrelado podendo assim exibir os conteúdo no template.
130 |
131 | Vamos mostrar um exemplo simples explicando os detalhes:
132 |
133 | ```html
134 |
135 |
136 |
137 |
162 |
163 | * o que o **v-for** está fazendo é pegar a **lista**, definindo cada parte da lista como **item** e percorrendo ele do começo ao fim, com isso podemos exibir itens específicos dos Objects da nossa lista, no caso **item.nome**.
164 |
165 | * para conseguir utilizar o **v-for**, precisamos passar uma **chave** usando a diretiva **v-bind**, no caso estamos passando o **id** como chave em **:key="item.id"**.
166 |
167 | Podemos capturar o segundo argumento, assim passando como **key** diretamente:
168 |
169 | ```html
170 |
171 |
172 |
173 |
Nome do Usuário: {{ item.nome }}
174 |
175 |
176 |
177 | ```
178 |
179 | o **v-for** não altera a maioria das diretivas, podendo usar normalmente, por exemplo:
180 |
181 | ```html
182 |
183 |
184 |
185 |
Par
186 |
Ímpar
187 |
188 |
189 |
190 | ```
191 |
192 | ---
193 |
194 | ## V-MODEL
195 |
196 | O **v-model** é usado para setar mudanças em uma variavel de **input**, por exemplo:
197 |
198 | ```html
199 |
200 |
201 |
202 |
{{ input }}
203 |
204 |
205 |
206 |
215 | ```
216 |
217 | Desta forma podemos atrelar diretamente uma variável que receberá o valor de uma entrada de dados, podendo assim manipular essa variável de forma flexiva.
218 |
219 | * O funcionamento do **v-model** em **propriedades** tem a necessidade de emitir o evento de alteração de volta para o componente pai por meio do **$emit** do vue, se quiser saber como fazer, clique [aqui](https://blog.oddeven.ch/blog/how-to-make-reusable-form-input-element-in-vue-js-2-6-and-vue-js-3-0/).
220 |
221 | * O **v-model** tem um funcionamento próprio para cada **type**, então recomendamos fortemente que olhe a [documentação](https://br.vuejs.org/v2/guide/forms.html) sobre o **v-model**.
222 |
223 | Na próxima seção, iremos falar sobre **computed properties** e **watchers**, mostrando como podem ser úteis durante o seu desenvolvimento, te esperamos lá! :)
224 |
225 | [Próxima Seção](./3-Computed%20e%20Watch.md)
226 |
--------------------------------------------------------------------------------
/docs/tutorial/2-Conceitos/1-Data, Methods e Modificadores.md:
--------------------------------------------------------------------------------
1 | # Data
2 |
3 | É o objeto de dados para a instância do Vue. O Vue converterá recursivamente suas propriedades em getters e setters para torná-lo "reativo". O objeto deve ser simples: objetos nativos, como objetos de API do navegador e propriedades de protótipo, são ignorados. Uma regra prática é que os dados devem ser apenas dados - não é recomendável observar objetos com seu próprio comportamento estável.
4 |
5 | Agora vamos declarar o **data**
6 |
7 | ```ts
8 |
17 | ```
18 |
19 | Dessa forma, declaramos **contador** de uma forma reativa, como fala na seção passado, se **contador** for passado para uma **propriedade** e o valor de **contador** mudar, o que está sendo exibido na **propriedade** também irar mudar.
20 |
21 | Precisamos retornar um objeto para o **data** para que cada instância possa manter uma cópia independente do objeto de dados retornado, assim mantendo a "reatividade".
22 |
23 | No **data** podemos declarar qualquer tipo de dado(objetos, arrays, etc...)
24 |
25 | ```ts
26 |
39 | ```
40 |
41 | A sintaxe do **Vue** em tudo que está dentro do **export default** é baseado nos [objetos literais](https://tableless.com.br/javascript-objetos-literais-vs-funcoes-construtoras/).
42 |
43 | ---
44 |
45 | Na seção de **props**, passamos a string de maneira estática, mas também podemos passar dados diretamente no template:
46 |
47 | ```html
48 |
49 |
50 |
51 |
61 | ```
62 |
63 | ---
64 |
65 | O **Vue** permite executar expressões JavaScript diretamente no template:
66 |
67 | ```html
68 |
{{ concluido ? 'SIM' : 'NÃO' }}
69 | ```
70 |
71 | * No caso **concluido** pertence ao **data()**.
72 | * Atribuições e controle de fluxo **NÃO** funcionam.
73 |
74 | ---
75 |
76 | Podemos também preencher o que temos no **data** com dados **assíncronos** usando [LifeCycleHooks](https://br.vuejs.org/v2/guide/instance.html#Diagrama-do-Ciclo-de-Vida), mas iremos abordar esse tema mais para a frente pois precisamos ver alguns outros conceitos do **Vue** primeiramente.
77 |
78 | ## Methods
79 |
80 | Métodos que vão juntar na instância do Vue. Você pode acessar esses métodos diretamente na instância do vue ou usá-los em expressões de diretiva. Todos os métodos terão esse contexto automaticamente vinculado à instância do Vue. O funcionamento de um **método** é basicamente ao de uma **função**, diferenciando de uma **computed** que será explicado na próxima seção.
81 |
82 | Agora, vamos fazer um **contador** mutando a nossa variavel declarada na instância, usando **methods**:
83 |
84 | ```ts
85 |
86 |
87 |
88 |
116 |
117 |
118 |
119 |
136 | ```
137 | Podemos também capturar o **event**, contendo todos os dados do emissor, ou seja, o evento do DOM nativo:
138 |
139 | ```ts
140 |
149 | ```
150 |
151 | ---
152 |
153 | Como dito na seção de fluxo e props, podemos exibir algo da instância diretamente no template.No methods podemos retornar valores para o template usando o **v-bind**.
154 |
155 | ```ts
156 |
157 |
158 |
159 |
160 |
169 | ```
170 |
171 | ## Modificadores
172 |
173 | Para acessar variáveis que estão na instância do **data**, precisamos usar o **this**, como está sendo usado no **this.contador++**.
174 |
175 | Usando o **v-on** podemos escutar eventos do DOM (parecido com o funcionamento do eventListener)
176 |
177 | O **Vue** disponibiliza **modificadores de eventos** para evitar a propagação:
178 |
179 | ```html
180 | .stop
181 | .prevent
182 | .capture
183 | .self
184 | .once
185 | .passive
186 | ```
187 |
188 | Por exemplo:
189 |
190 | ```html
191 |
192 | ```
193 |
194 | Dessa forma, o submit não irá carregar a página devido ao **prevent**
195 |
196 |
197 | Lembrando que a sintaxe sem o **()** também é valida:
198 |
199 | ```html
200 |
201 | ```
202 |
203 | Também podemos acessar modificadores de teclado, como por exemplo:
204 |
205 | ```html
206 |
207 | ```
208 |
209 | ```html
210 | .enter
211 | .tab
212 | .delete
213 | .esc
214 | .space
215 | .up
216 | .down
217 | .left
218 | .right
219 | ```
220 |
221 | ---
222 |
223 | Existe uma convensão de sintaxe para simplificar o **v-bind** e **v-on**
224 |
225 | **v-on** é substituido por **@**
226 | **v-bind** é simplificado apenas para **:**
227 |
228 | ```html
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
245 | ```
246 |
247 | Mais sobre modificadores [aqui](https://br.vuejs.org/v2/guide/events.html#Modificadores-de-Evento)
248 |
249 | ---
250 |
251 | Na próxima seção, iremos introduzir formas de manipular o que será renderizado no DOM Virtual com **v-if** e **v-for**, esperamos te ver la!
252 |
253 | [Próxima Seção](./2-Diretivas.md)
--------------------------------------------------------------------------------
/docs/tutorial/4-Vue Router/3-Rotas Filhas.md:
--------------------------------------------------------------------------------
1 | # Rotas Filhas
2 |
3 | Primeiramente, vamos criar a nossa rota `/dashboard` e sua rota **filha**:
4 |
5 | `./src/routes.js`
6 |
7 | ```ts
8 | import Home from './pages/Home.vue';
9 | import Login from './pages/Login.vue';
10 | import Dashboard from './pages/Dashboard.vue';
11 |
12 | import DashboardHome from './components/dashboard/DashboardHome.vue';
13 |
14 | export default [
15 | {
16 | path: '/login',
17 | component: Login,
18 | },
19 | {
20 | path: '/dashboard',
21 | component: Dashboard,
22 | children: [
23 | { path: '/', component: DashboardHome },
24 | ],
25 | },
26 | {
27 | path: '/',
28 | component: Home,
29 | },
30 | {
31 | path: '*',
32 | redirect: '/',
33 | },
34 | ];
35 | ```
36 |
37 | * Dessa forma, iremos ter outro **router-view**, só que esse dentro da view **dashboard**, dessa forma podermos alterar o conteúdo do dashboard mantendo o nosso **drawer**
38 |
39 | * Como apenas estamos indo para `/dashboard`, o '/' é considerado a rota filha padrão do componente `Dashboard.vue`
40 |
41 | Agora em `./pages/Dashboard.vue`
42 |
43 | ```ts
44 |
45 |
46 |
47 |
52 |
53 |
54 |
55 |
56 |
57 | Olá {{ conta }}!
58 | Drawer
59 |
60 |
61 |
62 |
63 |
64 |
70 |
71 | {{ item.icon }}
72 |
73 |
74 | {{ item.titulo }}
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
138 | ```
139 |
140 | Calma, respira fundo que iremos explicar o que está acontecendo:
141 |
142 | * O primeiro **v-col** indica o **drawer** de itens, esse que carrega os **items** que estão em nosso **data**.
143 |
144 | * Pela lista, estamos anexando nosso **href** para redirecionar para as rotas filhas.
145 |
146 | * Fizemos o mesmo método que usamos na landing para **redirecionar**, existe outras formas de mudar de rota como o **replace()**, e outras manipulações como o **back()**, mas focaremos apenas no **push()** para ficar simples.
147 |
148 | * Na outra coluna, estamos usando o **router-view** para exibir nossa rota **filha**.
149 |
150 | * no **mounted()** estamos buscando o nosso objeto no localStorage e exibindo na aplicação no **drawer**
151 |
152 | ## Rota Filha
153 |
154 | No caso, a rota filha terá o seguinte conteúdo:
155 |
156 | `./src/components/dashboard/DashboardHome.vue`
157 |
158 | ```ts
159 |
160 |
163 |
164 |
167 |
168 |
175 |
176 |
182 |
186 |
187 | {{ active ? 'mdi-heart' : 'mdi-heart-outline' }}
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
222 | ```
223 |
224 | * Estamos fazendo um ternário para exibir o ícone correto
225 |
226 | * Pegando o elemento da lista e **concatenando** para requisitar as **imagens**
227 |
228 | * o **@click="toogle"** está diretamente relacionado os v-model no **group-item**.
229 |
230 | E como resultado final, o nosso dashboard ficará assim:
231 |
232 |
233 |
234 |
235 |
236 | Na próxima seção iremos ensinar a como implementar um **Middleware**, nos vemos lá!
237 |
238 | [Próxima Seção](./4-Guardas%20de%20Rota.md)
--------------------------------------------------------------------------------
/docs/tutorial/1-Iniciando com Vue/4-Fluxo e Props.md:
--------------------------------------------------------------------------------
1 | # Fluxo e Props
2 |
3 | Agora vamos falar sobre o **App.vue** e a propriedade **HelloWorld.vue**:
4 |
5 | ```html
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
23 |
24 |
34 | ```
35 |
36 | ## Elemento Raiz
37 |
38 | Vamos começar pelo template, a **div** é necessaria pois o **template** pode ter apenas um item em sua raiz:
39 |
40 | Correto:
41 |
42 | ```html
43 |
44 |
45 |
57 |
58 | ```
59 |
60 | O **HelloWorld** é um componente que está sendo importado por outro componente **App.vue**, para isso, precisamos registrar o componente:
61 |
62 | ```html
63 |
72 | ```
73 |
74 | ## Convensões de Importanção
75 |
76 | * Curiosidade: O **Vue** reconhece tanto **PascalCase** quanto **kebab-case** e vice-versa, exemplo:
77 |
78 | ```html
79 |
80 |
81 |
82 |
83 |
92 | ```
93 |
94 | ## Nome do Componente
95 |
96 | O **name** significa o nome do componente que está sendo exportado, por padrão o **Vue** exporta o nome que está descrito na extensão do arquivo, neste caso, **App** seria exportado da mesma forma.
97 |
98 | ```ts
99 |
104 | ```
105 |
106 | ## Propriedades
107 |
108 | Agora vamos diretamente para o componente **HelloWorld.vue**:
109 |
110 | ```ts
111 |
112 |
113 |
{{ msg }}
114 |
115 | For a guide and recipes on how to configure / customize this project,
116 | check out the
117 | vue-cli documentation.
118 |
141 |
142 |
143 |
151 | ```
152 |
153 | Vamos desconsiderar as listas, pois possuem apenas a lógica padrão do **HTML**, vamos focar no que o **Vue** disponibiliza:
154 |
155 | ```ts
156 |
157 |
158 |
{{ msg }}
159 |
160 |
161 |
162 |
169 | ```
170 |
171 | Primeiramente, uma **propriedade** (props) está sendo exportada, e dentro deste objeto temos a declaração de uma prop com o nome **msg**, tendo o tipo **obrigatório** String.
172 |
173 | Dessa forma, podemos atribuir um conteúdo de um componente **pai** para o componente **filho**, assim seguindo o conceito de **componentização**.
174 |
175 | No caso de **App.vue**, estamos passando a **msg** com o tipo **String**.
176 |
177 | ```html
178 |
179 | ```
180 |
181 | Como obrigatoriamente indicamos que **msg** precisa ser uma **String**, se passarmos:
182 |
183 | ```html
184 |
185 | ```
186 |
187 | Irá gerar o erro, pois estamos passando um **Number**, e não uma **String**.
188 |
189 | * O **v-bind** pertence ao conceito de diretivas do **Vue**, o que estamos fazendo é ao **Vue** reconhecer o que passamos como um número e não como string, por exemplo:
190 |
191 | ```html
192 |
193 | ```
194 |
195 | Neste caso, estariamos passando um **Object**. Iremos futuramente no curso explicar o que são as diretivas, então não se preocupe :)
196 |
197 | * Podemos também passar para as **props** outras restrições, como **required**(boolean, se a prop será obrigatória ou não), **default**(podemos definir um valor setado em caso o componente pai não mande nenhum conteúdo da prop setada).
198 |
199 | ```ts
200 |
210 | ```
211 |
212 | Agora vamos falar sobre a **msg** sendo exibida no template
213 |
214 | ```ts
215 |
216 |
217 |
{{ msg }}
218 |
219 |
220 | ```
221 |
222 | ## Interpolação
223 |
224 | A forma de exibir conteúdo da exportação no template chamamos de **interpolação**, passando dois abre e fecha conchete para representar
225 |
226 | ```html
227 | {{ }}
228 | ```
229 |
230 | No **Vue**, conteúdos passados por **interpolação** já são reativos, ou seja, se no **componente-pai** a **msg** for alterada durante a execução do DOM, o que está sendo exibido no template, mesmo por meio de **propriedade**, irá ser automaticamente trocada pelo novo conteúdo.
231 |
232 | * Em caso de entrada de dados, este comportamente é diferente.
233 |
234 | Podemos também intercalar conteúdos **estáticos** sem nenhum problema
235 |
236 | ```ts
237 |
238 |
239 |
Hello {{ world }}
240 |
241 |
242 |
243 |
254 | ```
255 |
256 | Recomendados que dê uma olhada melhor sobre a sintaxe dos [templates](https://br.vuejs.org/v2/guide/syntax.html#Texto).
257 |
258 | Nos próximos capítulos, iremos introduzir conceitos do **Vue**, como **data**, **methods**, **computed** e **watch**, esperamos te ver lá :)
259 |
260 | [Próxima Seção](./5-Componentização.md)
261 |
--------------------------------------------------------------------------------
/docs/tutorial/2-Conceitos/13-SCSS-Avançado.md:
--------------------------------------------------------------------------------
1 | # SCSS Avançado
2 |
3 | Nessa seção vamos abordar alguns conceitos mais avançados do SCSS, como extend, placeHolders, module mode e arquitetura de pastas.
4 |
5 | ## Extend
6 |
7 | O extend é um recurso em que você replica o mesmo estilo de uma classe em outra.
8 |
9 | Mas qual a diferença entre o @mixin e o @extend?
10 |
11 | O mixin vai gerar uma copia daquele estilo em outro componente na hora da compilação.
12 | Já o extends gera uma referência para a classe original.
13 |
14 | > Mixin
15 |
16 | ```scss
17 | /// Mixin input
18 |
19 | @mixin placeHolder {
20 | display: -webkit-box;
21 | display: -ms-flexbox;
22 | display: -webkit-flex;
23 | display: flex;
24 | }
25 | .classe1 {
26 | @include placeholder;
27 | }
28 | .classe2 {
29 | @include placeholder;
30 | }
31 |
32 | /// Mixin output
33 | .classe1 {
34 | display: -webkit-box;
35 | display: -ms-flexbox;
36 | display: -webkit-flex;
37 | display: flex;
38 | }
39 | .classe2 {
40 | display: -webkit-box;
41 | display: -ms-flexbox;
42 | display: -webkit-flex;
43 | display: flex;
44 | }
45 | ```
46 |
47 | > Extend
48 |
49 | ```scss
50 | /// Extend input
51 | %placeHolder {
52 | display: -webkit-box;
53 | display: -ms-flexbox;
54 | display: -webkit-flex;
55 | display: flex;
56 | }
57 |
58 | .classe1 {
59 | @extend %placeHolder;
60 | }
61 |
62 | .classe2 {
63 | @extend %placeHolder;
64 | }
65 |
66 | /// Extend output
67 | .classe1,
68 | .classe2 {
69 | display: -webkit-box;
70 | display: -ms-flexbox;
71 | display: -webkit-flex;
72 | display: flex;
73 | }
74 | ```
75 |
76 | Apesar do @extend ser mais simples, ele é tão poderoso quanto @mixin. Mas isso pode causar alguns problemas.
77 |
78 | Como a classe `%placeHolder` é copiada para duas classes, elas são independentes e não se comportam como se fossem uma única classe.
79 | Dependendo do comportamento da classe, a classe pai pode não ser a classe original.
80 |
81 | ### Quando usar ou não o @extend?
82 |
83 | - Mixin: Utilize para gerar seu código de modo dinâmico através de variáveis;
84 | - Extend: Utilize para elementos comuns mas que haverá pouca repetição;
85 | - Quando for necessário criar algum tipo de automatização utilize o @mixin, caso contrario utilize o @extend, ou até mesmo os dois juntos.
86 |
87 | ## PlaceHolders
88 |
89 | PlaceHolders ou seletores fantasmas são como classes, porém, não são geradas no CSS final. Eles são utilizados para reutilizar propriedades de um seletor em outro.
90 |
91 | Para poder aplicar isso, precisamos utilizar o `@extend`:
92 |
93 | ```scss
94 | // _card.scss
95 |
96 | %default-border-style {
97 | border: 1px solid #ccc;
98 | border-radius: 5px;
99 | }
100 |
101 | .card {
102 | @extend %default-border-style;
103 | padding: 10px;
104 | background-color: #ccc;
105 | }
106 |
107 | .card__button {
108 | @extend %default-border-style;
109 | background-color: #ccc;
110 | }
111 | ```
112 |
113 | Os placeholders são muito úteis para reutilizar estilos no contexto do seu componente.
114 |
115 | ## Module Mode
116 |
117 | A uns anos atrás foi lançado um feature no scss que é chamado de scss modules basicamente ela permite que o seu estilo funcione como um modulo da aplicação assim liberando alguns recursos interessantes.
118 |
119 | Existem duas formas de se utilizar o sass module:
120 |
121 | `nome.module.scss` ou `_nome.scss`
122 |
123 | Nas duas formas você vai poder usufruir de todos os recursos do sass module.
124 |
125 | As novidades que vieram foi justamente o ***@use*** que permite que você importe um arquivo de estilo dentro de outro, para ser utilizado naquele contexto.
126 |
127 | ***@foward*** que permite que você importe um arquivo de estilo dentro de outro e que ele seja passado para frente na importação.
128 |
129 | ### Porque o *@import* é um problema ?
130 |
131 | Usando o ***@import*** no scss encontramos um problema, um arquivo que possui por exemplo `margin: 5rem;` no final pode ficar com `margin: 10rem;`, caso tenha alguma variável com o mesmo nome da qual alimenta aquela propriedade, visto que o ***@import*** na hora da compilação leva em consideração a ordem.
132 |
133 | EXAMPLE:
134 |
135 | ```scss
136 | @import "spacings"; // margin: 10rem;
137 | @import "variables";// margin: 5rem;
138 | @import "mixins";
139 | @import "colors";
140 |
141 |
142 | .container {
143 | margin: var(--margin); // essa margin vem do variables
144 | }
145 | ```
146 |
147 | Caso a gente altere a ordem de importação, na hora que ocorrer a compilação será alterado o valor.
148 |
149 | ```scss
150 | @import "variables";// margin: 5rem;
151 | @import "spacings"; // margin: 10rem;
152 | @import "mixins";
153 | @import "colors";
154 |
155 |
156 | .container {
157 | margin: var(--margin); // essa margin vem do spacings
158 | }
159 | ```
160 |
161 | O sass compila de forma procedural, ou seja, o valor da propriedade vai ser alterado de acordo com a última variável encontrada.
162 |
163 | ### O problema que o ***@use*** e ***@foward*** resolve
164 |
165 | #### @foward
166 |
167 | Ele é similar ao @import, você vai passar para frente oque estiver em um contexto, não haverá sobre escrita. O ***@foward*** levará somente estruturas não complexas. Funções, mixins e blocos condicionais não serão levados para frente.
168 |
169 | #### @use
170 |
171 | É utilizado no contexto e recebe um namespace, então se o meu arquivo se chama util tudo que eu utilizar ali será necessário passar o util como prefixo.
172 |
173 | EXAMPLE:
174 |
175 | ```scss
176 | @use "_util";
177 |
178 | .container {
179 | margin: util.$margin;
180 | }
181 | ```
182 |
183 | Caso não queria usar o namespace, esteja em processo de migração ou deseja utilizar outro nome porque o atual é grande, basta utilizar as e colocar um alias.
184 |
185 | ```scss
186 | @use "_util" as u; // o prefixo agora é `u`
187 | @use "_animations" as *; // não será necessário passar o namespace
188 | ```
189 |
190 | ## Arquitetura de projetos
191 |
192 | ### 7-1 Pattern
193 |
194 | *"One file to RULE them all.
195 |
196 | One file to FIND them.
197 |
198 | One file to BRING them all.
199 |
200 | And in the sass way MERGE them".*
201 |
202 | [Esse é o pattern mais utilizado](https://sass-guidelin.es/pt/#o-padro-7-1) para desfrutar do scss modules, ou seja, o scss modules é um modo de modularizar, cada arquivo é um componente, e cada componente é um modulo. A sua estrutura é a seguinte:
203 | abstracts, vendors, base, layout, components, pages e themes
204 |
205 | Existem vários patterns 4-1, 5-1 etc. Tudo vai depender da sua necessidade.
206 |
207 | ```zsh
208 | styles/
209 | |
210 | |– base/
211 | | |– _reset.scss # Reset/normalize
212 | | |– _color.scss # Paleta de cores da aplicação
213 | | |– _typography.scss # Typography rules
214 | | |– _index.scss # File used to import all base
215 | |
216 | |– layout/
217 | | |– _navigation.scss # Navigation
218 | | |– _grid.scss # Grid system
219 | | |– _header.scss # Header
220 | | |– _footer.scss # Footer
221 | | |– _sidebar.scss # Sidebar
222 | | |– _forms.scss # Forms
223 | |
224 | |– pages/ # Base views -> HOME, ABOUT, CONTACT etc.
225 | | |– _home.scss # Home specific styles
226 | | |– _contact.scss # Contact specific styles
227 | |
228 | |– themes/
229 | | |– _theme.scss # Default theme
230 | |
231 | |– abstract/
232 | | |– _variables.scss # Sass Variables
233 | | |– _functions.scss # Sass Functions
234 | | |– _mixins.scss # Sass Mixins
235 | | |– _index.scss # File used to import all abstracts
236 | |
237 | `– _index.scss # Main Sass file
238 | ```
239 |
240 | ## Próximos passos
241 |
242 | Sua jornada não termina aqui, agora é hora de você praticar e se aprofundar mais no assunto.
243 |
244 | > Recomendações de leitura:
245 |
246 | - [Sass Guidelines](https://sass-guidelin.es/pt/) by *community*
247 | - [SCSS como você nunca viu](https://dev.to/deverebor/scss-como-voce-nunca-viu-1d99) by *@deverebor*
248 | - [Sass Basics](https://sass-lang.com/guide) by *Sass*
249 |
250 | ---
251 |
252 | [Próxima Seção](./14-Considerações.md)
253 |
--------------------------------------------------------------------------------
/docs/tutorial/3-Vuetify/2-Criando Componentes.md:
--------------------------------------------------------------------------------
1 | # Componentes
2 |
3 | Nesta seção iremos explorar todo a vasta gama de componentes que o **Vuetify** nos disponibiliza.
4 |
5 | ## Projeto
6 |
7 | A partir desse ponto de nosso curso, iremos utilizar o que iremos fazer para as outras seções, apenas implementando mais conteúdo, então faça o conteúdo que iremos passar e fique livre para implementar conteúdos adicionais :)
8 |
9 | Não iremos disponibilizar o projeto por cada seção, apenas o projeto final, pois o intuito é que você faça. "Ah mas eu tive um problema", perfeito! Revise seu código e procure entender o **porquê** passou despercebido e os motivos de não ter funcionado. Entregar o projeto final pronto só vai enfatizar seus erros, que, em um momento em que você **não pode errar**(ou que pelo menos não deveria) poderá te atrapalhar.Você pode contar com a ajudar da [He4rt](http://discord.io/He4rt) sempre que quiser!
10 |
11 | Iremos fazer uma simples landing page de começo, posteriormente uma aplicação com login e dashboard.
12 |
13 | Durante todo o processo iremos utilizar o **Vuetify**, mas se preferir utilizar outra framework de CSS de seu agrado, fica á vontade também :)
14 |
15 | ## Landing Page
16 |
17 | Vamos fazer a landing page baseado em: Header - Main
18 |
19 | Tanto o **Header** quanto o **Footer** serão componentes reutilizáveis, enquanto o **Main** fará parte da view.
20 |
21 | Dessa forma, conseguimos reaproveitar componentes e modularizar nosso projeto.
22 |
23 | Para começar, vamos excluir todo o conteúdo inicial do **Vuetify** que está no nosso projeto:
24 |
25 | * Excluir o componente HelloWorld.vue
26 | * Vamos trocar o conteúde do App.vue para:
27 |
28 | ```html
29 |
30 |
31 |
Hello He4rt
32 |
33 |
34 |
35 |
43 | ```
44 |
45 | ## Header
46 |
47 | Primeiramente, vamos fazer o Header.
48 |
49 | Crie uma pasta em `./src/components/header/Header.vue`
50 |
51 |
52 |
53 |
54 |
55 | E importe em seu componente App.vue:
56 |
57 | ```html
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
79 | ```
80 |
81 | Para começar, vamos utilizar o **v-app-bar**:
82 |
83 | ```html
84 |
85 |
90 |
91 |
92 | ```
93 |
94 | * Setamos a cor da nossa bar com o **color**, segundamente o **accent-4** acentua a coloração da bar
95 |
96 | * Dense retira os paddings default do **v-app-bar**
97 |
98 | * Dark quer dizer o tema que estamos usando, e esse tema por padrão deixa as letras com cor **branca**, iremos ter uma seção apenas para customizações, então não se preocupe.
99 |
100 | Agora iremos acrescentar conteúdos:
101 |
102 | ```html
103 |
104 |
109 |
110 |
111 | He4rt Developers
112 |
113 |
114 | ```
115 |
116 | * O **app-bar-nav-icon** é o ícone sanduiche por padrão.
117 |
118 | * Estamos criando um **título** com o **v-toolbar-title** com o nome da **He4rt**
119 |
120 | Vamos agora setar uma lista de botões e espaçar para a **direita**
121 |
122 | ```html
123 |
124 |
129 |
130 |
131 | He4rt Developers
132 |
133 |
134 |
135 |
139 |
140 |
141 | mdi-dots-vertical
142 |
143 |
144 |
145 | {}"
149 | >
150 | {{ titulo }}
151 |
152 |
153 |
154 |
155 |
156 |
157 |
169 | ```
170 |
171 | * O template irá indicar para a lista quando ela deve exibir o conteudo.
172 |
173 | * Usamos a desconstrução para passar dados no **v-for**.
174 |
175 | * O **@click** irá ativar o estilo do nosso botão.
176 |
177 | * Para ativar a lista também é possivel usando o **v-if**, mas vamo seguir usando o padrão do **Vuetify**.
178 |
179 | * O **href** iremos utilizar para redireciar usando **rotas** futuramente.
180 |
181 | Dessa forma, nosso **Header** ficará assim:
182 |
183 |
184 |
185 |
186 |
187 | ## Main
188 |
189 | O nosso **main** será bem simples, com a logo da He4rt, descrição e botões:
190 |
191 | ```html
192 |
193 |
194 |
227 |
228 |
229 | ```
230 |
231 | * O **Vuetify** possui um sistema de classes [proprias](https://vuetifyjs.com/pt-BR/styles/flex/) para usar, recomendo **MUITO** que veja para melhor aproveitamento.
232 |
233 | * Podemos usar o **:src** para procurar diretamente uma imagem em nossa aplicação, no caso em `./assets`.
234 |
235 | * O **Vue** possui um sistema de caminho relativo usando o **@**, tendo o **@** começando da pasta **/src**
236 |
237 | * Para baixar a imagem do Vue clique [aqui](https://en.wikipedia.org/wiki/Vue.js#/media/File:Vue.js_Logo_2.svg).
238 |
239 | * Também podemos formatar [textos](https://vuetifyjs.com/pt-BR/styles/text/) e espaçar [itens](https://vuetifyjs.com/pt-BR/styles/spacing/) com o **Vuetify**.
240 |
241 | * Fizemos uma forma simples de centralização, mas recomendamos que dê uma olhada no [grid](https://vuetifyjs.com/pt-BR/components/grids/).
242 |
243 | * Fizemos a landing com a temática do curso, mas fique a vontade para customizar a landing page da forma que te agradar mais :)
244 |
245 | * O **Main** poderia virar um componente também.
246 |
247 | A cara final da nossa landing page:
248 |
249 |
250 |
251 |
252 |
253 | Na próxima seção iremos mostrar em como customizar opção do **Vuetify**, assim colocando definições para todos os componentes, te vemos lá!
254 |
255 | [Próxima Seção](./3-Customização.md)
--------------------------------------------------------------------------------
/docs/tutorial/4-Vue Router/2-Navegação.md:
--------------------------------------------------------------------------------
1 | # Navegação
2 |
3 | Agora, vamos criar uma rota para `'/login`, assim criando nosso formuário:
4 |
5 | `./src/routes.js`
6 |
7 | ```ts
8 | import Home from './pages/Home.vue';
9 | import Login from './pages/Login.vue';
10 |
11 | export default [
12 | {
13 | path: '/login',
14 | component: Login,
15 | },
16 | {
17 | path: '/',
18 | component: Home,
19 | },
20 | {
21 | path: '*',
22 | redirect: '/',
23 | },
24 | ];
25 | ```
26 |
27 | `./src/pages/Login.vue`
28 |
29 | ```html
30 |
31 |
44 |
45 | * As rotas **genéricas** sempre ficam na parte de baixo do array, pois a leitura é de cima para baixo.
46 |
47 | Agora vamos fazer nosso **container** do login:
48 |
49 | ```html
50 |
51 |
52 |
53 |
57 |
61 |
66 |
67 |
72 | Formulário de Login
73 |
74 |
75 |
76 |
81 |
86 |
87 |
88 |
89 | Não possui uma conta? Clique
90 |
91 |
94 | aqui
95 |
96 |
97 |
98 |
99 | Entrar
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
112 | ```
113 |
114 | * Como falamos até mesmo de forma redundante, leia a documentação do Vuetify, fará muita diferença!
115 |
116 | * Iremos utilizar o sistema de **grid** do **Vuetify** para centralizar nosso **container**
117 |
118 | Na descrição para **registrar**, implementamos com o **router-link** para redirecionar para a rota **/registrar**, como essa rota ainda não foi implementada ela irá redireciar para '/'.
119 |
120 | Vamos implementar o **v-model** para **escutar** os input's de dados em nosso formulário:
121 |
122 | `./src/pages/Login.vue`
123 |
124 | ```html
125 |
126 |
127 |
128 |
132 |
136 |
141 |
142 |
147 | Formulário de Login
148 |
149 |
150 |
151 |
157 |
163 |
164 |
165 |
166 | Não possui uma conta? Clique
167 |
168 |
171 | aqui
172 |
173 |
174 |
175 |
176 | Entrar
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
196 | ```
197 |
198 | * Estamos disponibilizando o código direto da estrutura visual para te mostrar novos recursos, por isso demos uma seção apenas para o Vuetify.
199 |
200 | Para submeter nosso formulário, iremos usar a diretiva **v-on** no **form**, pois futuramente iremos fazer a validação deste formulário em nosso projeto.
201 |
202 | `./src/pages/Login.vue`
203 |
204 | ```html
205 | Entrar
210 |
211 | ```
212 |
213 | ```html
214 |
237 | ```
238 |
239 | * Estamos mandando os dados para o localStorage e pegando eles posteriores (não é uma boa ideia mandar a senha para o localStorage sem hash, tá?).
240 |
241 | * Também podemos redirecionar rotas acessando o `this.$router`.
242 |
243 | Agora com a rota, já podemos implementar na nossa landing o redirecionamento para a rota:
244 |
245 | `./src/components/header/Header.vue`
246 |
247 | ```html
248 |
249 |
254 |
255 |
256 | He4rt Developers
257 |
258 |
259 |
260 |
264 |
265 |
266 | mdi-dots-vertical
267 |
268 |
269 |
270 |
271 |
276 | {{ titulo }}
277 |
278 |
279 |
280 |
281 |
282 |
283 |
300 | ```
301 |
302 | Na próxima seção iremos mostrar o funcionamento de rotas filhas, implementando inicialmente um protótipo de **dashboard**, te vemos lá!
303 |
304 | [Próxima Seção](./3-Rotas%20Filhas.md)
--------------------------------------------------------------------------------
/docs/tutorial/7-Testes e Storybook/4-Vitest.md:
--------------------------------------------------------------------------------
1 | # Vitest
2 |
3 | > A ferramenta de testes mais rápida!
4 |
5 | ## Antes de começar
6 |
7 | Assim como no jest para utilizarmos o Vitest precisamos instalar o VueTestUtils, uma ferramenta que nos ajuda por meio de helpers e funcionalidades a testar e montar nossos componentes.
8 |
9 | > pode ser utilizado yarn, npm ou pnpm
10 |
11 | ```bash
12 | npm i @vue/test-utils
13 | ```
14 |
15 | > apos a instalação do VueTestUtils, vamos instalar o Vitest
16 |
17 | ```bash
18 | npm i -D vitest
19 | ```
20 |
21 | ## Oque é o Vitest ?
22 |
23 | O Vitest é uma ferramenta de testes que utiliza o Vite como base, e por isso é muito mais rápida que o Jest, e também é muito mais simples de configurar.
24 |
25 | ## Configuração do Vitest
26 |
27 | Para rodar os testes é necessário adicionar o seguinte script no package.json:
28 |
29 | ```tson
30 | {
31 | "scripts": {
32 | "test": "vitest",
33 | "coverage": "vitest run --coverage"
34 | }
35 | }
36 | ```
37 |
38 | ## Como utilizar o Vitest ?
39 |
40 | Para criar um teste com o Vitest, basta criar um arquivo com a extensão .test.ts ou .spec.ts se o seu projeto é vue + typescript dentro da pasta de testes, e dentro do arquivo, basta importar o método test do Vitest e criar um teste.
41 |
42 | ```ts
43 | import { shallowMount } from "@vue/test-utils";
44 | import HelloWorld from "@/components/HelloWorld.vue";
45 | import { describe, it, expect } from "vitest";
46 |
47 | describe("HelloWorld.vue", () => {
48 | it("renders props.msg when passed", () => {
49 | const msg = "new message";
50 |
51 | const wrapper = shallowMount(HelloWorld, {
52 | propsData: { msg }
53 | });
54 |
55 | expect(wrapper.text()).toMatch(msg);
56 | });
57 | });
58 | ```
59 |
60 | Assim como no Jest o Vitest também possui o describe e o it, e também o expect, que é o que utilizamos para fazer as asserções.
61 |
62 | > O describe é utilizado para agrupar os testes, e o it é utilizado para criar um teste, e o expect é utilizado para fazer as asserções.
63 |
64 | Depois de criar o teste, basta rodar o comando:
65 |
66 | ```bash
67 | npm run test
68 | ```
69 |
70 | ## Testando componentes
71 |
72 | Depois de entender o básico do Vitest, vamos criar um teste para um componente, para isso vamos criar um componente chamado Button.vue dentro da pasta components, e vamos criar um teste para ele.
73 |
74 | Vamos criar um componente chamado Button.vue dentro da pasta components, e vamos criar um teste para ele.
75 |
76 | ```vue
77 |
78 |
79 |
82 | Count: {{ message }}
83 |
84 |
85 |
86 |
110 | ```
111 |
112 | Agora vamos criar um teste para esse componente, para isso vamos criar um arquivo chamado Button.test.ts dentro da pasta tests, e vamos criar um teste para ele.
113 |
114 | ```ts
115 | import Vue from "vue";
116 | import { shallowMount, Wrapper } from "@vue/test-utils";
117 |
118 | import { describe, it, expect } from "vitest";
119 | import Button from "@/components/Button.vue";
120 |
121 | interface IButton extends Vue {
122 | message: string;
123 | increment: () => void;
124 | }
125 |
126 | describe("Button.vue", () => {
127 | it("should render props.msg when passed", () => {
128 | const wrapper = shallowMount(Button, {
129 | propsData: {
130 | msg: "new message"
131 | }
132 | }) as Wrapper;
133 |
134 | expect(wrapper.find("button").text()).toMatch("Click me");
135 | });
136 |
137 | it("should increment count when button is clicked", async () => {
138 | const wrapper = shallowMount(Button);
139 |
140 | await wrapper.find("button").trigger("click");
141 |
142 | expect(wrapper.vm.message).toBe("Count: 1");
143 | });
144 | });
145 | ```
146 |
147 | Que teste grande não é ? Mas vamos entender o que está acontecendo.
148 |
149 | Primeiro vamos entender o que é o shallowMount, o shallowMount é utilizado para montar o componente, e ele recebe como parâmetro o componente que queremos montar, e também podemos passar o propsData, que é utilizado para passar os props para o componente.
150 |
151 | Depois de montar o componente, podemos utilizar o find para encontrar um elemento dentro do componente, e também podemos utilizar o trigger para disparar um evento, e também podemos utilizar o vm para acessar os dados do componente.
152 |
153 | ### Vamos entender mais afundo o que está acontecendo no teste
154 |
155 | > Porque fizemos uma interface para o componente ?
156 |
157 | Porque o componente não tem tipagem, e para que possamos acessar os dados do componente, precisamos tipar o componente, e para isso criamos uma interface para o componente.
158 |
159 | ```ts
160 | interface IButton extends Vue {
161 | message: string;
162 | increment: () => void;
163 | }
164 | ```
165 |
166 | Estendemos a interface do Vue para que o componente tenha acesso a todos os métodos e propriedades do Vue. E também criamos uma interface para o componente, e dentro dessa interface criamos as **`computeds`** e **`methods`** que existem no nosso componente.
167 |
168 | > shallowMount é utilizado para montar o componente ?
169 |
170 | Sim, o shallowMount é utilizado para montar o componente, e ele recebe como parâmetro o componente que queremos montar, e também podemos passar as props, mocks e tudo relacionado ao componente que estamos testando.
171 |
172 | ```ts
173 | const wrapper = shallowMount(Button, {
174 | propsData: {
175 | msg: "new message"
176 | }
177 | }) as Wrapper;
178 | ```
179 |
180 | Caso seu componente tenha contatos com Vuex ou Vuetify, você pode passar os mocks para o shallowMount, e assim você consegue testar o componente e suas dependências.
181 |
182 | ```ts
183 | import { createLocalVue, shallowMount, Wrapper } from "@vue/test-utils";
184 |
185 | const localVue = createLocalVue();
186 |
187 | localVue.use(Vuetify);
188 | localVue.use(Vuex);
189 |
190 | describe("Button.vue", () => {
191 | const wrapper = shallowMount(Button, {
192 | localVue,
193 | propsData: {
194 | msg: "new message"
195 | }
196 | }) as Wrapper;
197 |
198 | // Teste...
199 | });
200 | ```
201 |
202 | Dessa maneira, você consegue testar o componente com as dependências do vuex como chamadas na store, e também consegue testar o componente com o vuetify como os breaking points.
203 |
204 | > Como acessamos os dados do componente ?
205 |
206 | Para acessar os dados do componente, podemos utilizar o **`vm`**, e para ter acesso a todas as propriedades do componente, precisamos tipar o componente, e para isso criamos uma interface para o componente.
207 |
208 | ## Dando um passo além
209 |
210 | ### Testando renderização do componente utilizando data-testid
211 |
212 | Para testar a renderização do componente, podemos utilizar o **`data-testid`**, e para isso precisamos adicionar o **`data-testid`** no elemento que queremos testar.
213 |
214 | ```vue
215 |
216 |
217 |
220 | Count: {{ message }}
221 |
222 |
223 |
224 |
248 | ```
249 |
250 | Depois de adicionar o **`data-testid`** no elemento, podemos utilizar o **`find`** para encontrar o elemento, e também podemos utilizar o **`trigger`** para disparar um evento.
251 |
252 | ```ts
253 | import Vue from "vue";
254 |
255 | import { describe, it, expect } from "vitest";
256 | import { shallowMount, Wrapper } from "@vue/test-utils";
257 |
258 | import Button from "@/components/Button.vue";
259 |
260 | interface IButton extends Vue {
261 | message: string;
262 | increment: () => void;
263 | }
264 |
265 | const DATA_TEST_ID = {
266 | INCREMENT_COUNT_BUTTON: "[data-testid='increment-count-button']"
267 | };
268 |
269 | describe("Button.vue", () => {
270 | it("should render props.msg when passed", () => {
271 | const wrapper = shallowMount(Button, {
272 | propsData: {
273 | msg: "new message"
274 | }
275 | }) as Wrapper;
276 |
277 | expect(wrapper.find(DATA_TEST_ID.INCREMENT_COUNT_BUTTON).text()).toMatch(
278 | "Click me"
279 | );
280 | });
281 |
282 | it("should increment count when button is clicked", async () => {
283 | const wrapper = shallowMount(Button);
284 |
285 | await wrapper.find(DATA_TEST_ID.INCREMENT_COUNT_BUTTON).trigger("click");
286 |
287 | expect(wrapper.vm.message).toBe("Count: 1");
288 | });
289 | });
290 | ```
291 |
292 | Usando o data-testid, além de facilitar encontrar o elemento que você deseja testar, você também auxilia na criação de testes e2e(Cypress), pois você consegue identificar os elementos que você deseja testar.
293 |
--------------------------------------------------------------------------------