Обновление реквизитов в компоненте через маршрутизатор-просмотр в vue js

#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. Я поддержал ваш ответ, но ошибка все еще там, я не знаю, почему.