Vue.js踩雷:坑爹的Component

在一个新项目里开始边学边用Vue.js和TypeScript,之后发现了一个让人非常难受的问题。

比对项目创建后默认的页面(我是使用Vue-Cli建的工程),自己写了一个Router,但是发现Router只要导入了新页面,新页面100%覆盖旧页面,根本无法正常路由、导航。

再三比对了各种代码,且经过了将近5小时的查资料和奋斗之后,仍然无果。在随便的胡乱尝试中,偶然发现了一个让人吐血的问题。

Components

在Vue.js里页面是通过一个一个的Component组织起来的,在TypeScript下每一个Component的导出可以采用Class写法。

也就是这个样子:

1
2
export default Class A {
}

微软在TypeScript上融合了很多.Net的东西,为了让.Net程序员能顺利过渡到JavaScript,微软其实在语法上的改动还是很多,习惯JavaScript ES5/6语法,用TypeScript反而会感到不适。

和C#比较类似,由于微软在TypeScript中引入了Class这么一个概念,自然这个Class也是可以继承的。在Vue框架下,如果要在页面上应用一个Component,Component必须继承基本的Vue,写法大概是这个样子的:

1
2
export default Class A extends Vue {
}

由于项目默认页面带来的误导,我起初认为一个页面应该就可以直接这样导出,并且在Router内导入。

但实际上不是这样!

坑爹的TypeScript实际上只允许一个页面(在SPA下就是主页面)这么写,在SPA的开发下,其他页面都应该使用Component的写法,当作Component进行处理。

没有当作Component处理的页面会被当作新的默认页面引入Router,覆盖掉原有的内容。

因而此处要加一行声明:

1
2
3
@Component
export default Class A extends Vue {
}

否则在Router动态导入这个页面的时候,会发生一个神奇的页面覆盖导致。

关于Router-view的刷新

起初以为是router-view的问题,在查询了资料之后在router-view上绑定了一个key值,并采用下面的方法通过随机key值强制刷新了router-view:

1
2
3
4
5
6
7
computed: {
key() {
return this.$route.name !== undefined
? this.$route.name + +new Date()
: this.$route + +new Date();
}
}

强制刷新看上去确实能解决问题,但是实际上并不能,因为虽然key值被改变了,但是Router并不会替换其中应该替换的Component,而是将整个页面的元素覆盖成了新导入的内容。

在修复这个路由问题之后,不强制刷新也是可以正常路由的。