在typescript + vue-class-component的语法下如何实现组件递归(recursive)

      为了实现递归显示某种类似树形结构的数据,我调研了下vue的技术,主要是使用递归组件的方法,即在组件内部又去调用自己,查了下网上网友的代码,找到的都是传统的js写法,如下图所示:

 <template>
   <div class="dicom-items">
     <div v-if="dicomItems && dicomItems.length > 0">
         <el-row  v-if="depth ==0" class="dicomItemHeader" >
           <div class="dicomTag">Tag</div> 
           <div class="dicomName" >Name</div> 
           <div class="dicomValue">Value</div>
        </el-row>
        <div v-for="(item,i) in dicomItems" v-bind:key="'item_'+i">
           <el-row class="dicomItem" >
           <div class="dicomTag">
                <span v-if="depth>0">&gt;</span>
               <a :href="dicomDictLink(item.Tag)" target="_blank">{{item.Tag}}</a>
           </div> 
           <div class="dicomName smallscrollbar">{{item.Name}}</div> 
           <div class="dicomValue smallscrollbar">{{item.Value}}</div>
           </el-row>
           <el-row v-if="item.Sequence && item.Sequence.length > 0">
                 <dicomitems :itemList="item.Sequence" :depth="depth+1" >  </dicomitems>
           </el-row> 
        </div>
     </div>
   </div>
</template>
<script lang="ts">
export default {
   name : "dicomitems",
   props: {
     itemList : Array ,
     depth : Number
   },
   data : (): any => {
     return {
            dicomItems : []
        }
   },    
   watch: {
     itemList : function(val: any):void {
      console.log(`itemList.length=${val.length}`);
      (this as any).dicomItems = val;
     }
   },
   mounted: function():void {
      console.log(`itemList.length=${(this as any).itemList.length}`);
      (this as any).dicomItems = (this as any).itemList;
   },
   methods: {
      dicomDictLink: (tag: string):string => 
     {
      return "https://dicom.innolitics.com/ciods/";
     }
   }
}

</script>

    后来,我替换采用typescript + vue-class-component写法时发现出现问题,即第一层的数据都可以正常显示,但递归的子组件没有任何显示 (注:使用npm run serve进行调试时可以正常显示,但一旦npm run build部署到生产环境就不显示),代码如下所示

 <template>
   <div class="dicom-items">
     <div v-if="dicomItems && dicomItems.length > 0">
         <el-row  v-if="depth ==0" class="dicomItemHeader" >
           <div class="dicomTag">Tag</div> 
           <div class="dicomName" >Name</div> 
           <div class="dicomValue">Value</div>
        </el-row>
        <div v-for="(item,i) in dicomItems" v-bind:key="'item_'+i">
           <el-row class="dicomItem" >
           <div class="dicomTag">
                <span v-if="depth>0">&gt;</span>
               <a :href="dicomDictLink(item.Tag)" target="_blank">{{item.Tag}}</a>
           </div> 
           <div class="dicomName smallscrollbar">{{item.Name}}</div> 
           <div class="dicomValue smallscrollbar">{{item.Value}}</div>
           </el-row>
           <el-row v-if="item.Sequence && item.Sequence.length > 0">
                 <dicomitems :itemList="item.Sequence" :depth="depth+1" >  </dicomitems>
           </el-row> 
        </div>
     </div>
   </div>
</template>
<script lang="ts">
import { Component, Prop, Vue,Watch } from 'vue-property-decorator';

@Component
export default class DicomItems extends Vue{
 @Prop({}) itemList!:[]
 @Prop({}) depth!: number
 
dicomItems = []

@Watch("itemList")
onItemListChange(newVal:[], oldVal:[]) {
   console.log(`itemList.length=${newVal.length}`);
   (this as any).dicomItems = newVal;
 }

 mounted():void {
      //debugger;
      console.log(`itemList.length=${this.itemList.length}`);
      this.dicomItems = this.itemList;
   }

 dicomDictLink(tag: string):string { 
      return "https://dicom.innolitics.com/ciods/";
 }

}

</script>

  经过排查后,问题解决,关键点在name, 代码如下

@Component({name:"dicomitems"})
export default class DicomItems extends Vue
......

 

 

posted on 2021-06-15 13:08  omage  阅读(74)  评论(0编辑  收藏  举报