Skip to content

Instantly share code, notes, and snippets.

@reginadiana
Last active May 15, 2023 23:36
Show Gist options
  • Save reginadiana/738c30a4671027175e7cc40746bb0b8e to your computer and use it in GitHub Desktop.
Save reginadiana/738c30a4671027175e7cc40746bb0b8e to your computer and use it in GitHub Desktop.
Anotações sobre o framework VueJS

Patterns

Assim como todo framework que se preze, o Vue conta com um guia de boas práticas (também chamado de style guides) e eles são essenciais para aproveitar o melhor que ele tem a oferecer e entender porque certas decisões foram tomadas na sua construção, ainda que a própria documentação cite que elas podem ser adaptadas ao contexto do projeto de forma consciente.

O guia contém 4 partes, divididas em uma hierarquia de regras por ordem de importância, que também podem ser interpretadas por ordem de flexibilidade, já que quanto menos importantes, mais liberdade o desenvolvedor tem de segui-las, desde que ele tenha conhecimento do que está fazendo. São elas: essenciais, fortemente recomendadas, recomendadas, e as que podem até ser quebradas, mas com cautela.

Essenciais

São regras que evitam erros, então é muito importante que elas sejam seguidas.

Nomeando Componentes

Pode parecer demais, mas é uma boa prática nomear os componentes indicando onde ele está inserido. Por exemplo:

// Melhor não fazer isso
export default {
  name: "List"
}
// Prefira
export default {
  name: "MenuList"
}

Isso é necessário pois quando vamos usar um componente em <template> queremos evitar o conflito entre outras tags, e como uma lista é algo genérico, ela pode estar inserida em vários contextos.

Usando o atributo Data

Dentro de um componente, data é onde declaramos os dados globais para aquele componente, e mesmo que ele seja reutilizado, esses dados devem ser alterados conforme o contexto em que foram instanciados e não devem ter ligação alguma com outras instancias.

O que acontece, é que quando declaramos esse data como um objeto, ele é compartilhado em todas as instancias daquele componente, ou seja, os dados não são modificados apenas internamente no contexto em que foi chamado, mas sim por todas as outras instancias.

// Melhor não fazer isso
export default {
  data: {
    position: 0
  }
}

Por exemplo: em uma página nós temos um menu que controla qual imagem deve aparecer no carrossel, mas decidimos reaproveitar esse componente para criar outro carrossel. Usando o data como objeto, toda vez que mudarmos a posição pelo menu de um carrossel, o outro também mudará, pois esses dados estão sendo compartilhados.

O correto seria que ao manipular um menu, o outro não se altere apesar de ser o mesmo componente, pois o contexto é diferente:

// Podemos declarar assim
export default {
  data: function() {
    return {
      position: 0
    }
  }
}

// Ou assim, ambos são funções
export default {
  data() {
    return {
      position: 0
    }
  }
}

Recebendo props

Props são dados compartilhados entre componentes pais e filhos, e uma das coisas interessantes que o Vue nos trás é poder detalhar sobre quais props estão chegando, como uma especie de documentação mesmo. Por isso é recomendado que se defina pelo menos o seu tipo, assim o Vue emitirá um alerta indicando que o dado não chegou no formato correto. Exemplo:

// Melhor não fazer isso, pode vir qualquer coisa
export default {
  props: ['position']
}
// Prefira detalhar a props
  export default {
    props: {
      position: {
        type: String,
        required: true
        ...
      }
    }
  }

Para saber mais, acesse a sobre as props na documentação do Vue, lá eles falam sobre os tipos de dados que podem ser compartilhados, dados default, validações e outros.

Uso de keys em loops

Toda vez que for usar o v-for para renderizar o conteúdo de um objeto ou lista, sempre defina uma key para cada um dos elementos renderizados. Para saber mais sobre o porquê, recomendo o artigo do Marko Burazin - How & Why to use the :key attribute in VueJS v-for loop

<template>
  <div>
    <div v-for="(item, key) in list" :key="key">
      <h1>{{ item }}</h1>
    </div>
  </div>
</template>

Uso de v-if em loops

É muito comum estar diante de uma situação em que precisamos renderizar condicionalmente uma informação, como por exemplo:

  1. Mostrar apenas os filmes disponiveis em cartaz;

  2. Mostrar apenas os planos ativos de uma academia;

  3. Mostrar apenas os boletos pagos no sistema.

Diante desses cenários, ficamos tentados a usar o v-if junto com o v-for, porém isso é um problema pois toda vez que aquele componente for renderizado, será verificado para cada item da lista/objeto se ele safisfaz a condição.

Nesses casos, prefira usar dados computados (computed), pois sua responsabilidade é retornar um dado a partir de outros após algum tipo de tratamento. O "tratamento", neste caso, será o filtro, gerando beneficios como:

  • Toda vez que o componente for renderizado, não será necessário que todos os itens passem pelo if novamente.

  • O filtro só será feito se o conteúdo do objeto/lista mudar.

  • Podemos remover essa lógica do html.

<template>
  <div>
    <!-- Evite -->
    <div v-for="(movie, key) in releasedMovies" :key="key" v-if="movie.released">
      <h1>{ { movie.title } }</h1>
    </div>
  </div>
</template>
<template>
  <div>
    <!-- Prefira -->
    <div v-for="(movie, key) in releasedMovies" :key="key">
      <h1>{ { movie.title } }</h1>
    </div>
  </div>
</template>

<script>
  export default {
    computed: {
      releasedMovies() {
        return this.movies.filter(({ released }) => released)
      }
    }
  }
</script>

Estilos de um componente

