vue项目创建步骤及路由router


Posted in Javascript onJanuary 14, 2020

1、创建一个vue项目步骤 (windows环境下)。创建vue项目前,检查系统是否具备创建项目的条件(是否已经安装好了node.js、webpack、vue-cli)。cmd打开终端。

1.1 如果还没安装node.js, 则先安装node.js ,安装完成后,查看node版本

node -v

1.2 安装淘宝镜像, 安装完成后查看npm版本:npm -v

npm install -g cnpm --registry=https://registry.npm.taobao.org

1.3 安装webpack

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 

npm install -g vue-cli

npm install -g @vue/cli

1.5 准备工作做好了,开始正式创建vue项目, 创建vue项目可以选择两种方式。下面的my_vue_pro是vue项目名字

vue init webpack my_vue_pro

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项目结构不同,配置方法不同,具体配置方法参考官方文档。

如果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

2、vue路由vue-router解说

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:

  • 嵌套的路由/视图表
  • 模块化的、基于组件的路由配置
  • 路由参数、查询、通配符
  • 基于 Vue.js 过渡系统的视图过渡效果
  • 细粒度的导航控制
  • 带有自动激活的 CSS class 的链接
  • HTML5 历史模式或 hash 模式,在 IE9 中自动降级
  • 自定义的滚动条行为

为了加深对路由的理解,在安装vue-router包后,如果项目自动生成了router.js, 先删除,我们手动来写一个router.js。创建router.js后,再新增加2个vue页面,命名pageA和pageB,如下图:

vue项目创建步骤及路由router

其中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 来获取所有查询参数。如下图:

vue项目创建步骤及路由router

我们打印this.$route变量,看到如上图右边部分内容:

  • this.$route.name : 页面名字。这个name就是在router.js中配置的那个name, 这个name也是有大用处的,比如在<router-link>中使用“命名路由”的时候就是用到它,举例说明,通过在路由链接标签的to属性设置name和相应的参数,然后跳转效果和设置路由path是一样的:
<router-link :to="{ name: 'pageA', params: { id: 5188, name:'王大锤' }}">命名路由pageA</router-link>
  • this.$route.path: 路由路径,包含路径参数,不包含查询参数
  • this.$route.fullPath: 路由全路径,包含路径参数和查询参数
  • this.$route.query: 路径所有查询参数
  • this.$route.params: 路径所有路径参数
  • this.$route.meta: 路由元信息,在配置路由的时候可以把自定义的一些数据存在meta中,用作其他用途
  • this.$route.matched: 里面包含了路由的一些匹配信息

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>

效果图:

vue项目创建步骤及路由router

 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"/>

vue项目创建步骤及路由router

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 依赖的页面。

3、路由导航守卫。

“导航”表示路由正在发生改变,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)
 }
}

完整的导航解析流程

  • 导航被触发。
  • 在失活的组件里调用离开守卫。
  • 调用全局的 beforeEach 守卫。
  • 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  • 在路由配置里调用 beforeEnter 。
  • 解析异步路由组件。
  • 在被激活的组件里调用 beforeRouteEnter 。
  • 调用全局的 beforeResolve 守卫 (2.5+)。
  • 导航被确认。
  • 调用全局的 afterEach 钩子。
  • 触发 DOM 更新。
  • 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。

-----------------------  导航守卫调用步骤记录 ---------------

1、beforeEach  //全局守卫
2、beforeEnter  //路由独享守卫
3、beforeRouteEnter  //组件内守卫
4、beforeResolve   //全局解析守卫
5、afterEach        //全局后置钩子
6、beforeRouteLeave  //离开页面的时候调用,组件内独享(不离开页面不调用)

如果是路由复用(路由不变,路径参数变化),调用步骤为:
1、beforeEach  //全局守卫
2、beforeRouteUpdate //组件内守卫
3、beforeResolve   //全局解析守卫
4、afterEach        //全局后置钩子
5、beforeRouteLeave  //离开页面的时候调用,组件内独享(不离开页面不调用)

