在另一个布局中呈现的布局中,从列表到页面连续绑定列表项值

Successively bind list item values, from list to page, in a layout rendered within another layout

桌面电子邮件应用程序是说明我正在尝试开发的最佳示例。

左侧有一个垂直菜单(在 quasar q-drawer 上)。

接下来,同样在左侧,有一个邮件列表(在 q-drawer 中的类星体 q-list 上)。

当每个项目被select编辑时,相应的内容会显示在右侧(在类星体q页面上)。

预期操作:

列表加载一次,当我连续select列表中的各个项目时,只应使用右侧的内容,并根据请求中作为参数发送的id更新内容.

请注意,列表组件只渲染一次;也就是说,每次从列表中 select 编辑一个项目时,它都不会再次呈现,并且在内容显示在右侧时保持可见

问题:

当我 select 邮件列表中的第一项时,它按预期正常工作,邮件内容显示在 q-page 上。

当我 select 列表中的第二个项目时,它不再起作用,控制台上显示以下错误:

Uncaught (in promise) NavigationDuplicated {_name: "NavigationDuplicated", name: "NavigationDuplicated", message: "Navigating to current location ("/mailcontent") is not allowed", stack: "Error at new NavigationDuplicated (webpack-int…node_modules/vue/dist/vue.runtime.esm.js:1853:26)"}

我将不胜感激有关如何解决此问题的建议。

以下代码主要是为了说明主要部分的问题:

路由: 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-drawer 和 router-view

<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>

当我有一个 router-link 指向同一条路线时,这发生在我身上。例如/products/1.

The user is able to click on the products, but if a product was already clicked (and the component view was already loaded) and the user attempts to click it again, the error/warning shows in the console.

您可以通过添加 catch 块来解决此问题。

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

        }
    },

但是在mail-content中,调用函数需要使用watch,首次调用需要使用mounted

临时示例 -

    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") },
    ]
  }
]