May*_*aya 13 vue.js vue-router vue-component vuejs2
我有一个页面,其中将包含证券(子组件)列表的ClientPortfolio(父组件)加载到v数据表列表中。
我遇到的问题是,每次我单击列表中的安全性时,ClientPortfolio都会完全重新加载,从而导致整个列表被刷新,从而导致滚动和所选类重置,以及不必要的性能开销。我看过Vue的文档,似乎没有什么能指出如何仅在具有参数的情况下刷新子组件的,看起来每次路由选择安全性时都会随着路由的更改而刷新父组件。 Vue 知道只有子(嵌套路由)在变化,因此只需要重新加载子组件
我得到的最接近的答案在https://github.com/vuejs/vue-router/issues/230上进行了说明,该代码未在代码中说明如何实现此目的。
route.js:
routes: [
{
path: '/client/:clientno/portfolios/:portfolioNo',
component: ClientPortfolios,
children: [
{ path: 'security/:securityNo', component: Security }
]
},
]
Run Code Online (Sandbox Code Playgroud)
ClientPortfolios.vue中的路由器链接:
<router-link tag="tr" style="cursor:pointer"
:to="`/client/${$route.params.clientno}/portfolios/${selectedPortfolioSequenceNo}/security/${props.item.SecurityNo}-${props.item.SequenceNo}`"
:key="props.item.SecurityNo+props.item.SequenceNo">
</router-link>
Run Code Online (Sandbox Code Playgroud)
ClientPortfolios.vue中的路由器视图(用于安全组件):
<v-flex xs10 ml-2>
<v-layout>
<router-view :key="$route.fullPath"></router-view>
</v-layout>
</v-flex>
Run Code Online (Sandbox Code Playgroud)
任何有关如何防止父母被重新加载的提示表示赞赏。
编辑:试图更接近该问题,我注意到,每当我更改安全性时,ClientPortfolios中的“关键”属性都会更改(如上面的Vue调试窗口所示),这可能是原因吗?尽管它不是子组件,是否可以将密钥分配给ClientPortfolios组件?还是在导航到其他证券时不更新其密钥的方法?
更新:完整代码
ClientPortfolios.vue
<template>
<v-layout row fill-height>
<v-flex xs2>
<v-layout column class="ma-0 pa-0 elevation-1">
<v-flex>
<v-select v-model="selectedPortfolioSequenceNo" :items="clientPortfolios" box label="Portfolio"
item-text="SequenceNo" item-value="SequenceNo" v-on:change="changePortfolio">
</v-select>
</v-flex>
<v-data-table disable-initial-sort :items="securities" item-key="Id" hide-headers hide-actions
style="overflow-y: auto;display:block;height: calc(100vh - 135px);">
<template slot="items" slot-scope="props">
<router-link tag="tr" style="cursor:pointer"
:to="{ name: 'Security', params: { securityNo: props.item.SecurityNo+'-'+props.item.SequenceNo } }"
>
</router-link>
</template>
<template v-slot:no-data>
<v-flex class="text-xs-center">
No securities found
</v-flex>
</template>
</v-data-table>
</v-layout>
</v-flex>
<v-flex xs10 ml-2>
<v-layout>
<keep-alive>
<router-view></router-view>
</keep-alive>
</v-layout>
</v-flex>
</v-layout>
</template>
<script>
import Security from '@/components/Security'
export default {
components: {
security: Security
},
data () {
return {
portfoliosLoading: false,
selectedPortfolioSequenceNo: this.$route.params.portfolioNo,
selectedPortfolio: null,
securityNo: this.$route.params.securityNo
}
},
computed: {
clientPortfolios () {
return this.$store.state.ClientPortfolios
},
securities () {
if (this.clientPortfolios == null || this.clientPortfolios.length < 1) {
return []
}
let self = this
this.selectedPortfolio = global.jQuery.grep(this.clientPortfolios, function (portfolio, i) {
return portfolio.SequenceNo === self.selectedPortfolioSequenceNo
})[0]
return this.selectedPortfolio.Securities
}
},
mounted () {
this.getClientPortfolios()
},
activated () {
},
methods: {
changePortfolio () {
this.$router.push({
path: '/client/' + this.$route.params.clientno + '/portfolios/' + this.selectedPortfolioSequenceNo
})
},
getClientPortfolios: function () {
this.portfoliosLoading = true
let self = this
this.$store.dispatch('getClientPortfolios', {
clientNo: this.$route.params.clientno
}).then(function (serverResponse) {
self.portfoliosLoading = false
})
}
}
}
</script>
Run Code Online (Sandbox Code Playgroud)
安全性
<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>
Run Code Online (Sandbox Code Playgroud)
router.js
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'
}
]
}
]
})
Run Code Online (Sandbox Code Playgroud)
更新:
刚刚更新了一段时间,我终于找到了问题所在,这是@matpie在其他地方指出的问题,我发现App.vue是在其中添加:key的罪魁祸首。应用程序的最根本部分:<router-view :key="$route.fullPath" />这是我从某个地方使用的模板,但是从不用看它是“正在工作”,删除密钥后,所有工作都按预期进行,从而标记了matpie答案。
阻止组件重新加载是Vue.js中的默认行为。Vue的反应性系统会自动映射属性依赖关系,并且仅执行最少的工作来确保DOM是最新的。
通过在:key任何地方使用属性,可以告诉Vue.js该元素或组件仅在键匹配时才匹配。如果密钥不匹配,则旧密钥将被销毁,而新密钥将被创建。
看起来您也在提取数据对象(Security.vue)上的路由参数。当路由参数更改时,这些参数不会更新,您应该将其添加到计算属性中,以便它们始终保持最新状态。
export default {
computed: {
clientNo: (vm) => vm.$route.params.clientno,
}
}
Run Code Online (Sandbox Code Playgroud)
这将确保clientNo始终匹配路由器中找到的内容,而不管Vue是否决定重用此组件实例。如果clientNo更改时需要执行其他副作用,则可以添加观察者:
vm.$watch("clientNo", (clientNo) => { /* ... */ })
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
964 次 |
| 最近记录: |