Input подлагивает когда использую emit во vue
Перейти к содержимому

Input подлагивает когда использую emit во vue

  • автор:

Пользовательские события

Подразумевается, что вы уже изучили и разобрались с разделом Основы компонентов. Если нет — прочитайте его сначала.

Стиль именования событий

В отличие от компонентов и входных параметров, имена событий не предоставляют никакой автоматической трансформации стиля именования события. Вместо этого, имя генерируемого события должно точно соответствовать имени, используемому при прослушивании события. К примеру, если генерируем событие с именем в camelCase:

this.$emit('myEvent')

Прослушивание kebab-cased версии этого имени не будет иметь никакого эффекта:

 
my-component v-on:my-event="doSomething">
my-component>

В отличие от компонентов и входных параметров, имена событий никогда не будут использоваться в качестве имён переменных или имён свойств в JavaScript, поэтому нет причин использовать camelCase или PascalCase. Кроме того, директивы прослушивания событий v-on внутри DOM-шаблонов автоматически преобразуются в нижний регистр (из-за нечувствительности HTML к регистру), поэтому v-on:myEvent станет v-on:myevent — что делает прослушивание события myEvent невозможным.

По этим причинам мы рекомендуем всегда использовать kebab-case для имён событий.

Настройка v-model у компонента

По умолчанию v-model на компоненте использует входной параметр value и событие input . Но некоторые типы полей, такие как чекбоксы или радиокнопки, могут использовать атрибут value для других целей. Использование опции model позволит избежать конфликта в таких случаях:

