Vue.js 如何防止在Vue js中更改参数化子组件时重新加载父组件

Vue.js 如何防止在Vue js中更改参数化子组件时重新加载父组件,vue.js,vuejs2,vue-component,vue-router,Vue.js,Vuejs2,Vue Component,Vue Router,我有一个页面,其中包含证券列表(子组件)的ClientPortfolio(父组件)加载到v-data-table列表中 我遇到的问题是,每次单击列表中的安全性时,ClientPortfolio都会被完全重新加载,导致整个列表被刷新,导致scroll和所选类被重置,以及不必要的性能开销。 我查看了Vue的文档,但似乎没有任何内容指出如何仅在子组件具有参数时刷新它。看起来父组件正在刷新,因为每次选择安全性时路由都在更改,尽管希望Vue只知道子组件(嵌套路由)正在更改,因此只需重新加载子组件 我得

我有一个页面,其中包含证券列表(子组件)的ClientPortfolio(父组件)加载到v-data-table列表中

我遇到的问题是,每次单击列表中的安全性时,ClientPortfolio都会被完全重新加载,导致整个列表被刷新,导致scroll和所选类被重置,以及不必要的性能开销。 我查看了Vue的文档,但似乎没有任何内容指出如何仅在子组件具有参数时刷新它。看起来父组件正在刷新,因为每次选择安全性时路由都在更改,尽管希望Vue只知道子组件(嵌套路由)正在更改,因此只需重新加载子组件

我得到的最接近的答案是在代码中没有解释如何实现这一点的解释

routes.js:

ClientPortfolions.vue中的路由器链接:

更新


经过一段时间的更新,我终于找到了问题所在,@matpie在其他地方指出,我发现我的App.vue是罪魁祸首,因为在应用程序的根目录中有一个:key add:
这是一个我从某处使用的模板,但在“工作”时,我从不需要查看它,取下钥匙后,一切正常,标记matpie应答已接受。

而不是在此处使用路由器。为所选证券和投资组合在根级别声明两个变量

根据所选投资组合列出证券

从显示的证券中选择证券时,使用

this.$root.selectedSecurityId = id;
您可以在安全组件级别使用
watch

从根本上说

<security selectedid="selectedSecurityId" />
组件将如下所示:

<portfolio>
  //active. list goes here
</portfolio>
........
<security selectedid="selectedSecurityId">
//info goes here
</security>

//活跃的。清单在这里
........
//信息在这里

上述方法将有助于避免路由器。希望这会有所帮助。

我曾经遇到过类似的问题。在我看来,这是由路径字符串解析引起的。 尝试为路线设置名称。并用对象替换路由器链接到参数。 并移除路由器视图
:键
道具。它不需要在那里。它用于在管线更改时强制更新零部件。这通常是坏代码的标志。您的组件(
安全性
)应该对路由参数更新做出反应。不是父组件强制它

因此,请尝试将代码更改为:

路线:[
{
路径:'/client/:clientno/portfolioNo',
组成部分:客户组合,
name:“ClientPortfoliosName”//它可以是您想要的任何东西。它只是内部使用的别名。
儿童:[
{ 
路径:“security/:securityNo”,
名称:“投资组合”,无论如何,考虑将路由名称作为良好的实践。
构成部分:安全
}
]     
}, 
]

它应该会起作用


注意:在您的
路由器链接中
您应指向您想要导航到的路线。在这种情况下,Vue.js中的默认行为是防止组件重新加载。Vue的反应性系统自动映射属性依赖关系,并且只执行最少量的工作来确保DOM是最新的

通过在任意位置使用
:key
属性,您可以告诉Vue.js,此元素或组件应仅在键匹配时匹配。如果密钥不匹配,旧密钥将被销毁,并创建一个新密钥

看起来您还在数据对象上引入路由参数(
Security.vue
)。这些参数不会在管线参数更改时更新,您应该将它们拉入计算属性,以便它们始终保持最新

