# API Global
breaking
O Vue 2.x possui várias APIs e configurações globais que alteram globalmente o comportamento do Vue. Por exemplo, para registrar um componente global, você usaria a API Vue.component
assim:
Vue.component('button-counter', {
data: () => ({
count: 0
}),
template: '<button @click="count++">Clicado {{ count }} vezes.</button>'
})
2
3
4
5
6
Da mesma forma, é assim que uma diretiva global é declarada:
Vue.directive('focus', {
inserted: el => el.focus()
})
2
3
Embora essa abordagem seja conveniente, ela leva a alguns problemas. Tecnicamente, o Vue 2 não tem um conceito de "aplicativo". O que definimos como um aplicativo é simplesmente uma instância raiz do Vue criada via new Vue()
. Cada instância raiz criada a partir do mesmo construtor Vue compartilha a mesma configuração global. Como resultado:
A configuração global facilita a poluição acidental de outros casos de teste durante o teste. Os usuários precisam armazenar cuidadosamente a configuração global original e restaurá-la após cada teste (ex.: redefinindo
Vue.config.errorHandler
). Algumas APIs comoVue.use
eVue.mixin
nem têm como reverter seus efeitos. Isso torna os testes envolvendo plugins particularmente complicados. Na verdade, vue-test-utils tem que implementar uma API especialcreateLocalVue
para lidar com isso:import { createLocalVue, mount } from '@vue/test-utils' // cria um construtor `Vue` estendido const localVue = createLocalVue() // instala um plugin “globalmente” no construtor “local” do Vue localVue.use(MyPlugin) // passa o `localVue` para as opções de montagem mount(Component, { localVue })
1
2
3
4
5
6
7
8
9
10A configuração global dificulta o compartilhamento da mesma cópia do Vue entre vários "apps" na mesma página, mas com configurações globais diferentes.
// isso afeta ambas as instâncias raiz Vue.mixin({ /* ... */ }) const app1 = new Vue({ el: '#app-1' }) const app2 = new Vue({ el: '#app-2' })
1
2
3
4
5
6
7
Para evitar esses problemas, no Vue 3 apresentamos…
# Uma Nova API Global: createApp
Chamar createApp
retorna uma instância de aplicativo, um novo conceito no Vue 3.
import { createApp } from 'vue'
const app = createApp({})
2
3
Se você estiver usando uma versão CDN do Vue, o createApp
será exposto por meio do objeto global Vue
:
const { createApp } = Vue
const app = createApp({})
2
3
Uma instância de aplicativo expõe um subconjunto das APIs globais do Vue 2. A regra geral é qualquer API que altere globalmente o comportamento do Vue agora foi movida para a instância do aplicativo. Aqui está uma tabela das APIs globais do Vue 2 e suas APIs de instância correspondentes:
2.x API Global | 3.x API de Instância (app ) |
---|---|
Vue.config | app.config |
Vue.config.productionTip | removido (veja abaixo) |
Vue.config.ignoredElements | app.config.compilerOptions.isCustomElement (veja abaixo) |
Vue.component | app.component |
Vue.directive | app.directiva |
Vue.mixin | app.mixin |
Vue.use | app.use (veja abaixo) |
Vue.prototype | app.config.globalProperties (veja abaixo) |
Vue.extend | removido (veja abaixo) |
Todas as outras APIs globais que não alteram globalmente o comportamento agora são exportações nomeadas, conforme documentado em Treeshaking da API Global.
# config.productionTip
Removido
No Vue 3.x, a dica "use production build" só aparecerá ao usar o "dev + full build" (a versão que inclui o compilador em tempo de execução e tem avisos).
Para construções de módulos ES, como são usados com empacotadores e, na maioria dos casos, uma CLI ou boilerplate configuraria o ambiente de produção corretamente, essa dica não aparecerá mais.
Sinalizador na compilação de migração: CONFIG_PRODUCTION_TIP
# config.ignoredElements
Agora É config.compilerOptions.isCustomElement
Essa opção de configuração foi introduzida com a intenção de oferecer suporte a elementos personalizados nativos, então a renomeação transmite melhor o que ela faz. A nova opção também espera uma função, o que fornece mais flexibilidade do que a antiga abordagem de string / RegExp:
// antes
Vue.config.ignoredElements = ['my-el', /^ion-/]
// depois
const app = createApp({})
app.config.compilerOptions.isCustomElement = tag => tag.startsWith('ion-')
2
3
4
5
6
Importante
No Vue 3, a verificação de se um elemento é um componente foi movida para a fase de compilação do template, portanto esta opção de configuração só é respeitada quando se utiliza a compilação em tempo de execução. Se você estiver usando a compilação somente em tempo de execução, isCustomElement
deve ser passado para @vue/compiler-dom
na configuração da compilação - por exemplo, através da opção compilerOptions
no vue-loader (opens new window).
- Se
config.compilerOptions.isCustomElement
for atribuído ao usar uma compilação somente em tempo de execução, um aviso será emitido instruindo o usuário a passar a opção na configuração da compilação; - Esta será uma nova opção de nível superior na configuração do Vue CLI.
Sinalizador na compilação de migração: CONFIG_IGNORED_ELEMENTS
# Vue.prototype
Substituído por config.globalProperties
No Vue 2, Vue.prototype
era comumente usado para adicionar propriedades que seriam acessíveis em todos os componentes.
O equivalente no Vue 3 é config.globalProperties
. Essas propriedades serão copiadas como parte da instanciação de um componente dentro do aplicativo:
// antes - Vue 2
Vue.prototype.$http = () => {}
2
// depois - Vue 3
const app = createApp({})
app.config.globalProperties.$http = () => {}
2
3
Usar provide
(discutido abaixo) também deve ser considerado como uma alternativa para globalProperties
.
Sinalizador na compilação de migração: GLOBAL_PROTOTYPE
# Vue.extend
Removido
No Vue 2.x, Vue.extend
era usado para criar uma "subclasse" do construtor Vue base com o argumento que deveria ser um objeto contendo opções de componente. No Vue 3.x, não temos mais o conceito de construtores de componente. A montagem de um componente deve sempre usar a API global createApp
:
// antes - Vue 2
// cria construtor
const Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} também conhecido como {{alias}}</p>',
data() {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// cria uma instância de Profile e monta em um elemento
new Profile().$mount('#mount-point')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// depois - Vue 3
const Profile = {
template: '<p>{{firstName}} {{lastName}} também conhecido como {{alias}}</p>',
data() {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
}
Vue.createApp(Profile).mount('#mount-point')
2
3
4
5
6
7
8
9
10
11
12
13
# Inferência de Tipos
No Vue 2, Vue.extend
também era usado para fornecer a inferência de tipo do TypeScript para as opções do componente. No Vue 3, a API global defineComponent
pode ser usada no lugar do Vue.extend
para o mesmo propósito.
Observe que, embora o tipo de retorno de defineComponent
seja um tipo estilo construtor, ele é usado apenas para inferência do TSX. Em tempo de execução, o defineComponent
é em grande parte um noop e retornará o objeto de opções como está.
# Herança de Componentes
No Vue 3, é altamente recomendável favorecer a composição via API de Composição sobre herança e mixins. Se por algum motivo você ainda precisar de herança de componentes, você pode usar a opção extends
em vez de Vue.extend
.
Sinalizador na compilação de migração: GLOBAL_EXTEND
# Uma Nota para Autores de Plugins
É uma prática comum para os autores de plugins instalarem os plugins automaticamente em suas compilações UMD usando Vue.use
. Por exemplo, é assim que o plugin oficial vue-router
se instala em um ambiente de navegador:
var inBrowser = typeof window !== 'undefined'
/* … */
if (inBrowser && window.Vue) {
window.Vue.use(VueRouter)
}
2
3
4
5
Como a API global use
não está mais disponível no Vue 3, este método deixará de funcionar e chamar Vue.use()
agora acionará um aviso. Em vez disso, o usuário final terá que especificar explicitamente o uso do plugin na instância do aplicativo:
const app = createApp(MyApp)
app.use(VueRouter)
2
# Montando a Instância do Aplicativo
Após ser inicializado com createApp(/* options */)
, a instância do aplicativo app
pode ser usada para montar uma instância de componente raiz com app.mount(domTarget)
:
import { createApp } from 'vue'
import MyApp from './MyApp.vue'
const app = createApp(MyApp)
app.mount('#app')
2
3
4
5
Com todas essas mudanças, o componente e a diretiva que temos no início do guia serão reescritos em algo assim:
const app = createApp(MyApp)
app.component('button-counter', {
data: () => ({
count: 0
}),
template: '<button @click="count++">Clicado {{ count }} vezes.</button>'
})
app.directive('focus', {
mounted: el => el.focus()
})
// agora cada instância do aplicativo montada com app.mount(), junto com sua
// árvore de componentes, terá o mesmo componente “button-counter”
// e diretiva “focus” sem poluir o ambiente global
app.mount('#app')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Sinalizador na compilação de migração: GLOBAL_MOUNT
# Prover / Injetar
Semelhante ao uso da opção provide
em uma instância raiz 2.x, uma instância de aplicativo Vue 3 também pode fornecer dependências que podem ser injetadas por qualquer componente dentro do aplicativo:
// na entrada
app.provide('guide', 'Guia do Vue 3')
// em um componente filho
export default {
inject: {
book: {
from: 'guide'
}
},
template: `<div>{{ book }}</div>`
}
2
3
4
5
6
7
8
9
10
11
12
Usar provide
é especialmente útil ao escrever um plugin, como uma alternativa para globalProperties
.
# Compartilhe Configurações Entre Aplicativos
Uma maneira de compartilhar configurações, como componentes ou diretivas entre apps é criar uma função fabricadora, assim:
import { createApp } from 'vue'
import Foo from './Foo.vue'
import Bar from './Bar.vue'
const createMyApp = options => {
const app = createApp(options)
app.directive('focus' /* ... */)
return app
}
createMyApp(Foo).mount('#foo')
createMyApp(Bar).mount('#bar')
2
3
4
5
6
7
8
9
10
11
12
13
Agora a diretiva focus
estará disponível em ambas as instâncias Foo
e Bar
e seus descendentes.