Vue.component('base-checkbox', { 
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `

type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})

Теперь, когда используем v-model на этом компоненте:

base-checkbox v-model="lovingVue"> base-checkbox> 

значение lovingVue будет передано во входном параметре checked . А обновляться свойство lovingVue будет когда сгенерирует событие change с новым значением.

Обратите внимание, что вам всё равно нужно объявлять входной параметр checked в опции props компонента.

Подписка на нативные события в компонентах

Иногда нужно подписаться на нативные события браузера на корневом элементе компонента. В таких случаях можно применять модификатор .native для v-on :

base-input v-on:focus.native="onFocus"> base-input> 

Иногда это может быть полезно, но это не очень хорошая идея, когда вы пытаетесь прослушивать очень специфичный элемент, к примеру . Например, компонент можно переделать так, чтобы корневой элемент был фактически элементом :

label> 
{{ label }}
input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
label>

В этом случае слушатель .native в родителе просто тихо перестанет работать. Ошибок не будет, но обработчик onFocus не будет вызываться, когда мы этого ожидаем.

Для решения этой проблемы Vue предоставляет свойство $listeners , содержащее объект всех слушателей, которые используются на компоненте. Например:

{ 
focus: function (event) { /* . */ }
input: function (value) { /* . */ },
}

Используя свойство $listeners , вы можете передать все слушатели событий на компоненте на определённый дочерний элемент с помощью v-on=»$listeners» . Для таких элементов как , вы также можете захотеть работоспособности с v-model , для чего бывает полезно создать новое вычисляемое свойство для слушателей, например inputListeners указанный ниже:

Vue.component('base-input', { 
inheritAttrs: false,
props: ['label', 'value'],
computed: {
inputListeners: function ( ) {
var vm = this
// `Object.assign` объединяет объекты вместе, чтобы получить новый объект
return Object.assign({},
// Мы добавляем все слушатели из родителя
this.$listeners,
// Затем мы можем добавить собственные слушатели или
// перезаписать поведение некоторых существующих.
{
// Это обеспечит, что будет работать v-model на компоненте
input: function (event) {
vm.$emit('input', event.target.value)
}
}
)
}
},
template: `

{{ label }}

v-bind="$attrs"
v-bind:value="value"
v-on="inputListeners"
>
`
})

Теперь компонент стал полностью прозрачной обёрткой, что означает, что его можно использовать точно также, как и обычный элемент : все те же атрибуты и слушатели будут работать без указания модификатора .native .

Модификатор .sync

В некоторых случаях нам может понадобиться «двусторонняя привязка» для входных параметров. К сожалению, настоящая двусторонняя привязка может создавать проблемы с поддержкой, поскольку дочерние компоненты смогут мутировать состояние родителя без источника, который является очевидным как у родителя, так и у потомков.

Поэтому вместо этого, мы рекомендуем генерировать события с определённым шаблоном имени update:myPropName . Например, в гипотетическом компоненте с входным параметром title , мы можем сообщить о намерении присвоить новое значение:

this.$emit('update:title', newTitle)

Затем, родитель может прослушать это событие и обновить локальное свойство, если захочет. Например:

text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
> text-document>

Для удобства мы предлагаем краткую запись для этого шаблона с помощью модификатора .sync :

text-document v-bind:title.sync="doc.title"> text-document> 

Обратите внимание, что v-bind с модификатором .sync не работает с выражениями (например, v-bind:title.sync=”doc.title + ‘!’” не будет работать). Вместо этого нужно указывать только имя свойства, которое хотите привязать, аналогично v-model .

Модификатор .sync также может использоваться вместе с v-bind при использовании объектной записи, чтобы сразу устанавливать значения нескольких входных параметров:

text-document v-bind.sync="doc"> text-document> 

Это передаёт каждое свойство в объекте doc (например, title ) в качестве индивидуальных входных параметров, а затем добавляет слушатели событий v-on для каждого из них.

Использование v-bind.sync с литеральным объектом, например таким как v-bind.sync=”{ title: doc.title }” , не будет работать, потому что необходимо будет учитывать слишком много различных пограничных случаев при анализе подобного сложного выражения.

Обнаружили ошибку или хотите добавить что-то своё в документацию? Измените эту страницу на GitHub! Опубликовано на Netlify .

# Изменения в работе v-model

Для получения дополнительной информации читайте дальше!

# Введение

Во Vue 2.0 директива v-model требовала, чтобы использовался входной параметр value . Для управления ещё другим входным параметром приходилось использовать v-bind.sync . Кроме того, жёстко прописанная связь между v-model и value приводила к проблемам при обработке нативных и пользовательских элементов.

В версии 2.2 была добавлена опция компонента model , которая позволила настраивать входной параметр и событие, используемые для v-model . Но использовать можно было всё равно только одну v-model на компоненте.

Во Vue 3 было унифицировано API для двусторонней привязки данных, чтобы уменьшить путаницу и предоставить разработчикам больше гибкости в работе с директивой v-model .

# Синтаксис в 2.x

В версии 2.x использование v-model на компоненте эквивалентно передаче входного параметра value и отслеживании сгенерированного события input :

ChildComponent v-model="pageTitle" /> ChildComponent :value="pageTitle" @input="pageTitle = $event" /> 

Если хочется изменить используемый входной параметр или имя события на другие, можно воспользоваться опцией model в компоненте ChildComponent :

 ChildComponent v-model="pageTitle" /> 
// ChildComponent.vue export default  model:  prop: 'title', event: 'change' >, props:  // это позволит использовать входной параметр `value` в других целях value: String, // теперь используем входной параметр `title` вместо `value` title:  type: String, default: 'Заголовок по умолчанию' > > > 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

В этом случае v-model будет сокращённым вариантом для

ChildComponent :title="pageTitle" @change="pageTitle = $event" /> 

# Использование v-bind.sync

В некоторых случаях может потребоваться «двусторонняя привязка» к входному параметру (иногда в дополнение к существующей v-model для другого). Для этого рекомендуется генерировать событие по шаблону update:myPropName . Например, для ChildComponent из предыдущего примера с входным параметром title можно передавать намерение о присвоении нового значения следующий образом:

this.$emit('update:title', newValue) 

Тогда родительский компонент может прослушать это событие и обновить локальное свойство, если захочет. Например:

ChildComponent :title="pageTitle" @update:title="pageTitle = $event" /> 

Для удобства, сокращённый вариант для этого шаблона с модификатором .sync такой:

ChildComponent :title.sync="pageTitle" /> 

# Синтаксис в 3.x

В версии 3.x v-model на пользовательском компоненте эквивалентно передаче входного параметра modelValue и отслеживании сгенерированного события update:modelValue :

ChildComponent v-model="pageTitle" /> ChildComponent :modelValue="pageTitle" @update:modelValue="pageTitle = $event" /> 

1
2
3
4
5
6
7
8

# Аргументы v-model

Чтобы изменить имя свойства, вместо использования опции model в компоненте, теперь можно передавать аргумент в директиву v-model :

ChildComponent v-model:title="pageTitle" /> ChildComponent :title="pageTitle" @update:title="pageTitle = $event" /> 

Анатомия v-bind

Это также служит заменой модификатору .sync и позволяет указать несколько v-model на пользовательском компоненте.

ChildComponent v-model:title="pageTitle" v-model:content="pageContent" /> ChildComponent :title="pageTitle" @update:title="pageTitle = $event" :content="pageContent" @update:content="pageContent = $event" /> 

1
2
3
4
5
6
7
8
9
10
11
12
13

# Модификаторы v-model

Кроме жёстко заданных модификаторов v-model в версии 2.x, таких как .trim , в версии 3.x теперь поддерживается создание пользовательских модификаторов:

ChildComponent v-model.capitalize="pageTitle" /> 

Подробнее о пользовательских модификаторах v-model можно прочитать в разделе пользовательских событий.

# Стратегия миграции

    проверить кодовую базу на использование .sync и заменить их на v-model :

ChildComponent :title.sync="pageTitle" /> ChildComponent v-model:title="pageTitle" /> 
ChildComponent v-model="pageTitle" /> 
// ChildComponent.vue export default  props:  modelValue: String // раньше было `value: String` >, emits: ['update:modelValue'], methods:  changePageTitle(title)  this.$emit('update:modelValue', title) // раньше было `this.$emit('input', title)` > > > 

1
2
3
4
5
6
7
8
9
10
11
12
13

  • COMPONENT_V_MODEL
  • COMPILER_V_BIND_SYNC

# Дальнейшие шаги

Более подробную информацию о новом синтаксисе v-model можно получить здесь:

  • Использование v-model на компонентах
  • Аргументы v-model
  • Обработка модификаторов v-model

(opens new window)
Последнее обновление страницы: около 2 лет назад

# Добавлена опция emits

Vue 3 теперь предоставляет опцию emits , похожую на существующую опцию props . Её можно использовать для объявления событий, которые могут быть сгенерированы компонентом для своих родителей.

# Поведение в 2.x

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

template> div> p>>p> button @click="$emit('accepted')">OKbutton> div> template> script> export default  props: ['text'] > script> 

1
2
3
4
5
6
7
8
9
10
11
12

# Поведение в 3.x

Аналогично входным параметрам, теперь можно определить события которые генерирует компонент с помощью опции emits :

template> div> p>>p> button @click="$emit('accepted')">OKbutton> div> template> script> export default  props: ['text'], emits: ['accepted'] > script> 

1
2
3
4
5
6
7
8
9
10
11
12
13

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

Для получения дополнительной информации, ознакомьтесь с документацией API для этой возможности.

# Стратегия миграции

Настоятельно рекомендуется документировать все события, которые может генерировать компонент с помощью emits .

Это особенно важно из-за удаления модификатора .native . Теперь любой слушатель события, не указанный в emits , будет добавлен в свойство $attrs компонента, что по умолчанию станет привязывать его к корневому узлу компонента.

# Пример

Для компонентов, которые переопределяют нативные события для своих родителей, это приведёт к генерации двух событий:

template> button @click="$emit('click', $event)">OKbutton> template> script> export default  emits: [] // без объявленного события > script> 

1
2
3
4
5
6
7
8
9

Когда родитель прослушивает событие click на компоненте:

my-button @click="handleClick">my-button> 

обработчик события будет вызван дважды:

  • Один раз от $emit() .
  • Один раз от нативного обработчика события, привязанного к корневому элементу.

Здесь есть два варианта:

  1. Корректно объявить событие click . Это полезно, если действительно добавите некоторую логику в обработчик события в .
  2. Удалить повторную генерацию события, так как родитель может легко отслеживать нативные события, без добавления .native . Подходит в тех случаях, когда действительно генерируете заново событие в любом случае.

# См. также

(opens new window)
Последнее обновление страницы: около 2 лет назад

vue.js select2 несколько выделенных

Уже много дней я ищу ответ на эту ошибку. Я пробовал много альтернатив, но ничего не сработало.

Мне нужно выбрать несколько значений. Когда я выбираю несколько значений, мой код зависает, но когда я использую один выбор, он хорошо работает с self.$emit(‘input’, this.value) . Мне нужно выбрать несколько значений.

Select2.vue

    

new.vue

 

Selected: >

export default < data()< return < model: < 'users_id': [], >, options: [], components:< 'select2': Select2 >,

Поделиться Источник 12 мая 2017 в 15:51

2 ответа

Похоже, вы использовали пример документации Vue обертки для select2 в качестве своей базы. Я изменил обертку для обработки нескольких select здесь.

Я ожидаю, что основная проблема, с которой вы столкнулись, заключается в том, что если вы сделаете это:

self.$emit('input', $(this).val()) // multiple select 

Вы окажетесь в бесконечном цикле, потому что вы выбрасываете новый массив, который будет запускать часы,

value: function (value) < $(this.$el).val(value).trigger('change'); >, 

который запускает изменение, которое запускает часы и т.д.

Чтобы исправить это, просто проверьте, идентично ли значение, переданное в часы, значениям select, и если оно есть, игнорируйте его. Вот как я это сделал.

value: function (value) < // check to see if the arrays contain the same values if ([. value].sort().join(",") !== [. $(this.$el).val()].sort().join(",")) $(this.$el).val(value).trigger('change'); >, 

Обратите внимание, что я превратил это в собственный компонент, select2Multiple . Возможно, вам захочется иметь один компонент, который обрабатывает несколько выбранных значений, а другой для одинарных значений.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *