#javascript #vue.js #vuetify.js
#javascript #vue.js #vuetify.js
Вопрос:
Итак, у меня есть страница, отображающая v-список на основе массива, подобного этому :
<v-list-tile v-for="item in array">
{{item}}
</v-list-tile>
и диалоговое окно с v-текстовым полем :
<v-dialog>
<v-text-field v-model="myInput">
</v-text-field>
</v-dialog>
На данный момент это довольно нормально.
Но с помощью теста производительности я увидел, что для каждого события, вызванного изменением в модели myInput (например, нажатием клавиши), v-for также запускается для повторного отображения списка, когда они фактически не связаны.
В моем огромном массиве это серьезная проблема и делает пользовательский интерфейс действительно отстающим. Я думаю, что это нормальное поведение для приложения vuejs, но мне было интересно, могу ли я точно указать элементу желания проверить повторный рендеринг.
Я пробовал некоторые операторы v-if, но это не помогло.
Я надеюсь, что на это есть ответ, я думаю, я что-то упускаю.
Если вы хотите протестировать то, о чем я говорю здесь, это готовый к работе HTML-файл, пожалуйста, отладьте его с помощью своей консоли отладки, вы увидите [vue warn] сообщение о дублированном ключе, подтверждающее тот факт, что v-for действительно вызывается при каждом нажатии клавиши.
Представьте теперь, что массив (здесь элементы) намного больше этого и упакован в сложные компоненты, выполнение этого вызова слишком сильно влияет на производительность, когда мы просто стремимся изменить значение «myInput».
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{data}}
<ul>
<li v-for="item in items" :key="item">
{{ item.message }}
</li>
</ul>
<input v-model="data"></input>
</div>
</body>
<script>
new Vue({
el: '#app',
data: () => ({
data: '',
items: [{
message: 'Foo'
},
{
message: 'Bar'
}
]
})
})
</script>
</html>
Комментарии:
1. находится ли диалоговое окно внутри списка?
2. @dandavis Это не так.
3. возможно, попробуйте использовать v-bind вместо v-model. Для v-bind вы можете указать, какой тип события вы хотите обновить в поле
4. Для меня работает нормально, как вы улучшаете «производительность»?
Ответ №1:
Вот codepen, показывающий внутренний цикл в его собственном компоненте
Я добавил элементы списка Date.now()
после items[x].message
, чтобы они отображались при повторном отображении списка.
В случае, если codepen когда-либо выйдет из строя:
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>
<body>
<div id="app">
Main vue: {{data}}
<loop-component :data="loopdata"></loop-component>
<input v-model="data"></input>
<input v-model="loopdata"></input>
</div>
<script>
Vue.component('loop-component', {
props: ['data'],
data() {
return {
items: [
{message: 'Foo'},
{message: 'Bar'}
]
}
},
template: `
<div>
Loop component: {{ data }}
<ul>
<li v-for="(item, index) in items" :key="index">
{{ item.message ' Date.now(): ' Date.now() }}
</li>
</ul>
</div>
`
});
let app = new Vue({
el: '#app',
data: () => ({
data: '',
'loopdata': '',
items: [
{message: 'Foo'},
{message: 'Bar'},
]
}),
});
</script>
</body>
</html>
Ответ №2:
Попробуйте использовать.отложенный модификатор для синхронизации после событий изменения.
<input v-model.lazy="data"></input>
https://v2.vuejs.org/v2/guide/forms.html#lazy
Редактировать
@IVO GELOV прав, когда изменяется компонент, это повторный рендеринг. Решение состоит в разделении вашего компонента на несколько дочерних компонентов.
https://v2.vuejs.org/v2/guide/reactivity.html
Это код, использующий слоты, чтобы сделать его похожим на ваш пример.
HTML
<div id="app">
<new-component>
<ul>
<li v-for="item in items" :key="item">
{{ item.message }}
</li>
</ul>
</new-component>
</div>
Javascript
Vue.component('new-component', {
data: () => {
return {
data: ''
}
},
template: `
<div>
<div>{{ data }}</div>
<slot></slot>
<input v-model="data"></input>
</div>`
})
new Vue({
el: '#app',
data: () => ({
items: [{
message: 'Foo'
},
{
message: 'Bar'
}
]
})
})
Комментарии:
1. Я не знаю, заметил ли кто-нибудь это, но количество предупреждений соответствует формуле.
warning_errors = array.length (array.length - 1)
Я найду наиболее удовлетворительный ответ.
Ответ №3:
Начиная с Vue 2.0 , всякий раз, когда обнаруживается изменение, весь компонент повторно отображается. Если вы хотите избежать этого — разделите свой компонент на несколько дочерних компонентов.
Ваш пример не доказывает вашу точку зрения — тот факт, что внутри есть предупреждение о дублирующихся ключах, v-for
не означает, что v-for
это пересчитывается при каждом нажатии клавиши. Чтобы подтвердить мое утверждение — просто измените свой код следующим образом:
<li v-for="(item,idx) in items" :key="idx">
Теперь предупреждения нет.
Комментарии:
1. Это не решает проблему. Скрывает ошибку, но не решает проблему с производительностью. Дело не в предупреждении…
2. Итак, ваш пример не имеет отношения к вашему вопросу / жалобе. И вы, кажется, игнорируете мой совет разделить компонент на дочерние компоненты — например, один компонент для ввода и другой компонент для
v-list
.