Day1
提示:以下是本篇文章正文内容,下面案例可供参考
@vue/cli 4.5.8
当你安装完以后,你会看到有着几个目录,route文件夹是放路由配置文件,而components是放组件,views是放页面。其他的不用管,用不到。
第一步我们先来,分析src/router/index.js代码,我们先分段解释。
导入view文件夹里面的Home.vue为Home
import Home from '../views/Home.vue'
设置组件和路径映射关系
第 3 行:路径为 / 。
第 5 行:组件(component)为刚刚 import 进来的 Home 。
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: function () {
return import(/* webpackChunkName: "about" */ '../views/About.vue')
}
}
]
将刚刚设置的 组件和路径映射 关系(routes)给到router
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
最后将router导出
export default router
使用router-link标签,显示
<template>
<div id="nav">
<router-link to="/">Homerouter-link> |
<router-link to="/about">Aboutrouter-link>
div>
<router-view/>
template>
router-view 是决定模板渲染位置
App.vue
<template>
<div id="nav">
<router-link to="/test1">test1router-link> |
<router-link to="/test2">test2router-link>
div>
<router-view/>
template>
components/test1.vue
<template>
<div>
<h2>我是测试1h2>
<h2>我是测试1h2>
div>
template>
components/test2.vue
<template>
<div>
<h2>我是测试2h2>
<h2>我是测试2h2>
div>
template>
couter/index.js
import test1 from '../components/test1'
import test2 from '../components/test2'
const routes = [
{
path: '/test1',
name: 'test1',
component: test1
},
{
path: '/test2',
name: 'test2',
component: test2
}
]
App.vue
<template>
<div id="nav">
<router-link to="/test1">test1router-link> |
<router-link to="/test2">test2router-link>
div>
<router-view/>
template>
因为在默认是用hash,我们现在就修改为history
src/router/index.js
// 在vue-cli3中
const router = createRouter({
mode: 'history',
routes
})
// 在vue-cli4中
const router = createRouter({
history: createWebHistory(),
routes
})
我们这里设置了当打开网页的时候,使用redirect重定向到 test1 页面里
{
path: '/',
redirect: 'test1'
}
使用的其他属性
tag,指定渲染成任意组件
replace,页面跳转的时候禁止返回
active-class,对应的路由匹配成功时, 会自动给当前元素设置一个router-link-active的class, 设置active-class可以修改默认的名称.
<template>
<div id="app">
<router-link to="/test1" tag="button" replace active-class="my-active">test1router-link> |
<router-link to="/test2" tag="button" replace active-class="my-active">test2router-link>
div>
<router-view/>
template>
<style>
.my-active{
color: red;
}
style>
// router/index.js
const router = createRouter({
history: createWebHistory(),
routes,
linkActiveClass: 'my-active'
})
<button @click="test1click">test1button>
<button @click="test2click">test2button>
<script>
export default {
name:'App',
methods: {
test1click() {
this.$router.push('/test1')
console.log('test1click')
},
test2click(){
this.$router.push('/test2')
console.log('test2click')
}
}
}
script>
一个懒加载对应一个打包后的js文件
const home = () => import('../components/home')
在children数组里写路由记录,其中redirect是设置重定向。
// router/index.js
const test1 = () => import('../components/home')
const routes = [
{
path: '/test1',
name: 'test1',
component: test1,
children: [
{
path: '',
redirect: '/test1/children1'
},
{
path: 'children1',
component: () => import('../components/children1')
},
{
path: 'children2',
component: () => import('../components/children2')
}
]
}
]
在 test1 里调用子组件
<template>
<div>
<h2>我是测试1h2>
<h2>我是测试1h2>
<router-link to="/test1/children1">children1router-link> |
<router-link to="/test1/children2">children2router-link>
<router-view>router-view>
div>
template>
我们新建一个params.vue。
params.vue,中的abc是调用 router/index.js的abc。
params,是直接用浏览器地址后面的Id
<template>
<div id="nav">
<router-link to="/test1" tag="button">test1router-link> |
<router-link to="/test2">test2router-link> |
<router-link :to="'/params/' + paramsId">paramsrouter-link>
div>
<router-view/>
template>
<script>
export default {
name: 'App',
data() {
return {
paramsId: 'params'
}
}
}
script>
<template>
<div>
<h2>我是paramsh2>
<h2>{{$route.params.abc}}h2>
div>
template>
<script>
export default {
name: "params",
computed: {
userId() {
return this.$route.params.abc
}
}
}
script>
<script>
const routes = [
{
path: '/params/:abc',
name: 'params',
component: params
}
]
script>
URI = scheme:[//authority]path[?query][#fragment]
通过query传递参数
<h2>{{$route.query.name}}h2>
<router-link :to="{path: '/query', query:{name: '我是query里面的name'}}">queryrouter-link>
通过2个按钮传递数据,一个是用动态路由,一个是用参数传递。
<template>
<div id="nav">
<button @click="paramsClick">paramsClickbutton>
<button @click="queryClick">paramsClickbutton>
div>
<router-view/>
template>
<script>
export default {
name: 'App',
data() {
return {
paramsId: 'params'
}
},
methods:{
paramsClick(){
this.$router.push('/params/' + this.paramsId);
},
queryClick(){
this.$router.push({
path: '/query',
query:{
name:'我是属于按钮的query'
}
});
}
}
}
script>
我们在开始讲这个区别的时候,首先要知道一件事:所有组件都继承于Vue类的原型
如果我们在Vue的原型上加一个方法,那么所有的组件都可以调用这个方法。
图中:上面打印的是router,下面是route
在这里我们可以很清楚的看到,router 打印的其实是Vue的原型,而 route 打印的是按钮信息
我们来看下vue-router的一部分源码:src/install.js
Vue.mixin({
beforeCreate () {
if (isDef(this.$options.router)) {
this._routerRoot = this
this._router = this.$options.router
this._router.init(this)
Vue.util.defineReactive(this, '_route', this._router.history.current)
} else {
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
}
registerInstance(this, this)
},
destroyed () {
registerInstance(this)
}
})
Object.defineProperty(Vue.prototype, '$router', {
get () { return this._routerRoot._router }
})
Object.defineProperty(Vue.prototype, '$route', {
get () { return this._routerRoot._route }
})
Vue.component('RouterView', View)
Vue.component('RouterLink', Link)
我们先来看第18~20行的代码
18~20的结论:
定义一个属性函数(Object.defineProperty)
给(Vue.prototype)定义的属性
属性的键是($router)
属性的值是(this._routerRoot. _router)
Object.defineProperty //是定义属性函数
Vue.prototype //给这个定义一个属性
$router //属性的键
this._routerRoot._router //属性的值
Vue.prototype.$router = this._routerRoot._router //结果
接下来我们看第3行的:
this.$options,这是指向Vue实例,而后面的:.router而是指向Vue实例里面的router。整段的意思是判断在Vue实例里面有没有router,有就执行下一段代码。
this.$options.router
new Vue({
el: '#app',
router
})
第5行的代码:
第一步我们先把刚刚的 route (这个route其实就是Vue实例里面的route)给到 this._ router ,第二步刚刚的 _ router其实就是,等于 this._routerRoot. _router
this._routerRoot = this // 第二步 this.routerRoot._router = this.$options.router
this._router = this.$options.router // 第一步理解先将router给到_router
最后我们看回代码的结果:
Vue.prototype.$router = this._routerRoot._router //第18~20行的代码
this.$options.router // 第3行的代码
this.routerRoot._router = this.$options.router // 第5行的代码
最后我们得出了一个结论:
这个结论需要我们结合刚刚的理解:
首先我们需要看向第18到20行代码:我们是在Vue实例定义一个属性函数名为($router)
第二步:他的值是
this._routerRoot._router
第三步:
this._routerRoot._router = this.$options.router
// 而
this.$options.router
// 根据第三行的代码得出,他等于VUe实例里面的route
所以,$router永远指向Vue实例的route
最后结论:router是指向Vue实例的router,而route他永远是指向当前活跃的对象,看上面那张图就可以得出这个结论,当按钮被点击时(此时按钮正处于活跃),就返回按钮信息
跳转到某个页面的时候,将该页面的标题改为该页面的名字
to:目标路由对象
from:当前导航将要离开的路由对象
next:调用该方法才能进入下一个钩子
router/index.js
const routes = [
{
path: '/test1',
name: 'test1',
component: test1,
}
]
router.beforeEach((to, from, next) =>{
document.title = to.name
next()
})
将页面的标题,改为上面routers里面的name
作用是:避免组件被频繁的销毁创建
通过 activated() 和 beforeRouteLeave()函数实现,保持状态,点击children2后切换到其他页面,在回来还是显示children2。
test1.vue
export default {
name: "test1",
data() {
return {
message: '你好啊',
path: '/test1/children1'
}
},
// 这两个函数, 只有该组件被保持了状态使用了keep-alive时, 才是有效的
activated() {
this.$router.push(this.path);
console.log('activated');
},
deactivated() {
console.log('deactivated');
},
beforeRouteLeave (to, from, next) {
console.log(this.$route.path);
this.path = this.$route.path;
next()
}
}
App.vue
有些时候我们希望离开某个组件的时候,该组件不被缓存,我们可以使用 exclude
Props:
include
- 字符串或正则表达式。只有名称匹配的组件会被缓存。exclude
- 字符串或正则表达式。任何名称匹配的组件都不会被缓存。max
- 数字。最多可以缓存多少组件实例。这里的test2指向例外一个页面,test2页面被创建,点击test1时,test1页面被创建而test2页面被销毁,在点回test2页面 test2页面被创建。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R0xEU5NM-1605677649829)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201118130820009.png)]