阅读目录

一:vue-router是什么?

二:vue-router的实现原理

三:vue-router使用及代码配置

四:理解vue设置路由导航的两种方法。

五:理解动态路由和命名视图

六:理解嵌套路由

七:在nginx上部署vue项目(history模式)

八:vue-router 之 keep-alive

一. vue-router是什么?

vue-router是vue.js官方的路由插件,它和vue.js是集成的。它用于构建单页面应用,vue的单页面应用是基于路由和组件的,路由是用于设定访问路径的,并且路径和组件会产生映射起来。在vue-router单页面应用中,路径之间的切换,可以理解为组件的切换,路由模块的本质:是建立起url和页面之间的映射关系。

二:vue-router的实现原理

vue-router是用于构建单页面的,单页面的核心是更新视图而不会重新请求页面,这也就是为什么在页面中不用a标签的原因,因为页面只有一个index.html。那么它在实现单页面前端路由时,提供了两种模式,hash模式和History模式。默认情况下是使用hash模式。

2.1 hash模式

hash是URL的锚点(#), 代表网页中的一个位置,如果只改变#后的部分,浏览器会滚动到相应的位置,而不会重新加载网页,并且每次改变#后的部分,都会在浏览器的访问历史中增加一条记录,当我们使用后退按钮的时候,就可以返回到上一个位置。因此hash模式通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据。

2.2 history模式

上面是通过hash模式的,页面的地址就会加上 # 号,比如我们的地址类似这样的:http://localhost:8080/#/,我们使用history的话,那么访问页面的时候就和平常一样,不带井号的;如下地址也可以访问 http://localhost:8080/ ,使用路由history模式的话,只需要在配置路由规则时,加入 'mode': 'history'即可,它是利用html5中的 history.pushState的API来完成的URL跳转,无需重新加载页面的。
不过这种配置需要后台开发支持一下的,具体怎么配置,下面会详细讲到。

三:vue-router使用及代码配置

在vue-router中,定义了两个标签<router-link>和<router-view>来对应点击和显示,<router-link>是点击的部分,<router-view>是定义显示的部分,当我们点击之后,路由匹配组件的内容后会在<router-view>显示出来,<router-link>还需要一个属性 to, 它的含义就是到哪里去的意思。
比如 <router-link to="/home">111</router-link> 的含义是当我们点击111的时候,它会找到home相对应的组件,然后会在 <router-view>中显示出来。

理解配置路由

路由一般使用两个部分组成,path和component,path指路径,component指的是组件,它是一个对象,比如 { path: '/home', component: home }

比如我们这边定义两条路由,如下代码:

const routes = [
{ path: '/home', component: Home },
{ path: '/xxx', component: XXX }
];

2. 创建router管理
创建router对路由进行管理,它是由构造函数 new vueRouter()创建,接收上面的routes参数。如下代码:

const router = new vueRouter({
routes: routes
});

3. 实列注入到vue根实列中

我们接着把上面router实列注入待vue根实列中,我们就可以使用路由了。如下代码:

new Vue({
el: '#app',
router: router,
render: h => h(Index)
});

在配置代码之前,我们还是看看我们的项目整个目录结构如下:(基于第十三篇文章的基础之上再进行构建的)。

### 目录结构如下:
demo1 # 工程名
| |--- dist # 打包后生成的目录文件
| |--- node_modules # 所有的依赖包
| |--- app
| | |---index
| | | |-- views # 存放所有vue页面文件
| | | |-- components # 存放vue公用的组件
| | | |-- app.js # vue入口配置文件
| | | |-- router.js # 路由配置文件
| |--- views
| | |-- index.html # html文件
| |--- webpack.config.js # webpack配置文件
| |--- .gitignore
| |--- README.md
| |--- package.json
| |--- .babelrc # babel转码文件

在app/index/views 新建home.vue 和 xxx.vue 文件。
1. home.vue 代码如下:

<style lang='stylus'>
.home-container
width 100%
</style>
<template>
<div class="home-container">
<h1>欢迎来到Home</h1>
<p>{{msg}}</p>
</div>
</template> <script type="text/javascript">
export default {
data() {
return {
msg: '我是Home组件'
}
}
}
</script>

xxx.vue 代码如下:

<style lang='stylus'>
.xxx-container
width 100%
</style>
<template>
<div class="xxx-container">
<h1>欢迎来到xxx</h1>
<p>{{msg}}</p>
</div>
</template> <script type="text/javascript">
export default {
data() {
return {
msg: '我是XXX组件'
}
}
}
</script>

2. 接着在 app/index/views 新建index.vue, 代码如下:

<style lang="stylus">

</style>

<template>
<div id="app">
<header>
<router-link to='/home'>Home</router-link>
<router-link to='/xxx'>XXX</router-link>
</header>
<!-- 对应组件的内容渲染到router-view中 -->
<router-view></router-view>
</div>
</template> <script type="text/javascript">
export default {
data() {
return { }
}
}
</script>

3. 在 app/index/router.js定义router,路径到组件的映射。 添加如下代码:

import Vue from 'vue';
import VueRouter from 'vue-router'; // 引入组件
import home from './views/home'; import xxx from './views/xxx'; // 告诉 vue 使用 vueRouter Vue.use(VueRouter); const routes = [
{
path: '/home',
component: home
},
{
path: '/xxx',
component: xxx
},
{
path: '*', // 其他没有的页面都重定向到 home页面去
redirect: '/home'
}
] var router = new VueRouter({
routes: routes
}); export default router;

当然上面引入组件的方法,我们还可以懒加载的方式加载,懒加载引入的优点是:当我们访问页面的时候才会去加载相关的资源,这样的话,能提高页面的访问速度。
比如如下这样:component: resolve => require(['@/views/HelloWorld'], resolve) // 使用懒加载

因此我们可以把上面的代码写成如下:

import Vue from 'vue';
import VueRouter from 'vue-router'; /*
// 引入组件
import home from './views/home'; import xxx from './views/xxx'; */ // 告诉 vue 使用 vueRouter
Vue.use(VueRouter); const routes = [
{
path: '/home',
component: resolve => require(['./views/home'], resolve) // 使用懒加载
},
{
path: '/xxx',
component: resolve => require(['./views/xxx'], resolve) // 使用懒加载
},
{
path: '*', // 其他没有的页面都重定向到 home页面去
redirect: '/home'
}
]
var router = new VueRouter({
base: '/app/index', // 配置单页应用的基路径
routes: routes
}); export default router;

如上base的含义:应用的基路径,比如整个单页应用服务在 /app/index 下,那么base就应该设置为 /app/index.

4. 实列注入到vue根实列中。
把路由注入到根实列中,启动路由,我们在app/index/app.js 入口文件添加如下代码:

import Vue from 'vue';

import Index from './views/index';

// 引入路由
import router from './router'; new Vue({
el: '#app',
router: router,
render: h => h(Index)
});

因此要运行上面代码之前,我们先要 下载 vue-router 到我们项目中来,如下代码命令:

npm i vue-router --save

下载完成后,我们再来运行打包命令,npm run dev 后,就可以启动页面了。

在页面访问如下

四:理解vue设置路由导航的两种方法。

vue设置路由导航的两种方法有 <router-link :to=''> 和 router.push().

4.1 to的值可以是一个字符串路径,或者一个描述地址的对象。比如如下都是可以的。

// 字符串
<router-link to='/home'>Home</router-link> // 对象
<router-link :to="{path: '/home'}">Home</router-link> // 命名路由
<router-link :to="{name: 'home'}">Home</router-link>
/*
如果是命名路由的话,需要在router.js 加上name字段,如下代码:
const routes = [
{
path: '/home',
name: 'home',
component: resolve => require(['./views/home'], resolve) // 使用懒加载
},
{
path: '/xxx',
name: 'xxx',
component: resolve => require(['./views/xxx'], resolve) // 使用懒加载
},
{
path: '*', // 其他没有的页面都重定向到 home页面去
redirect: '/home'
}
]
*/ // 直接路由带查询参数query,地址栏就变成 /home?id=1
<router-link :to="{path: 'home', query: {id: 1 }}">Home</router-link> // 如果是path的话,路由带参数params的话,params是不会生效的。如下代码 params的参数是不会在地址栏中显示的。
<router-link :to="{path: 'home', params: {id: 1 }}">Home</router-link> // 命名路由带路由参数params,地址栏还是 /home, 但是可以通过 this.$route.params.id拿到值的
<router-link :to="{name: 'home', params: {id: 1 }}">Home</router-link>

