Para facilitar a compreensão, dividi o setup em várias seções distintas:
<script setup>
// 1. Importação de dependências necessárias, como ref, reactive, etc.
// 2. Definição de props, ou seja, dados recebidos pelo componente
// 3. Definição de data, ou seja, dados internos do componente
// 4. Definição de emits, ou seja, eventos do componente
// 5. Definição de methods, ou seja, métodos do componente
// 6. Definição de computed, ou seja, propriedades computadas
// 7. Definição de watch, ou seja, observadores de dados
// 8. Definição do ciclo de vida do componente
// 9. Definição da interface exposta pelo componente
</script>
1. Importação de dependências
<script setup>
// Dependências comuns do Vue
import {
ref,
reactive,
toRefs,
computed,
watch,
onMounted,
onUpdated,
onUnmounted,
getCurrentInstance
} from 'vue'
// Algumas funções não precisam de importação, como:
// defineProps, defineEmits, defineExpose
// Importação de funções ou interfaces externas
import $utils from '@/common/js/utils.js'
</script>
2. Definição de props
<script setup><br></br> // Método 1: Definição simples de props<br></br> //const props = defineProps(['propA', 'propB'])<br></br><br></br> // Método 2: Definição detalhada de props<br></br> // Recomenda-se usar o método 2 para configuração rigorosa de cada prop
const props = defineProps({
// Verificação básica de tipo (`null` e `undefined` passam por qualquer validação)
valorNumerico: Number,
// Múltiplos tipos possíveis
valorAlfanumerico: [String, Number],
// String obrigatória
textoObrigatorio: {
type: String,
required: true
},
// Número com valor padrão
numeroPadrao: {
type: Number,
default: 100
},
// Objeto com valor padrão
objetoPadrao: {
type: Object,
// Objetos ou arrays precisam de uma função factory para valores padrão
default: function() {
return {
mensagem: 'olá'
}
}
},
// Função de validação personalizada
valorValidado: {
validator: function(valor) {
// O valor deve corresponder a uma das strings abaixo
return ['sucesso', 'alerta', 'perigo'].indexOf(valor) !== -1
}
}
})
// No script, use props.valorNumerico para acessar o valor
// No template, use a sintaxe de interpolação: <view>{{valorNumerico}}</view>
// Se não precisar acessar no script, pode usar defineProps({})
</script>
Observações:
- Recomenda-se usar a convenção camelCase para props, distinguindo maiúsculas de minúsculas. Por exemplo: classeArtigo
- Os tipos disponíveis para validação são:
StringNumberBooleanArrayObjectDateFunctionSymbol
- Não é possível acessar outras variáveis definidas em
<script setup>dentro dedefaultouvalidator, pois toda a expressão é movida para uma função externa durante a compilação. - Por padrão, quando um componente contém atributos não listados nas props, esses atributos são diretamente anexados ao elemento raiz do componente. Por exemplo:
Código do componente teste: <input type="text" class="conta"/>
Ao chamar o componente teste no componente pai, adicionando os atributos type e class, que não estão definidos nas props do componente teste: <teste class="entrada" type="numero"/>
O código do componente se torna: <teste class="conta entrada" type="numero"/>
O princípio adotado é: atributos, exceto class e style, são substituídos. Class e style são mesclados.
Se não desejar que o elemento raiz do componente herde atributos, pode definir inheritAttrs: false nas opções do componente. No entanto, inheritAttrs não afeta o binding de class e style!
Como o Vue setup não suporta opções de configuração, precisamos configurar em um <script> separado:
<script>
export default {
inheritAttrs: false
}
</script>
- Para o binding de dados bidirecional (v-model) e modificadores, consulte: https://vuejs.org/guide/components/v-model.html
3. Definição de dados
Abaixo estão as funções reativas para definição de dados. É importante compreender profundamente essas funções:
- ref() : Consulte https://vuejs.org/api/reactivity-core.html#ref
- reactive() : Consulte https://vuejs.org/api/reactivity-core.html#reactive
- toRef(), toRefs() Consulte https://vuejs.org/api/reactivity-utilities.html#toref
- readnoly() Consulte https://vuejs.org/api/reactivity-core.html#readon
- shallowRef() Consulte https://vuejs.org/api/reactivity-advanced.html#shallowref
- shallowReactive() Consulte https://vuejs.org/api/reactivity-advanced.html#shallowreactive
- triggerRef() Consulte https://vuejs.org/api/reactivity-advanced.html#triggerref
- shallowReadonly() Consulte https://vuejs.org/api/reactivity-advanced.html#shallowreadonly
- toRaw() Consulte https://vuejs.org/api/reactivity-utilities.html#toraw
- markRaw() Consulte https://vuejs.org/api/reactivity-utilities.html#markraw
- customRef() Consulte https://vuejs.org/api/reactivity-advanced.html#customref
- isRef(), unref(), isProxy(), isReactive(), isReadonly() Consulte https://vuejs.org/api/reactivity-utilities.html
4. Eventos personalizados
Componente teste.vue
<template>
<button @click="instancia.emit('obterInfo', estudante)">Clique para enviar informações do estudante para o componente pai</button>
</template>
<script setup>
import {
reactive,
getCurrentInstance
} from 'vue'
var estudante = reactive({
nome: 'João Silva',
idade: 18,
contato: {
telefone: '21987654321',
whatsapp: '21987654322',
email: 'joao.silva@example.com'
}
})
// Definição: evento personalizado
defineEmits(['obterInfo'])
// Definição de evento com função de validação
// Mesmo que a validação falhe, o componente pai ainda será executado. Apenas um aviso é exibido no console: [Vue warn]: Invalid event arguments: event validation failed for event "obterInfo".
// Portanto, a validação tem utilidade limitada.
//defineEmits({
// 'obterInfo': estudante => {
// return estudante.idade > 18 ? true : false
// }
//})
// Obtenção da instância atual
var instancia = getCurrentInstance()
</script>
Componente pai chamando o evento:
<template>
<teste ref="estudante" @obterInfo="imprimirEstudante"></teste>
</template>
<script setup>
function imprimirEstudante(dados) {
console.log(dados.nome);
}
</script>
5. Definição de métodos do componente
Os métodos do componente são definidos como funções JavaScript comuns:
function metodo1(param1, param2) {
// lógica do método...
}
const metodo2 = (param1, param2)=>{
// lógica do método...
}
6. Definição de propriedades computadas
Sintaxe básica:
const contadorIncrementado = computed(() => contador.value + 1)
Sintaxe completa:
const propriedadeComputada = computed({
get() {
return contador.value
},
set(valor) {
contador.value = valor
}
})
Para mais informações sobre computed(), consulte: https://vuejs.org/api/reactivity-core.html#computed
Métodos relacionados a efeitos e escopos: effectScope(), getCurrentScope(), onScopeDispose()
Consulte: https://vuejs.org/api/reactivity-advanced.html#effectscope
7. Definição de observadores de dados
No setup, é possível usar watch() ou watchEffect() para observar mudanças nos dados. Ambas as funções precisam ser importadas.
<script setup>
import {
watch,
watchEffect
} from 'vue'
</script>
Para mais informações sobre watch() e watchEffect(), consulte: https://vuejs.org/api/reactivity-core.html#watch
Métodos relacionados a efeitos e escopos: effectScope(), getCurrentScope(), onScopeDispose()
Consulte: https://vuejs.org/api/reactivity-advanced.html#effectscope
8. Ciclo de vida do componente
onBeforeMount(), onMounted(), onBeforeUnmount(), onUnmounted()
Descrição: Ciclos de vida de montagem e desmontagem do componente
Consulte: https://vuejs.org/api/composition-api-lifecycle.html
onBeforeUpdate(), onUpdated()
Descrição: Ciclos de vida de atualização de visualização
Consulte: https://vuejs.org/api/composition-api-lifecycle.html
onActivated(), onDeactivated()
Descrição: Ciclos de vida de componentes mantidos em cache pelo
Consulte: https://vuejs.org/api/composition-api-lifecycle.html#onactivated
9. Exposição de interface do componente
Um componente pode expor seus dados e métodos internos para o componente chamador através da função defineExpose().
A função defineExpose() não precisa ser importada e pode ser usada diretamente.
Em , o defineExpose() está desativado por padrão.
<script setup>
import {
ref
} from 'vue'
const quantidade = ref(0)
const processar = ()=>{
// lógica do método...
}
defineExpose({
quantidade, // exposição de dados
processar // exposição de métodos
})
</script>