programing

Vue js에서 매개 변수화된 하위 구성 요소를 변경할 때 상위 구성 요소가 다시 로드되지 않도록 하는 방법

newsource 2022. 8. 12. 23:28

Vue js에서 매개 변수화된 하위 구성 요소를 변경할 때 상위 구성 요소가 다시 로드되지 않도록 하는 방법

v-data-table 목록에 Securities(하위 구성 요소) 목록이 포함된 ClientPortolio(상위 구성 요소)가 로드된 페이지가 있습니다.

여기에 이미지 설명 입력

여기서 발생하는 문제는 목록 내의 보안을 클릭할 때마다 ClientPortolio가 완전히 새로고침되어 목록 전체가 새로고침되고 스크롤 및 선택한 클래스가 리셋되며 불필요한 성능 오버헤드가 발생한다는 것입니다.Vue의 매뉴얼을 살펴보았는데 파라미터가 있는 경우 하위 컴포넌트만 새로 고치는 방법을 나타내는 것은 아무것도 없는 것 같습니다.Vue는 하위(네스트된 루트)만 변경되므로 다시 작성하기만 하면 된다는 것을 알 수 있지만 보안이 선택될 때마다 경로가 변경되면 상위 컴포넌트가 새로 고쳐지는 것처럼 보입니다.자 컴포넌트를 로드하다

여기에 이미지 설명 입력

제가 받은 가장 가까운 답변은 https://github.com/vuejs/vue-router/issues/230에서 설명되었습니다.이것에는, 코드에 이것을 실현하는 방법이 기재되어 있지 않습니다.

routes.syslog:

routes: [
    {
      path: '/client/:clientno/portfolios/:portfolioNo',
      component: ClientPortfolios,
      children: [
        { path: 'security/:securityNo', component: Security }
      ]     
    }, 
  ]

ClientPortolios 라우터 링크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>

ClientPortolios의 라우터 뷰(보안 컴포넌트용).vue:

<v-flex xs10 ml-2>
      <v-layout>
          <router-view :key="$route.fullPath"></router-view>
      </v-layout>
    </v-flex>

부모가 새로고침되지 않도록 하는 방법에 대한 힌트를 주시면 감사하겠습니다.

편집: 이 문제에 접근하려고 하면 보안을 변경할 때마다 ClientPortfolios의 [Key] 속성이 (위의 [Vue]디버깅창에 나타나듯이) 변경되는 것을 알 수 있습니다.그것이 원인일까요?ClientPortfolios 컴포넌트에 키를 할당하는 방법이 있습니까?아니면 다른 증권으로 이동할 때 키를 업데이트하지 않는 방법?

업데이트: 풀코드

클라이언트 포트폴리오스표시하다

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

보안.표시하다

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

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가 다른 곳에서 지적한 것을 알 수 있었습니다만, 제 앱이 그 사실을 알게 되었습니다.vue는 응용 프로그램의 루트에 :key가 추가된 원인입니다.<router-view :key="$route.fullPath" />이것은 어딘가에서 사용한 템플릿이지만, 「작동중」이기 때문에 볼 필요가 없습니다.키를 떼어내면, 모든 것이 정상적으로 동작해, matpie의 회답이 받아들여집니다.

Vue.js에서는 컴포넌트 새로고침을 방지하는 것이 기본 동작입니다.Vue의 반응성 시스템은 속성 종속성을 자동으로 매핑하고 최소한의 작업만 수행하여 DOM을 최신 상태로 유지합니다.

「」를 사용해 .:keyattribute anywhere를 지정하면 키가 일치할 때만 이 요소 또는 컴포넌트가 일치해야 한다고 Vue.js에 알립니다.키가 일치하지 않으면 이전 키가 삭제되고 새 키가 생성됩니다.

오브젝트의 것 (이러한 파라미터는 데이터 오브젝트에 포함되어 있습니다.Security.vue루트 파라미터가 변경되어도 이들 파라미터는 갱신되지 않으므로 항상 최신 상태를 유지하기 위해 계산된 속성에 풀인해야 합니다.

export default {
  computed: {
    clientNo: (vm) => vm.$route.params.clientno,
  }
}

하면 「 」는 할 수 .clientNo는 Vue가 이 컴포넌트인스턴스를 재사용할지 여부에 관계없이 항상 라우터에 있는 내용과 일치합니다. clientNo을 사용하다

vm.$watch("clientNo", (clientNo) => { /* ... */ })

보안 컴포넌트의 로컬 등록을 삭제한 후 다시 확인해 주시겠습니까?이는 vue 라우터 자체에 의해 처리되기 때문에 필요하지 않습니다.

components: { // delete this code

      security: Security
    },

여기서 라우터를 사용하는 대신.선택한 보안 및 포트폴리오에 대해 루트 레벨에서 두 가지 변수를 선언합니다.

선택한 포트폴리오를 기준으로 유가증권을 나열합니다.

표시된 증권에서 보안을 선택할 때 루트 변수를 업데이트한다.

this.$root.selectedSecurityId = id;

watch보안 컴포넌트 레벨로 설정합니다.

근본적으로는

<security selectedid="selectedSecurityId" />

" " " 。security ,

....
watch:{
   selectedid:function(){
   //fetch info and show
   }
}
... 

구성 요소는 다음과 같습니다.

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

위의 접근방식은 라우터를 회피하는 데 도움이 됩니다.이게 도움이 되길 바라.

저도 비슷한 문제가 있었어요.IMO를 사용하다경로의 이름을 설정해 보십시오. 를 합니다.to. object을 param param param param param param param router-view를 삭제합니다.:key됩니다.루트가 변경되었을 때 컴포넌트를 강제로 갱신하기 위해 사용됩니다.이치노Security는 루트 는 루트 파라미터의 갱신에 응답합니다.부모 컴포넌트가 강제하지 않습니다.

따라서 코드를 다음과 같이 변경해 보십시오.

routes: [
    {
      path: '/client/:clientno/portfolios/:portfolioNo',
      component: ClientPortfolios,
      name: "ClientPortfoliosName", // it can be anything you want. It`s just an alias for internal use.
      children: [
        { 
           path: 'security/:securityNo', 
           name: "PortfolioSecurities", // anyway, consider setting route names as good practice
           component: Security 
        }
      ]     
    }, 
  ]
 <router-link tag="tr" style="cursor:pointer"
              :to="{ name: 'PortfolioSecurities', params: { clientno: $route.params.clientno, portfolioNo: selectedPortfolioSequenceNo, securityNo: props.item.SecurityNo+'-'+props.item.SequenceNo } }"
              :key="props.item.SecurityNo+props.item.SequenceNo">

            </router-link>

그리고 효과가 있을 거야

: ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」router-link이동하려는 경로를 가리켜야 합니다. 경우, 「 」PortfolioSecurities

언급URL : https://stackoverflow.com/questions/56126497/how-to-prevent-parent-component-from-reloading-when-changing-a-parameterised-chi