4.2 router.push()方法

// 支持字符串
this.$router.push('xxx'); // 支持对象
this.$router.push({
path: 'xxx'
}); // 支持命名路由方式
this.$router.push({
name: 'xxx'
}); // 直接路由带查询参数 query, 地址栏变成 /xxx?id=1
this.$router.push({
path: 'xxx',
query: { id: 1 }
}); // 命名路由带查询参数query,地址栏变成 /xxx?id=1
this.$router.push({
name: 'xxx',
query: { id: 1 }
}); // 如果提供了path,直接路由带参数params, params不会生效,在xxx页面通过
// console.log(this.$route.params.id) 是获取不到值的。
this.$router.push({
path: 'xxx',
params: { id: 1 }
}); // 命名路由带路由参数params,地址栏是/xxx。在xxx页面通过 console.log(this.$route.params.id) 是可以获取到值的。
this.$router.push({
name: 'xxx',
params: { id: 1 }
});

总结:1. 无论是直接路由path还是命名路由name,带查询参数query,地址栏会变成 /url?查询参数名=查询参数值

2. 直接路由path带路由参数params,params不生效。在xxx页面通过 console.log(this.$route.params.id) 是获取不到值的。

3. 命名路由name带路由参数params地址栏保持是 /url/路由参数值。在xxx页面通过 console.log(this.$route.params.id) 是可以获取到值的。

五:理解动态路由和命名视图

5.1 动态路由
动态路由也可以叫做路由传参。
在前面我们介绍了路由导航功能是不能传递参数的,我们可以叫他们静态路由,而能传递参数的路由模式,并且对应的路由数量是不确定的,因此我们可以叫他动态路由。

应用场景:当我们的多个页面或组件都要被多次重复利用的时候,我们的路由都指向同一个组件,这时候从不同的地方进入相同的组件的时候,我们根据传递的参数不同,来渲染不同的数据。

比如如下代码:

const routes = [
{
path: '/xxx/:id', // 动态路由信息
name: 'xxx',
component: resolve => require(['./views/xxx'], resolve) // 使用懒加载
}
];

如上代码 path: /xxx/:id, 这种形式,这样定义之后,vue-router将会匹配所有的 /xxx/1, /xxx/2,.....

比如我现在有多个页面需要进入xxx组件内,这时候我们可以在配置路由路径后加个:id。index.vue 改成如下代码:

<template>
<div id="app">
<header>
<router-link to="home">Home</router-link>
<router-link to='xxx/on'>XXX</router-link>
</header>
<!-- 对应组件的内容渲染到router-view中 -->
<router-view></router-view>
</div>
</template>

当我点击 XXX 时候,会进入xxx组件内,那么在xxx.vue组件内,可以通过 this.$route.params.id 获取传的参数值了。

如下图所示:

5.2 理解命名视图

有时候我们想同时显示多个视图,比如一个单页应用页面,有侧导航(sidebar) 和 头部(header) 和 main(主内容)等三个视图,这个时候命名视图就派上用场了。
我们可以在页面中拥有多个单独命名的视图,而不是和我们上面一样只有一个单独的视图。如果 router-view 没有设置名字,那么默认为default。

现在我们可以在 app/index/components 新建文件夹为sidebar, header, main, 及在各对应的目录下新建index.vue.

现在我们的项目的目录结构变成如下了:

### 目录结构如下:
demo1 # 工程名
| |--- dist # 打包后生成的目录文件
| |--- node_modules # 所有的依赖包
| |--- app
| | |---index
| | | |-- views # 存放所有vue页面文件
| | | | |-- home.vue
| | | | |-- index.vue
| | | | |-- xxx.vue
| | | |-- components # 存放vue公用的组件
| | | | |--- header
| | | | | |-- index.vue # 公用的头部组件
| | | | |--- main
| | | | | |-- index.vue # 主体组件
| | | | |--- sidebar
| | | | | |-- index.vue # 侧导航公用的组件
| | | | |
| | | |-- app.js # vue入口配置文件
| | | |-- router.js # 路由配置文件
| |--- views
| | |-- index.html # html文件
| |--- webpack.config.js # webpack配置文件
| |--- .gitignore
| |--- README.md
| |--- package.json
| |--- .babelrc # babel转码文件

