programing

구성 요소 재렌더에서 Vue.js 무한 루프

copysource 2022. 8. 28. 19:12
반응형

구성 요소 재렌더에서 Vue.js 무한 루프

이전 컴포넌트에서 선택한 몇 가지 속성을 기반으로 테이블을 작성하려고 합니다.XML 파일과 해당 속성 및 값을 비교하기 위해 'branch-comparison'이라는 구성 요소를 렌더링하고 있습니다.이 컴포넌트에는 다음 두 가지 소품이 있습니다.

selected Envs: 이름과 오브젝트가 있는 오브젝트 배열

공통 파일:이름과 객체가 있는 파일 배열

vue-tables-2로 테이블을 만들고 있습니다.템플릿의 맨 위에서 getProps()라는 함수를 실행하여 각 파일에서 가능한 모든 속성 세트를 생성합니다.현재 사용자가 한 번에 하나의 파일만 선택할 수 있도록 하기 때문에 0으로 하드코딩했습니다.그런 다음 각 파일(1개만)을 통과하여 메인 테이블과 비교 테이블에 대한 데이터를 가져옵니다.이들 기능은 사실상 동일하지만(getHeadData와 getTableData), 추가 커스터마이즈를 위해 일단 분리했습니다.이 코드는 실제로 테이블을 생성하는 데는 그다지 중요하지 않지만, 그 안에 있는 어떤 것이 내 코드를 무한 루프 상태로 만듭니다.

컴포넌트의 초기 렌더링에서는 무한 루프가 존재하지 않습니다.모든 것이 관통하고 전혀 파손되지 않고 훌륭하게 작동합니다.그러나 컴포넌트가 렌더링되고 소품을 변경하거나 단순히 파일을 에디터에 저장하고 vue-cli가 핫 새로고침하면 무한 루프 상태가 됩니다.모든 데이터는 정상적으로 생성되고 컴포넌트는 정상적으로 동작합니다.하지만 무슨 일이 있어도 101번 반복됩니다.

제가 조사한 내용:

데이터 변경:데이터 변경 시 컴포넌트가 렌더링되는 것을 충분히 이해했습니다.그러나 메서드 호출에서 반응성 데이터를 변경할 수는 없습니다.함수 내에서 로컬로 선언하고 임시 변수로 되돌리는 것 뿐입니다., 이 경우, 초기 컴포넌트 부하로 무한 루프 상태가 될 이라고 생각합니다만, 그렇지 않습니다.리프레시 또는 프로펠러 변경 시에만 무한 루프에 들어갑니다.

Vuex 상태 변환:나는 이것을 조사했지만, 나는 어떤 상태도 바꿀 수 없다.단순히 getTableData 및 getHeadData 메서드로 접근합니다.그런 다음 이 상태 객체를 가리키도록 변수를 할당하면 해당 개체가 해당 상태에 액세스하는 무언가에 기반하여 다시 렌더링될 수 있다고 생각했기 때문에 대신 시도했습니다.

