# Composição

# mixins

  • Tipo: Array<Object>

  • Detalhes:

    A opção mixins aceita um array de objetos mixin. Esses objetos mixin podem conter opções de instância como objetos de instância normais, e eles serão mesclados com as opções eventuais usando a lógica de mesclagem de opções. Por exemplo, se seu mixin contiver um gatilho created e o próprio componente também, ambas as funções serão chamadas.

    Os gatilhos do mixin são chamados na ordem em que são fornecidos e chamados antes dos gatilhos do próprio componente.

    INFO

    No Vue 2, os mixins eram o principal mecanismo para criar blocos reutilizáveis de lógica de componentes. Embora os mixins continuem sendo suportados no Vue 3, a API de Composição agora é a abordagem preferida para reutilização de código entre componentes.

  • Exemplo:

    const mixin = {
      created() {
        console.log(1)
      }
    }
    
    createApp({
      created() {
        console.log(2)
      },
      mixins: [mixin]
    })
    
    // => 1
    // => 2
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
  • Ver também: Mixins

# extends

  • Tipo: Object

  • Detalhes:

    Permite que um componente estenda outro, herdando suas opções de componente.

    De uma perspectiva de implementação, extends é quase idêntico a mixins. O componente especificado por extends será tratado como se fosse o primeiro mixin.

    No entanto, extends e mixins expressam intenções diferentes. A opção mixins é usada principalmente para compor blocos de funcionalidade, enquanto extends está principalmente preocupado com herança.

    Assim como em mixins, todas as opções serão mescladas usando a estratégia de mesclagem relevante.

  • Exemplo:

    const CompA = { ... }
    
    const CompB = {
      extends: CompA,
      ...
    }
    
    1
    2
    3
    4
    5
    6