app/index/components/header/index.vue 代码如下:

<style lang="stylus">
* {margin: 0; padding: 0}
.header-container
width 100%
height 50px
background #000
div
font-size 16px
color #fff
text-align center
</style> <template>
<div class="header-container">
<div>我的头部导航</div>
</div>
</template> <script type="text/javascript">
export default {
data() {
return { }
}
}
</script>

app/index/components/sidebar/index.vue 代码如下:

<style lang="stylus">
.sidebar-container
width 200px
height 100%
min-height 500px
background red
float left
div
font-size 12px
color #fff
text-align center
</style> <template>
<div class="sidebar-container">
<div>我的左侧导航</div>
</div>
</template> <script type="text/javascript">
export default {
data() {
return { }
}
}
</script>

app/index/components/main/index.vue 代码如下:

<style lang="stylus">
.main-container
margin-left 200px
height 100%
min-height 500px
background green
div
font-size 12px
color #fff
text-align center
</style> <template>
<div class="main-container">
<div>我的主体部分</div>
</div>
</template> <script type="text/javascript">
export default {
data() {
return { }
}
}
</script>

框架搭建完成后,我们需要在index.vue 代码变成如下:

<style lang="stylus">

</style>

<template>
<div id="app">
<!--
<header>
<router-link to="/home">Home</router-link>
<router-link to='/xxx/on'>XXX</router-link>
</header>
-->
<router-view name="Header"></router-view>
<router-view name="Sidebar"></router-view>
<router-view name="Main"></router-view>
<!-- 对应组件的内容渲染到router-view中 -->
<router-view></router-view>
</div>
</template> <script type="text/javascript">
export default {
data() {
return { }
}
}
</script>

接着我们需要在router.js下配置代码如下:

import Vue from 'vue';
import VueRouter from 'vue-router'; // 引入组件
import home from './views/home'; import xxx from './views/xxx'; // 告诉 vue 使用 vueRouter
Vue.use(VueRouter); const routes = [
{
path: '/home',
name: 'home',
components: {
default: resolve => require(['./views/home'], resolve), // 使用懒加载
Header: resolve => require(['./components/header/index'], resolve), // 使用懒加载
Sidebar: resolve => require(['./components/sidebar/index'], resolve), // 使用懒加载
Main: resolve => require(['./components/main/index'], resolve) // 使用懒加载
}
},
{
path: '/xxx/:id',
name: 'xxx',
components: {
default: resolve => require(['./views/xxx'], resolve), // 使用懒加载
Header: resolve => require(['./components/header/index'], resolve), // 使用懒加载
Sidebar: resolve => require(['./components/sidebar/index'], resolve), // 使用懒加载
Main: resolve => require(['./components/main/index'], resolve) // 使用懒加载
}
},
{
path: '*', // 其他没有的页面都重定向到 home页面去
redirect: '/home'
}
] var router = new VueRouter({
base: '/app/index', // 配置单页应用的基路径
routes: routes
}); export default router;

然后打包运行下,在浏览器上可以看到如下图所示的结构。

如上可以看到,我们可以使用 命名视图 来搭建我们网站的框架,这可以理解命名视图的作用了。

六:理解嵌套路由

什么是嵌套路由?比如我们进入到我们home页面的时候,它下面还有分类,比如叫 java书籍,node书籍等,那么当我点击各个类目的时候,就对应到相应的组件。比如首先我进入的是 /home 这个路由,然后当我进入 /home下面的分类的 java书籍的话,那么我们的路由就是 /home/java, 如果进入分类的是 node书籍的话,那么路由就是 /home/node 了。因此 vue提供了 childrens这个属性来做这件事,它也是一组路由。

首先我们在 app/index/views 下 新建 java.vue 和 node.vue.

java.vue代码如下:

