Vue路由的分类与使用
watchEffect
立即运行一个函数,同时响应式的追踪其依赖,并重新执行函数
<template><div><h1>{{ num1 }} + {{ num2 }} = {{ num1 + num2 }}</h1><button @click="changeNum1">num1++</button><button @click="changeNum2">num2++</button></div>
</template>
<script lang="ts" setup name="Person">
import {ref, watch, watchEffect} from "vue";
let num1 = ref(1);
let num2 = ref(3);const changeNum1 = () => {num1.value += 1;
}const changeNum2 = () => {num2.value += 1;
}
/*watch([num1, num2], (value) => {const [newNum1, newNum2] = value;console.log(newNum1, newNum2)if (newNum1 == 5 || newNum2 == 7) {console.log("数据到达");}
})*/
const stopWatch = watchEffect(() => {console.log(num1.value,num2.value)if (num1.value == 5 || num2.value == 7) {console.log("数据到达,停止监视");stopWatch();}
})</script><style scoped></style>
标签ref属性
作用 在普通的DOM上 获取DOM节点,用在组件上 获取组件实例
用于DOM 获取节点
<h1 ref="title1">猿究院</h1><h1 ref="title2">北大街</h1><h1 ref="title3">Vue</h1><input type="text" value="默认值" ref="ipt"/>let title1 = ref();
let title2 = ref();
let title3 = ref();
let ipt = ref();const showLog = () => {console.log(title1.value)console.log(title2.value)console.log(title3.value)//ipt > RefImpl >value <input 对象 .valueconsole.log(ipt.value.value)
}
ref作用于组件上
<Message ref="msg"></Message>********* 子组件中
//使用defineExpose将组件的数据交给外部组件
defineExpose({title, desc})
*********
let msg = ref();
const getMessage = () => {console.log(msg.value.title)console.log(msg.value.desc)}
props
<template><Person :list="persons"></Person>
</template>
<script lang="ts" setup name="App">
import Person from "@/components/Person.vue";
import {reactive} from "vue";
import type {Persons} from "@/assets/IPersonInter";
import {nanoid} from "nanoid";let persons = reactive<Persons>([{id: nanoid(), name: '张三', age: 20},{id: nanoid(), name: '李四', age: 19},{id: nanoid(), name: '王五', age: 25}
])</script>
<style lang="scss" scoped>
</style><template><ul v-if="list != undefined"><li v-for="(p,index) in list" :key="p.id">{{ p.name }} - {{ p.age }}</li></ul><div v-else>暂无数据</div>
</template><script lang="ts" setup name="Person">
import type {Persons} from "@/assets/IPersonInter";
//第一种写法
// const props = defineProps(['list']);//第二种写法 接收 + 限制类型
// const props =defineProps<{list:Persons}>();//第三种写法 接收 + 限制类型 + 指定默认值+限制必要性 (? 可以传 可不传)
const props = withDefaults(defineProps<{ list?: Persons }>(), {list: () => [{id: "001", name: '默认值', age: 0}]
});//在setup中使用 接收到的数据时 需要通过 props对象 .
console.log(props.list)
</script>
<style scoped>
</style>
自定义的hook
本质是一个函数,把setup中的 组合式 API进行封装。
hook 优势:让代码复用 ,让setup中的逻辑更清楚。
useDog.ts
import {onMounted, reactive} from "vue";
import axios, {AxiosError} from "axios";export default function () {let dogList = reactive<string[]>([])async function getDog() {//发送请求try {let {data} = await axios.get("https://dog.ceo/api/breed/weimaraner/images/random");console.log("请求的结果:", data);dogList.push(data.message)} catch (error) {const err = <AxiosError>error;console.log(err.message)}}onMounted(() => {getDog();})return {dogList, getDog}
}
useSum.ts
import {ref, onMounted} from 'vue'
export default function () {let sum = ref(0);const increment = () => {sum.value += 1;}const decrement = () => {sum.value -= 1;}onMounted(() => {console.log("执行了useSum的onMounted")increment();})//向外暴露数据return {sum, increment, decrement}
}
Person.vue
<template><h2>当前求和:{{ sum }}</h2><button @click="increment">点我+1</button><button @click="decrement">点我-1</button><hr/><button @click="getDog">再来一直狗子</button><img style="width: 200px;" :src="(dog as string)" v-for="(dog,index) in dogList" :key="index">
</template><script lang="ts" setup name="Person">
import useSum from "@/assets/useSum";
import {onMounted} from "vue";
import useDog from "@/assets/useDog";let {sum, increment, decrement} = useSum();
let {dogList, getDog} = useDog();onMounted(() => {console.log("我是person组件的onMounted")
})</script>
<style scoped>
</style>
路由
1.安装 npm install vue-router@4
2.使用 在 src/router/index.ts文件
import {createRouter, createWebHistory} from 'vue-router'//被路由的组件
import Home from "@/components/Home.vue";
import About from "@/components/About.vue";const router = createRouter({history: createWebHistory(),routes: [{path: "/", 默认访问component: Home},{path: '/home',component: Home},{path: '/about',component: About}]
})export default router;<!-- 声明式路由 --><RouterLink to="/home">Home</RouterLink><RouterLink to="/about">About</RouterLink><hr/><!-- 被路由的组件 会显示在 RouterView --><RouterView></RouterView>
路由的模式
1.history (createWebHistory) URL地址更加美观 不带# 更加接近传统的URL。
后期上线后 需要后台配合处理路径问题 否则 刷新可能会有404错误
2.createWebHashHistory 兼容性更好,后期不需要后台的处理
to属性 的两种写法
to 字符串写法<RouterLink to="/home">Home</RouterLink>to对象写法
嵌套路由
router/index.ts
import {createRouter, createWebHashHistory, createWebHistory} from 'vue-router'//被路由的组件
import Home from "@/components/Home.vue";
import About from "@/components/About.vue";
import News from "@/components/News.vue";
import Detail from "@/components/Detail.vue";const router = createRouter({history: createWebHashHistory(),routes: [{path: "/",component: Home},{path: '/home',component: Home,children: [ 嵌套路由{path: "news", 路径前不加/component: News,children: [{path: "detail",component: Detail}]}]},{path: '/about',component: About}]
})export default router;使用
news.vue
<!-- 导航-->
to:需要写全路径
<RouterLink to="/home/news/detail">Detail</RouterLink>
<!-- 展示被路由的组件-->
<RouterView></RouterView>
命名路由
在路由配置文件 新增属性(name)
{path: "news",component: News,children: [{path: "detail",name:'xq',component: Detail}]}
使用
<!-- 使用命名路由 需要对象写法的to属性 --><RouterLink :to="{name:'xq'}">Detail</RouterLink>
路由懒加载
import {createRouter, createWebHashHistory, createWebHistory} from 'vue-router'// //被路由的组件
// import Home from "@/components/Home.vue";
// import About from "@/components/About.vue";
// import News from "@/components/News.vue";
// import Detail from "@/components/Detail.vue";const router = createRouter({
history: createWebHashHistory(),routes: [{path: "/",component: () => import('@/components/Home.vue')},{path: '/home',component: () => import('@/components/Home.vue'),children: [{path: "news",component: () => import('@/components/News.vue'),children: [{path: "detail",name: 'xq',component: () => import('@/components/Detail.vue')}]}]},{path: '/about',component: () => import('@/components/About.vue')}]
})export default router;
路由重定向
{path: "/",component: () => import('@/components/Home.vue'),redirect: to => {// 方法接收目标路由作为参数// return 重定向的字符串路径/路径对象return {// path:"/home/news/detail"name:'xq' //命名路由}
}
},{path: "/",component: () => import('@/components/Home.vue'),redirect: { // path:"/home/news/detail"name:'xq' //命名路由}
},
路由传参
1.query传参
<RouterLink to="/home/news/detail?id=1&title=测试数据A">Detail</RouterLink><!-- <RouterLink :to="{name:'xq',query:{id:2,title:'测试数据B'}}">--><!-- Detail--><!-- </RouterLink>-->
接收
import {useRoute} from "vue-router";const route = useRoute();{{route.query.参数名}}-{{route.query.title}}2.
2.params传参
1.index.ts中 路由配置占位符{path: "news",component: () => import('@/components/News.vue'),children: [{path: "detail/:id/:title", 占位符name: 'xq',component: () => import('@/components/Detail.vue')}]}
使用
<!--params 传参 字符串写法-->
<RouterLink to="/home/news/detail/1/测试数据A">Detail</RouterLink><!-- params 传参 使用命名路由 需要对象写法的to属性 -->
<RouterLink :to="{name:'xq',params:{id:2,title:'测试数据B'}}">Detail</RouterLink>接收
import {useRoute} from "vue-router";const route = useRoute();
接收属性
route.params.属性名
简化接收参数的方式 路由的props
ruter/index.tspath: "detail/:id/:title",name: 'xq',component: () => import('@/components/Detail.vue'),props:{id:'0000',title:'暂无数据'} // 固定值//props 布尔写法 将收到的params参数作为 props传入组件props:true
props 函数写法
props(route) {return route.query;}
replace属性
作用:控制路由跳转是 浏览器的历史记录
push 默认值 : 追加历史记录
replace 替换当前记录
编程式路由
import router from "@/router";
// router.replace({
router.push({// path:''name: 'xq',params: {id: id,title: title}})