1.Hooks
就是进行数据的封装,同一种类型的 数据 方法 计算属性 ,放在一起
命名规范 use+'功能名称'.ts 或.js
创建一个文件夹 hooks
1.useDog.ts
import { reactive,onMounted } from "vue";
import axios from "axios";
export default function () {
//数据
let dogList = reactive([
"https://images.dog.ceo/breeds/pembroke/n02113023_14262.jpg",
]);
//方法
async function addDog() {
try {
let result = await axios.get("https://dog.ceo/api/breeds/image/random");
dogList.unshift(result.data.message);
} catch (error) {
alert(error.message);
}
}
onMounted(()=>{
addDog();
})
return { dogList, addDog };
}
2.useSum.ts
import { ref ,onMounted,computed} from "vue";
export default function () {
//数据
let sum = ref(0);
let bigSum = computed(()=>{
return sum.value*10;
})
//方法
function changeSUM() {
sum.value++;
}
onMounted(()=>{
sum.value+=10;
})
//向外部提供东西
return {
sum,
changeSUM,
bigSum
}
}
3.person.vue
<template>
<div class="person">
<h2>求和为:{{ sum }} 计算出十倍后的数:{{ bigSum }}</h2>
<button @click="changeSUM">点我sum+1</button>
<hr />
<img v-for="item in dogList" :key="item" :src="item" alt="" />
<br />
<button @click="addDog">再来一只小狗</button>
</div>
</template>
<!-- 会自动暴露出去 -->
<script lang="ts" setup name="Person">
import useSum from '@/hooks/useSum';
import useDog from '@/hooks/useDog';
let {sum,changeSUM,bigSum} = useSum();
let {dogList,addDog} = useDog();
</script>
<style scoped>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
button {
margin: 0 5px;
}
img {
height: 100px;
margin-right: 10px;
}
</style>
2.Vue3 的路由
1.安装路由器
npm i vue-router
2.创建文件
3.router.ts
//创建一个路由器,并暴露出去
// 第一步:引入createRouter
import {createRouter,createWebHistory} from 'vue-router'
//引入一个一个可能要呈现的组件
import Home from '@/components/Home.vue'
import News from '@/components/News.vue'
import About from '@/components/About.vue'
//第二步: 创建路由器
const router = createRouter({
history:createWebHistory(),//路由器的工作模式(稍后讲解)
routes:[
{
path:'/home',
component: Home
},
{
path:'/news',
component: News
},
{
path:'/about',
component: About
}
]
})
//暴露出去
export default router
4.app.vue
<template>
<div class="app">
<h2 class="title">Vue 路由测试</h2>
<!-- 导航区 -->
<div class="navigate">
<RouterLink to="/home" active-class="xiaozhupeiqi">首页</RouterLink>
<RouterLink to="/news" active-class="xiaozhupeiqi">新闻</RouterLink>
<RouterLink to="/about" active-class="xiaozhupeiqi">关于</RouterLink>
</div>
<!-- 展示区 -->
<div class="main-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script lang="ts" setup name="App">
import { RouterView,RouterLink } from 'vue-router';
</script>
<style scoped>
/* App */
.title {
text-align: center;
word-spacing: 5px;
margin: 30px 0;
height: 70px;
line-height: 70px;
background-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.xiaozhupeiqi {
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;
}
.active{
background-color: #ffc268;
}
</style>
5.main.ts
//引入 createApp用于创建应用
import {createApp} from 'vue';
//引入 App 根组件
import App from './App.vue';
//引入路由器
import router from './router';
//创建一个应用
const app = createApp(App);
//使用一个插件
app.use(router);
//挂载整个应用到app容器中
app.mount('#app');
6.两个注意点
7.路由器的工作模式
解决history模式404问题
8.to的两种写法
9.嵌套路由
1.Detail.vue
//创建一个路由器,并暴露出去
// 第一步:引入createRouter
import {createRouter,createWebHistory,createWebHashHistory} 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模式
// history:createWebHashHistory(),//Hash模式
routes:[
{
name: 'zhuye',
path:'/home',
component: Home
},
{
name:'xinwen',
path:'/news',
component: News,
children:[
{
path:'detail',
component:Detail
}
]
},
{
name:'guanyu',
path:'/about',
component: About
}
]
})
//暴露出去
export default router
2.News.vue
<template>
<div class="news">
<!-- 导航区 -->
<ul>
<li v-for="news in newsList" :key="news.id"><RouterLink :to="{path:'/news/detail'}">{{ news.title }}</RouterLink></li>
</ul>
<!-- 展示取 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script setup lang="ts" name="News">
import { nanoid } from 'nanoid';
import { reactive } from 'vue';
import { RouterView } from 'vue-router';
const newsList = reactive([
{id:nanoid(),title:'一种游戏',content:'西兰花'},
{id:nanoid(),title:'一种水果',content:'学IT'},
{id:nanoid(),title:'如何一夜暴富',content:'明天是周一'},
{id:nanoid(),title:'震惊,玩玩没想到',content:'快过年了'},
]);
</script>
<style scoped>
/* 新闻 */
.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>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;
}
</style>
10.query参数
<template>
<div class="news">
<!-- 导航区 -->
<ul>
<li v-for="news in newsList" :key="news.id">
<!-- 第一种写法 -->
<!-- <RouterLink :to="`/news/detail?id=${news.id}&title=${news.title}&content=${news.content}`">{{ news.title }}</RouterLink> -->
<!-- 第二种写法 -->
<RouterLink :to="{
// path: '/news/detail',
name: 'xiangqing',
query: {
id: news.id,
title: news.title,
content: news.content
}
}">{{ news.title }}</RouterLink>
</li>
</ul>
<!-- 展示取 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script setup lang="ts" name="News">
import { nanoid } from "nanoid";
import { reactive } from "vue";
import { RouterView } from "vue-router";
const newsList = reactive([
{ id: nanoid(), title: "一种游戏", content: "西兰花" },
{ id: nanoid(), title: "一种水果", content: "学IT" },
{ id: nanoid(), title: "如何一夜暴富", content: "明天是周一" },
{ id: nanoid(), title: "震惊,玩玩没想到", content: "快过年了" },
]);
</script>
<style scoped>
/* 新闻 */
.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;
}
</style>
<template>
<ul class="news-list">
<li>编号:{{ query.id }}</li>
<li>标题:{{ query.title }}</li>
<li>内容:{{ query.content }}</li>
</ul>
</template>
<script setup lang="ts" name="Detail">
// 这是一个hooks,向这个组件实例暴露了一个函数
import { useRoute } from "vue-router";
import { toRefs } from "vue";
const route = useRoute();
const {query} = toRefs(route);
// console.log(route.query);
</script>
<style scoped>
.news-list {
list-style: none;
padding-left: 20px;
}
.news-list > li {
line-height: 30px;
}
</style>
11.params参数
<template>
<div class="news">
<!-- 导航区 -->
<ul>
<li v-for="news in newsList" :key="news.id">
<!-- 第一种写法 纯字符串 -->
<!-- <RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">{{ news.title }}</RouterLink> -->
<!-- 第二种写法 -->
<RouterLink
:to="{
name: 'xiangqing',//params不允许path传参,只能用name 而且参数只能是基本类型
params: {
id: news.id,
title: news.title,
// content: news.content,
},
}"
>{{ news.title }}</RouterLink
>
</li>
</ul>
<!-- 展示取 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script setup lang="ts" name="News">
import { nanoid } from "nanoid";
import { reactive } from "vue";
import { RouterView } from "vue-router";
const newsList = reactive([
{ id: nanoid(), title: "一种游戏", content: "西兰花" },
{ id: nanoid(), title: "一种水果", content: "学IT" },
{ id: nanoid(), title: "如何一夜暴富", content: "明天是周一" },
{ id: nanoid(), title: "震惊,玩玩没想到", content: "快过年了" },
]);
</script>
<style scoped>
/* 新闻 */
.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;
}
</style>
<template>
<div class="news">
<!-- 导航区 -->
<ul>
<li v-for="news in newsList" :key="news.id">
<!-- 第一种写法 纯字符串 -->
<!-- <RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">{{ news.title }}</RouterLink> -->
<!-- 第二种写法 -->
<RouterLink
:to="{
name: 'xiangqing',//params不允许path传参,只能用name 而且参数只能是基本类型
params: {
id: news.id,
title: news.title,
// content: news.content,
},
}"
>{{ news.title }}</RouterLink
>
</li>
</ul>
<!-- 展示取 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script setup lang="ts" name="News">
import { nanoid } from "nanoid";
import { reactive } from "vue";
import { RouterView } from "vue-router";
const newsList = reactive([
{ id: nanoid(), title: "一种游戏", content: "西兰花" },
{ id: nanoid(), title: "一种水果", content: "学IT" },
{ id: nanoid(), title: "如何一夜暴富", content: "明天是周一" },
{ id: nanoid(), title: "震惊,玩玩没想到", content: "快过年了" },
]);
</script>
<style scoped>
/* 新闻 */
.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;
}
</style>
12.Props路由配置
//创建一个路由器,并暴露出去
// 第一步:引入createRouter
import { createRouter, createWebHistory, createWebHashHistory } 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模式
// history:createWebHashHistory(),//Hash模式
routes: [
{
name: 'zhuye',
path: '/home',
component: Home
},
{
name: 'xinwen',
path: '/news',
component: News,
children: [
{
name: 'xiangqing',
path: 'detail',//问号代表可传可不传
component: Detail,
//第一种写法,将路由收到的所有params参数作为props传给路由组件
// props:true //params参数全部变成 params
//第二种写法 函数写法 可以自己决定将什么作为props给路由组件
props(route){
// console.log(route)
return route.query
}
//第三种写法 写死了
// props: {
// a: 100,
// b: 200
// }
}
]
},
{
name: 'guanyu',
path: '/about',
component: About
}
]
})
//暴露出去
export default router
<template>
<div class="news">
<!-- 导航区 -->
<ul>
<li v-for="news in newsList" :key="news.id">
<!-- 第一种写法 纯字符串 -->
<!-- <RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">{{ news.title }}</RouterLink> -->
<!-- 第二种写法 -->
<RouterLink
:to="{
name: 'xiangqing',//params不允许path传参,只能用name 而且参数只能是基本类型
query: {
id: news.id,
title: news.title,
content: news.content,
},
}"
>{{ news.title }}</RouterLink
>
</li>
</ul>
<!-- 展示取 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script setup lang="ts" name="News">
import { nanoid } from "nanoid";
import { reactive } from "vue";
import { RouterView } from "vue-router";
const newsList = reactive([
{ id: nanoid(), title: "一种游戏", content: "西兰花" },
{ id: nanoid(), title: "一种水果", content: "学IT" },
{ id: nanoid(), title: "如何一夜暴富", content: "明天是周一" },
{ id: nanoid(), title: "震惊,玩玩没想到", content: "快过年了" },
]);
</script>
<style scoped>
/* 新闻 */
.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;
}
</style>
<template>
<ul class="news-list">
<li>编号:{{ id }}</li>
<li>标题:{{ title }}</li>
<li>内容:{{ content }}</li>
</ul>
</template>
<script setup lang="ts" name="Detail">
// import { useRoute } from 'vue-router';
// import { toRefs } from 'vue';
// const route = useRoute();
// const {params} =toRefs(route);
defineProps(["id", "title", "content"]);
</script>
<style scoped>
.news-list {
list-style: none;
padding-left: 20px;
}
.news-list > li {
line-height: 30px;
}
</style>
13.replace属性
<template>
<div class="app">
<h2 class="title">Vue 路由测试</h2>
<!-- 导航区 -->
<div class="navigate">
<!-- 对象写法 路径跳转 -->
<RouterLink :to="{path:'/home'}" active-class="active" replace>首页</RouterLink>
<!-- 对象写法 名字跳转 -->
<RouterLink :to="{name:'xinwen'}" active-class="active" replace>新闻</RouterLink>
<!-- 字符串写法 -->
<RouterLink to="/about" active-class="active" replace>关于</RouterLink>
</div>
<!-- 展示区 -->
<div class="main-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script lang="ts" setup name="App">
import { RouterView,RouterLink } from 'vue-router';
</script>
<style scoped>
/* App */
.title {
text-align: center;
word-spacing: 5px;
margin: 30px 0;
height: 70px;
line-height: 70px;
background-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;
}
.active{
background-color: #ffc268;
}
</style>
14.编程式路由导航
脱离<RouterLink> 实现路由跳转
<template>
<div class="news">
<!-- 导航区 -->
<ul>
<li v-for="news in newsList" :key="news.id">
<button @click="showNewsDetail(news)">查看新闻</button>
<!-- 第二种写法 -->
<RouterLink
:to="{
name: 'xiangqing',//params不允许path传参,只能用name 而且参数只能是基本类型
query: {
id: news.id,
title: news.title,
content: news.content,
},
}"
>{{ news.title }}</RouterLink
>
</li>
</ul>
<!-- 展示取 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script setup lang="ts" name="News">
import { nanoid } from "nanoid";
import { reactive } from "vue";
import { RouterView,useRouter } from "vue-router";
const newsList = reactive([
{ id: nanoid(), title: "一种游戏", content: "西兰花" },
{ id: nanoid(), title: "一种水果", content: "学IT" },
{ id: nanoid(), title: "如何一夜暴富", content: "明天是周一" },
{ id: nanoid(), title: "震惊,玩玩没想到", content: "快过年了" },
]);
const router = useRouter();
function showNewsDetail(news){
//对象写法 和 to同理
router.push({
name:'xiangqing',
query:{
...news
}
})
// router.replace({
// name:'xiangqing',
// query:{
// ...news
// }
// })
}
</script>
<style scoped>
/* 新闻 */
.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;
}
</style>
15.重定向
//创建一个路由器,并暴露出去
// 第一步:引入createRouter
import { createRouter, createWebHistory, createWebHashHistory } 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模式
// history:createWebHashHistory(),//Hash模式
routes: [
{
name: 'zhuye',
path: '/home',
component: Home
},
{
name: 'xinwen',
path: '/news',
component: News,
children: [
{
name: 'xiangqing',
path: 'detail',//问号代表可传可不传
component: Detail,
//第一种写法,将路由收到的所有params参数作为props传给路由组件
// props:true //params参数全部变成 params
//第二种写法 函数写法 可以自己决定将什么作为props给路由组件
props(route){
// console.log(route)
return route.query
}
//第三种写法 写死了
// props: {
// a: 100,
// b: 200
// }
}
]
},
{
name: 'guanyu',
path: '/about',
component: About
},
{
path:'/',//重定向
redirect:'/home'
}
]
})
//暴露出去
export default router