Outro ponto sobre o Vue é sobre estilos isolados, chamados de scoped. Isso significa que é possível declarar estilos do zero para cada componente, sem serem sobrescritos pelos pais e sem sobrescrever os filhos.

Por isso, o nome das classes podem ser mais clean pois ao declarar uma mesma classe em 5 componentes usando scoped, nenhum estilo sofrerá conflito. Isso ajuda bastante na manutenção e refatoração do css pois os estilos são internos ao componente e não "vazam" para outros.

É claro que existem casos em que queremos aproveitar algum estilo padrão para botões, listas, etc, por isso, prefira ter arquivos isolados para esses estilos e importá-los nos seus componentes quando necessário.

<style lang="scss" scoped>
@import "../assets/button.scss"; // Reaproveitado os estilos desse arquivo
  .modal__title {
    color: pink; // Esse estilo e classe só serão usados nesse componente
  }
</style>

Organização das declarações em componentes

Dentro da tag <script>, usamos partes como data(), mounted(), props, dentre tantas outras que devem ser chamadas em uma ordem, a fim de manter a organização e padronização. São eles:

  1. el
  2. name
  3. parent
  4. functional
  5. delimiters
  6. comments
  7. components
  8. directives
  9. filters
  10. extends
  11. mixins
  12. inhiattrs
  13. model
  14. props
  15. data
  16. computed
  17. watch
  18. beforeCreate
  19. created
  20. beforeMounted
  21. mounted
  22. beforeUpdate
  23. updated
  24. activated
  25. deactivated
  26. beforeDestroy
  27. destroyed
  28. methods
  29. template/render
  30. renderError

Outros

A seguir apresento outros patterns/dicas de boas práticas que encontrei lendo artigos na internet ou assistindo palestras:

  1. Não use o index como key ao interar elementos que podem mudar a ordem. Ao invés disso, podemos usar o próprio id.

  2. Lifecycle hooks são métodos de ciclo de vida dos componentes mounted, updated, etc

VueJS

Primeiros Passos

Para começar, importamos o vue dentro da primeira tag <script>. Depois, iniciamos uma tag html com um id. Por fim, realizamos a instancia de Vue passando o id para o parametro el. Tudo isso pode ser feito sem a instalação de qualquer dependencia.

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<div id="app">
  <p>{{ message }}</p>
</div>

<script>
  new Vue({
    el: "#app",
    data: {
      message: 'Ola, mundo Vue'
    }
  })
</script>

Diretivas

Mostrando uma mensagem após o efeito de hover em um elemento

...

<div id="app" v-bind:title="message">
  <p>Passe por aqui para ver a mensagem</p>
</div>

<script>
  new Vue({
    el: "#app",
    data: {
      message: "Ola, mundo Vue",
    },
  });
</script>

Usando if

...

<div id="app" v-if="see">
  <p>Voce só pode ver isso se 'see' for true</p>
</div>

<script>
  new Vue({
    el: "#app",
    data: {
      see: true,
    },
  });
</script>

Usando loops

...

<div id="app">
  <ol>
    <li v-for="(item, key) in items" :key="key">{{ item.text }}</li>
  </ol>
</div>

<script>
  var app = new Vue({
    el: "#app",
    data: {
      items: [{ text: "primeiro" }, { text: "segundo" }, { text: "terceiro" }],
    },
  });
</script>

Ouvindo eventos (listening events)

  1. Neste próximo exemplo estamos usando um botão para ouvir o evento onClick pelo v-on:click. Também poderiamos usar o @dblclick para detectar o click duplo em um elemento.

  2. Quando esse evento acontecer, chamamos a função invert, pegamos a mensagem com this.message e a invertemos.

<div id="app">
  <p>{{ message }}</p>
  <button v-on:click="invert">Inverter string</button>
</div>

<script>
  new Vue({
    el: "#app",
    data: {
      message: "Ola, mundo Vue",
    },
    methods: {
      invert() {
        this.message = this.message.split("").reverse().join("");
      },
    },
  });
</script>

Escutando o valor de um elemento

Com v-model conseguimos escutar o valor de inputValue e atualizar o que aparece na tela dentro da tag p automaticamente.

...
<div id="app">
  <p>{{ inputValue }}</p>
  <input v-model="inputValue" />
</div>

<script>
  new Vue({
    el: "#app",
    data: {
      inputValue: "valor default",
    },
  });
</script>

Criando e executando a versão CLI do VUE

Instale o VUE na sua máquina de acordo com a documentação

Depois, crie o projeto com:

vue create <nome-do-projeto>

Em seguida, o VUE vai te perguntar algumas coisas para configurar e instalar as dependencias do projeto. Depois disso, entre na pasta e execute:

cd <nome-do-projeto> && yarn server

Usando o watch (equivalente ao onChange do React)

<textarea v-model="comment" id="comment"/>
    
watch: {
  // sempre que o comentário mudar, essa função será executada
  comment: function () {
    console.log(this.comment)
  }
},

Estrutura do Vue

Uma das particularidades do Vue é que os componentes de arquivo único possuem 3 partes (html, js e css), para muitos isso pode parecer um problema, já que aparentemente teremos muitas responsabilidades, porém, eles foram desenvolvidos assim a fim de mantê-los mais fáceis de realizar manutenção, já que todo o script e estilo são acoplados naquele componente.

Outro ponto importante, é que essa estrutura nos estimula a criar componentes menores por estarem todos juntos.

Para saber mais, recomendo a própria documentação que fala sobre separação de responsabilidades e o artigo Descomplicando os Single File Components do Vue.js, por Emanuel G de Souza

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment