在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">></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">></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
......