Vue 3中文官网:https://cn.vuejs.org/
截止2025年6月6日,最新稳定版本是v3.5.16。

前提条件:
npm i -g pnpmVite是新一代前端构建工具,官方推荐基于Vite创建项目,具体操作如下。
创建项目命令:pnpm create vue@latest,将会安装并执行create-vue,它是Vue官方的项目脚手架工具。
具体配置:
┌ Vue.js - The Progressive JavaScript Framework │ ◇ 请输入项目名称: │ vue-project │ ◇ 请选择要包含的功能: (↑/↓ 切换,空格选择,a 全选,回车确认) │ TypeScript 正在初始化项目 D:\vue-project... │ └ 项目初始化完成,可执行以下命令: cd vue-project pnpm install pnpm dev | 可选:使用以下命令在项目目录中初始化 Git: git init && git add -A && git commit -m "initial commit"
安装官方推荐的VS Code插件:Vue - Official。
setup是Vue 3中的一个新配置项,值是一个函数。它是Composition API表演的舞台,组件中所用到的:数据、方法、计算属性、监视等等,均配置在setup中。
特点如下:
setup与Options API关系
setup函数有个语法糖写法。
扩展:上述代码name="Person",需要安装一个插件:pnpm i vite-plugin-vue-setup-extend -D
接着,修改vite.config.ts文件:
import VueSetupExtend from 'vite-plugin-vue-setup-extend' export default defineConfig({ plugins: [vue(), vueDevTools(), VueSetupExtend()], ... })
宏观角度看:
两者区别:
.value(可以使用Vue插件自动添加.value)使用原则:
情况一:监视【ref】定义的【基本类型】数据。
情况二:监视【ref】定义的【对象类型】数据。
情况三:监视【reactive】定义的【对象类型】数据。
情况四:监视【ref】或【reactive】定义的【对象类型】数据中的某个属性。
情况五:监视上述的多个数据。
watch( [() => person.name, person.car], (newValue, oldValue) => { console.log('person.car变化了', newValue, oldValue) }, { deep: true } )
watch对比watchEffect:
用在普通DOM标签上:
用在组件标签上,子组件Person.vue:
父组件App.vue:
button { margin: 0 0 30px; }
新建文件src\types\index.ts: // 定义接口 export interface PersonInter { id: string name: string age?: number // age 可有可无 }
// 自定义类型 // export type Persons = Array // 另一种写法 export type Persons = PersonInter[]
父组件App.vue:
子组件Person.vue:
父组件App.vue:
子组件Person.vue:
Vue组件实例在创建时要经历一系列的初始化步骤,在此过程中Vue会在合适的时机,调用特定的函数,从而让开发者有机会在特定阶段运行自己的代码,这些特定的函数统称为:生命周期钩子。
生命周期整体分为四个阶段,分别是:创建、挂载、更新、卸载,每个阶段都有两个钩子,一前一后。Vue 3生命周期:
setuponBeforeMount、onMountedonBeforeUpdate、onUpdatedonBeforeUnmount、onUnmounted常用钩子:onMounted(挂载完毕)、onUpdated(更新完毕)、onBeforeUnmount(卸载之前)。
hook本质上是一个函数,把setup函数中使用的Composition API进行了封装。自定义hook的优势:复用代码, 让setup中的逻辑更清楚易懂。
父组件App.vue:
子组件Person.vue:
.person { background-color: skyblue; box-shadow: 0 0 10px; border-radius: 10px; padding: 20px; } li { font-size: 20px; } img { height: 100px; margin-right: 10px; }
新建文件src\hooks\useDog.ts:
import { reactive, onMounted } from 'vue' import axios, { AxiosError } from 'axios' // pnpm i axios export default function () { let dogList = reactive<string[]>([]) // 方法 async function getDog() { try { // 发请求 let { data } = await axios.get('https://dog.ceo/api/breed/pembroke/images/random') // 维护数据 dogList.push(data.message) } catch (error) { // 处理错误 const err = error console.log(err.message) } } // 挂载钩子 onMounted(() => { getDog() }) //向外部暴露数据 return { dogList, getDog } }
两个注意点:
路由器工作模式
history模式
优点:URL更加美观,不带有#
缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有404错误
hash模式
优点:兼容性更好,因为不需要服务器端处理路径
缺点:URL带有#不太美观,且在SEO优化方面相对较差
首先,新建路由组件src\pages\About.vue:
.about { display: flex; justify-content: center; align-items: center; height: 100%; color: rgb(85, 84, 84); font-size: 18px; }src\pages\Home.vue: .home { display: flex; justify-content: center; align-items: center; height: 100%; }
src\pages\News.vue:
.news { padding: 0 20px; display: flex; justify-content: space-between; height: 100%; } .news ul { margin-top: 30px; /* list-style: none; */ padding-left: 10px; } .news li::marker { color: #64967e; } .news li > a { font-size: 18px; line-height: 40px; text-decoration: none; color: #64967e; text-shadow: 0 0 1px rgb(0, 84, 0); } .news-content { width: 70%; height: 90%; border: 1px solid; margin-top: 20px; border-radius: 10px; }
src\pages\Detail.vue:
.news-list { list-style: none; padding-left: 20px; } .news-list > li { line-height: 30px; }
然后,新建路由配置文件src\router\index.ts:
import { createRouter, createWebHistory } from 'vue-router' import Home from '@/pages/Home.vue' import News from '@/pages/News.vue' import About from '@/pages/About.vue' import Detail from '@/pages/Detail.vue' // 创建路由器 const router = createRouter({ history: createWebHistory(), // history模式,hash模式为createWebHashHistory routes: [ { name: 'home', // 给路由规则命名,以简化路由跳转及传参 path: '/home', component: Home, }, { path: '/news', component: News, children: [ // 嵌套路由 { path: 'detail', // 子级路由不用写 / component: Detail, }, ], }, { path: '/about', component: About, }, { path: '/', redirect: '/home', // 重定向 }, ], }) export default router
main.ts:
import { createApp } from 'vue' import App from './App.vue' import router from './router/index' const app = createApp(App) app.use(router) app.mount('#app')
App.vue:
.title { text-align: center; word-spacing: 5px; margin: 30px 0; height: 70px; line-height: 70px; border-image: linear-gradient(45deg, gray, white); border-radius: 10px; box-shadow: 0 0 2px; font-size: 30px; } .navigate { display: flex; justify-content: space-around; margin: 0 100px; } .navigate a { display: block; text-align: center; width: 90px; height: 40px; line-height: 40px; border-radius: 10px; background-color: gray; text-decoration: none; color: white; font-size: 18px; letter-spacing: 5px; } .navigate a.active { background-color: #64967e; color: #ffc268; font-weight: 900; text-shadow: 0 0 1px black; font-family: 微软雅黑; } .main-content { margin: 0 auto; margin-top: 30px; border-radius: 10px; width: 90%; height: 400px; border: 1px solid; }
params参数:
修改路由规则src\router\index.ts: routes: [ { path: '/news', component: News, children: [ { name: 'detail', path: 'detail/
/?', // ?表示可选参数 component: Detail, }, ], }, ],修改src\pages\News.vue: {{ news.title }}修改src\pages\Detail.vue:作用:让路由组件更方便的收到参数(可将路由参数作为props传给组件)。
修改路由规则src\router\index.ts: children: [ { name: 'detail', path: 'detail/
/?', component: Detail, // 布尔值写法,把收到的每一组 params 参数,作为props传给Detail组件 props: true, }, ],修改src\pages\Detail.vue:children: [ { name: 'detail', path: 'detail/
/?', component: Detail, // 函数写法,把返回对象中的每一组key-value作为props传给Detail组件 props(route) { // return route.query return route.params }, }, ],children: [ { name: 'detail', path: 'detail/
/?', component: Detail, // 对象写法,把对象中的每一组key-value作为props传给Detail组件 props: { id: '123', content: 'hello world', }, }, ],作用:控制路由跳转时操作浏览器历史记录的模式。
浏览器历史记录有两种写入方式:push和replace:
开启replace模式: 新闻
路由组件的两个重要属性:router变成了两个hooks,可脱离实现路由跳转。
修改src\pages\Home.vue,实现3s后跳转到新闻页面:
定时器setTimeout()的本质,就是在指定时间后将函数添加到消息队列中。setInterval()是每间隔一段时间就将函数添加到消息队列中,但是如果函数执行速度比较慢,它是无法确保每次执行间隔都一样的。
本文作者:a
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!