前言
本文介绍用vue2.6x+TypeScript+CompositionAPI开发web页面。
选择vue2,是因为我们的网页需要支持IE11,但是同时,我们又非常向往vue3那种组合式API的开发方式,所以我们用上@vue/composition-api这个插件。
如果条件允许,请直接上vue3,毕竟本文的这个方案,很多vue3的优秀新功能都没有,都算不上平替。都2022年了,还不用vue3?本文的方案也算是一种无奈之举。
最后,为了进一步写出规范的代码,减少出错的可能,我们再用上TypeScript,TypeScript的使用,处理更好的类型判断,最最重要的,是更好的面向接口编程。
将会学到
- vue2+TypeScript
- vue2的组合式API插件@vue/composition-api
开始实践
创建vue2 的ts项目
首先我们用vue-cli创建一个vue2的ts项目,创建时选择自定义,一路勾选上TypeScript、ESLint、vue2。这样,我们就得到了vue2+TypeScript的工程。
引入组合式API
安装@vue/composition-api。
npm install --save--dev @vue/composition-api
在main.ts加入@vue/composition-api插件。
import VueCompositionAPI from '@vue/composition-api'
Vue.use(VueCompositionAPI)
改写.vue文件的ts代码。
使用defineComponent
定义组件,以HomeView为示例。
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>{{ dataMsg }}</h2>
</div>
</template>
<script lang="ts">
import { ref, defineComponent } from '@vue/composition-api'
export default defineComponent({
name: 'HelloWorld',
props: {
msg: String
},
setup (props, context) {
console.log('context', context)
const dataMsg = ref('This is data msg')
return {
dataMsg
}
}
})
</script>
使用组合式API的注意事项
使用defineComponent为vue实例提供更好的类型推导
export default {}
的{}
是简单的Object类型,ts无法针对性的提示我们vue组件需要哪些属性,export default defineComponent({})
把{}
作为defineComponet的参数,通过对参数的类型提示,可以实现对vue组件的类型提示。
具体原理参考这篇文章Vue 中的 defineComponent
@vue/composition-api和vue3组合式api相比的限制
参考限制
getCurrentInstance不总是能获取到
getCurrentInstance
用于访问当前内部组件的实例,但是不总是能访问的到。
WARNING
getCurrentInstance
只暴露给高阶使用场景,典型的比如在库中。强烈反对在应用的代码中使用getCurrentInstance
。请不要把它当作在组合式 API 中获取this
的替代方案来使用。
getCurrentInstance
只能在 setup 或生命周期钩子中调用。
参考下面的例子:
const MyComponent = {
setup() {
const internalInstance = getCurrentInstance() // 有效
const id = useComponentId() // 有效
const handleClick = () => {
getCurrentInstance() // 无效
useComponentId() // 无效
internalInstance // 有效
}
onMounted(() => {
getCurrentInstance() // 有效
})
return () =>
h(
'button',
{
onClick: handleClick
},
`uid: ${id}`
)
}
}
在组合式api中是用vue-router
由于setup中没有this,vue-router4.x给vue3提供了额外的方法可以获取router和route。
//vue3 + vue-router4.x
import { useRouter, useRoute } from 'vue-router'
export default {
setup() {
const router = useRouter()
const route = useRoute()
function pushWithQuery(query) {
router.push({
name: 'search',
query: {
...route.query,
},
})
}
},
}
但是在vue2的vue-router3.x中没有相关的方法,我们可以自己export出一个 useRouter和useRoute方法,暴露出router和route。
//vue2 + @vue/composition-api + vue-router3.x
import Vue from 'vue';
import VueRouter from 'vue-router';
import routes from './routes';
Vue.use(VueRouter);
const router = new VueRouter({
routes,
});
export const useRouter = () => router;
export const useRoute = () => router.currentRoute;
export default router;
总结
该方案作者也是刚刚用起来,具体还会遇到什么坑,作者遇到再记录下,会继续补充这个文档,敬请关注。。。