<style lang='stylus'>
.java-container
width 100%
</style> <template>
<div class="java-container">
<h1>欢迎来到java类书籍</h1>
<p>{{msg}}</p>
</div>
</template> <script type="text/javascript">
export default {
data() {
return {
msg: '我是java组件'
}
},
methods: { }
}
</script>

node.vue 代码如下:

<style lang='stylus'>
.node-container
width 100%
</style> <template>
<div class="node-container">
<h1>欢迎来到node类书籍</h1>
<p>{{msg}}</p>
</div>
</template> <script type="text/javascript">
export default {
data() {
return {
msg: '我是node组件'
}
},
methods: { }
}
</script>

app/index/router.js 代码就改成如下:

import Vue from 'vue';
import VueRouter from 'vue-router'; // 引入组件
import home from './views/home'; import xxx from './views/xxx'; // 告诉 vue 使用 vueRouter
Vue.use(VueRouter); const routes = [
{
path: '/home',
name: 'home',
component: resolve => require(['./views/home'], resolve),
// 子路由
children: [
{
path: 'java',
component: resolve => require(['./views/java'], resolve)
},
{
path: 'node',
component: resolve => require(['./views/node'], resolve)
}
]
},
{
path: '/xxx/:id',
name: 'xxx',
component: resolve => require(['./views/xxx'], resolve)
},
{
path: '*', // 其他没有的页面都重定向到 home页面去
redirect: '/home'
}
] var router = new VueRouter({
base: '/app/index', // 配置单页应用的基路径
routes: routes
}); export default router;

app/index/views/index.vue 代码如下:

<style lang="stylus">

</style>

<template>
<div id="app">
<header>
<router-link to="/home" tag='li'>Home</router-link>
<router-link to="/home/java">java</router-link>
<router-link to="/home/node">node</router-link>
<router-link to='/xxx/on'>XXX</router-link>
</header>
<!--
<router-view name="Header"></router-view>
<router-view name="Sidebar"></router-view>
<router-view name="Main"></router-view>
-->
<!-- 对应组件的内容渲染到router-view中 -->
<router-view></router-view>
</div>
</template> <script type="text/javascript">
export default {
data() {
return { }
}
}
</script>

如上代码增加完成后,进行打包,编译都正常,但是点击java或node的时候,子路由一直没有渲染到对应的组件,网上很多资料说,子路由多写了 /, 但是我router.js里面也没有这些东西的,但是经过搜索,发现问题并不是在这里,而是说在嵌套的子模块里面引用子路由的时候,也需要加上 <router-view></router-view> 这句代码,如下是home.vue 代码:

<template>
<div class="home-container">
<h1>欢迎来到Home</h1>
<p>{{msg}}</p>
<p @click="func">进入index页面</p>
<router-view></router-view>
</div>
</template>

注意:路由嵌套的真正的含义是:点击子路由的时候,父级组件还是会显示的,子组件也会显示的,这才是使用子路由嵌套的用途。
如果仅仅想显示子组件的话,不想显示父组件的话,那就不要使用路由嵌套,直接使用兄弟路由,写死路径即可。

比如

const router = [
{
path: '/home',
name: 'home',
component: resolve => require(['./views/home'], resolve),
},
// 兄弟路由
{
path: '/home/java',
name: 'home',
component: resolve => require(['./views/java'], resolve),
}
]

github源码 webpack+vue+router

