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