一、props的使用
父组件可以传递简单类型和响应式对象类型的数据给子组件,具体操作只需要在调用子组件时,给子组件标签加属性,子组件接收该属性的,并展示对应的值。
子组件具体是通过defineProps([属性1,属性2......])来接收数据的。// 是一个数组,接收多个值。
下面是父组件的示例:
<template>
<h2>props-父亲</h2>
<button @click="addAddr">父加一条地址</button>
<hr>
<person a="儿子,我是爸爸" :address="addrs"/>
</template>
<script setup>
import person from '@/views/person.vue'
import {reactive} from 'vue'
let addrs = reactive([
{ id: 1, addrName: '现居住', city: '北京朝阳区', detail: '朝阳街1号' },
{ id: 2, addrName: '公司', city: '北京海淀区', detail: '海淀1号' },
{ id: 3, addrName: '老家', city: '山西省大同市', detail: '中央大街1号' }
])
function addAddr(){
let id = Math.floor(Math.random() * 1000) // 可能重复,这里只是示例
addrs.push({ id: id, addrName: '新地址' + id, city: '新地址朝阳区', detail: '新地址朝阳街1号' })
}
</script>
下面是子组件的示例:
<template>
<h2>props-儿子</h2>
<div>来自父亲传过来的数据:{{ a }}</div>
<ul>
<li v-for="item in address" :key="item.id">{{ item.addrName }}的详细地址是{{ item.city }}{{ item.detail }}</li>
</ul>
</template>
<script setup>
defineProps(['a','address'])
</script>
二、生命周期
1、Vue2的生命周期
vue2的生命周期是分为4个阶段8个函数
具体如下:
| 生命周期 | 函数 |
|---|---|
| 创建 | beforeCreate(), created() |
| 挂载 | beforeMount(), mounted() |
| 更新 | beforeUpdate(), updated() |
| 销毁 | beforeDestroy(),destroyed() |
2、Vue3的生命周期
在 vue3 中,不用再写 beforeCreate 和 created ,用 setup 函数替代了;销毁改为卸载了。
vue3的生命周期是分为4个阶段7个函数
具体如下:
| 生命周期 | 函数 |
|---|---|
| 创建 | setup |
| 挂载 | onBeforeMount(), onMounted() |
| 更新 | onBeforeUpdate(), onUpdated() |
| 卸载 | onBeforeUnmount(),onUnmounted() |
代码示例-父组件:
<template>
<button @click="flag = !flag">点我更新person组件状态</button>
<person v-if="!flag"/>
</template>
<script setup>
import person from '@/views/person.vue'
import {ref} from 'vue'
let flag = ref(true)
</script>
代码示例-子组件:
<template>
<div>{{ sum }}</div>
<button @click="sum+=1">点我sum+1</button>
</template>
<script setup>
import {ref,onBeforeMount, onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted } from 'vue';
let sum = ref(0)
onBeforeMount(()=>{
console.log('onBeforeMount执行了-挂载前')
})
onMounted(()=>{
console.log('onMounted执行了-挂载后')
})
onBeforeUpdate(()=>{
console.log('onBeforeUpdate执行了-更新前')
})
onUpdated(()=>{
console.log('onUpdated执行了-更新后')
})
onBeforeUnmount(()=>{
console.log('onBeforeUnmount执行了-卸载前')
})
onUnmounted(()=>{
console.log('onUnmounted执行了-卸载后')
})
</script>
三、Hooks用法和真正的Composition组合式API
一、Hooks介绍
Hooks,顾名思义,挂钩;钩子的意思。在Vue3里,通过hooks,将不同的功能的数据,方法,计算属性,生命周期函数等,所有和该功能有关联的内容,封装到一个函数中。只需要在使用该功能的地方直接引入即可。多个功能,多个Hooks。这样实际就组成了Vue3中真正的Composition组合式API。
二、示例
我们定义2个功能:(只为演示说明)用不同实现,看下效果。
功能1:计算2个数字的和。
功能2:修改个人信息
2.1 不用hooks实现
<template>
<div>{{ count }}</div>
<button @click="addCount">点我count+10</button>
<hr>
<h2>个人信息展示:{{ person.name }}的年龄是{{ person.age }},爱好是{{ person.hobby }}</h2>
<button @click="changeInfo">点我修改个人信息</button>
</template>
<script setup>
import {ref,reactive} from 'vue'
let count = ref(10)
let person = reactive({name:'张三',age:18,hobby:'打球'})
function addCount(){
count.value +=10
}
function changeInfo(){
person.hobby = '追剧'
}
</script>
但是两个功能是这样子,那么多个功能呢?假设有100个功能,那每个功能的数据、方法、计算属性都放到一起,那有需求变化时,简直就是噩梦。这就需要用到开头说的hooks来进行封装了。
2.2 使用hooks实现
首先呢,需要新建hooks文件,文件的命名规范是use开头功能结尾,比如我们这个就可以写成useCount和usePerson,如下,新建hooks目录和文件。
目录和文件:

count功能useCount.ts代码如下:
import {ref} from 'vue'
export default function(){
let count = ref(10)
function addCount(){
count.value +=10
}
return{count,addCount}
}
修改个人信息的usePerson.ts代码如下:
import {reactive} from 'vue'
export default function(){
let person = reactive({name:'张三',age:18,hobby:'打球'})
function changeInfo(){
person.hobby = '追剧'
}
return{person,changeInfo}
}
主文件内容如下:
<template>
<div>{{ count }}</div>
<button @click="addCount">点我count+10</button>
<hr>
<h2>个人信息展示:{{ person.name }}的年龄是{{ person.age }},爱好是{{ person.hobby }}</h2>
<button @click="changeInfo">点我修改个人信息</button>
</template>
<script setup>
import useCount from '@/Hooks/useCount'
import usePerson from '@/Hooks/usePerson'
let {count,addCount} = useCount()
let {person,changeInfo} = usePerson()
</script>
四、路由
- 对路由的理解
它允许你通过定义不同的路径来导航到不同的组件,并且可以实现页面间的无缝切换而不重新加载整个页面。
- 路由配置演示
(1) 如果还没下载vue-router需要先下载
npm install vue-router
(2)scr 目录下新建 router 文件夹,在其下创建index.ts 文件

