Vue-Router
-
路由
—路由:通过互联的网络把信息从源地址传输到目的地址的活动;路由器提供两种机制路由和转送,路由时决定数据包从来源到目的地的路径,转送将输入端的数据的转移到合适的输出端;
—路由中有一个非常重要的概念叫路由表,路由表本质上就是一个映射表,决定数据包的指向;包括内网ip:电脑标识(mac地址);
—IP地址必须是唯一的,内网IP(192.168.1.110等)和公网IP(202.111.23.45等是永远不重复的!唯一的身份标识);
—前端渲染和后端渲染?
后端路由阶段:
(1)后端渲染:早期网页的开发是通过jsp(java server page)/php,HTML页面都是由服务器渲染的,服务器直接生产渲染好的对应的HTML页面,返回给客户端进行展示;前端页面会将一个url请求发送给后端服务器 ,服务器端的java代码的作用是从数据库中读取数据(HTML+CSS+Java),并且将它动态的渲染过后(HTML+CSS)的直接放在页面中;
(2)多页面服务器如何处理?
URL会发送到服务器,服务器会通过正则对该URL进行匹配,并且最后交给一个Contorller进行处理;
Controller进行各种处理,最终生成HTML或者数据,返回给前端;这就完成一个IO操作!
这种情况渲染好的页面,不需要单独加载任何的js和css,可以直接交给浏览器展示,这样有利于SEO的优化;
(3)后端路由:后端服务器处理URL和页面之间的映射关系;页面需要请求不同的路径内容,服务器会进行渲染处理,并将渲染好的页面返回给客户端;
(4)后端路由的缺点
整个页面的模块都是由后端人员来编写和维护的;
前端开发人员如果要开发页面,需要通过PHP和Java等语言来编写页面代码;
通常情况下HTML代码和数据以及对应的逻辑关系会混在一起,编写和维护都是非常糟糕的;
前后端路由分离阶段(前端渲染):
(1)随着Ajax的出现,有了前后端分离的开发模式;后端只提供API返回的数据,不负责任何阶段的内容;前端通过Ajax获取数据,并且可以通过JavaScript将数据渲染到页面中;
(2)客服端发送一个URL请求到静态资源服务器中,然后从静态资源服务器中获取html+css+js,html+css可以直接渲染,但是js代码是由浏览器执行,此时js代码中会发送API请求到服务器中,后端服务器会将数据返回到浏览器,浏览器通过js代码进行渲染;
(3)优点:前后端负责的清晰,后端专注于数据的处理,前端专注于交互和可视化处理;并且当移动端(iOS/Android)出现后,后端不需要进行任何处理,依然使用之前的一套API即可;目前很多网站依然采用这种模式开发;
前端渲染:浏览器中显示的网页中的大部分内容是由前端编写js代码并在浏览器执行的,最终渲染出来的!
单页面富应用阶段SPA:
(1)其实SPA最主要的特点是再前后端分离的基础上加了一层前端路由,也就是前端来维护一套路由规则;
(2)SPA整个网页只有一个html页面,也就说再静态资源管理器中只会返回一个index.html+css+js的包,需要前端路由生成一个url和页面的映射关系,通过前端路由可以分离出不同页面的显示,即通过不同url根据前端路由映射不同组件显示不同页面;
前端路由的核心:改变URL,但是页面不进行刷新(不向服务器请求任何资源);
URL的hash哈希
—URL的hash也就是锚点(#),本质上是改变window.location的href属性;
—可以直接通过赋值
location.hash
来改变href
,但是页面不发生刷新;例如:location.hash='/foo'
;—一般通过该方法进行路由映射访问,即不需要访问服务器,通过哈希刷新url,然后在前端路由中根据不同url渲染不同的组件;
HTML5中的history模式:pushState
—通过
history.pushState({},'','home')
改变网页地址(不刷新)实际上是一个栈结构(压栈);网页url中永远显示最后入栈的,即栈顶元素;—可以通过
history.back()
进行依次访问栈中的元素(弹栈),满足后进先出的原则;—可以通过
history.replaceState({},'','home')
实现当前url的替换,但是不可以通过history.back()
进行页面的返回;—
history.back()
等价于history.go(-1)
;history.forward()
等价于history.go(1)
,这两个接口相当于浏览器界面的后退和前进;vue-router
—目前前端流行的三大框架,都有自己的路由实现:
(1)Angular的ngRouter;
(2)React的ReactRouter;
(3)Vue的vue-router;
—vue-router是Vue.js官网的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用;可以通过官网进行学习;
—vue-router是基于路由和组件的;路由用于设定访问路径,将路径和组件映射起来,再vue-router的单页面应用中,页面的路径的改变就是组件的切换;
—安装路由:
npm install vue-router --save
—模块化工程中使用它(因为是一个插件,所以可以通过Vue.use()来安装路由功能):
(1)导入路由对象
import VueRouter from 'vue-router'
,并且通过Vue.use(VueRouter)
安装插件;(2)创建路由实例
const router = new VueRouter({routers:[配置路由和组件之间的映射关系]})
,并且传入路由映射配置;注意这里的路由映射名称为routers,不能随意改变,可能会报错;(3)在Vue实例中挂载创建的路由实例;首先将router对象导出:
export default router
,然后在main.js中导入router
并挂载在vue实例中;路由映射配置和呈现
(1)创建路由组件
(2)配置路由映射:组件和路径映射关系
const routers = [ { //这里可能会因为加入/报错 path:'/home', component:Home }, { path:'/about', component:About } ]
(3)使用路由:通过
<router-link>
和<router-view>
//该标签是一个vue-router已经内置的组件,它会被渲染成为一个<a>标签 <router-link to="/home">首页</router-link> <router-link to="/about">关于</router-link> //相当于占位,组件内容会替代当前router-view在页面中显示 //根据当前路径,动态渲染出不同的组件; <router-view></router-view>
—在路由切换时,切换的是
<router-view>
挂载的组件,其他内容不会发生改变;—
<router-link>
中可以通过to
属性指定跳转的路径,它还有其他属性:(1)
tag
:可以指定<router-link>
之后渲染成什么组件,比如渲染成为一个<li>
元素而不是默认的<a>
元素;<router-link tag="button">
(2)
replace
:不会留下history
记录,所以指定replace
的情况下,后退键返回不能返回到上一个页面中;(3)
active-class
:当<router-link>
对应的路由匹配成功时,会自动给当前元素设置一个router-link-active
的class
,设置active-class
可以修改默认名称:在进行高亮显示的导航菜单或者底部
tabbar
时,会使用到该类;但是通常不会修改类的属性,会直接使用默认的
router-link-active
即可;如果想要修改多组
<router-link>
的class
名称,可以在路由文件下路由实例中修改:const route = new VueRouter({ linkActiveClass:'active' })
—路由的默认值
const routes = [ { //配置根路径 path:'/', //重定向,将根路径重定向到/home路径下 redirect:'/home' } ]
—我们创建路由的时候,默认是hash模式,修改为history模式如下:
const router = new VueRouter({ routes, mode:'history' })
通过代码跳转路由
export default{ methods:{ homeClick(){ //push等价于pushState this.$router.push('/home'+this.userId) //或者可以使用replace this.$router.replace('/about') } } }
-
动态路由
—在某些情况下,一个页面的path路径可能不确定,比如进入用户页面时,希望后面跟上用户ID,这种path和Component的匹配关系,我们称之为动态路由(也是路由传递数据的一种方式);
—首先需要在路由映射中进行配置:
{path:'/user/:id',component:User}
—然后在总组件中指定跳转路径,需要通过
v-bind
进行属性绑定:<router-link :to="'/user/'+userId">
data(){return userId:'zhangsan'}
—之后在User组件中可以获取用户ID并显示,注意这里是
$route
表示正在活跃的路由:<h2>{{$route.params.id}}<h2>
-
路由的懒加载
—当打包构建应用时,JavaScript包会变得非常大,影响页面加载;如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问到的时候才加载对应组件,这样就更高效了!
—路由懒加载的基本思想就是用到时在加载
—打包文件解析:
js文件:
app.js为当前应用程序开发的所有代码(业务代码);
vendor.js为项目中引用的第三方程序(例如vue/vue-router/axios/bs);
manifest.js为打包的代码作底层支撑(导入导出等)的程序;
—路由通常会定义很多不同的页面,这个页面最后打包下来放在一个js文件下,会造成页面非常大,一次性从服务器请求下来这个页面,需要花费一定时间,甚至会在用户电脑上出现短暂空白;因此路由懒加载可以解决这个问题!
—路由懒加载主要作用是将路由对应的组件打包成一个个的js代码块,只有在这个路由被访问的时候才会加载对应的组件;
—懒加载方式:
(1)结合Vue的异步组件和Webpack的代码分析;
(2)AMD写法
(3)ES6中,更加简单的方法组织Vue异步组件和Webpack的代码分割;
const Home = () => import('../components/Home')
-
路由的嵌套
—路由路径映射一个组件,切换路由就是切换组件;
—实现路由嵌套:
(1)创建对应的子组件,并且在路由映射中配置对应的子路由;
{ path:'/home', component:Home, children:[ { //默认路由映射 path:'', redirect:'news' }, { path:'news', component:HomeNews } ] }
(2)在组件内部使用
<router-view>
标签,注意在父组件中通过<router-link>
添加路径时,需要完整路径:<router-link to="/home/news">新闻</router-link>
; -
参数传递
—传递参数主要有两种类型:
params
和query
—
params
的类型配置动态路由
(1)配置路由格式:
/router/:id
;<router-link :to="'/user'+userId"></router-link>
(2)传递的方式:在
path
后面跟上对应的值;(3)传递后形成的路径:
/router/abc
—
query
类型(对应的是一个对象)(1)配置路由格式:
/router
,也就是普通配置;(2)传递的方式:对象中使用
query
的key
作为传递方式:<router-link :to="{path:'/profile',query:{name:'Tom'}}"></router-link>
(3)传递后形成的路径:
router?id=abc
(4)同样可以通过
{{$router.query}}
取出对应内容;—一个URL的组成部分:协议://localhost:端口(默认80端口)/路径path?查询(query内容)
scheme://host:port/path?query#fragment
-
区分$route和$router
—
$router
是一个Vuerouter对象实例,指向我们新建的Vuerouter实例,如果想要导航到不同的URL,则使用$router.push()
;—而
$route
是当前router跳转对象中活跃的路由,可以获取其query
和params
参数;—所有的组件都继承着Vue类的原型!
-
导航守卫
—生命周期(钩子函数):
created()
会在创建组件进行回调,mounted()
会挂载在DOM对象上进行回调的,updated()
会在发生刷新进行回调;—需求:网页标题是通过
<title>
来显示的,但是SPA只有一个固定的HTML,切换不同页面时,标题不会改变,但是我们可以通过JavaScript来修改<title>
内容;{ path:'/home', component:Home, meta:{ title:'首页' } } //前置守卫guard router.beforeEach((to,from,next) => { document.title = to.matched[0].meta.title next() })
—导航钩子的三个参数解析:
to
:即将要进入的目标的路由对象;from
:当前导航即将要离开的路由对象;next
:调用该方法,才能进入下一个钩子;—后置钩子hook
afterEach()
只有两个参数to
和from
,不需要主动调用next()
函数;—以上前置守卫和后置钩子创建的守卫称之为全局守卫,除此之外还有路由独享守卫和组件内的守卫;可以通过官网学习;
-
vue-router-keep-alive
—
keep-alive
是Vue内置的一个组件,可以使被包含的组件保留状态,或者避免重新渲染;<keep-alive><router-view/></keep-alive>
—
activated()
和deactivated()
只有在该组件被保持了状态,使用了keep-alive
时才是有效的;—
keep-alive
包含两个属性:(1)
include
-字符串或正则表达,只有匹配的组件会被缓存;(2)
exclude
-字符串或正则表达式,任何匹配的组件都不会被缓存;多个匹配组件可以使用逗号隔开,但是不要随便加入空格;
—
router-view
也是一个组件,如果直接被包在keep-alive
里面,所有路径匹配到的视图组件都会被缓存,避免重复渲染;