У меня есть страница, где ClientPortfolio (родительский компонент), содержащий список ценных бумаг (дочерний компонент), загружаются в список v-data-table.
У меня проблема в том, что ClientPortfolio полностью перезагружается каждый раз, когда я щелкаю по безопасности в списке, в результате чего обновляется весь список, что приводит к сбросу прокрутки и выбранного класса, а также к ненужным потерям производительности. Я посмотрел документацию по Vue, и, кажется, ничто не указывает на то, как обновлять дочерний компонент только тогда, когда у него есть параметры, похоже, что родительский компонент обновляется при изменении маршрута каждый раз, когда выбирается защита, несмотря на то, что Vue будет знать, что меняется только sub (вложенный маршрут), следовательно, нужно только перезагрузить дочерний компонент
Самый близкий ответ, который я получил, был объяснен на https://github.com/vuejs/vue-router/issues/230, который не объясняет в коде, как этого добиться.
routes.js:
routes: [
{
path: '/client/:clientno/portfolios/:portfolioNo',
component: ClientPortfolios,
children: [
{ path: 'security/:securityNo', component: Security }
]
},
]
Ссылка на маршрутизатор в 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>
Представление маршрутизатора (для компонента безопасности) в ClientPortfolios.vue:
<v-flex xs10 ml-2>
<v-layout>
<router-view :key="$route.fullPath"></router-view>
</v-layout>
</v-flex>
Любой совет о том, как предотвратить перезагрузку родителей, приветствуется.
РЕДАКТИРОВАТЬ: Пытаясь приблизиться к проблеме, я замечаю, что атрибут "Ключ" в ClientPortfolios изменяется (как показано в окне отладки Vue выше) всякий раз, когда я меняю Security, может ли это быть причиной? Есть ли способ назначить ключ компоненту 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>
Security.vue
<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>
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'
}
]
}
]
})
ОБНОВЛЕНИЕ:
Просто чтобы обновить это, как это было давно, я наконец-то узнал, в чем проблема, о чем @matpie указал в другом месте, я обнаружил, что мой App.vue является виновником, где есть: ключ, добавляемый к сам корень приложения: <router-view :key="$route.fullPath"/>
это был шаблон, который я использовал откуда-то, но мне никогда не приходилось смотреть, как он работал, после удаления ключа все работает Как и положено, маркировка Matpie ответа принята.