Vite+Vue3+TypeScript学习笔记


1、学习背景
随着前端web应用的需求不断发展和变化,vue生态圈也紧跟开发者步伐,不断演化。尽管vue2.0已经很完善了,很多人掌握的vue2.0,感觉实在学不动了,意料之外的是尤先生继续更新vue到3.0版本,以补充vue2.0的不足之处。随着vue3.0问世,vite2.5.1也油然而生,vue始终没有放弃对项目响应速度和编译速度的追求,vite的到来,对于前端开发者而言,简直不要太幸福了。vue3.0不仅全面支持TypeScript语法,还对生命周期钩子进行了优化和剔除,加上工具setup的语法糖,vue单页面多个根元素的扩展,代码精简不说,还很有条理,vue3.0的出现再次提升了开发者的编码体验和幸福感。另外vue3整合typescript语言是前端未来发展的必然趋势,而生为vue家族的新成员vite也是前端技术爱好者的学习目标,赢在起点,从学习新技术开始。活到老,学到老,是一个合格前端开发者的毕生信仰。
2、vite简介
vite诞生是为了提升web项目运行性能,以更快的速度将应用页面展示给用户。Vite 以 原生 ESM 方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。
提供的驱动力:
2.1、优化缓慢的服务器启动(冷启动开发服务器和正式环境响应速度);
2.2、优化缓慢的项目更新(vite服务器);

3、vite创建项目
兼容性注意:
Vite 需要 Node.js 版本 >= 12.0.0。
必须安装Volar插件,用vscode编辑器
// 安装vite
1、npm init vite@latest

// 安装vite同时创建vite项目
2、npm init vite@latest my-vue-app --template vue
{
"scripts": {
"dev": "vite", // 启动开发服务器
"build": "vite build", // 为生产环境构建产物
"serve": "vite preview" // 本地预览生产构建产物
}
}
4、版本依赖兼容和项目目录介绍
package.json版本依赖说明, 这里是整个项目依赖版本配置,相关安装指令后面视频中会逐个教大家如何安装。
注意:vuex和router都是4.0及以上版本的,否则用vue3时,找不到暴露的api
{
"name": "vite-ts-vue3-plus-demo",
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"serve": "vite preview"
},
"dependencies": {
"@element-plus/icons": "0.0.11",
"dotenv": "^10.0.0",
"element-plus": "^1.1.0-beta.7",
"vue": "^3.0.5",
"vue-router": "^4.0.11",
"vuex": "^4.0.2"
},
"devDependencies": {
"@types/node": "^16.7.1",
"@vitejs/plugin-vue": "^1.3.0",
"@vue/compiler-sfc": "^3.0.5",
"node-sass": "^6.0.1",
"sass": "^1.38.1",
"sass-loader": "^12.1.0",
"typescript": "^4.3.2",
"vite": "^2.4.4",
"vue-tsc": "^0.2.2"
}
}
5、setup语法糖使用
5.1 setup前身组合式API(基础用法)
注意:在setup()中不能用this
setup 中你应该避免使用 this,因为它不会找到组件实例。setup 的调用发生在 data property、computed property 或 methods 被解析之前,所以它们无法在 setup 中被获取,这也是为了避免setup()和其他选项式API混淆。
/* 参数说明

  • props 是响应式的,当传入新的 prop 时,它将被更新
  • context 是一个普通的上下文JavaScript对象,它暴露组件的三个 property(包括属性,插槽,方法),
  • 如下示例1所示
    */
    // 示例1

5.2 setup后世(高级用法),推荐用法
注意:defineProps不需要引入,vue单文件内部自动暴露的API

// 高级用法

6、defineProps 和 defineEmits
注意:defineProps 和 defineEmits 都是只在 6.2 、父组件vue 温馨提示:这里介绍一哈volar插件小图标在vue文件里的作用: 点击这个三角形图标,会将文件归类显示,方便编写代码;

7、正确使用defineExpose
使用

7.2、父组件调用子组件方法和属性

7.3 在setup如何定义变量(字符串,对象,数组)

{{count}} {{user.name}}


{{item}}
<button @click="setName">点击我增加

8、Watch和WatchEffect
1、基本使用方法:

{{originData.count}} {{originData.user.name}}


{{item}}


