1.vue-router功能介绍嵌套路由/视图表模块化、基于组件的路由配置路由参数、查询、通配符基于Vue.js转场系统的详细视图转场效果GranularnavigationcontrolLinkswithautomaticallyactivatedCSSclassHTML5historymodeorhashmode,IE9自动降级自定义滚动条行为三种路由模式(hash,history,abstract)2.动态路由配置通用参数:我们经常需要映射匹配的所有路由同一组件的特定模式。例如,我们有一个User组件,它为所有具有不同ID的用户呈现。那么,我们可以在vue-router的路由路径中使用“动态路径参数”(dynamicsegment)来实现这个效果:constUser={template:'
User
'}constrouter=newVueRouter({routes:[//动态路径参数以冒号开头{path:'/user/:id',component:User}]})模式匹配路径$route.params/user/:username/user/evan{username:'evan'}/user/:username/post/:post_id/user/evan/post/123{username:'evan',post_id:'123'}注意:使用路由参数时,比如从/user/foo导航到/user/bar,原来的组件实例将被重用。因为两条路线都渲染相同的组件,所以重用比销毁和重新创建更有效。然而,这也意味着组件的生命周期钩子将不再被调用。路由监控可以使用watchconstUser={template:'...',watch:{'$route'(to,from){//响应路由变化...}}}或者使用中介绍的2.2beforeRouteUpdateNavigationGuardconstUser={template:'...',beforeRouteUpdate(to,from,next){//对路由变化做出反应...//不要忘记调用next()}}常规非常规参数参数将只匹配以/分隔的URL片段中的字符。如果我们想匹配任何路径,我们可以使用通配符(*):{//将匹配所有路径path:'*'}{//将匹配任何以`/user-`开头的路径path:'/user-*'}3。嵌套路由constrouter=newVueRouter({routes:[{path:'/user/:id',component:User,children:[{//当/user/:id/profile匹配成功时,//UserProfile会被渲染inUser's
path:'profile',component:UserProfile},{//当/user/:id/posts匹配成功//UserPosts将在User'sinpath:'posts'中呈现,component:UserPosts}]}]})注意:以/开头的嵌套路径将被视为根路径。这使您可以充分利用嵌套组件而无需设置嵌套路径。此时,基于上面的配置,当你访问/user/foo时,User出口不会渲染任何东西,因为没有匹配到合适的子路由。如果你想渲染一些东西,提供一个空的子路由:constrouter=newVueRouter({routes:[{path:'/user/:id',component:User,children:[//当/user/:id匹配成功,//UserHome将在用户的中呈现{path:'',component:UserHome},//...其他子路由]}]})4.程序化导航1).router.push(location,onComplete?,onAbort?)当你点击时,内部会调用这个方法,所以,点击相当于Callrouter.推(...)。声明式编程router.push(...)//stringrouter.push('home')//objectrouter.push({path:'home'})//Namedrouterouter.push({name:'user',params:{userId:'123'}})//加上查询参数,就变成/register?plan=privaterouter.push({path:'register',query:{plan:'private'}})注意:如果提供路径,params将被忽略注意:如果目的地与当前路线相同,则只有参数发生变化(例如从一个用户配置文件到另一个/用户/1->/users/2),需要使用beforeRouteUpdate来响应这种变化(比如抓取用户信息)。2).router.replace(location,onComplete?,onAbort?)和router.push很像,唯一不同的是它不会往history中添加新的记录,而是和它有相同的方法名——替换当前的历史记录。声明式编程router.replace(...)3).router.go(n)该方法的参数是一个整数,表示添加到历史记录中前进或后退多少步,类似于window.history.go(n)。//浏览器记录前进一步,相当于history.forward()router.go(1)//后退一步记录,相当于history.back()router.go(-1)//前进三步记录router.go(3)//如果历史记录不够,则静默失败router.go(-100)router.go(100)总结:你可能注意到router.push、router.replace和router.go跟随window.history.pushState、window.history.replaceState和window.history.go看似是仿照window.historyAPI开发的。5.命名视图有时你希望同时(同级)显示多个视图,而不是嵌套显示。例如,创建一个包含两个视图的布局:sidebar(侧边导航)和main(主要内容)。这时候,命名视图就派上用场了。您可以在界面中有多个单独命名的视图,而不是只有一个插座。如果router-view没有设置名称,则默认为default。constrouter=newVueRouter({routes:[{path:'/',components:{default:Foo,a:Bar,b:Baz}}]})注意:a视图是使用一个组件呈现的,因此多个视图需要多个组件用于同一路由。确保正确使用组件配置(带s):6.HTML5历史模式历史模式需要后台配置支持。因为我们的应用是单页客户端应用,如果后台配置不对,用户在浏览器直接访问时,会返回404,不好看。在服务器端添加一个涵盖所有情况的候选资源:如果URL没有匹配到任何静态资源,则应该返回相同的index.html页面后台配置示例:Apache
RewriteEngineOnRewriteBase/RewriteRule^index\.html$-[L]RewriteCond%{REQUEST_FILENAME}!-fRewriteCond%{REQUEST_FILENAME}!-dRewriteRule。/index.html[L]nginxlocation/{try_files$uri$uri//index.html;}nativeNode.jsconsthttp=require('http')constfs=require('fs')consthttpPort=80http.createServer((req,res)=>{fs.readFile('index.htm','utf-8',(err,content)=>{if(err){console.log('我们无法打开“index.htm”文件。')}res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'})res.end(content)})}).listen(httpPort,()=>{console.log('服务器侦听:http://localhost:%s',httpPort)})Warning请注意,因为这样做之后,您的服务器将不再返回404错误页面,因为将返回所有路径的index.html文件。为了避免这种情况,你应该覆盖你的Vue应用程序中的所有路由案例,然后给出一个404页面。constrouter=newVueRouter({mode:'history',routes:[{path:'*',component:NotFoundComponent}]})7.Navigationguards记住参数或查询更改不会触发进入/退出导航守卫。您可以通过观察$route对象或使用beforeRouteUpdate的组件内守卫来对这些更改做出反应。globalfrontguardbeforeEachconstrouter=newVueRouter({...})router.beforeEach((to,from,next)=>{//...//继续管道中的下一个钩子。如果所有钩子都被执行,导航的状态是**confirmed**(confirmed).next();//中断当前导航。如果浏览器的URL改变了(可能是用户手动或者浏览器后退按钮),那么URLaddress会被改变重置为`from`route对应的地址next(false)://跳转到不同的地址,中断当前导航,然后进行新的导航,可以传递任何位置对象给`next`,并允许设置选项,例如`replace:true`、`name:'home'`和[`router-link`](https://router.vuejs.org/zh/api/#to)或[`router.push`](https://router.vuejs.org/zh/api/#router-push)中的选项。next('/')`或`next({path:'/'})//如果传递给`next`的参数是一个`Error`实例,导航将被终止并且t错误将传递给[`router.onError()`](https://router.vuejs.org/zh/api/#router-onerror)注册回调。next(error)})globalresolutionguardbeforeResolve在2.5.0+中你可以用router.beforeResolve注册一个全局守卫。这类似于router.beforeEach,除了在导航确认之前调用解析守卫,并且在解析完所有组件内守卫和异步路由组件之后。constrouter=newVueRouter({...})router.beforeResolve((to,from,next)=>{//...next();})globalposthookafterEachconstrouter=newVueRouter({...'/foo',component:Foo,beforeEnter:(to,from,next)=>{//...}}]})beforeRouteEnter,beforeRouteUpdate,beforeRouteLeaveconstFoo={template:`...`,beforeRouteEnter(to,from,next){//在渲染组件的相应路由被确认之前调用//否!有能力的!获取组件实例`this`//因为在守卫执行之前还没有创建组件实例},beforeRouteUpdate(to,from,next){//当前路由变化时调用,但是组件被复用//对于例如说,对于一个带动态参数的路径/foo/:id,当在/foo/1和/foo/2之间跳转时,//由于会渲染同一个Foo组件,所以组件实例会被复用。在这种情况下将调用此钩子。//可以访问组件实例`this`},beforeRouteLeave(to,from,next){//当导航离开组件对应的路由时调用//可以访问组件实例`this`}}8.完成导航分析过程1.导航被触发。2.在去激活的组件中调用leaveguard。3.调用全局`beforeEach`守卫。4.在可重用组件中调用`beforeRouteUpdate`guard(2.2+)。5.在路由配置中调用`beforeEnter`。6.解析异步路由组件。7.在激活的组件中调用`beforeRouteEnter`。8.调用全局`beforeResolve`守卫(2.5+)。9.确认导航。10.调用全局`afterEach`钩子。11.触发DOM更新。12.使用创建的实例调用传递给`beforeRouteEnter`守卫中的`next`的回调函数。9、过渡动画.fade-enter-active,.fade-leave-active{transition:opacity.5s;}。fade-enter,.fade-leave-to{opacity:0;}10。数据获取导航完成后获取数据exportdefault{data(){return{loading:false,post:null,error:null}},created(){//组件创建后获取数据,//此时数据已经观察到this.fetchData()},watch:{//如果路由发生变化,将再次执行此方法'$route':'fetchData'},methods:{fetchData(){this.error=this.post=nullthis.loading=true//用你的数据获取util/API包装器替换getPostgetPost(this.$route.params.id,(err,post)=>{this.loading=falseif(err){this.error=err.toString()}else{this.post=post}})}}}在导航完成之前获取数据exportdefault{data(){return{post:null,error:null}},beforeRouteEnter(吨o,from,next){getPost(to.params.id,(err,post)=>{next(vm=>vm.setData(err,post))})},//在路由改变之前,组件hasRenderingisdone//稍微不同的逻辑beforeRouteUpdate(to,from,next){this.post=nullgetPost(to.params.id,(err,post)=>{this.setData(err,post)next()})},methods:{setData(err,post){if(err){this.error=err.toString()}else{this.post=post}}}}11.滚动行为注意:该函数只支持history.pushState在浏览器中可用constrouter=newVueRouter({routes:[...],scrollBehavior(to,from,savedPosition){//当按下后退/前进按钮时返回预期的滚动位置它会像浏览器的本机性能if(savedPosition){returnsavedPosition}else{return{x:0,y:0}}//orenableanchorif(to.hash){return{selector:to.hash}}})12.路由延迟加载注意:如果你使用的是Babel,则需要添加syntax-dynamic-import插件,以便Babel可以正确解析语法。结合Vue的异步组件和Webpack的代码拆分功能,实现路由懒加载1)异步组件定义为一个返回Promise的工厂函数(该函数返回的Promise要自己解析组件):constFoo=()=>Promise.resolve({/*组件定义对象*/})2)在Webpack2中,我们可以使用动态导入语法来定义代码分割点(splitpoint):import('./Foo.vue')//returnPromise结合1)和2)实现路由的懒加载,如下:constFoo=()=>import('./Foo.vue')