菜单快捷导航:html
一、建立一个vue项目步骤 (windows环境下)。建立vue项目前,检查系统是否具有建立项目的条件(是否已经安装好了node.js、webpack、vue-cli)。cmd打开终端。vue
1.1 若是还没安装node.js, 则先安装node.js ,安装完成后,查看node版本node
node -v
1.2 安装淘宝镜像, 安装完成后查看npm版本:npm -vwebpack
npm install -g cnpm --registry=https://registry.npm.taobao.org
1.3 安装webpackgit
npm install webpack -g
1.4 安装vue全局脚手架,vue-cli2.x使用 npm install -g vue-cli , vue-cli3.x使用 npm install -g @vue/cli 安装, 查看vue版本: vue -V github
npm install -g vue-cli
或 web
npm install -g @vue/cli
1.5 准备工做作好了,开始正式建立vue项目, 建立vue项目能够选择两种方式。下面的my_vue_pro是vue项目名字vue-router
vue init webpack my_vue_pro
或vue-cli
vue create my_vue_pro
vue init 是vue-cli2.x的初始化方式,可使用github上面的一些模板来初始化项目,webpack是官方推荐的标准模板名。vue-cli2.x项目向3.x迁移只须要把static目录复制到public目录下,老项目的src目录覆盖3.x的src目录。 vue create 是vue-cli3.x的初始化方式,目前模板是固定的,模板选项可自由配置,建立出来的是vue-cli3的项目,与vue-cli2项目结构不一样,配置方法不一样,具体配置方法参考官方文档。npm
若是vue版本仍是2.x, 从vue-cli2.x升级到最新版:先执行卸载: npm uninstall -g vue-cli , 再安装最新版 npm install -g @vue/cli
1.6 cd进入项目
cd my_vue_pro
1.7 添加须要的依赖包,好比添加vue路由vue-router依赖包,可使用 npm install vue-router , 或者 vue add router
npm install vue-router
或
vue add router
1.8 安装全部依赖包, npm install 。卸载依赖包: npm uninstall xxx
cnpm install
1.9 运行项目,查看package.json文件中的scripts脚本中的运行方式, npm run dev 或 npm run serve
npm run serve
二、vue路由vue-router解说
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:
为了加深对路由的理解,在安装vue-router包后,若是项目自动生成了router.js, 先删除,咱们手动来写一个router.js。建立router.js后,再新增长2个vue页面,命名pageA和pageB,以下图:
其中router.js代码
import Vue from 'vue' import Router from 'vue-router' //自定义页面 import PageA from './views/PageA' import PageB from './views/PageB' //安装路由到vue Vue.use(Router) const routes = [ { path: '/', redirect: '/pageB' //重定向,设置默认进入pageB页面 }, { //动态路径参数,以冒号开头,若是有多个参数则继续日后面追加 path: '/pageA/:id/:name', name: 'pageA', component: PageA }, { path: '/pageB', name: 'pageB', component: PageB } ] export default new Router({ //mode: 'hash', //默认hash模式,hash模式有#;另外还有一种history模式,没有#符号 routes })
main.js是vue项目的入口脚本,在这里引入router.js, 传入路由配置。
import Vue from 'vue' import App from './App.vue' import router from './router.js' Vue.config.productionTip = false new Vue({ router, //key名字必须命名为router render: h => h(App) }).$mount('#app')
2.1 路由视图<router-view> 组件和 路由导航<router-link>组件
在项目启动模板页App.vue上面有个<router-view>路由视图组件,至关因而一个占位符同样(<slot>插槽也相似),以后页面的路由变化引发的页面替换都是在<router-view>路由视图上进行。
而<router-link>有点相似于超连接标签<a>,<router-link>上有个必写的属性to, 就相似于超连接<a>的href属性,设置要跳转的路由连接。
App.Vue测试代码:
<template> <div id="app"> <div id="nav"> <router-link to="/pageA/5188/王大锤">pageA</router-link> | <router-link to="/pageB">pageB</router-link> </div> <router-view/> </div> </template>
2.2 路径参数和查询参数
路径参数和查询参数做为页面之间的数据传递的一种方式,使用很是频繁。路径参数,望文生义意思是参数做为路径的一部分,在配置路由的时候把参数配置好,而后在浏览器中输入url时,必须传参,不然会找不到这个路由这个页面。例如,pageA页面的路由配置为:/pageA/:id/:name ,意思是pageA页面后面必须传一个id参数和name参数,这两个参数做为路径的一部分,必须传值。而后在pageA页面中用:this.$route.params 来获取全部的路径参数。
而查询参数则没有路径参数这么严格,路由不会对此作验证。路由参数在url中的表现为页面连接后面加 ?key=value&... , 而后在页面中用:this.$route.query 来获取全部查询参数。以下图:
咱们打印this.$route变量,看到如上图右边部份内容:
<router-link :to="{ name: 'pageA', params: { id: 5188, name:'王大锤' }}">命名路由pageA</router-link>
2.3 路由props设置及路径参数获取
在设置页面路由时,若是增长一个props属性,并设置为true, 则在页面中能够直接拿到参数,不须要经过this.$route.params来取参数。好比router.js中部分代码:
{ path: '/pageC/:id/:name', name: 'pageC', props: true, //设置props属性为true, 则能够在PageC页面中直接取参数 component: PageC }
在PageC页面中参数获取:
<template> <div class="box"> <h1>佛山 -- 黄飞鸿,from PageC </h1> <h3>男儿何不带吴钩,收取关山五十州</h3> <h3>路径参数id: {{this.id}}, name: {{this.name}}</h3> </div> </template> <script> export default { name: 'pageC', props: ['id', 'name'], //直接接收路径参数 created(){ console.log("id: ", this.id, ", name: ", this.name) } } </script>
2.4 嵌套路由。实际生活中的应用界面,一般由多层嵌套的组件组合而成。一样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件。好比如今PageB页面中嵌入页面PageC, 则须要在PageB页面中增长一个路由视图<router-view>标签,做为嵌套页面PageC的占位符。
路由部分代码:
{ path: '/pageB', name: 'pageB', component: PageB, meta: { isOK: true, type: 9 }, children: [ { path: 'pageC/:id/:name', component: PageC, props: true, //设置props属性为true, 则能够在PageC页面中直接取参数 name: 'subPageC', meta: { requiresAuth: true, id: 51666 }, //自定义数据 } ] },
PageB页面中部分代码:
<template> <div class="box"> <h1>一片云 -- 罗小虎,from PageB </h1> <h3>千磨万击还坚劲,任尔东南西北风</h3> <!-- 嵌套路由,嵌套页面占位符 --> <router-view></router-view> </div> </template> <script> export default { name: 'pageB', created(){ console.log('...pageB...') console.log(this.$route) } } </script>
效果图:
2.5 编程式的导航。 <router-link>叫声明式导航,还有种编程式导航,格式为:router.push(location, onComplete?, onAbort?), 在页面中的使用例子:
// 字符串 router.push('home') // 对象 router.push({ path: 'home' }) // 命名的路由 router.push({ name: 'user', params: { userId: '123' }}) // 带查询参数,变成 /register?plan=private router.push({ path: 'register', query: { plan: 'private' }}) /*注意:若是提供了 path,params 会被忽略,上述例子中的 query 并不属于这种状况。 取而代之的是下面例子的作法,你须要提供路由的 name 或手写完整的带有参数的 path: */ const userId = '123' router.push({ name: 'user', params: { userId }}) // -> /user/123 router.push({ path: `/user/${userId}` }) // -> /user/123 // 这里的 params 不生效, 即编程式导航若是提供了path, 则路径参数必须写入path中。而查询参数能够不写入 router.push({ path: '/user', params: { userId }}) // -> /user
一样的编程式导航规则也适用于<router-link>导航组件的to属性
router.replace(location, onComplete?, onAbort?) 和router.push(...)很像,惟一的不一样就是,它不会向 history 添加新记录,而是跟它的方法名同样 —— 替换掉当前的 history 记录。声明式导航替换用法: <router-link :to="..." replace> ,编程式导航替换用法: router.replace(...)
router.go(n)的使用,这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,相似 window.history.go(n)
。
// 在浏览器记录中前进一步,等同于 history.forward() router.go(1) // 后退一步记录,等同于 history.back() router.go(-1) // 前进 3 步记录 router.go(3) // 若是 history 记录不够用,那就默默地失败呗 router.go(-100) router.go(100)
2.6 命名视图。有时候想同时 (同级) 展现多个视图,而不是嵌套展现,例如建立一个布局,有 sidebar
(侧导航) 和 main
(主内容) 两个视图,这个时候命名视图就派上用场了。你能够在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。若是 router-view
没有设置名字,那么默认为 default
。
router.js中部分代码:
{ path: '/pageD', name: 'pageD', components: { //演示命名视图 default: PageD, tanA: PageA, tanB: PageB } }
App.vue中部分代码:
<router-view/> <!-- 命名视图, 路由视图名字匹配了,就会展现匹配的页面内容 --> <router-view name="tanA"/> <router-view name="tanB"/>
2.7 路由模式。默认路由模式是hash模式,即地址栏中域名后带有#符号(此 hash 不是密码学里的散列运算)。它的特色就是使用 URL 的 hash 来模拟一个完整的 URL,因而当 URL 改变时,页面不会从新加载。不过看起来不是很美观,另外hash模式的路由,在做为回调地址和一些第三方公司合做时,会有点麻烦,好比若是想实现微信快捷登陆或者获取微信用户受权时,当微信用户受权成功后,回跳回来时,微信返回的code参数会插入到#符号前面,这样的话就为了获取这个code,就须要一系列的另外操做了。
路由模式还有另一种模式就是history模式,这种模式是没有#符号的,符合咱们日常的使用习惯。这种模式充分利用 history.pushState
API 来完成 URL 跳转而无须从新加载页面。
export default new Router({ //mode: 'hash', //默认hash模式,hash模式有#;另外还有一种history模式,没有#符号 mode: 'history', //history模式,没有#符号 routes })
不过这种模式要玩好,还须要后台配置支持。由于咱们的应用是个单页客户端应用,若是后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id
就会返回 404,这就很差看了。
因此呢,你要在服务端增长一个覆盖全部状况的候选资源:若是 URL 匹配不到任何静态资源,则应该返回同一个 index.html
页面,这个页面就是你 app 依赖的页面。
三、路由导航守卫。“导航”表示路由正在发生改变,vue-router提供的导航守卫主要用来经过跳转或取消的方式守卫导航,从而达到控制导航走向。有多种机会植入路由导航过程当中:全局的,单个路由独享的,或者组件级的。
3.1 全局前置守卫: router.beforeEach
import router from './router.js' Vue.config.productionTip = false //全局守卫 //beforeEach, 全局前置守卫,当一个导航触发时,全局前置守卫按照建立顺序调用。 router.beforeEach((to, from, next)=>{ console.log("....beforeEach....") //数据校验时 // if (to.fullPath === '/home'){ // next('/login') // } if (to.path != '/login'){ next(); } else { setTimeout(()=>{ next(); }, 1000) } console.log(to) console.log(from) console.log(next); })
当一个导航触发时,全局前置守卫按照建立顺序调用。守卫是异步解析执行,此时导航所在全部守卫resolve完以前一直处于等待中。
每一个守卫方法接收三个参数:
to: Route
: 即将要进入的目标 路由对象。from: Route
: 当前导航正要离开的路由next: Function
: 必定要调用该方法来 resolve 这个钩子。执行效果依赖 next
方法的调用参数。
next()
: 进行管道中的下一个钩子。若是所有钩子执行完了,则导航的状态就是 confirmed (确认的)。next(false)
: 中断当前的导航。若是浏览器的 URL 改变了 (多是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from
路由对应的地址。next('/')
或者 next({ path: '/' })
: 跳转到一个不一样的地址。当前的导航被中断,而后进行一个新的导航。你能够向 next
传递任意位置对象,且容许设置诸如 replace: true
、name: 'home'
之类的选项以及任何用在 router-link
的 to
prop 或 router.push
中的选项。next(error)
: (2.4.0+) 若是传入 next
的参数是一个 Error
实例,则导航会被终止且该错误会被传递给 router.onError()
注册过的回调。确保要调用 next
方法,不然钩子就不会被 resolved。
3.2 全局解析守卫: router.beforeResolve ,这和 router.beforeEach 相似,区别是在导航被确认以前,同时在全部组件内守卫和异步路由组件被解析以后,解析守卫就被调用
3.3 全局后置钩子: router.afterEach ,然而和守卫不一样的是,这些钩子不会接受 next
函数也不会改变导航自己:
router.afterEach((to, from)=>{ console.log("....afterEach....") console.log(to) console.log(from) })
3.4 路由独享守卫: beforeEnter ,参数和全局前置守卫同样,执行顺序在全局前置守卫以后,在全局解析守卫以前。router.js中部分测试代码:
{ //动态路径参数,以冒号开头,若是有多个参数则继续日后面追加 path: '/pageA/:id/:name', name: 'pageA', component: PageA, //路由独享的守卫 beforeEnter: (to, from, next) => { console.log(".....路由独享的守卫...beforeEnter...") console.log(to) console.log(from) console.log(next) next(); } },
3.5 组件内路由守卫。进入组件时、组件路径参数变化时,离开组件时分别监听。
<script> export default { name: 'pageA', //组件内的守卫 beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 由于当守卫执行前,组件实例还没被建立 console.log('...组件内守卫beforeRouteEnter...') console.log(to) console.log(from) next(); }, beforeRouteUpdate (to, from, next) { // 在当前路由改变,可是该组件被复用时调用 // 举例来讲,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 因为会渲染一样的 Foo 组件,所以组件实例会被复用。而这个钩子就会在这个状况下被调用。 // 能够访问组件实例 `this` console.log('...组件内守卫beforeRouteUpdate2222...') console.log(to) console.log(from) next(); }, beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由时调用 // 能够访问组件实例 `this` console.log('...组件内守卫beforeRouteLeave3333...') console.log(to) console.log(from) next(); } } </script>
注意: beforeRouteEnter 守卫卫 不能 访问 this,由于守卫在导航确认前被调用,所以即将登场的新组件还没被建立。不过,你能够经过传一个回调给 next
来访问组件实例。在导航被确认的时候执行回调,而且把组件实例做为回调方法的参数。
beforeRouteEnter (to, from, next) { next(vm => { // 经过 `vm` 访问组件实例 }) }
beforeRouteEnter 是支持 给next 传递回调的惟一守卫。对于 beforeRouteUpdate 和 beforeRouteLeave 来讲,this已经可用了,因此不支持传递回调,由于没有必要了。
beforeRouteLeave 这个离开守卫一般用来禁止用户在还未保存修改前忽然离开。该导航能够经过 next(false)
来取消。
beforeRouteLeave (to, from , next) { const answer = window.confirm('Do you really want to leave? you have unsaved changes!') if (answer) { next() } else { next(false) } }
完整的导航解析流程
next
的回调函数。----------------------- 导航守卫调用步骤记录 ---------------
一、beforeEach //全局守卫 二、beforeEnter //路由独享守卫 三、beforeRouteEnter //组件内守卫 四、beforeResolve //全局解析守卫 五、afterEach //全局后置钩子 六、beforeRouteLeave //离开页面的时候调用,组件内独享(不离开页面不调用) 若是是路由复用(路由不变,路径参数变化),调用步骤为: 一、beforeEach //全局守卫 二、beforeRouteUpdate //组件内守卫 三、beforeResolve //全局解析守卫 四、afterEach //全局后置钩子 五、beforeRouteLeave //离开页面的时候调用,组件内独享(不离开页面不调用)
测试DEMO:https://github.com/xiaotanit/tan_vue
原文出处:https://www.cnblogs.com/tandaxia/p/12121681.html