# provide / inject

  • Tipo:

    • provide: Object | () => Object
    • inject: Array<string> | { [key: string]: string | Symbol | Object }
  • Detalhes:

    Esse par de opções é usado em conjunto para permitir que um componente ancestral sirva como um injetor de dependência para todos os seus descendentes, independentemente da profundidade da hierarquia do componente, desde que estejam na mesma cadeia do pai. Se você estiver familiarizado com React, isso é muito semelhante ao recurso context do React.

    A opção provide deve ser um objeto ou uma função que retorne um objeto. Este objeto contém as propriedades que estão disponíveis para injeção em seus descendentes. Você pode usar Symbols do ES2015 como chaves neste objeto, mas apenas em ambientes que suportem nativamente Symbol e Reflect.ownKeys.

    A opção inject deve ser:

    • um array de strings, ou
    • um objeto em que as chaves são o nome do vínculo local e o valor é:
      • a chave (string ou Symbol) para procurar nas injeções disponíveis, ou
      • um objeto onde:
        • a propriedade from é a chave (string ou Symbol) para procurar nas injeções disponíveis, e
        • a propriedade default é usada como valor de fallback

    Nota: os vínculos provide e inject NÃO são reativos. Isso é intencional. No entanto, se você transmitir um objeto reativo, as propriedades desse objeto permanecerão reativas.

  • Exemplo:

    // componente pai fornecendo 'foo'
    const Provider = {
      provide: {
        foo: 'bar'
      }
      // ...
    }
    
    // componente filho injetando 'foo'
    const Child = {
      inject: ['foo'],
      created() {
        console.log(this.foo) // => "bar"
      }
      // ...
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    Com Symbols do ES2015, a função provide e objeto inject:

    const s = Symbol()
    
    const Provider = {
      provide() {
        return {
          [s]: 'foo'
        }
      }
    }
    
    const Child = {
      inject: { s }
      // ...
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    Usando um valor injetado como default para uma prop:

    const Child = {
      inject: ['foo'],
      props: {
        bar: {
          default() {
            return this.foo
          }
        }
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    Usando um valor injetado como entrada de dados:

    const Child = {
      inject: ['foo'],
      data() {
        return {
          bar: this.foo
        }
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    As injeções podem ser opcionais com um valor padrão (default):

    const Child = {
      inject: {
        foo: { default: 'foo' }
      }
    }
    
    1
    2
    3
    4
    5

    Se precisar ser injetado de uma propriedade com um nome diferente, use from para denotar a propriedade de origem:

    const Child = {
      inject: {
        foo: {
          from: 'bar',
          default: 'foo'
        }
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    Semelhante aos valores padrão de prop, você precisa usar uma função fabricadora para valores não primitivos:

    const Child = {
      inject: {
        foo: {
          from: 'bar',
          default: () => [1, 2, 3]
        }
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
  • Ver também: Prover / Injetar

# setup

  • Tipo: Function

A função setup é uma nova opção de componente. Ela serve como ponto de entrada para usar a API de Composição dentro dos componentes.

  • Momento de Invocação

    setup é chamada logo após a resolução inicial das props quando uma instância do componente é criada. Em termos de ciclo de vida, ela é chamado antes do gatilho beforeCreate.

  • Uso com templates

    Se setup retornar um objeto, as propriedades do objeto serão mescladas no contexto de renderização do template do componente:

    <template>
      <div>{{ count }} {{ object.foo }}</div>
    </template>
    
    <script>
      import { ref, reactive } from 'vue'
    
      export default {
        setup() {
          const count = ref(0)
          const object = reactive({ foo: 'bar' })
    
          // expõe ao template
          return {
            count,
            object
          }
        }
      }
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    Note que refs retornados de setup são automaticamente desempacotadas quando acessados ​​no template, então não há necessidade de .value nos templates.

  • Uso com Funções de Renderização / JSX

    setup também pode retornar uma função de renderização, que pode usar diretamente o estado reativo declarado no mesmo escopo:

    import { h, ref, reactive } from 'vue'
    
    export default {
      setup() {
        const count = ref(0)
        const object = reactive({ foo: 'bar' })
    
        return () => h('div', [count.value, object.foo])
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  • Argumentos

    A função recebe as props resolvidas como seu primeiro argumento:

    export default {
      props: {
        name: String
      },
      setup(props) {
        console.log(props.name)
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    Observe que este objeto props é reativo - ou seja, ele é atualizado quando novas props são passadas ​​e pode ser observado e reagido ao usar watchEffect ou watch:

    export default {
      props: {
        name: String
      },
      setup(props) {
        watchEffect(() => {
          console.log(`nome é: ` + props.name)
        })
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    No entanto, NÃO desestruture o objeto props, pois ele perderá reatividade:

    export default {
      props: {
        name: String
      },
      setup({ name }) {
        watchEffect(() => {
          console.log(`nome é: ` + name) // Não será reativo!
        })
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    O objeto props é imutável para o código do usuário durante o desenvolvimento (irá emitir um aviso se o código do usuário tentar alterá-lo).

    O segundo argumento fornece um objeto de contexto que expõe vários objetos e funções que podem ser úteis no setup:

    const MyComponent = {
      setup(props, context) {
        context.attrs
        context.slots
        context.emit
        context.expose
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    attrs, slots e emit são equivalentes às propriedades de instância $attrs, $slots e $emit respectivamente.

    attrs e slots são proxies para os valores correspondentes na instância interna do componente. Isso garante que eles sempre exponham os valores mais recentes, mesmo após as atualizações, para que possamos desestruturá-los sem nos preocupar em acessar uma referência obsoleta:

    const MyComponent = {
      setup(props, { attrs }) {
        // uma função que pode ser chamada em um estágio posterior
        function onClick() {
          console.log(attrs.foo) // garantido ser a referência mais recente
        }
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    expose, adicionado no Vue 3.2, é uma função que permite que propriedades específicas sejam expostas através da instância pública do componente. Por padrão, a instância pública recuperada usando refs, $parent ou $root é equivalente à instância interna usada pelo template. Chamar expose criará uma instância pública separada com as propriedades especificadas:

    const MyComponent = {
      setup(props, { expose }) {
        const count = ref(0)
        const reset = () => count.value = 0
        const increment = () => count.value++
    
        // Somente reset estará disponível externamente, ex. via $refs
        expose({
          reset
        })
    
        // Internamente, o template tem acesso à count e increment
        return { count, increment }
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    Existem várias razões para colocar props como um primeiro argumento separado em vez de incluí-lo no contexto:

    • É muito mais comum um componente usar props do que as outras propriedades, e muitas vezes um componente usa apenas props.

    • Ter props como um argumento separado torna mais fácil digitá-lo individualmente sem atrapalhar os tipos de outras propriedades no contexto. Também torna possível manter uma assinatura consistente em setup, render e componentes funcionais simples com suporte a TSX.

  • Ver também: API de Composição