this.$store.state.branchesToCompare[branchIdx].obj[env.name].app_config[this.commonFiles[fileIdx]].forEach(envProp
=> {

사용하다

var x = JSON.parse(JSON.stringify(this.$store.state.branchesToCompare[branchIdx].obj[env.name].app_config[this.commonFiles[fileIdx]])

그리고나서

x.forEach(envProp =>

그래도 안 돼요.

getHeadData() 및 getTableData()를 호출하는 코드를 코멘트 아웃하면 적절한 시간 내에 루프됩니다.

여기 암호가 있습니다.저는 아직 Vue에 익숙하지 않기 때문에 더 일반적인 제안이 있으면 기꺼이 받아 들일 수 있습니다.

 <template>
   <div id="BranchComparison">
      <div :set="info = getProps(0)">
         <div class="file" v-for="(file, fileIdx) in commonFiles" :key="(file, fileIdx)">
            <h3>{{ file }} </h3>
            <b-row :set="mainTable = getHeadData(fileIdx, info.props, info.columns)">
               <b-col class="mainBranch">
                  <h5 class="fileName"> {{ $store.state.branchSelection.split('.').slice(0, -1).join('.') }} <span style="font-size: 14px;">vs </span> </h5>
                  <v-client-table
                     :data="mainTable.data"
                     :columns="mainTable.columns"
                     :options="mainTableOptions"
                     size="small"
                  ></v-client-table>
               </b-col>
               <b-col class="compareBranch" v-for="(branch, branchIdx) in $store.state.branchesToCompare" :key="(branch, branchIdx)">  
                  <h5> {{ branch.name.split('.').slice(0, -1).join('.') }} </h5>
                  <v-client-table
                     :set="temp = getTableData(fileIdx, branchIdx, info.props, info.columns, mainTable)"
                     :data="temp.data"
                     :columns="temp.columns"
                     :options="temp.options"
                     size="small"
                  ></v-client-table>
               </b-col>
            </b-row>
         </div>
      </div>
   </div>
</template>

<script>

export default {

   props: ['selectedEnvs', 'commonFiles'],

   data(){
      return{
         mainTableOptions:{
            filterable: false,
            filterByColumn: false,
            perPage: 200,
            pagination: {
               show: false,
               dropdown: false
            },
            sortable: [''],
            resizableColumns: false,
         },
      }  
   },

   methods: {
      getTableData(fileIdx, branchIdx, props, columns, mainTable){

         var data = []

         var compareTableOptions = {
            filterable: false,
            perPage: 200,
            pagination: {
               show: false,
            },
            sortable: [''],
            hiddenColumns: ['Property'],
            resizableColumns: false,
            cellClasses: {}
         }


         props.forEach(prop => {
            var temp = { Property: prop }
            this.selectedEnvs.forEach(env => {
               var found = false;
               this.$store.state.branchesToCompare[branchIdx].obj[env.name].app_config[this.commonFiles[fileIdx]].forEach(envProp => {
                  if(envProp){
                     if (prop == envProp["@name"]) {
                        compareTableOptions.cellClasses[env.name] = []
                        compareTableOptions.cellClasses[env.name].push({
                           class: 'same',
                           condition: row => {
                              try{
                                 return row[env.name] == mainTable.data[i][env.name]
                              } catch{
                                 console.log('This is a different problem ')
                              }
                           }
                        })
                        found = true;
                        temp[env.name] = envProp["@value"]
                     }
                  }
               });
               if (!found){
                  temp[env.name] = 'Not found'
               } 
            })
            data.push(temp)
         });

         return {
            columns: columns,
            data: data,
            options: compareTableOptions
         }
      },

      getHeadData(fileIdx, props, columns){
         var data = []
         props.forEach(prop => {
            var temp = { Property: prop }
            this.selectedEnvs.forEach(env => {
               var found = false;
               this.$store.state.jsonObject[env.name].app_config[this.commonFiles[fileIdx]].forEach(envProp => {
                  if(envProp){
                     if (prop == envProp["@name"]) {
                        found = true;
                        temp[env.name] = envProp["@value"]
                     }
                  }
               });
               if (!found){
                  temp[env.name] = 'Not found'
               } 
            })
            data.push(temp)
         });

         return {
            columns: columns,
            data: data
         }
      },

      getProps(fileIdx){

         if(this.commonFiles.length == 0) return

         var columns = ['Property']
         var props = new Set()

         this.selectedEnvs.forEach((env, idx) => {
            columns.push(env.name)
            this.$store.state.branchesToCompare.forEach(branch => {
               branch.obj[env.name].app_config[this.commonFiles[fileIdx]].forEach(prop => {
                  if(prop){
                     props.add(prop["@name"])
                  }
               })
            });
            this.$store.state.jsonObject[env.name].app_config[this.commonFiles[fileIdx]].forEach(prop => {
               if(prop){
                  props.add(prop["@name"]);
               }
            });
         });

         var ret = { props: props, columns: columns }

         return ret;
      }
   }
}

</script>

생산품

해결했어요.위의 코드는 사실 괜찮습니다.코드를 게시하기 직전에 getHeadData()의 v-for AND에서 계산된 속성을 사용하고 있었습니다.내부 루프에서 다시 계산한 후 외부 루프를 다시 시도하는 등의 작업을 수행했습니다.왜 첫 번째 렌더링에서 효과가 있는지 아직 잘 모르겠습니다만, 아, 그렇군요.지금 되고 있어요.

언급URL : https://stackoverflow.com/questions/64070051/vue-js-infinite-loop-on-component-re-render

반응형