index.ts 文件( 将一组一组的路由配置到routes里。这里引入了2个页面组件,用来切换和显示***)***
import {createRouter,createWebHistory} from 'vue-router'
import Person from '@/views/person.vue'
import Count from '@/views/count.vue'
const router = createRouter({
history:createWebHistory(),
routes:[
{
path:'/person',
component:Person
},
{
path:'/count',
component:Count
},
]
})
export default router
createRouter: 这是从 vue-router 包中导入的一个函数,用于创建一个新的路由器实例。
createWebHistory:也是从vue-router 包中导入的一个函数,意味着应用将使用 history 模式,与之对应的还有hash模式。
export default router:导出路由实例,以方便在其他地方导入使用。
(3) 在main.ts 下使用 vue-router
main.ts 文件
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
//第一步:引入创建pinia的函数
import { createPinia } from 'pinia'
const app = createApp(App)
//第二步:创建pinia的函数,最好在创建完app以后
const pinia = createPinia()
//第三步:将pinia应用到app上
app.use(router)
app.use(pinia)
app.mount('#app')
(4) 声明式导航代码示例 ------ 新建几个组件,并编写跳转代码
App.vue 文件
<template>
<div>
<router-link to="/person" active-class="active">人员信息</router-link>
<router-link to="/count" active-class="active">count相关的信息</router-link>
</div>
<div class="main">
<RouterView></RouterView>
</div>
</template>
<script setup></script>
<style>
a{
border: 1px solid #000;
margin-right: 10px;
}
.main{
margin-top: 20px;
width: 100%;
height: 200px;
border: 1px solid #000;
}
.active {
background-color: skyblue;
}
</style>
通过<RouterLink to="/person" active-class="active">person</RouterLink> 来识别和控制路由切换,以及选中样式的添加。
to有3种写法,:to="{path:'/person'}"和to="/person" 和:to="{name: 'xinxi'}"
通过<RouterView></RouterView>来定位路由切换后页面组件的显示位置。
person.vue
<template>
<h2>个人信息展示:{{ person.name }}的年龄是{{ person.age }},爱好是{{ person.hobby }}</h2>
<button @click="changeInfo">点我修改个人信息</button>
</template>
<script setup>
import usePerson from '@/Hooks/usePerson'
let {person,changeInfo} = usePerson()
</script>
count.vue
<template>
<div>{{ count }}</div>
<button @click="addCount">点我count+10</button>
</template>
<script setup>
import useCount from '@/Hooks/useCount'
let {count,addCount} = useCount()
</script>
上面实现一个基本的路由切换
五、编程式路由导航
在实际开发中,我们经常是通过在<script>脚本里来进行路由跳转的,直接用<RouterLink>的时候较少。使用编程式导航的场景更多。
如下,将跳转person的路由替换成一个button,调用一个方法。在方法中进行跳转路由,这里需要引入useRouter,并使用router.push或者router.replace方法进行路由跳转。方法里的内容和<RouterLink>里属性to的内容完全是一样的。
举个例子:从count.vue跳转到person.vue
//count.vue
<template>
<button @click="toPerson()">Person</button>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router';
const router = useRouter();
function toPerson() {
router.push(
{
path: '/person',
query: {
id: 1,
name: '王大拿',
age: 56
}
}
)
}
</script>
//person.vue
<template>
<div>从count组件接收到的信息是:{{query.name }}的年龄是{{ query.age }}</div>
</template>
<script setup>
import {useRoute} from 'vue-router'
const {query} = useRoute()//接收参数
</script>
跳转的时候可以使用push跳转,也可以使用replace,push和replace的区别就是,push的留存浏览记录的,可以在浏览器前进和回退里进行操作上一步或者下一步,而replace是不保存浏览记录的。在浏览器前进和回退是无法点击的。
六、路由的两种模式 ------ History 与 Hash 模式
1.1 history 模式
优点:url 更加美观,不带有 #,更接近传统网站的url.
缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有 404 报错。
1.2 hash 模式
优点:兼容性更好,因为不需要服务器端处理路径。
缺点:url 不美观,且在`SEO`优化方面相对较差。
1.3 刷新导致404的原因
使用 history 模式,如果服务端不配合处理路径问题,那么刷新会有404 报错。原因是当你直接访问某个路由路径或刷新页面时,浏览器会向服务器请求该路径,而服务器如果没有正确配置,则会返回 404 错误。
hash模式不会出现这种情况的原因是,'#'号后面的部分被称为 hash部分,例如一个链接 http://xxxxx.xxx/#aaa 浏览器在请求页面时,只会发送 http://xxxxx.xxx 这部分 URL 给服务器,而这部分 #aaa(即 hash 部分)不会被发送。因此无论用户访问的路径是什么(例如 /home /about ),服务器始终只接收到根路径 / 的请求。这意味着服务器总是返回 index.html 文件,然后由 Vue Router 在客户端解析并显示相应的组件。
关于路由更详细的内容可以参考:https://blog.csdn.net/qq_58195504/article/details/145496539