一、动态组件
动态切换组件的显示与隐藏
1.首先要注册组件components:{ Left,Right}
2.data里声明一个变量comName来控制需要展示的组件名字:
data(){
return {
comName:'Left' //名字要用字符串
}
},
3.在需要展示的位置写上占位符,让占位符的is属性指向变量:
<component :is="comName"></component>
之后可通过按钮的点击使得变量comName发生改变,从而展示不同的组件
<button @click="comName='Left'">展示Left</button>
<button @click="comName='Right'">展示Right</button>
动态组件的切换默认会把被切换的组件销毁,再切回来又是全新的组件,所以需要<keep-alive>标签进行缓存而不是销毁。
<keep-alive>
<component :is="comName"></component>
</keep-alive>
这样用</keep-alive>包起来的组件,
切换走触发deactivated被缓存生命周期函数,状态是失活。;
切换回来被激活触发activated被激活生命周期函数,状态是激活。
如果只需要指定缓存某个组件,可以用include属性指定:
<keep-alive include="Left"> 写组件的注册名称
<component :is="comName"></component>
</keep-alive>
如果某个不需要被缓存,用exclude属性指定,注意这两个属性不能同时用
二、插槽
把不确定放置,由用户指定的部分定义为插槽。
1.首先要注册组件components:{ Left}
2.父组件使用<Left>子组件,用<template>标签包裹需要放到插槽的内容,并且用 v-slot属性指定放置哪个插槽,可以简写为#:
<Left>
<template #hh>
<p>这是指定放某个插槽的</p>
</template>
</Left>
3.子组件定义插槽,找好位置并起名字:<slot name=“hh”></slot>
父组件使用子组件不一定传插槽内容,子组件可以在<slot name=“hh”>这里面写内容</slot>
内容会默认展示,如果父组件传内容,就展示父组件的内容
三、路由
前端路由的工作方式:
1.用户点击了页面的路由链接router-link(本质就是a链接)
2.导致了URL地址栏中的hash值发生了变化
3.前端路由监听到了hash地址的变化
4.前端路由把当前hash地址对应的组件渲染到浏览器中
所以路由是不需要注册组件的,只需要使地址变化,路由会把对应组件渲染到浏览器
使用步骤:
1.安装 npm i vue-router@3.5.2 -S
2.创建路由模块,src下建立router目录,目录下建index.js
目的要在这里使用路由插件,所以步骤是:
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
然后import导入所有路由组件
3.创建路由的实例对象并传入一个对象配置项,用routes数组包好地址和组件的对应关系:
const router =new VueRouter( {
routes:[
{path:'/home',component:Home},
{path:'/home',component:Home},
{path:'/home',component:Home},
]})
4.向外共享路由的实例对象
export default router
5.main文件导入并挂载
import router from '@/router/index.js'
new Vue({
render: h => h(App),
router
}).$mount('#app')
6.标签写上<router-view></router-view>占位符
让地址的改变可以有两种方式
(1)声明式导航:点击链接实现导航的方式,叫做声明式导航,例如普通网页中国点击a链接,vue项目中点击router-link链接都属于声明式导航
<router-link to="/home">点击home</router-link>
(2)编程式导航:调用API方法实现。
this.$router.push('hash地址') 跳转到指定的hash地址,并增加一条历史记录
this.$router.replace('hash地址') 跳转到指定的hash地址,并替换当前的历史记录,相当于是不留当前记录,返回不回来
this.$router.go(数值n) n可以正数也可以负数,有历史记录就可以前进后退到,但是replace的就搞不了哈,后退层数超过上限则原地不动,都可以直接写标签行内,this要省略否则会报错:
$router.go简化:
$router.back()后退到上一层
$router.forword()前进到上一层
动态路由:
如果是信息一 信息二 信息三 这样的,不需要设置三个地址和三个路由组件的对应关系,只需要有一个路由组件就可以了,它会随着传来的参数不同展示不同的内容。这就是动态路由,改变地址的时候带参数,带参数也有两种方式:
1.查询参数query:
声明式导航:<router-link :to="{name:'home', query: {id:1}}"> //路由可不配置
编程式导航:this.$router.push({name:'home',query: {id:'1'}})
this.$router.push({path:'/home',query: {id:'1'}})
2.路径参数params:
声明式导航:<router-link :to="{name:'home', params: {id:1}}">
编程式导航:this.$router.push({name:'home',params: {id:'1'}}) // 只能用 name
路由配置:
{path: "/home/:id,。。。}
query和params区别:
query类似 get, 跳转之后页面 url后面会拼接参数,类似?id=1, 非重要性的可以这样传,刷新页面id还在
params类似 post, 跳转之后页面 url后面不会拼接参数 , 刷新页面id 会消失
取参:
html: $route.query.id $route.params.id
script:this.$route.query.id this.$route.params.id
路由配置允许接收参数,并且在动态路由自定义属性prop:[id] 就可以直接用{{id}}:
{path: "/home/:id,......prop:true}
四、三者区别
路由知识扩展:
导航守卫:可以控制路由的访问权限
全局前置守卫router.beforeEach:
每次发生路由的导航跳转时,都会触发全局前置守卫,因此在全局前置守卫中,程序员可以对每个路由进行访问权限的控制:
router.beforeEach(function (to, from, next) {
// 1.拿到用户将要访问的hash地址
// 2.判断hash地址是否等于/main,等于则需要登录才能访问,不等于就直接放行
if (to.path === "/main") {
const token = localStorage.getItem("token");
if (token) {有token就放行
next();
} else {没有token就去登录页面
next("/login");
}
} else {不去主页随便放行
next();
}
});
to是将要访问的路由的信息对象 to.path 就是hash地址
from是将要离开的路由的信息对象
next是一个函数,调用next()表示放行,允许这次路由导航,添加参数指定往哪个hash地址放行
如果多个地址需要守卫:
1.新建一个js模块:export default ['/home','/home/users','/home/rights']
2.路由模块引入:import pathArr from ''。。"
router.beforeEach(function (to, from, next) {
if (pathArr.indexOf(to.path)!==-1) {
const token = localStorage.getItem("token");
if (token) {
......后面都一样