<button @click="incriment">点击我count增加

2、watch与 watchEffect 比较,推荐watch监听
watch: 页面更新后不会立即执行,而watchEffect 它会执行;
如果要实现:watch在页面更新之后就执行,需要增加立即执行的属性;
watch([count,originData.user], (n, o)=> {console.log(n[0],n[1].name)}, {deep: true, immediate: true})
1、watch和watchEffect都懒执行副作用,不过watchEffect比较频繁,在vue组件更新之前执行;
2、watch更具体地说明什么状态应该触发侦听器重新运行,watchEffect就没有这么友好;
3、watch访问侦听状态变化前后的值。
9、在setup中的生命周期钩子
因为 setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup 函数中编写。
下表包含如何在 setup () 内部调用生命周期钩子:
选项式 APIHook inside setup
beforeCreateNot needed* 不需要
createdNot needed* 不需要
beforeMountonBeforeMount 挂载之前
mountedonMounted 页面加载完成时执行
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted 页面销毁时执行
errorCapturedonErrorCaptured
renderTrackedonRenderTracked
renderTriggeredonRenderTriggered
activatedonActivated
deactivatedonDeactivated

10、用Ts限制define(Emits|Props)参数类型
注意:
1、在setup语法糖中引入组件不需要注册声明就可以直接用了
2、ts 限制组件传参类型,默认是必须传值的,否则控制台出现警告, 引入组件的地方会出现红色提醒,不想必传在绑定参数后加?即可
3、ts传参支持多种类型校验,一个参数可以传字符串,数组,Boolean等
4、用ts方式限制defineEmits和defineProps参数类型
1、子组件

{{msg}}


{{title}}


<input v-model="inputValue" type="text" @blur="handleUpdate($event)">

2、父组件

11、递归组件
一个单文件组件可以通过它的文件名被其自己所引用。例如:名为 FooBar.vue 的组件可以在其模板中用 引用它自己。
请注意这种方式相比于 import 导入的组件优先级更低。如果有命名的 import 导入和组件的推断名冲突了,可以使用 import 别名导入:
import { FooBar as FooBarChild } from './components'
注意:这里有小问题,当单文件引入单文件时会出现内存溢出现象
12、component动态组件
由于组件被引用为变量而不是作为字符串键来注册的,在 13、ts限制普通函数/箭头函数参数类型 13.1 普通函数 13.2 箭头函数,推荐用法 14、引入vuex配置和使用 14.1 创建项目时我们已经引入了vuex4.0版本,接下来我们就开始配置vuex4.0并测试。 // 注意必须安装vuex4.0版本及以上 npm install vuex@next --save #or yarn add vuex@next --save 14.2 在src目录下创建store文件夹,新建文件index.ts, index.ts内容如下所示: import { InjectionKey } from 'vue' /** * 引入 InjectionKey 并将其传入 useStore 使用过的任何地方, * 很快就会成为一项重复性的工作。为了简化问题,可以定义自己 * 的组合式函数来检索类型化的 store */ // 未简化useStore版 // import { createStore, Store } from 'vuex' // 简化useStore版 import { useStore as baseUseStore, createStore, Store} from 'vuex'

// 为 store state 声明类型
export interface State {
username: string,
count: number
}

// 定义 injection key
export const key: InjectionKey<Store > = Symbol()

// 导出store模块
export const store = createStore ({
state: {
username: "测试store",
count: 0
},
getters:{
getName: state =>{
return state.username
}
},
mutations: {
// 重置名称
SET_NAME(state, params:string) {
state.username = params
}
},
actions:{}
})

// 定义自己的 useStore 组合式函数
export function useStore () {
return baseUseStore(key)
}
14.3 在根目录下新建vuex-d.ts文件,内容如下所示:
// 一个声明文件来声明 Vue 的自定义类型 ComponentCustomProperties
import { ComponentCustomProperties } from 'vue';
import { Store } from 'vuex';

declare module '@vue/runtime-core' {
// 声明自己的 store state
interface State {
count: number,
username: string
}
// 为 this.$store 提供类型声明
interface ComponentCustomProperties {
$store: Store
}
}
14.4 在main.ts中注入store模块
import { createApp } from 'vue';
import App from './App.vue';
// 导入store模块, 传入 injection key
import { store, key } from '@/store';
const app = createApp(App)
app.use(store, key)
app.mount('#app')
14.5 引用测试vuex配置是否正确
<el-button @click="changeName" size="small">点击修改名称

