Последовательное связывание значений элементов списка от списка к странице в макете, отображаемом в другом макете - PullRequest
0 голосов
/ 20 января 2020

Лучший пример для иллюстрации того, что я пытаюсь разработать, - это приложение для работы с электронной почтой на рабочем столе.

Слева находится вертикальное меню (на q-ящике квазара).

Далее также слева есть список рассылки (в q-списке квазара внутри q-ящика).

Когда выбран каждый элемент, соответствующий контент отображается справа (на q-странице квазара).

Ожидаемая операция:

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

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

Проблема:

Когда Я выбираю первый элемент в списке рассылки, он работает правильно, и, как и ожидалось, содержимое почты отображается на странице q.

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

Uncaught (в обещании) NavigationDuplicated {_name: "NavigationDuplicated", имя: "NavigationDuplicated", сообщение: "Переход к текущему местоположению (" / mailcontent ") не разрешено ", стек:" Ошибка при новом дублировании Navigation (int-packpack / node_modules / vue / dist / vue .runtime.esm. js: 1853: 26) "}

I Буду признателен за предложения по решению этой проблемы.

Следующий код предназначен для иллюстрации проблемы в основной части:

Маршруты : secondlayout является ребенок другой макет

const routes = [
  {
    path: "/index",
    component: () => import("layouts/AppLayout.vue"),
    children: [
      { path: "/home", component: () => import("pages/Home.vue") },
      {
        path: "secondlayout",
        component: () =>  import("Layouts/MailsPlace.vue"),
        children: [
            { path: "/mailcontent",  name: 'mailcontent', component: () => import("pages/MailContent.vue") },
        ]
      }
    ]
 }
];

Второй макет, в котором приложение электронной почты (список и содержимое) отображается с q-ящиком и видом маршрутизатора

<template>
    <q-layout view="lhh LpR lff" container class=" myclass shadow-2 window-height" >

        <q-drawer
            style="full-height"
            v-model="drawerLeft"
            :width="500"
            :breakpoint="700"
            elevated
            content-class="bg-grey-1"
          >
        <q-scroll-area 
            class="fit" 
            style="margin-top:80px">

             <q-list separator padding>
                  <q-separator />
                        <list-mails 
                            v-for="(mail, index) in mails" 
                            :mail="mail"                                                 
                            :key="mail.id_mail"
                            :id="index">
                        </list-mails>
                    <q-separator />
            </q-list> 
        </q-scroll-area>
      </q-drawer>

      <q-page-container>          
           <router-view></router-view>          
      </q-page-container>

</template>

<script>

export default {
  data () {
    return {        
      mails: {},

      drawerRight: false,
    }
  },

/*  watch: {
    $route(to, from) {
      console.log('after', this.$route.path);
    }
  },   
  beforeRouteUpdate(to, from, next) {
    console.log('before', this.$route.path);
    next();
  },*/          


    components: {            
        'list-mails': require("pages/ListMails.vue").default,
    },

   created: function() {
       this.listMails()
    },

    methods: {        
        listMails(){
           this.$axios.get("/listmails")        
            .then(response => {             
              if (response.data.success) {
                  this.mails = response.data.mails.data;
              } else {
                 showErrorNotify('msg');
              }
            })
            .catch(error => {         
              showErrorMessage(error.message); 
            });
        }
    }
</script>

Элемент списка рассылки с методом mailitemclick

<template>
        <q-item 
            clickable 
            v-ripple 
            exact 
            @click="mailitemclick(mail.id_mail)"
         >
          <q-item-section>
               <q-item-label side lines="2"> {{ mail.title_mail }}</q-item-label>
          </q-item-section>
      </q-item>

</template>

<script>
    export default { 
      props: ["mail"],
       methods:{
            mailitemclick(id){                
                 this.$router.push({
                     name: 'mailcontent', 
                     params: {id:id}
                });
            }
        }
    }
</script>

Содержимое почты

<template>            
      <q-page class="fit row wrap justify-center tems-start content-start" style="overflow: hidden;">
          <div style="padding:5px; margin:0px 0px 20px 0px; min-width: 650px;  max-width: 700px;" >
              <q-item>
                <q-item-label class="titulo"> {{ mail.title_mail }} </q-item-label>
                 <div v-html="mail.content_mail"></div>
                </q-item>
            </div>
      </q-page>
</template>

<script>

export default {
  name: 'mailcontent',
  data() {
  return { 
    mail: {},
    };
  },

  created() {
        this.$axios.get(`/mailcontent/${this.$route.params.id}`)                
        .then(response => {              
          if (response.data.success) {
              this.mail = response.data.mail[0])
          } else {
                 showErrorNotify('msg');
          }
        })
        .catch(error => {         
          showErrorMessage(error.message); 
        });
    }
}
</script>

1 Ответ

1 голос
/ 20 января 2020

Это случилось со мной, когда у меня был router-link, указывающий на тот же маршрут. например, /products/1.

Пользователь может щелкнуть по продуктам, но если продукт уже был нажат (и представление компонента уже загружено), и пользователь пытается щелкнуть его снова, в консоли отображается сообщение об ошибке / предупреждение.

Вы можете решить эту проблему, добавив catch block.

    methods: {
        mailitemclick(id) {
            this.$router.push({
                name: 'mailcontent',
                params: {'id': id}
            }).catch(err => {});

        }
    },

Но в mail-content вам необходимо использовать watch для вызова функции и смонтирован для первого вызова.

Пример Temp -

    data() {
        return {
            mail: {},
            test_mails: {
                12: {
                    content_mail: '<div>test 12<div>'
                },
                122:{
                    content_mail: '<div>test 122<div>'
                }
            }
        }
    },
    mounted() {
        this.mail = this.test_mails[this.$route.params.id]
    },
    watch:{
        '$route':function () {
            this.mail = this.test_mails[this.$route.params.id]
        }
    }

ИЛИ

Вы можете использовать :to в списке рассылки, чтобы избежать нажмите и поймайте -

<q-item
    clickable
    v-ripple
    exact
    :to="'/mailcontent/'+mail.id_mail"
  >
    <q-item-section>
      <q-item-label side lines="2"> {{ mail.title_mail }}</q-item-label>
    </q-item-section>
  </q-item>


children: [
  { path: '', component: () => import('pages/Index.vue') },
  {
    path: "secondlayout",
    component: () =>  import("layouts/mail-place.vue"),
    children: [
        { path: "/mailcontent/:id",  name: 'mailcontent', component: () => import("pages/mail-content.vue") },
    ]
  }
]
...