测试DEMO:https://github.com/xiaotanit/tan_vue

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
filemanage功能中用到的lib.js
Apr 08 Javascript
javascript 密码强弱度检测万能插件
Feb 25 Javascript
JavaScript对象、属性、事件手册集合方便查询
Jul 04 Javascript
JQuery插件Style定制化方法的分析与比较
May 03 Javascript
Javascript基础教程之定义和调用函数
Jan 18 Javascript
省市联动效果的简单实现代码(推荐)
Jun 06 Javascript
JavaScript语言精粹经典实例(整理篇)
Jun 07 Javascript
ES6记录异步函数的执行时间详解
Aug 31 Javascript
利用webstrom调试Vue.js单页面程序的方法教程
Jun 06 Javascript
浅析webpack 如何优雅的使用tree-shaking(摇树优化)
Aug 16 Javascript
node.js中TCP Socket多进程间的消息推送示例详解
Jul 10 Javascript
Vue核心概念Getter的使用方法
Jan 18 Javascript
JS实现容器模块左右拖动效果
Jan 14 #Javascript
vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多(步骤详解)
Jan 14 #Javascript
vue页面加载时的进度条功能(实例代码)
Jan 13 #Javascript
微信小程序canvas截取任意形状的实现代码
Jan 13 #Javascript
js实现列表向上无限滚动
Jan 13 #Javascript
vue 组件销毁并重置的实现
Jan 13 #Javascript
VUE实现自身整体组件销毁的示例代码
Jan 13 #Javascript
You might like
用Socket发送电子邮件
2006/10/09 PHP
PHP数据缓存技术
2007/02/14 PHP
浅析虚拟主机服务器php fsockopen函数被禁用的解决办法
2013/08/07 PHP
详解Laravel视图间共享数据与视图Composer
2016/08/04 PHP
Swoole源码中如何查询Websocket的连接问题详解
2020/08/30 PHP
PHP7 list() 函数修改
2021/03/09 PHP
JavaScript面象对象设计
2008/04/28 Javascript
ajaxControlToolkit AutoCompleteExtender的用法
2008/10/30 Javascript
url 特殊字符 传递参数解决方法
2010/01/01 Javascript
javascript:文字不间断向左移动的实例代码
2013/08/08 Javascript
JavaScript使用replace函数替换字符串的方法
2015/04/06 Javascript
在AngularJS中使用AJAX的方法
2015/06/17 Javascript
jquery中取消和绑定hover事件的实现代码
2016/06/02 Javascript
jquery easyui DataGrid简单示例
2017/01/23 Javascript
Vue项目pdf(base64)转图片遇到的问题及解决方法
2018/10/19 Javascript
nodejs使用async模块同步执行的方法
2019/03/02 NodeJs
Vue2(三)实现子菜单展开收缩,带动画效果实现方法
2019/04/28 Javascript
vue resource发送请求的几种方式
2019/09/30 Javascript
JavaScript的一些小技巧分享
2021/01/06 Javascript
python进阶教程之词典、字典、dict
2014/08/29 Python
python读写ini配置文件方法实例分析
2015/06/30 Python
用Python写冒泡排序代码
2016/04/12 Python
Python计算时间间隔(精确到微妙)的代码实例
2019/02/26 Python
python爬虫 猫眼电影和电影天堂数据csv和mysql存储过程解析
2019/09/05 Python
通过 Django Pagination 实现简单分页功能
2019/11/11 Python
django xadmin action兼容自定义model权限教程
2020/03/30 Python
python获取本周、上周、本月、上月及本季的时间代码实例
2020/09/08 Python
python简单实现插入排序实例代码
2020/12/16 Python
HTML5 history新特性pushState、replaceState及两者的区别
2015/12/26 HTML / CSS
学前教育教师求职自荐信
2013/09/22 职场文书
捐款倡议书
2014/04/14 职场文书
彩妆大赛策划方案
2014/05/13 职场文书
节约用电通知
2015/04/25 职场文书
入党介绍人意见怎么写
2015/06/03 职场文书
《彼得与狼》教学反思
2016/02/20 职场文书
Sql-Server数据库单表查询 4.3实验课
2021/04/05 SQL Server