vite官网
兼容性注意
Vite 需要 Node.js 版本 >= 12.0.0
项目创建:要构建一个 Vite + Vue 项目,运行:
# npm 6.x npm init @vitejs/app my-vue-app --template vue # npm 7+, 需要额外的双横线: npm init @vitejs/app my-vue-app -- --template vue # yarn yarn create @vitejs/app my-vue-app --template vue
支持的模板预设包括:
- vanilla
- vue
- vue-ts
- react
- react-ts
- preact
- preact-ts
- lit-element
- lit-element-ts
查看 @vitejs/create-app 获取每个模板的更多细节。
初始化
npm init vite@latest
创建完成后选择 vue-ts安装依赖
npm i
安装UI组件库
npm i @nutui/nutui@next
安装路由
npm install vue-router@4
安装vuex
npm install vuex@next --save
新建页面 配置路由
路由meta对象参数说明
/** * 路由meta对象参数说明 * meta: { * title: 菜单栏及 tagsView 栏、菜单搜索名称(国际化) * isLink: 是否超链接菜单,开启外链条件,`1、isLink:true 2、链接地址不为空` * isHide: 是否隐藏此路由 * isKeepAlive: 是否缓存组件状态 * isAffix: 是否固定在 tagsView 栏上 * isIframe: 是否内嵌窗口,,开启条件,`1、isIframe:true 2、链接地址不为空` * roles: 当前路由权限标识,取角色管理。控制路由显示、隐藏。超级管理员:admin 普通角色:common * icon: 菜单、tagsView 图标,阿里:加 `iconfont xxx`,fontawesome:加 `fa xxx` * } */
引入路由
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
const dynamicRoutes: Array<RouteRecordRaw> = [ { path: '/', name: '/', component: () => import('@/layout/index.vue'), redirect: '/home', meta: { isKeepAlive: true, }, children: [ { path: '/home', name: 'home', component: () => import('@/views/Index/index.vue'), meta: { title: 'message.router.home', isLink: '', isHide: false, isKeepAlive: true, isAffix: true, isIframe: false, icon: 'iconfont icon-shouye', }, }, ], }, ]; const router = createRouter({ history: createWebHashHistory(), routes: dynamicRoutes, }); // 导出路由 export default router;
main.ts配置路由
import router from './router'; const app = createApp(App); app .use(router) .mount('#app');
引入UI组件库(这里用的是 京东的 nutUI)
import { createApp } from 'vue' import App from './App.vue' import router from './router'; const app = createApp(App); import NutUI from "@nutui/nutui"; import "@nutui/nutui/dist/style.css"; app .use(router) .use(NutUI) .mount('#app');
配置App.vue
<template> <router-view /> </template>
新建页面 Index、User
@/views/Index/index.vue @/views/User/index.vue
新建Layout组件
<template> <nut-tabbar :bottom="true" :safeAreaInsetBottom="true" @tab-switch="tabSwitch"> <nut-tabbar-item tab-title="首页" to="/home" icon="home" num="11"></nut-tabbar-item> <nut-tabbar-item tab-title="分类" icon="category"></nut-tabbar-item> <nut-tabbar-item tab-title="发现" icon="find"></nut-tabbar-item> <nut-tabbar-item tab-title="商城" icon="cart" num="110"></nut-tabbar-item> <nut-tabbar-item tab-title="我的" to="/userCenter" icon="my"></nut-tabbar-item> </nut-tabbar> <!-- 主内容区域 --> <div class="main-content"> <router-view /> </div> </template> <script setup lang="ts"> //tab点击事件 const tabSwitch = (v:String):any=>{ console.log(v) } </script> <style scoped> .main-content{ height:calc(100% - 48px); } </style>
页面路由跳转可以使用 <nut-tabbar-item 里面的 to 属性
<nut-tabbar-item tab-title="我的" to="/userCenter" icon="my"></nut-tabbar-item>
shim.d.ts文件
主要内容
/* eslint-disable */ /** * shims-vue.d.ts的作用 * 为了 typescript 做的适配定义文件,因为.vue 文件不是一个常规的文件类型,ts 是不能理解 vue 文件是干嘛的, * 加这一段是是告诉 ts,vue 文件是这种类型的。 * 可以把这一段删除,会发现 import 的所有 vue 类型的文件都会报错。 */ // 声明文件,*.vue 后缀的文件交给 vue 模块来处理 declare module '*.vue' { import type { DefineComponent } from 'vue'; const component: DefineComponent<{}, {}, any>; export default component; } // 声明文件,定义全局变量。其它 app.config.globalProperties.xxx,使用 getCurrentInstance() 来获取 interface Window { nextLoading: boolean; }
shims-vue.d.ts是为了 typescript 做的适配定义文件,因为.vue 文件不是一个常规的文件类型,ts 是不能理解 vue 文件是干嘛的,
加这一段是是告诉 ts,vue 文件是这种类型的。
这一段删除,会发现 import 的所有 vue 类型的文件都会报错。
引入vue-echarts(在.d.ts文件中)
/** * shims-vue.d.ts的作用 * 为了 typescript 做的适配定义文件,因为.vue 文件不是一个常规的文件类型,ts 是不能理解 vue 文件是干嘛的, * 加这一段是是告诉 ts,vue 文件是这种类型的。 * 可以把这一段删除,会发现 import 的所有 vue 类型的文件都会报错。 */ declare module '*.vue' { //declare声明宣告, 声明一个ambient module(即:没有内部实现的 module声明) import Vue from 'vue' export default Vue } declare module 'vue-echarts' // 引入vue-echarts
以下方式可能产生报错
<script lang="ts"> /* eslint-disable @typescript-eslint/camelcase */ import { Vue, Component, Watch } from 'vue-property-decorator' import ECharts from 'vue-echarts' //报错,按上面的方法在shims-vue.d.ts文件中引入即可 import 'echarts/lib/chart/line' import 'echarts/lib/chart/pie' import 'echarts/lib/component/tooltip' </script>
source.d.ts 文件
使用模块声明导入文件(导入文件类型定义)
declare module '*.json'; declare module '*.png'; declare module '*.jpg'; declare module '*.scss'; declare module '*.ts'; declare module '*.js';
因为在typescript里面使用以下的语句 很可能报错,
Cannot find module 'xxx.json'
解决办法,可以在根目录建立一个typings.d.ts文件
declare module "*.json" { const value: any; export default value; }
然后就可以通过下面的方式使用
import * as data from './xxx.json'; const word = (<any>data).name;
Vite.config.ts 文件
UserConfig
配置跨域
import type { UserConfig } from 'vite'; const viteConfig:UserConfig = { port: 8080, hostname: "localhost", proxy: { '/api': { target: 'http://zhanhongzhu.top', changeOrigin: true, ws: true, rewrite: path => path.replace(/^\/api/, '') } } } //导出 export default viteConfig;
其他配置项
/** * vite总配置文件 */ const path = require('path'); import type { UserConfig } from 'vite'; // const viteConfig: UserConfig = { // 端口号(默认3000) port: 8080, // 是否自动打开浏览器(默认false) open: true, // 是否开启 https // https: false, // 服务端渲染 // ssr: false, // 引入第三方的配置 // optimizeDeps: { // include: ["moment", "echarts", "axios", "mockjs"] // }, // 生产环境路径,类似webpack的assetsPath base: './', // 打包后目录,默认dist outDir: 'www', // 别名配置 alias: { // 键必须以斜线开始和结束 '/@/': path.resolve(__dirname, './src') }, // 代理配置 port: 8080, hostname: "localhost", proxy: { '/api': { target: 'http://zhanhongzhu.top', changeOrigin: true, ws: true, rewrite: path => path.replace(/^\/api/, '') } } } // export default viteConfig;
vite+typescript从入门到实战(二):https://developer.aliyun.com/article/1483572