# Композиция

# mixins

  • Тип: Array<Object>

  • Подробности:

    Опция mixins принимает массив объектов примесей. Эти объекты могут содержать опции экземпляра, как и обычные объекты экземпляра, и они будут объединены в окончательный набор опций с использованием специальной логики объединения. Например, если хук created указан в примеси и есть в компоненте, то будут вызваны обе функции.

    Хуки в примесях вызываются в порядке их определения до вызова собственных хуков компонента.

  • Пример:

    const mixin = {
      created: function() {
        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
  • См. также: Примеси

# extends

  • Тип: Object | Function

  • Подробности:

    Позволяет декларативно наследоваться от другого компонента (который может быть как обычным объектом опций, так и конструктором). Главным образом предназначается для облегчения наследования между однофайловыми компонентами.

    Функциональность аналогична опции mixins.

  • Пример:

    const CompA = { ... }
    
    // наследуем CompA без необходимости вызова `Vue.extend`
    const CompB = {
      extends: CompA,
      ...
    }
    
    1
    2
    3
    4
    5
    6
    7

# provide / inject

  • Тип:

    • provide: Object | () => Object
    • inject: Array<string> | { [key: string]: string | Symbol | Object }
  • Подробности:

    Эта пара опций используется вместе, чтобы позволить компоненту-родителю внедрять зависимости во все компоненты-потомки. Не имеет значения, насколько глубоко в иерархии они находятся, пока располагаются в той же самой родительской цепочке. Если знакомы с React, то это очень похоже на функцию context.

    Опция provide должна быть объектом или функцией, возвращающей объект. Этот объект содержит свойства, которые после внедрения будут доступны в потомках. Можно использовать ES2015 Symbols в качестве ключей объекта, но только в окружениях, которые нативно поддерживают Symbol и Reflect.ownKeys.

    Опция inject должна быть:

    • массивом строк;
    • или объектом, где ключами являются локальные имена привязки, а значением может быть:
      • ключ (строка или Symbol) для поиска в доступных внедрениях;
      • объект, в котором
        • свойство from является ключом (строка или Symbol) для поиска в доступных внедрениях,
        • свойство default используется в качестве запасного значения.

    Примечание: привязки provide и inject НЕ РЕАКТИВНЫ. Так сделано специально. Однако, если передать реактивный объект, то его свойства останутся реактивными.

  • Пример:

    // родительский компонент предоставляет доступ к 'foo'
    const Provider = {
      provide: {
        foo: 'bar'
      }
      // ...
    }
    
    // дочерний компонент внедряет '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

    Работа с функциями provide и объектом inject с использованием ES2015 Symbols:

    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

    Использование внедряемого значения для входного параметра в качестве значения по умолчанию:

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

    Использование внедряемого значения в качестве данных:

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

    Инъекции можно указывать с собственным значением по умолчанию:

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

    Для внедрения значение из свойства под другим именем можно использовать опцию from для определения свойства-источника:

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

    Как и для значений по умолчанию входных параметров, для не-примитивных значений необходимо использовать фабричную функцию:

    const Child = {
      inject: {
        foo: {
          from: 'bar',
          default: () => [1, 2, 3]
        }
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
  • См. также: Provide / Inject

# setup

  • Тип: Function

Функция setup — новая опция компонента. Она будет стартовой точкой для использования Composition API внутри компонентов.

  • Время вызова

    Функция setup вызывается сразу после первичного разрешения входных параметров, когда создаётся экземпляр компонента. В жизненном цикле вызов будет перед хуком beforeCreate.

  • Использование с шаблонами

    Если setup возвращает объект, его свойства будут объединены в контексте отрисовки для шаблона компонента:

    <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' })
    
          // предоставляем доступ в шаблоне
          return {
            count,
            object
          }
        }
      }
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    Обратите внимание, что refs, возвращаемые из setup, автоматически разворачиваются при обращениях в шаблоне. Поэтому нет необходимости указывать .value в шаблонах.

  • Использование с render-функциями / JSX

    Функция setup также может возвращать render-функцию, которая может напрямую использовать реактивное состояние, объявленное в той же области видимости:

    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
  • Аргументы

    Первым аргументом функция принимает разрешённые входные параметры:

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

    Обратите внимание, что объект props является реактивным — т.е. он обновляется при передаче новых значений входных параметров. Это позволяет его отслеживать и реагировать на изменения с помощью watchEffect или watch:

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

    НЕ ИСПОЛЬЗУЙТЕ деструктуризацию для объекта props, потому что это приведёт к потере его реактивности:

    export default {
      props: {
        name: String
      },
      setup({ name }) {
        watchEffect(() => {
          console.log(`Имя: ` + name) // Реактивности уже не будет!
        })
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    Объект props иммутабелен для пользовательского кода в процессе разработки (будет выводиться предупреждение при попытке его изменять).

    Второй аргумент предоставляет объект с контекстом, который позволяет получить доступ к перечисленному списку свойств, ранее доступных через this:

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

    Свойства attrs и slots являются прокси для соответствующих значений экземпляра внутреннего компонента. Это гарантирует, что они всегда содержат актуальные значения даже после обновления, чтобы была возможность уничтожать их, не беспокоясь о доступе по устаревшей ссылке:

    const MyComponent = {
      setup(props, { attrs }) {
        // функция, которая может вызываться где-то позднее
        function onClick() {
          console.log(attrs.foo) // гарантированно будет актуальной ссылкой
        }
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    Есть ряд причин, почему props указываются в качестве отдельного первого аргумента, а не включаются в контекст:

    • Гораздо чаще компонент использует props, чем какие-либо другие свойства. Очень часто компонент использует только props.

    • Наличие props в качестве отдельного аргумента облегчает вывод их типов, без путаницы с типами других свойств в контексте. Это также позволяет сохранить консистентную сигнатуру между setup, render и простыми функциональными компонентами с поддержкой TSX.

  • См. также: Composition API