来吧,解锁 vue3 全家桶+Ts 的正确姿势,音视频开发面试

87 阅读3分钟

// 联合类型

type RouteConfig = RouteRecordRaw & {hidden?: boolean}; //hidden 是可选属性

const routes: Array = [

{

path: '/',

name: 'Home',

component: Home,

hidden: true,

meta: {

permission: true,

icon: ''

}

}

];

在setup中使用

需要导入useRouter创建一个router实例。

<script lang="ts">

import { useRouter } from 'vue-router';

import { defineComponent } from 'vue';

export default defineComponent({

setup () {

const router = useRouter();

goRoute(path) {

router.push({path})

}

}

})

vuex


使用this.$store

import { createStore } from 'vuex';

export type State = {

count: number

}

export default createStore({

state: {

count: 0

}

});

需要创建一个声明文件vuex.d.ts

// vuex.d.ts

import {ComponentCustomProperties} from 'vue';

import {Store} from 'vuex';

import {State} from './store'

declare module '@vue/runtime-core' {

interface ComponentCustomProperties {

$store: Store

}

}

在setup中使用

定义InjecktionKey

在安装插件时传入key

在使用useStore时传入

import { InjectionKey } from 'vue';

import { createStore, Store } from 'vuex';

export type State = {

count: number

}

// 创建一个injectionKey

export const key: InjectionKey<Store> = Symbol('key');

// main.ts

import store, { key } from './store';

app.use(store, key);

<script lang="ts">

import { useStore } from 'vuex';

import { key } from '@/store';

export default defineComponent({

setup () {

const store = useStore(key);

const count = computed(() => store.state.count);

return {

count

}

}

})

模块

新增一个todo模块。导入的模块,需要是一个vuex中的interface Module的对象,接收两个泛型约束,第一个是该模块类型,第二个是根模块类型

// modules/todo.ts

import { Module } from 'vuex';

import { State } from '../index.ts';

type Todo = {

id: number,

name: string,

completed: boolean

}

const initialState = {

todos: [] as Todo[]

};

export type TodoState = typeof initialState;

export default {

namespaced: true,

state: initialState,

mutations: {

addTodo (state, payload: Todo) {

state.todos.push(payload);

}

}

} as Module<TodoState, State>; //Module<S, R> S 该模块类型 R根模块类型

// index.ts

export type State = {

count: number,

todo?: TodoState // 这里必须是可选,不然state会报错

}

export default createStore({

state: {

count: 0

}

modules: {

todo

}

});

使用:

setup () {

console.log(store.state.todo?.todos);

}

elementPlus


yarn add element-plus

完整引入

import { createApp } from 'vue'

import ElementPlus from 'element-plus';import 'element-plus/lib/theme-chalk/index.css';import App from './App.vue';

import 'dayjs/locale/zh-cn'

import locale from 'element-plus/lib/locale/lang/zh-cn'

const app = createApp(App)

app.use(ElementPlus, { size: 'small', zIndex: 3000, locale })

app.mount('#app')

按需加载

需要安装babel-plugin-component插件:

yarn add babel-plugin-component -D

// babel.config.js

plugins: [

[收起

'component',

{

libraryName: 'element-plus',

styleLibraryName: 'theme-chalk'

}

]

]

import 'element-plus/lib/theme-chalk/index.css';

import 'dayjs/locale/zh-cn';

import locale from 'element-plus/lib/locale';

import lang from 'element-plus/lib/locale/lang/zh-cn';

import {

ElAside,

ElButton,

ElButtonGroup,

} from 'element-plus';

const components: any[] = [

ElAside,

ElButton,

ElButtonGroup,

];

const plugins:any[] = [

ElLoading,

ElMessage,

ElMessageBox,

ElNotification

];

const element = (app: any):any => {

// 国际化

locale.use(lang);

// 全局配置

app.config.globalProperties.$ELEMENT = { size: 'small' };

components.forEach(component => {

app.component(component.name, component);

});

plugins.forEach(plugin => {

app.use(plugin);

});

};

export default element;

// main.ts

import element from './plugin/elemment'

const app = createApp(App);

element(app);

axios


axios的安装使用和vue2上没有什么大的区别,如果需要做一些扩展属性,还是需要声明一个新的类型。

type Config = AxiosRequestConfig & {successNotice? : boolean, errorNotice? : boolean}

import axios, { AxiosResponse, AxiosRequestConfig } from 'axios';

import { ElMessage } from 'element-plus';

const instance = axios.create({

baseURL: process.env.VUE_APP_API_BASE_URL || '',

timeout: 120 * 1000,

withCredentials: true

});

// 错误处理

const err = (error) => {

if (error.message.includes('timeout')) {

ElMessage({

message: '请求超时,请刷新网页重试',

type: 'error'

});

}

if (error.response) {

const data = error.response.data;

if (error.response.status === 403) {

ElMessage({

message: 'Forbidden',

type: 'error'

});

}

if (error.response.status === 401) {

ElMessage({

message: 'Unauthorized',

type: 'error'

});

}

}

return Promise.reject(error);

};

type Config = AxiosRequestConfig & {successNotice? : boolean, errorNotice? : boolean}

// 请求拦截

instance.interceptors.request.use((config: Config) => {

config.headers['Access-Token'] = localStorage.getItem('token') || '';

return config;

}, err);

// 响应拦截

instance.interceptors.response.use((response: AxiosResponse) => {

const config: Config = response.config;

const code = Number(response.data.status);

if (code === 200) {

if (config && config.successNotice) {

ElMessage({

message: response.data.msg,

type: 'success'

});

}

return response.data;

} else {

let errCode = [402, 403];

if (errCode.includes(response.data.code)) {

ElMessage({

message: response.data.msg,

type: 'warning'

});

}

}

}, err);

export default instance;

setup script


官方提供了一个实验性的写法,直接在script里面写setup的内容,即:setup script

之前我们写组件是这样的:

<script lang="ts">

import { ref, defineComponent } from "vue";

import ImgReview from "./components/ImgReview.vue";

export default defineComponent({

components: {

ImgReview,

},

setup() {

const count = ref(0);

return { count };

}

});

启用setup script后:在script上加上setup

<script lang="ts" setup>

import { ref } from "vue";

import ImgReview from "./components/ImgReview.vue";

const count = ref(0);

是不是看起来简洁了很多,组件直接导入就行了,不用注册组件,数据定义了就可以用。其实我们可以简单的理解为script包括的内容就是setup中的,并做了return

导出方法

<script lang="ts" setup>

const handleClick = (type: string) => {

console.log(type);

}

定义props

使用props需要用到defineProps来定义,具体用法跟之前的props写法类似:

基础用法

<script lang="ts" setup>

import { defineProps } from "vue";

const props = defineProps(['userInfo', 'gameId']);

构造函数进行检查 给props定义类型:

const props = defineProps({

gameId: Number,

userInfo: {

type: Object,

required: true

}

});

使用类型注解进行检查

defineProps<{

name: string

phoneNumber: number

userInfo: object

tags: string[]

}>()

可以先定义好类型:

interface UserInfo {

id: number,

name: string,

age: number

}

defineProps<{

name: string

userInfo: UserInfo

}>()

defineEmit

<script lang="ts" setup>

import { defineEmit } from 'vue';

// expects emits options

const emit = defineEmit(['kk', 'up']);

const handleClick = () => {

最后

由于篇幅限制,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!

开源分享:docs.qq.com/doc/DSmRnRG…