Vue3项目中引用TS语法的实例讲解

发布时间:2024-09-20 09:01

目录
  • 基础语法
  • vue-router
  • vuex#####
  • elementPlus
  • axios
  • setup script

基础语法

定义data 

//script标签上 **lang=\"ts\"**

定义props

import { defineComponent, PropType} from \'vue\';
interface UserInfo = {
  id: number,
  name: string,
  age: number
}
export default defineComponent({
//props需要使用PropType泛型来约束。
  props: {
    userInfo: {
      type: Object as PropType, // 泛型类型
      required: true
    }
  },
})

定义methods 

import { defineComponent, reactive, ref, toRefs } from \'vue\';
type Todo = {
  id: number,
  name: string,
  completed: boolean
}
export default defineComponent({
  const data = reactive({
    todoList: [] as Todo[]
  })
  // 约束输入和输出类型
  const newTodo = (name: string):Todo  => {
    return {
      id: this.items.length + 1,
      name,
      completed: false
    };
  }
  const addTodo = (todo: Todo): void => {
    data.todoList.push(todo)
  }
  return {
    ...toRefs(data),
    newTodo,
    addTodo
  }
})

vue-router

import { createRouter, createWebHistory, RouteRecordRaw } from \'vue-router\';
import Home from \'../views/Home.vue\';
//routes的约束类型是RouteRecordRaw
const routes: Array< RouteRecordRaw > = [
  {
    path: \'/\',
    name: \'Home\',
    component: Home,
  },
  {
    path: \'/about\',
    name: \'About\',
    component: () => import(/* webpackChunkName: \"about\" */ \'../views/About.vue\')
  }
];
//createRouter创建router实例
const router = createRouter({
//router的模式分为
    //createWebHistory -- history模式
    //createWebHashHistory -- hash模式
  history: createWebHistory(process.env.BASE_URL),
  routes
});
export default router;

扩展路由额外属性

// 联合类型
//在实际项目开发中,常常会遇到这么一个场景
//某一个路由是不需要渲染到侧边栏导航上的
//此时我们可以给该路由添加一个hidden属性来实现。
//在ts的强类型约束下,添加额外属性就会报错,那么我们就需要扩展RouteRecordRaw类型。
type RouteConfig = RouteRecordRaw & {hidden?: boolean}; //hidden 是可选属性
const routes: Array = [
  {
    path: \'/\',
    name: \'Home\',
    component: Home,
    hidden: true,
    meta: {
      permission: true,
      icon: \'\'
    }
  }
];

在setup中使用

//需要导入useRouter创建一个router实例。
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
import {ComponentCustomProperties} from \'vue\';
import {Store} from \'vuex\';
import {State} from \'./store\'
declare module \'@vue/runtime-core\' {
    interface ComponentCustomProperties {
        $store: Store
    }
}

在setup中使用

  • 定义InjecktionKey 
import { InjectionKey } from \'vue\';
import { createStore, Store } from \'vuex\';
export type State = {
  count: number
}
// 创建一个injectionKey
export const key: InjectionKey> = Symbol(\'key\');
  • 在安装插件时传入key
// main.ts
import store, { key } from \'./store\';
app.use(store, key);
  • 在使用useStore时传入
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的对象,接收两个泛型约束
  • 第一个是该模块类型
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; //Module 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\'
      }
    ]
]
  • 创建 element 组件文件 
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。
  • 之前我们写组件是这样的:
  • 启用setup script后:在script上加上setup
  • 是不是看起来简洁了很多,组件直接导入就行了,不用注册组件,数据定义了就可以用。其实我们可以简单的理解为script包括的内容就是setup中的,并做了return。

导出方法

const handleClick = (type: string) => {
  console.log(type);
}

定义props

  • 使用props需要用到defineProps来定义,具体用法跟之前的props写法类似:
  • 基础用法
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

import { defineEmit } from \'vue\';
// expects emits options
const emit = defineEmit([\'kk\', \'up\']);
const handleClick = () => {
  emit(\'kk\', \'点了我\');
};

获取上下文

  • 在标准组件写法里,setup 函数默认支持两个入参: 

\"Vue3项目中引用TS语法的实例讲解_第1张图片\"

  • 在setup script 中使用useContext获取上下文:
 import { useContext } from \'vue\'
 const { slots, attrs } = useContext();
  • 获取到的slots,attrs跟setup里面的是一样的。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号