Write the Code. Change the World.

5月 27

vue3 项目,配置了 ts 来开发。如果某一些组件,不使用 ts,编译的时候会报错。有时候并不是不想用 ts,只是那些文件是第三方编写的,又耦合比较高。这个时候,允许这些文件继续使用 js 来编写是一个需求。

这里以一个 LivePlayer 组件为例。

步骤

  1. 创建一个 src/components/LivePlayer/LivePlayer.vue。 部分代码如下。这里没有设置 lang='ts',也没有使用 ts 的强类型。
components<template>
    <div class="relative overflow-hidden shrink-0 w-[320px] h-[405px]">
        <div id="remoteVideo" class="w-[720px] h-[405px] ml-[-200px]"></div>
    </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';

const playIng = false

const urls = ref([])

function play(value) {
    urls.push(value)

    playVideo()
}

function playVideo() {
    if (playIng) {
        return
    }

    const url = urls.shift()
    if (!url) {
        return
    }

    playIng = true
    // todo
}

defineExpose({ play })
</script>
  1. tsconfig.app.json 中加入黑名单,ts 编译器对这些文件不做处理。如:
{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
  "exclude": ["src/**/__tests__/*", "src/components/LivePlayer/LivePlayer.vue"],
  …
  1. 添加类型声明。在 typings 目录下,增加类型声明。typings 目录根据实际项目配置为准。
// 定义一个接口来描述暴露给模板的属性或方法  
interface LivePlayerExpose {  
    speakMessage: (value:string) => void
}

// 声明一个 Vue 组件实例类型,它扩展了 Vue 组件的基础类型,并添加了 LivePlayerExpose 接口  
declare type LivePlayerComponent = InstanceType<DefineComponent<{}, {}, {}, {}>> & LivePlayerExpose

declare module '@/components/LivePlayer/LivePlayer.vue' {  
    import { DefineComponent } from 'vue'

    const component: DefineComponent<{}, {}, {}, {}> & {  
        // 注意:这里我们并不直接导出 component,而是声明了它的类型  
        // 在实际使用时,Vue 会处理 component 的导出和注册  
    };  

    // 导出的是组件的实例类型,以便在模板或其他组件中引用时具有正确的类型  
    export default component
    // 导出组件实例类型以供外部使用  
    export type Instance = LivePlayerComponent
  }
  1. 项目中使用组件
components<template>
    <div class="w-full">
        <LivePlayer ref="livePlayerRef" />
    </div>
</template>

<script setup lang='ts'>
import { ref, onMounted } from 'vue';

const livePlayerRef = ref<InstanceType<typeof LivePlayer> | null>(null)

onMounted(() => {
    livePlayerRef.value?.play("xxx")
})
</script>