#javascript #vue.js #vuejs2 #vuetify.js #vue-props
Вопрос:
Я хочу передать логическое значение из одного из моих представлений в представлении маршрутизатора до корневого App.vue, а затем на один из компонентов в App.vue. Я смог это сделать, но я столкнулся с ошибкой:
Избегайте прямого изменения prop, так как значение будет перезаписываться при повторной отрисовке родительского компонента. Вместо этого используйте данные или вычисленное свойство, основанное на значении реквизита. Опора мутирует: «ящик»
Ниже приведен мой код:
Домой.vue:
<template>
<div class="home" v-on:click="updateDrawer">
<img src="...">
</div>
</template>
<script>
export default {
name: "Home",
methods:{
updateDrawer:function(){
this.$emit('updateDrawer', true)
}
};
</script>
Вышеприведенное представление находится в представлении маршрутизатора, и я получаю значение в приложении.vue ниже:
<template>
<v-app class="">
<Navbar v-bind:drawer="drawer" />
<v-main class=" main-bg">
<main class="">
<router-view v-on:updateDrawer="changeDrawer($event)"></router-view>
</main>
</v-main>
</v-app>
</template>
<script>
import Navbar from '@/components/Navbar'
export default {
name: 'App',
components: {Navbar},
data() {
return {
drawer: false
}
},
methods:{
changeDrawer:function(drawz){
this.drawer = drawz;
}
},
};
</script>
Я отправляю значение ящика, привязав его в компоненте navbar.
Navbar.vue:
<template>
<nav>
<v-app-bar app fixed class="white">
<v-app-bar-nav-icon
class="black--text"
@click="drawer = !drawer"
></v-app-bar-nav-icon>
</v-app-bar>
<v-navigation-drawer
temporary
v-model="drawer"
>
...
</v-navigation-drawer>
</nav>
</template>
<script>
export default {
props:{
drawer:{
type: Boolean
}
},
};
</script>
Это сработает один раз, а затем выдаст мне вышеуказанную ошибку. Я признателен, если кто-нибудь сможет объяснить, что мне следует делать и как решить эту проблему.
Ответ №1:
В Navbar.vue вы берете свойство «ящик», и всякий раз, когда кто-то нажимает на «значок v-приложения-панели навигации», вы меняете ящик на «быть»!выдвижной ящик.
Проблема здесь в том, что вы изменяете (изменяете значение) свойства со стороны дочернего элемента (Navbar.vue является дочерним). Это не так, как работает Vue, реквизиты используются только для передачи данных от родителя к ребенку (App.vue является родителем, а Navbar.vue-дочерним), и никогда наоборот.
Правильный подход здесь был бы следующим: каждый раз, когда в Navbar.vue вы хотите изменить значение «ящик», вы должны выдавать событие точно так же, как в Home.vue.
Затем вы можете прослушать это событие в App.vue и соответствующим образом изменить переменную ящика.
Пример:
Navbar.vue
<v-app-bar-nav-icon
class="black--text"
@click="$emit('changedrawer', !drawer)"
></v-app-bar-nav-icon>
Приложение.vue
<Navbar v-bind:drawer="drawer" @changedrawer="changeDrawer"/>
Я изначально пропустил тот факт, что вы также использовали v-модель=»ящик» в Navbar.vue.
v-модель также изменяет значение ящика, что, опять же, нам не нужно.
Мы можем решить эту проблему, разделив v-модель на v-on:вход и :значение, например:
<v-navigation-drawer
temporary
:value="drawer"
@input="val => $emit('changedrawer', val)"
>
В этом сценарии также было бы здорово использовать какое-то централизованное государственное управление, такое как Vuex 😉
Комментарии:
1. это дает ту же ошибку после того, как я применю ваши изменения 🙁
2. Я пропустил это раньше, но в вашем v-навигационном ящике также есть v-модель для ящика. Измените это следующим образом :value=»ящик» @input=»newVal => $emit(‘changedrawer’, newVal)»
3. Отредактировал свой ответ, чтобы включить проблему с v-образной моделью
4. теперь он функционирует нормально, но ошибка все еще показывает, что с ним не так ?
5. Я поддержал ваш ответ, ошибка все еще там, но теперь функциональность в порядке.
Ответ №2:
Что вы могли бы сделать, так это следить за изменениями в реквизите ящика в Navbar.vue, вот так:
<template>
<nav>
<v-app-bar app fixed class="white">
<v-app-bar-nav-icon
class="black--text"
@click="switchDrawer"
/>
</v-app-bar>
<v-navigation-drawer
temporary
v-model="navbarDrawer"
>
...
</v-navigation-drawer>
</nav>
</template>
<script>
export default {
data () {
return {
navbarDrawer: false
}
},
props: {
drawer: {
type: Boolean
}
},
watch: {
drawer (val) {
this.navbarDrawer = val
}
},
methods: {
switchDrawer () {
this.navbarDrawer = !this.navbarDrawer
}
}
}
</script>
Домой.vue
<template>
<div class="home">
<v-btn @click="updateDrawer">Updrate drawer</v-btn>
</div>
</template>
<script>
export default {
name: 'Home',
data () {
return {
homeDrawer: false
}
},
methods: {
updateDrawer: function () {
this.homeDrawer = !this.homeDrawer
this.$emit('updateDrawer', this.homeDrawer)
}
}
}
</script>
Приложение.vue
<template>
<v-app class="">
<Navbar :drawer="drawer" />
<v-main class="main-bg">
<main class="">
<router-view @updateDrawer="changeDrawer"></router-view>
</main>
</v-main>
</v-app>
</template>
<script>
import Navbar from '@/components/Navbar'
export default {
name: 'App',
components: { Navbar },
data () {
return {
drawer: false
}
},
methods: {
changeDrawer (newDrawer) {
this.drawer = newDrawer
}
}
}
</script>
Это не изменяет опору ящика, но реагирует на изменения.
Комментарии:
1. Я попробовал ваше решение, оно работает, но ошибка сохраняется.
2. Не знаю, что происходит. Я обновил свой ответ всеми тремя компонентами. Он работает над новой установкой на моей стороне.
3. Я поддержал ваш ответ, но ошибка все еще там, я не знаю, почему.