导出默认值{
计算:{
clientNo:(vm)=>vm.$route.params.clientNo,
}
}
这将确保
clientNo
始终匹配路由器中找到的内容,而不管Vue是否决定重新使用此组件实例。如果在
clientNo
更改时需要执行其他副作用,可以添加观察者:

vm.$watch(“clientNo”,(clientNo)=>{/*…*/})

删除安全组件的本地注册后,是否可以再次检查?因为这是由vue路由器本身处理的,所以不需要它

components: { // delete this code

      security: Security
    },

您可以提供JSFIDLE或等效工具吗?使用vuex存储当前选定的安全性是否比使用路由器加载子组件更容易?然后,只要vuex store属性更改,您就可以抓取子数据。这将如何解决在安全性更改时重新加载ClientPortfolio的问题?我可以vuex存储证券等,但父组件仍然需要重新加载一次。此外,我在每个投资组合中都有数千种证券,我不认为vuex设计用于存储如此多的od数据。如果您可以共享更多代码,那就太好了。您是否尝试过使用以下代码包装组件:您的顶层上碰巧没有定义:键?如果是这样的话,这可能就是问题所在。但是如果没有路由器,用户可以拥有特定证券的最终url,而不需要浏览客户和投资组合吗?为了安全起见,复制和粘贴url对于用户通过电子邮件/聊天等进行交流非常重要。这是一种非常好的方法。为此,我们可以在路由器中加载一个页面,从url读取传递的安全性和公文包,并相应地加载。如果未传递任何安全id或投资组合,则显示默认页面。设置将信息作为URL的一部分传递时的顶级变量。使用类似于
/
的URL。因此,您可以避免使用静态关键字。但是使用此。$root.selectedSecurityId=id更新安全性将如何更新路由?我不明白it@Kajal... 你可以用gists,只要你想做什么就做什么
<template>
  <v-flex>
    <v-layout class="screen-header">
      <v-flex class="screen-title">Security Details </v-flex>

    </v-layout>
    <v-divider></v-divider>
    <v-layout align-center justify-space-between row class="contents-placeholder" mb-3 pa-2>
      <v-layout column>
        <v-flex class="form-group" id="security-portfolio-selector">
          <label class="screen-label">Sequence</label>
          <span class="screen-value">{{security.SequenceNo}}</span>
        </v-flex>
        <v-flex class="form-group">
          <label class="screen-label">Security</label>
          <span class="screen-value">{{security.SecurityNo}}-{{security.SequenceNo}}</span>
        </v-flex>

        <v-flex class="form-group">
          <label class="screen-label">Status</label>
          <span class="screen-value-code" v-if="security.Status !== ''">{{security.Status}}</span>
        </v-flex>
      </v-layout>

    </v-layout>

  </v-flex>

</template>
<script>
  export default {
    props: ['securityNo'],
    data () {
      return {
        clientNo: this.$route.params.clientno,
        securityDetailsLoading: false
      }
    },
    computed: {
      security () {
        return this.$store.state.SecurityDetails
      }
    },

    created () {
      if (this.securityNo.length > 1) {
        this.getSecurityDetails()
      }
    },

    methods: {
      getSecurityDetails: function () {
        let self = this
        this.securityDetailsLoading = true

        this.$store.dispatch('getSecurityDetails', {
          securityNo: this.securityNo,
          clientNo: this.clientNo

        }).then(function (serverResponse) {
          self.securityDetailsLoading = false
        })
      }
    }
  }
</script>
const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      component: Dashboard
    },
    {
      path: '/client/:clientno/details',
      component: Client,
      props: true
    },

    {
      path: '/client/:clientno/portfolios/:portfolioNo',
      component: ClientPortfolios,
      name: 'ClientPortfolios',
      children: [
        { path: 'security/:securityNo',
          component: Security,
          name: 'Security'
        }
      ]
    }
  ]
})
this.$root.selectedSecurityId = id;
<security selectedid="selectedSecurityId" />
....
watch:{
   selectedid:function(){
   //fetch info and show
   }
}
... 
<portfolio>
  //active. list goes here
</portfolio>
........
<security selectedid="selectedSecurityId">
//info goes here
</security>
components: { // delete this code

      security: Security
    },