深入浅出的webpack构建工具--webpack4+vue+router项目架构(十四)的更多相关文章

  1. 深入浅出的webpack构建工具--webpack4+vue搭建环境 (十三)

    深入浅出的webpack构建工具--webpack4+vue搭建环境 (十三) 从上面一系列的webpack配置的学习,我们现在来使用webpack来搭建vue的开发环境.首先我们来设想下我们的项目的 ...

  2. 深入浅出的webpack构建工具---devTool中SourceMap模式详解(四)

    阅读目录 一:什么是SourceMap? 二:理解webpack中的SourceMap的eval,inline,sourceMap,cheap,module 三:开发环境和线上环境如何选择source ...

  3. 深入浅出的webpack构建工具---tree shaking打包性能优化(十二)

    阅读目录 1. 什么是tree-shaking? 2. 在webpack中如何使用 tree-shaking 呢? 3. 使用webpack-deep-scope-plugin 优化 回到顶部 1. ...

  4. 深入浅出的webpack构建工具---AutoDllPlugin插件(八)

    深入浅出的webpack构建工具---AutoDllPlugin插件(八) DllPlugin插件能够快速打包,能把第三方依赖的文件能提前进行预编译打包到一个文件里面去.提高了构建速度.因为很多第三方 ...

  5. 深入浅出的webpack构建工具---webpack基本配置(一)

    深入浅出的webpack构建工具---webpack基本配置(一) 阅读目录 一:webpack入门构建: 1. 安装webpack到全局 2. 安装webpack到本项目. 3. 如何使用webpa ...

  6. 深入浅出的webpack构建工具---DevServer配置项(二)

    深入浅出的webpack构建工具---DevServer配置项(二) 阅读目录 DevServer配置项 1. contentBase 2. port 3. host 4. headers 5. hi ...

  7. 深入浅出的webpack4构建工具--webpack4+vue+route+vuex项目构建(十七)

    阅读目录 一:vue传值方式有哪些? 二:理解使用Vuex 三:webpack4+vue+route+vuex 项目架构 回到顶部 一:vue传值方式有哪些? 在vue项目开发过程中,经常会使用组件来 ...

  8. 深入浅出的webpack构建工具---PostCss(五)

    一:PostCss是什么?  PostCss是一个样式处理工具,它通过自定义的插件和工具生态体系来重新定义css.它鼓励开发者使用规范的css原生语法编写代码,然后配置编译器转换需要兼容的浏览器版本, ...

  9. 深入浅出的webpack构建工具---HappyPack优化构建(九)

    阅读目录 一:什么是HappyPack? 作用是什么? 二:如何在配置中使用HappyPack? 回到顶部 一:什么是HappyPack? 作用是什么? Webpack是允许在NodeJS中的,它是单 ...

随机推荐

  1. 【Java并发编程】15、ReentrantLock实现原理深入探究

    原文已经写得非常详细了,直接把大神的文章转发过来了  https://www.cnblogs.com/xrq730/p/4979021.html 前言 这篇文章被归到Java基础分类中,其实真的一点都 ...

  2. 解决VM提示:VMware Workstation cannot connect to the virtual machine. Make sure you have rights to run the program, access all directories the program uses, and access all directories for temporary files.

    问题: 在开启虚拟机的时候报: VMware Workstation cannot connect to the virtual machine. Make sure you have rights ...

  3. 自定义基于jquery竖向瀑布流插件

    公司新项目做了一个关于图片的板块,网上找了一些瀑布流插件都不是很适合自己,于是就自己造轮子写一个,并封装成插件github 于是就想分享一下,主要是为了更好的学习与记忆. 如果大家进来了,希望能给我g ...

  4. 前端周报:前端面试题及答案总结;JavaScript参数传递的深入理解

    1.2017前端面试题及答案总结 |掘金技术征文 "金三银四,金九银十",用来形容求职最好的几个月.但是随着行业的饱和,初中级前端er就业形势不容乐观. 行业状态不可控,我们能做的 ...

  5. pip install 报错

    问题描述,在使用pip安装django相关软件包时,提示错误如下: [root@test4 install]# pip install django==1.6 Downloading/unpackin ...

  6. 转载--tomcat调优

    转载  https://www.cnblogs.com/wangsen/p/9337969.html

  7. CloudSim源代码学习——云数据中心(Datacenter)

    package org.cloudbus.cloudsim; import java.text.DecimalFormat;//十进制 import java.util.ArrayList; impo ...

  8. 网络基础 cookie详解

    cookie详解 by:授客 QQ:1033553122 cookie干嘛用的? 参见文章http 会话(session)详解: 网络基础 http 会话(session)详解   cookie分类 ...

  9. Java数据解析---JSON

    一.Java数据解析分为:XML解析和JSON解析 XML解析即是对XML文件中的数据解析,而JSON解析即对规定形式的数据解析,比XML解析更加方便 JSON解析基于两种结构: 1.键值对类型 { ...

  10. JavaScript非数字(中文)排序

    直接上代码: var arr=[ {name:"张散步",age:"23",sports:"篮球",number:"231123& ...