15、router配置以及使用详解
15.1 安装
创建项目时我们已经引入了router4.0版本,接下来我们就开始配置router4.0并测试。
// 注意:安装router必须是4.0及以上
npm install vue-router@4
15.2 页面准备
目录结构

页面具体内容:
1、layout/index.vue



2、layout/header/index.vue


<h2 @click="handleClick(1)">首页
<h2 @click="handleClick(0)">关于

3、pages/home/index.vue

home



4、pages/about/index.vue

15.3 在src目录下创建router文件夹,然后创建index.ts文件,内容如下所示:
import { createRouter, createWebHashHistory } from "vue-router";
import LayOut from "../components/layout/index.vue";

const routes = [
{
path: '/',
component: LayOut,
redirect: '/home',
children:[
{
path: '/home',
name: 'home',
component: ()=> import("../pages/home/index.vue"),
meta:{
title: '首页',
icon: ''
}
},
{
path: '/about',
name: 'about',
component: ()=> import("../pages/about/index.vue"),
meta:{
title: '关于',
icon: ''
}
}
]
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
15.4 在main.ts中注入router模块, 重新启动项目,访问路由,看是否正确
import { createApp } from 'vue'
import App from './App.vue'
import { store, key } from './store';
import router from './router';

const app = createApp(App);
app.use(store, key);
app.use(router);
app.mount('#app');
15.5 使用路由


<h2 @click="handleClick(1)">首页
<h2 @click="handleClick(0)">关于

16、引入element-plus以及注意事项
16.1 安装
npm install element-plus --save

or

yarn add element-plus

安装icon图标依赖库

npm install @element-plus/icons

or

yarn add @element-plus/icons
16.2 在main.ts 文件中引入配置
import { createApp } from 'vue'
import App from './App.vue'
import { store, key } from './store';
// 注入路由
import router from './router';

// 引入ui组件
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App);
app.use(store, key);
app.use(router);
app.use(ElementPlus);
app.mount('#app');
16.3 在vue文件中引用ui组件
1、单个图标引用

2、全局注册图标使用
import { createApp } from 'vue'
import App from './App.vue'

import { Edit,Search } from '@element-plus/icons'

const app = createApp(App);
app.component("edit", Edit)
app.component("search", Search)
app.mount('#app');
2、1 使用图标

home页面


主要按钮
成功按钮






17、配置vite.config.ts
这里主要配置vite服务器的打包保存地址,打包分解,端口号,是否自动打开浏览器,远程请求地址代理目标,目录别名,全局样式配置等。
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { loadEnv } from 'vite';
// nodejs写法,获取项目目录
import path from 'path';

// https://vitejs.dev/config/
export default({ command, mode }) => {
return defineConfig({
plugins: [vue()],
server:{
host: '127.0.0.1',
port: Number(loadEnv(mode, process.cwd()).VITE_APP_PORT),
strictPort: true, // 端口被占用直接退出
https: false,
open: true,// 在开发服务器启动时自动在浏览器中打开应用程序
proxy: {
// 字符串简写写法
// '/foo': '',
// 选项写法
'/api': {
target: loadEnv(mode, process.cwd()).VITE_APP_BASE_URL,
changeOrigin: true,
rewrite: (path) => path.replace(/^/api/, '')
},
// 正则表达式写法
// '^/fallback/.': {
// target: 'http://jsonplaceholder.typicode.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^/fallback/, '')
// },
},
hmr:{
overlay: true // 屏蔽服务器报错
}
},
resolve:{
alias:{
'@': path.resolve(__dirname,'./src')
}
},
css:{
// css预处理器
preprocessorOptions: {
// 引入 var.scss 这样就可以在全局中使用 var.scss中预定义的变量了
// 给导入的路径最后加上 ;
scss: {
additionalData: '@import "@/assets/styles/global.scss";'
}
}
},
build:{
chunkSizeWarningLimit: 1500, // 分块打包,分解块,将大块分解成更小的块
rollupOptions: {
output:{
manualChunks(id) {
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
}
}
}
}
})
}
18、tsconfig.json 配置
这是typescript的识别配置文件,也是ts向js转化的中间站,这里配置了许多关于ts的文件类型和策略方法。
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"baseUrl": ".",
"paths": {
"@/
":["src/"]
}
},
"include": ["src/**/
.ts", "src//*.d.ts", "src//.tsx", "src/**/.vue"]
}
19、shims-vue.d.ts配置, 声明vue文件全局模块
这里是配置声明,比如css,vue等文件,ts不能识别,需要配置声明模块类型。
declare module '*.vue' {
import { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}
20、安装scss并配置全局样式文件
// 注意要使用scss,必须安装依赖,否则报错
npm install node-sass sass-loader sass -D
20.1 需要在src目录的assets静态目录新增一个全局global.scss文件,其他样式文件导入到该文件即可全局使用和修改。

或者在global.scss写一个单独属性测试
$color-primary: #007aff;
vue使用全局样式变量

home页面


20.2 在vite.config.ts 文件中配置global.scss
css:{
// css预处理器
preprocessorOptions: {
// 引入 var.scss 这样就可以在全局中使用 var.scss中预定义的变量了
// 给导入的路径最后加上 ;
scss: {
additionalData: '@import "@/assets/styles/global.scss";'
}
}
}
21、响应式API
响应式状态需要明确使用响应式 APIs 来创建。和从 setup() 函数中返回值一样,ref 值在模板中使用的时候会自动解包:

22、.env.环境变量配置和读取 环境变量建议放到项目根目录下, 方便vite.config.ts文件读取和使用 .env.production // 生产环境配置文件 .env.development // 开发环境配置文件 22.1 生产和开发环境配置文件内容如下: 写变量时一定要以VITE_开头,才能暴露给外部读取 # 开发环境 / #生产环境 VITE_APP_TITLE = "前端技术栈" VITE_APP_PORT = 3001

请求接口

VITE_APP_BASE_URL = "http://39.12.29.12:8080"

//env.d.ts文件内进行 环境变量智能提示配置
interface ImportMetaEnv {
VITE_APP_TITLE: string,
VITE_APP_PORT: string,
VITE_APP_BASE_URL: string
}
22.2 vite.config.ts 读取配置文件
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { loadEnv } from 'vite';
// nodejs写法,获取项目目录
import path from 'path';

// https://vitejs.dev/config/
export default({ command, mode }) => {
// console.log(command, mode, 5555);
return defineConfig({
plugins: [vue()],
server:{
host: '127.0.0.1',
port: Number(loadEnv(mode, process.cwd()).VITE_APP_PORT),
strictPort: true, // 端口被占用直接退出
https: false,
open: true,// 在开发服务器启动时自动在浏览器中打开应用程序
proxy: {
// 字符串简写写法
// '/foo': '',
// 选项写法
'/api': {
target: loadEnv(mode, process.cwd()).VITE_APP_BASE_URL,
changeOrigin: true,
rewrite: (path) => path.replace(/^/api/, '')
},
// 正则表达式写法
// '^/fallback/.*': {
// target: 'http://jsonplaceholder.typicode.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^/fallback/, '')
// },
// 使用 proxy 实例
// '/api': {
// target: 'http://jsonplaceholder.typicode.com',
// changeOrigin: true,
// configure: (proxy, options) => {
// // proxy 是 'http-proxy' 的实例
// },
// }
},
hmr:{
overlay: true // 屏蔽服务器报错
}
},
resolve:{
alias:{
'@': path.resolve(__dirname,'./src')
}
},
css:{
// css预处理器
preprocessorOptions: {
// 引入 var.scss 这样就可以在全局中使用 var.scss中预定义的变量了
// 给导入的路径最后加上 ;
scss: {
additionalData: '@import "@/assets/styles/global.scss";'
},
sass: {
additionalData: '@import "@/assets/styles/global.scss";'
}
}
},
build:{
chunkSizeWarningLimit: 1500, // 分块打包,分解块,将大块分解成更小的块
rollupOptions: {
output:{
manualChunks(id) {
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
}
}
}
}
})
}
22.3 其他文件读取环境变量

附上学习视频:
https://www.bilibili.com/video/BV1QP4y1p748?spm_id_from=333.999.0.0


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM