Vue+typescript+vite简单项目

本文详细介绍了使用Vite和Vue.js创建一个基于TypeScript的项目,包括设置基础结构、安装依赖、配置路由、ESLint和Prettier插件,以及实现登录验证和API调用。还展示了如何在VSCode中管理和配置项目相关设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 1.直接创建 hello-world为项目名称

npm create vite@latest hello-world -- --template vue-ts

2. 执行连贯操作命令如下

cd hello-world && npm install && npm run dev 

3. 见运行效果, 如下: 

 4.在VScode安装ESLint和Prettier - Code formatter,更全的插件可搜索史上最全vscode配置使用教程 - 知乎

基本插件

npm install vue-router

 npm install element-plus

 npm i --save-dev @types/node

npm install axios 

npm install qs

 5.内容填充

 App.vue

router页面

import { createRouter, createWebHashHistory } from 'vue-router'
const router =createRouter({
    history:createWebHashHistory(),
    routes:[
        {
            path:'/',
            redirect:'/login'
        },
        {
            path:'/login',
            name:'Login',
            component:() => import('../views/login/login.vue')
        },
        {
            path:'/main',
            name:'Main',
            component:() => import('../views/main/main.vue')
        }
    ]
})
export default router

main.ts文件

vite.config.ts文件。proxy代理路径可配置成测试环境或者正式环境的,如果本地服务没启的话

tsconfig.json 

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true, 
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"], 
      "@views/*": ["src/views/*"]
    },
    "types": ["element-plus/global", "node"]
  },
  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

login页面

<template>

<div>

    <h1>登录页面</h1>

    <el-form

    ref="formLogin"

    :model="loginData.loginForm"

    class="login-form"

    label-position="top"

    label-width="120px"

    size="large"

  >

    <el-row style="maring-left: -10px; maring-right: -10px">

      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">

        <el-form-item>

          <LoginFormTitle style="width: 100%; text-align: center" />

        </el-form-item>

      </el-col>

      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">

        <el-form-item prop="username">

          <el-input

            v-model="loginData.loginForm.username"

            placeholder="请输入用户名"

          />

        </el-form-item>

      </el-col>

      <el-col :span="24" style="padding-left: 10px; padding-right: 10px">

        <el-form-item prop="password">

          <el-input

            v-model="loginData.loginForm.password"

            placeholder="请输入密码 "  

            type="password"

          />

        </el-form-item>

      </el-col>

      <el-col :span="24" style="padding-left: 10px; padding-right: 10px; height: 55px">

        <el-form-item>

          <img :src="loginData.yzm" style="width: 17%; " />

          <el-icon class="icon"

            ><component  @click="getYZM" style="cursor: pointer"

          /></el-icon>

          <el-input

            v-model="loginData.securityCode"

            placeholder="运算结果"

          />

        </el-form-item>

      </el-col>

      <el-col :span="24" style="padding-left: 10px; padding-right: 10px;    margin-top: 6%;">

        <el-form-item>

          <el-Button   class="full-width" type="primary" @click="handleLogin">

            登录

          </el-Button>

        </el-form-item>

      </el-col>

    </el-row>

  </el-form>

</div>

</template>

<script lang="ts" name="Login" setup>

import * as LoginApi from "@/api/login";

import router from '@/router';

import { onMounted, reactive, ref } from 'vue';

const formLogin = ref();

const loginData = reactive({

  isShowPassword: false,

  loginForm: {

    tenantName: "",

    username: "",

    password: "",

    captchaVerification: "",

    rememberMe: false

  },

  yzm: "",

  securityCode: "",

  yzmValue: ""

})

onMounted(() => {

  getYZM()

})

//获取验证码图片

const getYZM = async () => {

  const res = await LoginApi.getYZM({})

  if (!res) {

    return

  } else {

    loginData.yzm = window.URL.createObjectURL(res.data)

    loginData.yzmValue = res.headers.captcha

  }

}

// 登录

const handleLogin = async () => {

  try {

    if (loginData.securityCode !== loginData.yzmValue) {

      alert("验证码错误")

      return

    }

    const res = await LoginApi.RHLogin({

      loginName: 'admin',

      password: 'SuperETL_InAT2023'

    })

    if (!res) {

      return

    }

    router.push({ path:'/main' })

  } finally {

    

  }

}

</script>

js部分

main页面

<template>
  <h1>项目信息页面</h1>
    <el-button type="primary" class="user" plain @click="getMsg" style="margin-right:30px;"><i-ep-Brush />获取项目信息</el-button> 
    <el-button type="primary" plain @click="goTo"><i-ep-Brush />返回</el-button>   
  <div style="margin-top:30px;width:60%"> 
    <el-table
    :data="tableData"
     style="width: 100%"
    >
    <el-table-column
      prop="subsystemName"
      label="日期"
      width="180">
    </el-table-column>
    <el-table-column
      prop="brand"
      label="姓名"
      width="180">
    </el-table-column>
    <el-table-column
      prop="person"
      label="地址">
    </el-table-column>
  </el-table> 
    
  </div>
</template>

<script lang="ts" setup name="Main">  
import router from "@/router";
import loadData from "./main.ts";
const {  tableData,   getList} = loadData()

function goTo(){
  router.push({
    name:'Login'
  })
}
function getMsg(){
  getList()
}
 
</script>
<style scoped lang="scss">
.search-box {
  display: flex;
  justify-content: space-between;
  border-bottom: var(--solid-border);
  margin-bottom: 15px;
  :deep(.el-input__inner) {
    width: 100px;
  }
}
.btn-container {
  margin-bottom: 15px;
  display: flex;
}
.area {
  width: 159px;
}
.lupload {
  margin-left: 12px;
}
</style>
./main.ts

main.ts文件,将main.vue页面中的js部分踢出,单独放在main.ts文件中

import { subSystemList } from "@/api/main"
import { subsystemQueryForm } from "@/types/subsystem"
import {ref} from 'vue'
//初始化数据
const getDefaultValue = (): subsystemQueryForm => {
  return {
    appId: "",
    subsystemName: "",
    brand: "",
    person: "",
    protocolTypeId: "",
    developName: "",
    createTime: "",
    page: 1,
    limit: 20
  }
} 
export default function loadData() {
  // 查询条件表单
  const queryParams = ref<subsystemQueryForm>(getDefaultValue())
  // 分页信息
  const total = ref<number>(6)
  // 表格数据
  const tableData = ref<[]>([])
  // 列表的loading
  const loading = ref<boolean>(false) 
  //获取列表数据
  const getList = async () => {
    loading.value = true
    try {
      queryParams.value.appId = "58";
      const res = await subSystemList(queryParams.value)
      if (res) {
        tableData.value = res.data.list
        total.value = res.data.totalCount
      }
    } catch (error) {
    } finally {
      loading.value = false
    }
  } 
  // 更改分页操作
  const handlePagination = () => getList() 
  return {
    queryParams,
    getList,
    tableData,
    total,
    loading,
    handlePagination
  }
}

main.ts中获取接口,在types中定义实体类,用来接受接口返回信息

// 项目基本参数
export interface subsystemQueryForm extends Page {
  appId: string
  subsystemName: string
  brand: string
  person: string
  protocolTypeId: string
  developName: string
  createTime: string
}

实体类中继承的page类,封装在global.d.ts文件中

export { }

declare global {

  interface Fn<T = any> {

    (...arg: T[]): T

  }

  type Nullable<T> = T | null

  type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>

  type Recordable<T = any, K = string> = Record<K extends null | undefined ? string : K, T>

  type ComponentRef<T> = InstanceType<T>

  type LocaleType = "zh-CN" | "en"

  type SexType = 1 | 2

  type AxiosHeaders =

    | "application/json"

    | "application/x-www-form-urlencoded"

    | "multipart/form-data"

  type AxiosMethod = "get" | "post" | "delete" | "put" | "GET" | "POST" | "DELETE" | "PUT"

  type AxiosResponseType = "arraybuffer" | "blob" | "document" | "json" | "text" | "stream"

  type Position = "left" | "right" | "top" | "middle" | "bottom"

  interface AxiosConfig {

    params?: any

    data?: any

    url?: string

    method?: AxiosMethod

    headersType?: string

    responseType?: AxiosResponseType

  }

  interface IResponse<T = any> {

    code: string

    data: T extends any ? T : T & any

  }

  interface PageParam {

    pageSize?: number

    pageNum?: number

  }

  interface Page {

    page: number

    limit: number

  }

  interface Tree {

    id: string | number

    name: string

    children?: Tree[]

  }

  type DataTreeResult = Tree & {

    parentId: string | number

  }

  interface DepartTreeResult {

    id: string | number

    departName: string

    departCode: string

    parentId: string | number

    children?: DepartTreeResult[]

  }

  interface TreeSelectOpts {

    value: string | number | boolean | object

    label: string

    children: TreeSelectOpts[]

  }

  interface DictOpts {

    value: string | number | boolean | object

    label: string

  }

  export interface InterfaceMenu extends Tree {

    path: string

    show: boolean

    icon: any

    children?: InterfaceMenu[]

  }

  interface Window {

    T: any // 天地图对象

  }

}

api接口路径配置页面

export enum URL_CONFIG { 
  api = "/api"  
}

//融合平台接口
//验证码
export const captcha = `${URL_CONFIG.api}/platform/sysUser/captcha`
// 登录
export const RH_LOGIN_URL = `${URL_CONFIG.api}/platform/sysUser/login`

//获取项目列表
export const appBrowse_url = `${URL_CONFIG.api}/platform/app/browse`

// 子系统管理
export const tagAccess_url = `${URL_CONFIG.api}/platform/sysReport/tagAccess`
export const subsystemAccess_url = `${URL_CONFIG.api}/platform/sysReport/subsystemAccess`
export const subSystemList_url = `${URL_CONFIG.api}/platform/subSystem/browse`
export const subSystemInfo_url = `${URL_CONFIG.api}/platform/subSystem/info`
export const subSystemDelete_url = `${URL_CONFIG.api}/platform/subSystem/delete`
export const subSystemModify_url = `${URL_CONFIG.api}/platform/subSystem/modify`
export const subSystemAdd_url = `${URL_CONFIG.api}/platform/subSystem/add`
export const subSystemExport_url = `${URL_CONFIG.api}/platform/subSystem/export`
export const subSystemImport_url = `${URL_CONFIG.api}/platform/subSystem/import`

按照login页面和main页面分别创建ts文件,实现接口的调用

import request from "@/api/axios"
import {
  RH_LOGIN_URL,
  captcha
} from "./api"

export interface SmsCodeVO {
  mobile: string
  scene: number
}

export interface SmsLoginVO {
  mobile: string
  code: string
} 
// 登录
export const RHLogin = (data: object) => {
  return request.post({ url: RH_LOGIN_URL, data })
}
// 验证码
export const getYZM = (data: object) => { 
  return request.download({ url: captcha, data })
} 
  

import request from "@/api/axios"

import { subsystemQueryForm } from "@/types/subsystem"

import { subSystemList_url } from "./api"

export const subSystemList = (data: subsystemQueryForm) => {

  return request.post({ url: subSystemList_url, data })

}

axios请求封装一下

login或者main页面js封装

登录成功,跳转到/main页面,点击按钮,通过axios获取接口信息

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值