Vue高级部分(二)

Vue-router

路由的简介

路由的理解

什么是路由?

  • 一个路由就是一个映射关系(key:value)。

  • key为路径,value可能是function或component。

路由分类

  • 后端路由:


    • 理解:value是function, 用来处理客户端提交的请求。

    • 注册路由:router.get(path, function(req, res))

    • 工作过程:当服务器接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据。
  • 前端路由:


    • 浏览器端路由,value是component,用于展示页面内容。

    • 注册路由: <Route path="/test" component={Test}>

    • 工作过程:当浏览器的path变为/test时, 当前组件就会变为Test组件。

SPA的理解

  • 单页Web应用(single page web application,SPA)。

  • 整个应用只有一个完整页面

  • 点击页面中的超链接不会刷新页面,只会做页面的局部更新

  • 数据都是通过ajax请求获取,并在前端异步展示。

vue-router的理解

  • Vue的一个插件库。

  • 专门用来实现一个SPA应用。

  • 基于Vue的项目都会使用此库。

  • 中文文档:https://router.vuejs.org/zh/guide/

路由的基本使用

使用步骤

  • ① 安装vue-router:
yarn add vue-router
  • ② 安装插件:
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import router from './router';
//关闭生产提示
Vue.config.productionTip = false;
//安装VueRouter
Vue.use(VueRouter);

new Vue({
  el'#app',
  renderh => h(App),
  router
});
  • ③ 编写router配置项:
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../components/About';
import Home from '../components/Home';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home
    },
  ]
});
export default router;
  • ④ 实现切换(active-class可以配置高亮样式):
<router-link active-class="active" class="list-group-item " to="/home">Home</router-link>
<router-link active-class="active" class="list-group-item" to="/about">About</router-link>
  • ⑤ 指定展示位置:
<router-view></router-view>

应用示例

  • 示例:

  • 目录:

|-- README.md
|-- babel.config.js
|-- package.json
|-- public
|   |-- css
|   |   `-- bootstrap.css
|   |-- favicon.ico
|   `-- index.html
|-- src
|   |-- App.vue
|   |-- assets
|   |   `-- logo.png
|   |-- components
|   |   |-- About.vue
|   |   `-- Home.vue
|   |-- main.js
|   `-- router
|       `-- index.js
|-- vue.config.js
`-- yarn.lock
  • main.js
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import router from './router';
//关闭生产提示
Vue.config.productionTip = false;
//安装VueRouter
Vue.use(VueRouter);

new Vue({
  el'#app',
  renderh => h(App),
  router
});
  • App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header"><h2>Vue Router Demo</h2></div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- 原始HTML中我们使用a标签实现页面的跳转 -->
          <!--          <a class="list-group-item" href="./about.html">About</a>   -->
          <!--          <a class="list-group-item active" href="./home.html">Home</a>   -->
          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link active-class="active" class="list-group-item " to="/home">Home</router-link>
          <router-link active-class="active" class="list-group-item" to="/about">About</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 指定组件对应的呈现位置  -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name'App',
};
</script>
  • router/index.js
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../components/About';
import Home from '../components/Home';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home
    },
  ]
});
export default router;
  • components/About.vue
<template>
  <div>我是About的内容</div>
</template>

<script>
export default {
  name'About'
};
</script>

<style scoped>

</style>
  • components/Home.vue
<template>
  <div>我是Home的内容</div>
</template>

<script>
export default {
  name'Home'
};
</script>

<style scoped>

</style>

路由的注意点

  • 路由组件通常存放在pages目录下,一般组件通常存放在components目录下。

  • 通过切换,”隐藏”了的路由组件,默认是被销毁的,需要的时候再去挂载。

  • 每个组件都有自己的$route属性,里面存储自己的路由信息。

  • 整个应用只有一个router,可以通过组件的$router属性获取到。

嵌套路由

使用步骤

  • ① 配置路径规则,使用children配置项:
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [ //通过children配置自己路由
        {
          path'news'//此处一定不要写 /news
          component: News
        },
        {
          path'message'//此处一定不要写 /message
          component: Message
        },
      ]
    },
  ]
});
export default router;
  • ② 路径(要写完整路径):
<router-link active-class="active" class="list-group-item" to="/home/message">Message</router-link>

应用示例

  • 示例:

  • 目录结构:

|-- README.md
|-- babel.config.js
|-- package.json
|-- public
|   |-- css
|   |   `-- bootstrap.css
|   |-- favicon.ico
|   `-- index.html
|-- src
|   |-- App.vue
|   |-- assets
|   |   `-- logo.png
|   |-- components
|   |   `-- Banner.vue
|   |-- main.js
|   |-- pages
|   |   |-- About.vue
|   |   |-- Home.vue
|   |   |-- Message.vue
|   |   `-- News.vue
|   `-- router
|       `-- index.js
|-- vue.config.js
`-- yarn.lock
  • main.js
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import router from './router';
//关闭生产提示
Vue.config.productionTip = false;
//安装VueRouter
Vue.use(VueRouter);

new Vue({
  el'#app',
  renderh => h(App),
  router
});
  • App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header">
          <Banner/>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link active-class="active" class="list-group-item " to="/home">Home</router-link>
          <router-link active-class="active" class="list-group-item" to="/about">About</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 指定组件对应的呈现位置  -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Banner from './components/Banner';

export default {
  name'App',
  components: {
    Banner
  }
};
</script>
  • router/index.js
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [ //通过children配置自己路由
        {
          path'news'//此处一定不要写 /news
          component: News
        },
        {
          path'message'//此处一定不要写 /message
          component: Message
        },
      ]
    },
  ]
});
export default router;
  • components/Banner.vue
<template>
  <h2>Vue Router Demo</h2>
</template>

<script>
export default {
  name'Banner'
};
</script>

<style scoped>

</style>
  • pages/About.vue
<template>
  <div>我是About的内容</div>
</template>

<script>
export default {
  name'About'
};
</script>

<style scoped>

</style>
  • pages/Home.vue
<template>
  <div>
    <h2>Home组件内容</h2>
    <div>
      <ul class="nav nav-tabs">
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/news">News</router-link>
        </li>
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/message">Message</router-link>
        </li>
      </ul>
      <ul>
        <router-view></router-view>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  name'Home'
};
</script>

<style scoped>

</style>
  • pages/News.vue
<template>
  <ul>
    <li>news001</li>
    <li>news002</li>
    <li>news003</li>
  </ul>
</template>

<script>
export default {
  name'News'
};
</script>

<style scoped>

</style>
  • pages/Message.vue
<template>
  <div>
    <ul>
      <li>
        <a href="/message1">message001</a>&nbsp;&nbsp;
      </li>
      <li>
        <a href="/message2">message002</a>&nbsp;&nbsp;
      </li>
      <li>
        <a href="/message/3">message003</a>&nbsp;&nbsp;
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name'Message'
};
</script>

<style scoped>

</style>

路由传参(query参数)

使用步骤

  • ① 传递参数:
<!-- 跳转路由并携带query参数,to的字符串写法 -->
<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{ m.title }}</router-link>
<!-- 跳转路由并携带query参数,to的对象写法 -->
<router-link :to="{
 path:'/home/message/detail',
    query:{id:m.id,title:m.title}
}"
>
{{ m.title }}</router-link>

  • ② 接收参数:
<ul>
    <li>消息编号:{{ $route.query.id }}</li>
    <li>消息标题:{{ $route.query.title }}</li>
</ul>

应用示例

  • 示例:

  • 目录结构:

|-- README.md
|-- babel.config.js
|-- package.json
|-- public
|   |-- css
|   |   `-- bootstrap.css
|   |-- favicon.ico
|   `-- index.html
|-- src
|   |-- App.vue
|   |-- assets
|   |   `-- logo.png
|   |-- components
|   |   `-- Banner.vue
|   |-- main.js
|   |-- pages
|   |   |-- About.vue
|   |   |-- Detail.vue
|   |   |-- Home.vue
|   |   |-- Message.vue
|   |   `-- News.vue
|   `-- router
|       `-- index.js
|-- vue.config.js
`-- yarn.lock
  • main.js
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import router from './router';
//关闭生产提示
Vue.config.productionTip = false;
//安装VueRouter
Vue.use(VueRouter);

new Vue({
  el'#app',
  renderh => h(App),
  router
});
  • App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header">
          <Banner/>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link active-class="active" class="list-group-item" to="/about">About</router-link>
          <router-link active-class="active" class="list-group-item " to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 指定组件对应的呈现位置  -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Banner from './components/Banner';

export default {
  name'App',
  components: {
    Banner
  }
};
</script>
  • router/index.js
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [ //通过children配置自己路由
        {
          path'news'//此处一定不要写 /news
          component: News
        },
        {
          path'message'//此处一定不要写 /message
          component: Message,
          children: [
            {
              path'detail',
              component: Detail
            }
          ]
        },
      ]
    },
  ]
});
export default router;
  • components/Banner.vue
<template>
  <h2>Vue Router Demo</h2>
</template>

<script>
export default {
  name'Banner'
};
</script>

<style scoped>

</style>
  • pages/About.vue
<template>
  <div>我是About的内容</div>
</template>

<script>
export default {
  name'About'
};
</script>

<style scoped>

</style>
  • pages/Home.vue
<template>
  <div>
    <h2>Home组件内容</h2>
    <div>
      <ul class="nav nav-tabs">
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/news">News</router-link>
        </li>
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/message">Message</router-link>
        </li>
      </ul>
      <ul>
        <router-view></router-view>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  name'Home'
};
</script>

<style scoped>

</style>
  • pages/News.vue
<template>
  <ul>
    <li>news001</li>
    <li>news002</li>
    <li>news003</li>
  </ul>
</template>

<script>
export default {
  name'News'
};
</script>

<style scoped>

</style>
  • pages/Message.vue
<template>
  <div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
        <!-- 跳转路由并携带query参数,to的字符串写法 -->
        <!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{ m.title }}</router-link>-->
        <!-- 跳转路由并携带query参数,to的对象写法 -->
        <router-link :to="{path:'/home/message/detail',query:{id:m.id,title:m.title}}">{{ m.title }}</router-link>
      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name'Message',
  data () {
    return {
      messageList: [
        {
          id'001'title'消息001'
        },
        {
          id'002'title'消息002'
        },
        {
          id'003'title'消息003'
        },
      ]
    };
  }
};
</script>

<style scoped>

</style>
  • pages/Detail.vue
<template>
  <ul>
    <li>消息编号:{{ $route.query.id }}</li>
    <li>消息标题:{{ $route.query.title }}</li>
  </ul>
</template>

<script>
export default {
  name'Detail',
  mounted () {
    console.log(this.$route.query);
  }
};
</script>

<style scoped>

</style>

命名路由

概述

  • 命名路由可以简化路由的跳转。

使用步骤

  • ① 给路由命名:
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      name'about'//给路由命名
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [
        {
          path'news',
          component: News
        },
        {
          path'message',
          component: Message,
          children: [
            {
              name'detail'//给路由命名
              path'detail',
              component: Detail
            }
          ]
        },
      ]
    },
  ]
});
export default router;
  • ② 简化跳转:
<!-- 简化前,需要写完整的路径 -->
 <router-link :to="{path:'/home/message/detail',query:{id:m.id,title:m.title}}">{{ m.title }}</router-link>
<!-- 简化后,直接通过名字跳转 -->
<router-link :to="{name:'detail'}">{{ m.title }}</router-link>
<!-- 简化后,配合传递参数 -->
<router-link :to="{name:'detail',query:{id:m.id,title:m.title}}">{{ m.title }}</router-link>

应用示例

  • 示例:

  • 目录结构:

|-- README.md
|-- babel.config.js
|-- package.json
|-- public
|   |-- css
|   |   `-- bootstrap.css
|   |-- favicon.ico
|   `-- index.html
|-- src
|   |-- App.vue
|   |-- assets
|   |   `-- logo.png
|   |-- components
|   |   `-- Banner.vue
|   |-- main.js
|   |-- pages
|   |   |-- About.vue
|   |   |-- Detail.vue
|   |   |-- Home.vue
|   |   |-- Message.vue
|   |   `-- News.vue
|   `-- router
|       `-- index.js
|-- vue.config.js
`-- yarn.lock
  • main.js
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import router from './router';
//关闭生产提示
Vue.config.productionTip = false;
//安装VueRouter
Vue.use(VueRouter);

new Vue({
  el'#app',
  renderh => h(App),
  router
});
  • App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header">
          <Banner/>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link :to="{name:'about'}" active-class="active" class="list-group-item">About</router-link>
          <router-link active-class="active" class="list-group-item " to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 指定组件对应的呈现位置  -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Banner from './components/Banner';

export default {
  name'App',
  components: {
    Banner
  }
};
</script>
  • router/index.js
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      name'about',
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [
        {
          path'news',
          component: News
        },
        {
          path'message',
          component: Message,
          children: [
            {
              name'detail',
              path'detail',
              component: Detail
            }
          ]
        },
      ]
    },
  ]
});
export default router;
  • components/Banner.vue
<template>
  <h2>Vue Router Demo</h2>
</template>

<script>
export default {
  name'Banner'
};
</script>

<style scoped>

</style>
  • pages/About.vue
<template>
  <div>我是About的内容</div>
</template>

<script>
export default {
  name'About'
};
</script>

<style scoped>

</style>
  • pages/Home.vue
<template>
  <div>
    <h2>Home组件内容</h2>
    <div>
      <ul class="nav nav-tabs">
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/news">News</router-link>
        </li>
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/message">Message</router-link>
        </li>
      </ul>
      <ul>
        <router-view></router-view>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  name'Home'
};
</script>

<style scoped>

</style>
  • pages/News.vue
<template>
  <ul>
    <li>news001</li>
    <li>news002</li>
    <li>news003</li>
  </ul>
</template>

<script>
export default {
  name'News'
};
</script>

<style scoped>

</style>
  • pages/Message.vue
<template>
  <div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
        <!-- 跳转路由并携带query参数,to的字符串写法 -->
        <!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{ m.title }}</router-link>-->
        <!-- 跳转路由并携带query参数,to的对象写法 -->
        <router-link :to="{name:'detail',query:{id:m.id,title:m.title}}">{{ m.title }}</router-link>
      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name'Message',
  data () {
    return {
      messageList: [
        {
          id'001'title'消息001'
        },
        {
          id'002'title'消息002'
        },
        {
          id'003'title'消息003'
        },
      ]
    };
  }
};
</script>

<style scoped>

</style>
  • pages/Detail.vue
<template>
  <ul>
    <li>消息编号:{{ $route.query.id }}</li>
    <li>消息标题:{{ $route.query.title }}</li>
  </ul>
</template>

<script>
export default {
  name'Detail',
  mounted () {
    console.log(this.$route.query);
  }
};
</script>

<style scoped>

</style>

路由传参(params参数)

使用步骤

  • ① 配置路由,声明接收params参数:
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      name'about',
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [
        {
          path'news',
          component: News
        },
        {
          path'message',
          component: Message,
          children: [
            {
              name'detail',
              path'detail/:id/:title'//使用占位符声明接收params参数
              component: Detail
            }
          ]
        },
      ]
    },
  ]
});
export default router;
  • ② 传递参数:
<!-- 跳转路由并携带params参数,to的字符串写法 -->
<router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{ m.title }}</router-link>
<!-- 跳转路由并携带params参数,to的对象写法 -->
<router-link :to="{name:'detail',params:{id:m.id,title:m.title}}">{{ m.title }}</router-link>

注意:路由携带params参数时,如果使用to的对象写法,则不能使用path,必须使用name配置

  • ③ 接收参数:
<ul>
    <li>消息编号:{{ $route.params.id }}</li>
    <li>消息标题:{{ $route.params.title }}</li>
</ul>

应用示例

  • 示例:

  • 目录结构:

|-- README.md
|-- babel.config.js
|-- package.json
|-- public
|   |-- css
|   |   `-- bootstrap.css
|   |-- favicon.ico
|   `-- index.html
|-- src
|   |-- App.vue
|   |-- assets
|   |   `-- logo.png
|   |-- components
|   |   `-- Banner.vue
|   |-- main.js
|   |-- pages
|   |   |-- About.vue
|   |   |-- Detail.vue
|   |   |-- Home.vue
|   |   |-- Message.vue
|   |   `-- News.vue
|   `-- router
|       `-- index.js
|-- vue.config.js
`-- yarn.lock
  • main.js
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import router from './router';
//关闭生产提示
Vue.config.productionTip = false;
//安装VueRouter
Vue.use(VueRouter);

new Vue({
  el'#app',
  renderh => h(App),
  router
});
  • App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header">
          <Banner/>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link :to="{name:'about'}" active-class="active" class="list-group-item">About</router-link>
          <router-link active-class="active" class="list-group-item " to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 指定组件对应的呈现位置  -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Banner from './components/Banner';

export default {
  name'App',
  components: {
    Banner
  }
};
</script>
  • router/index.js
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      name'about',
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [
        {
          path'news',
          component: News
        },
        {
          path'message',
          component: Message,
          children: [
            {
              name'detail',
              path'detail/:id/:title'//使用占位符声明接收params参数
              component: Detail
            }
          ]
        },
      ]
    },
  ]
});
export default router;
  • components/Banner.vue
<template>
  <h2>Vue Router Demo</h2>
</template>

<script>
export default {
  name'Banner'
};
</script>

<style scoped>

</style>
  • pages/About.vue
<template>
  <div>我是About的内容</div>
</template>

<script>
export default {
  name'About'
};
</script>

<style scoped>

</style>
  • pages/Home.vue
<template>
  <div>
    <h2>Home组件内容</h2>
    <div>
      <ul class="nav nav-tabs">
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/news">News</router-link>
        </li>
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/message">Message</router-link>
        </li>
      </ul>
      <ul>
        <router-view></router-view>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  name'Home'
};
</script>

<style scoped>

</style>
  • pages/News.vue
<template>
  <ul>
    <li>news001</li>
    <li>news002</li>
    <li>news003</li>
  </ul>
</template>

<script>
export default {
  name'News'
};
</script>

<style scoped>

</style>
  • pages/Message.vue
<template>
  <div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
        <!-- 跳转路由并携带params参数,to的字符串写法 -->
        <!-- <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{ m.title }}</router-link> -->
        <!-- 跳转路由并携带params参数,to的对象写法 -->
        <router-link :to="{
          name:'detail',
          params:{id:m.id,title:m.title}
        }"
>
{{ m.title }}
        </router-link>
      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name'Message',
  data () {
    return {
      messageList: [
        {
          id'001'title'消息001'
        },
        {
          id'002'title'消息002'
        },
        {
          id'003'title'消息003'
        },
      ]
    };
  }
};
</script>

<style scoped>

</style>
  • pages/Detail.vue
<template>
  <ul>
    <li>消息编号:{{ $route.params.id }}</li>
    <li>消息标题:{{ $route.params.title }}</li>
  </ul>
</template>

<script>
export default {
  name'Detail',
  mounted () {
    console.log(this.$route.params);
  }
};
</script>

<style scoped>

</style>

路由的props配置

概述

  • 让路由组件更方便的接收到参数。

  • 第一种写法:值是对象,该对象中的key和value都会以props的形式传递给Detail组件(几乎不用)

// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      name'about',
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [
        {
          path'news',
          component: News
        },
        {
          path'message',
          component: Message,
          children: [
            {
              name'detail',
              path'detail/:id/:title'//使用占位符声明接收params参数
              component: Detail,
              //props的第一种写法,值为对象,该对象中的key和value都会以props的形式传递给Detail组件
               props: {
                 a1,
                 b2
               }
            }
          ]
        },
      ]
    },
  ]
});
export default router;
  • 第二种写法:值为布尔值,如果布尔值为true,就会把路由组件收到的所有params参数,以props的形式传递给Detail组件
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      name'about',
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [
        {
          path'news',
          component: News
        },
        {
          path'message',
          component: Message,
          children: [
            {
              name'detail',
              path'detail/:id/:title'//使用占位符声明接收params参数
              component: Detail,
              //props的第二种写法,值为布尔值,如果布尔值为true,就会把路由组件收到的所有params参数,以props的形式传递给Detail组件
              propstrue
            }
          ]
        },
      ]
    },
  ]
});
export default router;
  • 第三种写法:值为函数。
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      name'about',
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [
        {
          path'news',
          component: News
        },
        {
          path'message',
          component: Message,
          children: [
            {
              name'detail',
              path'detail/:id/:title'//使用占位符声明接收params参数
              component: Detail,
              //props的第三种写法:值为函数,
              props ($route) {
                return { id: $route.params.id, title: $route.params.title };
              }
              /*props ({ params: { id, title } }) {
                return { id, title };
              }*/

            }
          ]
        },
      ]
    },
  ]
});
export default router;

应用示例

  • 示例:

  • 目录结构:

|-- README.md
|-- babel.config.js
|-- package.json
|-- public
|   |-- css
|   |   `-- bootstrap.css
|   |-- favicon.ico
|   `-- index.html
|-- src
|   |-- App.vue
|   |-- assets
|   |   `-- logo.png
|   |-- components
|   |   `-- Banner.vue
|   |-- main.js
|   |-- pages
|   |   |-- About.vue
|   |   |-- Detail.vue
|   |   |-- Home.vue
|   |   |-- Message.vue
|   |   `-- News.vue
|   `-- router
|       `-- index.js
|-- vue.config.js
`-- yarn.lock
  • main.js
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import router from './router';
//关闭生产提示
Vue.config.productionTip = false;
//安装VueRouter
Vue.use(VueRouter);

new Vue({
  el'#app',
  renderh => h(App),
  router
});
  • App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header">
          <Banner/>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link :to="{name:'about'}" active-class="active" class="list-group-item">About</router-link>
          <router-link active-class="active" class="list-group-item " to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 指定组件对应的呈现位置  -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Banner from './components/Banner';

export default {
  name'App',
  components: {
    Banner
  }
};
</script>
  • router/index.js
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      name'about',
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [
        {
          path'news',
          component: News
        },
        {
          path'message',
          component: Message,
          children: [
            {
              name'detail',
              path'detail/:id/:title'//使用占位符声明接收params参数
              component: Detail,
              //props的第一种写法,值为对象,该对象中的key和value都会以props的形式传递给Detail组件
              /* props: {
                 a: 1,
                 b: 2
               }*/


              //props的第二种写法,值为布尔值,如果布尔值为true,就会把路由组件收到的所有params参数,以props的形式传递给Detail组件
              // props: true

              //props的第三种写法:值为函数,
              props ($route) {
                return { id: $route.params.id, title: $route.params.title };
              }
              /*props ({ params: { id, title } }) {
                return { id, title };
              }*/

            }
          ]
        },
      ]
    },
  ]
});
export default router;
  • components/Banner.vue
<template>
  <h2>Vue Router Demo</h2>
</template>

<script>
export default {
  name'Banner'
};
</script>

<style scoped>

</style>
  • pages/About.vue
<template>
  <div>我是About的内容</div>
</template>

<script>
export default {
  name'About'
};
</script>

<style scoped>

</style>
  • pages/Home.vue
<template>
  <div>
    <h2>Home组件内容</h2>
    <div>
      <ul class="nav nav-tabs">
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/news">News</router-link>
        </li>
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/message">Message</router-link>
        </li>
      </ul>
      <ul>
        <router-view></router-view>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  name'Home'
};
</script>

<style scoped>

</style>
  • pages/News.vue
<template>
  <ul>
    <li>news001</li>
    <li>news002</li>
    <li>news003</li>
  </ul>
</template>

<script>
export default {
  name'News'
};
</script>

<style scoped>

</style>
  • pages/Message.vue
<template>
  <div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
        <!-- 跳转路由并携带params参数,to的字符串写法 -->
        <!-- <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{ m.title }}</router-link> -->
        <!-- 跳转路由并携带params参数,to的对象写法 -->
        <router-link :to="{
          name:'detail',
          params:{id:m.id,title:m.title}
        }"
>
{{ m.title }}
        </router-link>
      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name'Message',
  data () {
    return {
      messageList: [
        {
          id'001'title'消息001'
        },
        {
          id'002'title'消息002'
        },
        {
          id'003'title'消息003'
        },
      ]
    };
  }
};
</script>

<style scoped>

</style>
  • pages/Detail.vue
<template>
  <ul>
    <li>消息编号:{{ id }}</li>
    <li>消息标题:{{ title }}</li>
  </ul>
</template>

<script>
export default {
  name'Detail',
  mounted () {
    console.log(this);
  },
  props: ['id''title']
};
</script>

<style scoped>

</style>

router-link的replace属性

  • 作用:控制路由跳转时操作浏览器历史记录的模式。

  • 浏览器的历史记录有两种写入方式:分别为pushreplacepush是追加历史的记录,replace是替换当前记录,路由跳转的时候默认为push

  • 如何开启replace模式?

<!-- 只需要添加replace属性即可 -->
<router-link replace>About</router-link>

编程式路由导航

概述

  • 不借助<router-link>实现路由跳转,让路由跳转更加灵活。

  • 点击路由链接,可以返回到当前路由界面:

this.$router.push({
        name'detail',
        params: { id: m.id, title: m.title }
});
  • 点击路由链接,不可以返回到当前路由界面:
this.$router.replace({
        name'detail',
        params: { id: m.id, title: m.title }
});
  • 请求返回上一个记录路由:
this.$router.back();
  • 请求下一个记录路由:
 this.$router.forward();

应用示例

  • 示例:

  • 目录结构:

|-- README.md
|-- babel.config.js
|-- package.json
|-- public
|   |-- css
|   |   `-- bootstrap.css
|   |-- favicon.ico
|   `-- index.html
|-- src
|   |-- App.vue
|   |-- assets
|   |   `-- logo.png
|   |-- components
|   |   `-- Banner.vue
|   |-- main.js
|   |-- pages
|   |   |-- About.vue
|   |   |-- Detail.vue
|   |   |-- Home.vue
|   |   |-- Message.vue
|   |   `-- News.vue
|   `-- router
|       `-- index.js
|-- vue.config.js
`-- yarn.lock
  • main.js
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import router from './router';
//关闭生产提示
Vue.config.productionTip = false;
//安装VueRouter
Vue.use(VueRouter);

new Vue({
  el'#app',
  renderh => h(App),
  router
});
  • App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header">
          <Banner/>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link :to="{name:'about'}" active-class="active" class="list-group-item">About</router-link>
          <router-link active-class="active" class="list-group-item " to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 指定组件对应的呈现位置  -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Banner from './components/Banner';

export default {
  name'App',
  components: {
    Banner
  }
};
</script>
  • router/index.js
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      name'about',
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [
        {
          path'news',
          component: News
        },
        {
          path'message',
          component: Message,
          children: [
            {
              name'detail',
              path'detail/:id/:title'//使用占位符声明接收params参数
              component: Detail,
              //props的第一种写法,值为对象,该对象中的key和value都会以props的形式传递给Detail组件
              /* props: {
                 a: 1,
                 b: 2
               }*/

              //props的第二种写法,值为布尔值,如果布尔值为true,就会把路由组件收到的所有params参数,以props的形式传递给Detail组件
              // props: true
              //props的第三种写法:值为函数,
              props ($route) {
                return { id: $route.params.id, title: $route.params.title };
              }
              /*props ({ params: { id, title } }) {
                return { id, title };
              }*/

            }
          ]
        },
      ]
    },
  ]
});
export default router;
  • components/Banner.vue
<template>
  <div>
    <h2>Vue Router Demo</h2>
    <button @click="back">后退</button>
    &nbsp;
    <button @click="forward">前进</button>
  </div>
</template>

<script>
export default {
  name'Banner',
  methods: {
    forward () {
      this.$router.forward();
    },
    back () {
      this.$router.back();
    }
  }
};
</script>

<style scoped>

</style>
  • pages/About.vue
<template>
  <div>我是About的内容</div>
</template>

<script>
export default {
  name'About'
};
</script>

<style scoped>

</style>
  • pages/Home.vue
<template>
  <div>
    <h2>Home组件内容</h2>
    <div>
      <ul class="nav nav-tabs">
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/news">News</router-link>
        </li>
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/message">Message</router-link>
        </li>
      </ul>
      <ul>
        <router-view></router-view>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  name'Home'
};
</script>

<style scoped>

</style>
  • pages/News.vue
<template>
  <ul>
    <li>news001</li>
    <li>news002</li>
    <li>news003</li>
  </ul>
</template>

<script>
export default {
  name'News'
};
</script>

<style scoped>

</style>
  • pages/Message.vue
<template>
  <div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
        <!-- 跳转路由并携带params参数,to的字符串写法 -->
        <!-- <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{ m.title }}</router-link> -->
        <!-- 跳转路由并携带params参数,to的对象写法 -->
        <router-link :to="{
          name:'detail',
          params:{id:m.id,title:m.title}
        }"
>
{{ m.title }}
        </router-link>
        <button @click="pushShow(m)">push查看</button>
        <button @click="replaceShow(m)">replace查看</button>
      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name'Message',
  data () {
    return {
      messageList: [
        {
          id'001'title'消息001'
        },
        {
          id'002'title'消息002'
        },
        {
          id'003'title'消息003'
        },
      ]
    };
  },
  methods: {
    pushShow (m) {
      this.$router.push({
        name'detail',
        params: { id: m.id, title: m.title }
      });
    },
    replaceShow (m) {
      this.$router.replace({
        name'detail',
        params: { id: m.id, title: m.title }
      });
    }
  }
};
</script>

<style scoped>

</style>
  • pages/Detail.vue
<template>
  <ul>
    <li>消息编号:{{ id }}</li>
    <li>消息标题:{{ title }}</li>
  </ul>
</template>

<script>
export default {
  name'Detail',
  mounted () {
    console.log(this);
  },
  props: ['id''title']
};
</script>

<style scoped>

</style>

缓存路由组件

概述

  • 作用:让不展示的路由组件保持挂载,不被销毁。

  • 具体编码:

<!--  include里面是组件名,缓存一个路由组件   -->
<keep-alive include="News">
    <router-view></router-view>
</keep-alive>
<!--  include里面是组件名,缓存多个路由组件   -->
<keep-alive :include="['News','Message']">
    <router-view></router-view>
</keep-alive>

应用示例

  • 示例:

  • 目录结构:

|-- README.md
|-- babel.config.js
|-- package.json
|-- public
|   |-- css
|   |   `-- bootstrap.css
|   |-- favicon.ico
|   `-- index.html
|-- src
|   |-- App.vue
|   |-- assets
|   |   `-- logo.png
|   |-- components
|   |   `-- Banner.vue
|   |-- main.js
|   |-- pages
|   |   |-- About.vue
|   |   |-- Detail.vue
|   |   |-- Home.vue
|   |   |-- Message.vue
|   |   `-- News.vue
|   `-- router
|       `-- index.js
|-- vue.config.js
`-- yarn.lock
  • main.js
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import router from './router';
//关闭生产提示
Vue.config.productionTip = false;
//安装VueRouter
Vue.use(VueRouter);

new Vue({
  el'#app',
  renderh => h(App),
  router
});
  • App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header">
          <Banner/>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link :to="{name:'about'}" active-class="active" class="list-group-item">About</router-link>
          <router-link active-class="active" class="list-group-item " to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 指定组件对应的呈现位置  -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Banner from './components/Banner';

export default {
  name'App',
  components: {
    Banner
  }
};
</script>
  • router/index.js
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      name'about',
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [
        {
          path'news',
          component: News
        },
        {
          path'message',
          component: Message,
          children: [
            {
              name'detail',
              path'detail/:id/:title'//使用占位符声明接收params参数
              component: Detail,
              //props的第一种写法,值为对象,该对象中的key和value都会以props的形式传递给Detail组件
              /* props: {
                 a: 1,
                 b: 2
               }*/

              //props的第二种写法,值为布尔值,如果布尔值为true,就会把路由组件收到的所有params参数,以props的形式传递给Detail组件
              // props: true
              //props的第三种写法:值为函数,
              props ($route) {
                return { id: $route.params.id, title: $route.params.title };
              }
              /*props ({ params: { id, title } }) {
                return { id, title };
              }*/

            }
          ]
        },
      ]
    },
  ]
});
export default router;
  • components/Banner.vue
<template>
  <div>
    <h2>Vue Router Demo</h2>
    <button @click="back">后退</button>
    &nbsp;
    <button @click="forward">前进</button>
  </div>
</template>

<script>
export default {
  name'Banner',
  methods: {
    forward () {
      this.$router.forward();
    },
    back () {
      this.$router.back();
    }
  }
};
</script>

<style scoped>

</style>
  • pages/About.vue
<template>
  <div>我是About的内容</div>
</template>

<script>
export default {
  name'About'
};
</script>

<style scoped>

</style>
  • pages/Home.vue
<template>
  <div>
    <h2>Home组件内容</h2>
    <div>
      <ul class="nav nav-tabs">
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/news">News</router-link>
        </li>
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/message">Message</router-link>
        </li>
      </ul>
      <!--  include里面是组件名   -->
      <keep-alive include="News">
        <router-view></router-view>
      </keep-alive>
    </div>
  </div>
</template>

<script>
export default {
  name'Home'
};
</script>

<style scoped>

</style>
  • pages/News.vue
<template>
  <ul>
    <li>news001 <input type="text"></li>
    <li>news002 <input type="text"></li>
    <li>news003 <input type="text"></li>
  </ul>
</template>

<script>
export default {
  name'News'
};
</script>

<style scoped>

</style>
  • pages/Message.vue
<template>
  <div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
        <!-- 跳转路由并携带params参数,to的字符串写法 -->
        <!-- <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{ m.title }}</router-link> -->
        <!-- 跳转路由并携带params参数,to的对象写法 -->
        <router-link :to="{
          name:'detail',
          params:{id:m.id,title:m.title}
        }"
>
{{ m.title }}
        </router-link>
        <button @click="pushShow(m)">push查看</button>
        <button @click="replaceShow(m)">replace查看</button>
      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name'Message',
  data () {
    return {
      messageList: [
        {
          id'001'title'消息001'
        },
        {
          id'002'title'消息002'
        },
        {
          id'003'title'消息003'
        },
      ]
    };
  },
  methods: {
    pushShow (m) {
      this.$router.push({
        name'detail',
        params: { id: m.id, title: m.title }
      });
    },
    replaceShow (m) {
      this.$router.replace({
        name'detail',
        params: { id: m.id, title: m.title }
      });
    }
  }
};
</script>

<style scoped>

</style>
  • pages/Detail.vue
<template>
  <ul>
    <li>消息编号:{{ id }}</li>
    <li>消息标题:{{ title }}</li>
  </ul>
</template>

<script>
export default {
  name'Detail',
  mounted () {
    console.log(this);
  },
  props: ['id''title']
};
</script>

<style scoped>

</style>

activated和deactivated生命周期钩子

概述

  • 作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。

  • activated:路由组件被激活的时候触发。

  • deactivated:路由组件失活的时候触发。

应用示例

  • 示例:

  • 目录结构:

|-- README.md
|-- babel.config.js
|-- package.json
|-- public
|   |-- css
|   |   `-- bootstrap.css
|   |-- favicon.ico
|   `-- index.html
|-- src
|   |-- App.vue
|   |-- assets
|   |   `-- logo.png
|   |-- components
|   |   `-- Banner.vue
|   |-- main.js
|   |-- pages
|   |   |-- About.vue
|   |   |-- Detail.vue
|   |   |-- Home.vue
|   |   |-- Message.vue
|   |   `-- News.vue
|   `-- router
|       `-- index.js
|-- vue.config.js
`-- yarn.lock
  • main.js
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import router from './router';
//关闭生产提示
Vue.config.productionTip = false;
//安装VueRouter
Vue.use(VueRouter);

new Vue({
  el'#app',
  renderh => h(App),
  router
});
  • App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header">
          <Banner/>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link :to="{name:'about'}" active-class="active" class="list-group-item">About</router-link>
          <router-link active-class="active" class="list-group-item " to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 指定组件对应的呈现位置  -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Banner from './components/Banner';

export default {
  name'App',
  components: {
    Banner
  }
};
</script>
  • router/index.js
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      name'about',
      path'/about',
      component: About
    },
    {
      path'/home',
      component: Home,
      children: [
        {
          path'news',
          component: News
        },
        {
          path'message',
          component: Message,
          children: [
            {
              name'detail',
              path'detail/:id/:title'//使用占位符声明接收params参数
              component: Detail,
              //props的第一种写法,值为对象,该对象中的key和value都会以props的形式传递给Detail组件
              /* props: {
                 a: 1,
                 b: 2
               }*/

              //props的第二种写法,值为布尔值,如果布尔值为true,就会把路由组件收到的所有params参数,以props的形式传递给Detail组件
              // props: true
              //props的第三种写法:值为函数,
              props ($route) {
                return { id: $route.params.id, title: $route.params.title };
              }
              /*props ({ params: { id, title } }) {
                return { id, title };
              }*/

            }
          ]
        },
      ]
    },
  ]
});
export default router;
  • components/Banner.vue
<template>
  <div>
    <h2>Vue Router Demo</h2>
    <button @click="back">后退</button>
    &nbsp;
    <button @click="forward">前进</button>
  </div>
</template>

<script>
export default {
  name'Banner',
  methods: {
    forward () {
      this.$router.forward();
    },
    back () {
      this.$router.back();
    }
  }
};
</script>

<style scoped>

</style>
  • pages/About.vue
<template>
  <div>我是About的内容</div>
</template>

<script>
export default {
  name'About'
};
</script>

<style scoped>

</style>
  • pages/Home.vue
<template>
  <div>
    <h2>Home组件内容</h2>
    <div>
      <ul class="nav nav-tabs">
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/news">News</router-link>
        </li>
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/message">Message</router-link>
        </li>
      </ul>
      <!--  include里面是组件名   -->
      <keep-alive include="News">
        <router-view></router-view>
      </keep-alive>
    </div>
  </div>
</template>

<script>
export default {
  name'Home'
};
</script>

<style scoped>

</style>
  • pages/News.vue
<template>
  <ul>
    <li :style="{opacity}">欢迎学习Vue</li>
    <li>news001 <input type="text"></li>
    <li>news002 <input type="text"></li>
    <li>news003 <input type="text"></li>
  </ul>
</template>

<script>
export default {
  name'News',
  data () {
    return {
      opacity1
    };
  },
  /*
  mounted () {
    this.timer = setInterval(() => {
      console.log('@');
      this.opacity -= 0.01;
      if (this.opacity <= 0) {
        this.opacity = 1;
      }
    }, 16);
  },
  */

  // beforeDestroy () {
  //   clearInterval(this.timer);
  // }
  activated () {
    console.log('路由组件被激活了');
    this.timer = setInterval(() => {
      console.log('@');
      this.opacity -= 0.01;
      if (this.opacity <= 0) {
        this.opacity = 1;
      }
    }, 16);
  },
  deactivated () {
    console.log('路由组件失活了');
    clearInterval(this.timer);
  }
};
</script>

<style scoped>

</style>
  • pages/Message.vue
<template>
  <div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
        <!-- 跳转路由并携带params参数,to的字符串写法 -->
        <!-- <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{ m.title }}</router-link> -->
        <!-- 跳转路由并携带params参数,to的对象写法 -->
        <router-link :to="{
          name:'detail',
          params:{id:m.id,title:m.title}
        }"
>
{{ m.title }}
        </router-link>
        <button @click="pushShow(m)">push查看</button>
        <button @click="replaceShow(m)">replace查看</button>
      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name'Message',
  data () {
    return {
      messageList: [
        {
          id'001'title'消息001'
        },
        {
          id'002'title'消息002'
        },
        {
          id'003'title'消息003'
        },
      ]
    };
  },
  methods: {
    pushShow (m) {
      this.$router.push({
        name'detail',
        params: { id: m.id, title: m.title }
      });
    },
    replaceShow (m) {
      this.$router.replace({
        name'detail',
        params: { id: m.id, title: m.title }
      });
    }
  }
};
</script>

<style scoped>

</style>
  • pages/Detail.vue
<template>
  <ul>
    <li>消息编号:{{ id }}</li>
    <li>消息标题:{{ title }}</li>
  </ul>
</template>

<script>
export default {
  name'Detail',
  mounted () {
    console.log(this);
  },
  props: ['id''title']
};
</script>

<style scoped>

</style>

路由守卫

概述

  • 作用:对路由进行权限控制。

  • 分类:全局守卫、独享守卫、组件内守卫。

  • 全局守卫:

//全局前置路由守卫---初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to, from, next) => {
  console.log('全局前置路由守卫', to, from);
  if (to.meta.isAuth) { //判断是否鉴权
    if (localStorage.getItem('school') === 'suzhoudaxue') {
      next();
    } else {
      alert('学校名不对,没有权限');
    }
  } else {
    next();
  }
});

//全局后置路由守卫---初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to, from) => {
  console.log('全局后置路由守卫', to, from);
  document.title = to.meta.title || '后台管理系统';
});
  • 独享守卫:
{
    name'news',
    path'news',
    component: News,
    meta: {
        isAuthtrue,
        title'新闻'
    },
    beforeEnter (to, from, next) { //独享守卫
        if (to.meta.isAuth) { //判断是否鉴权
            if (localStorage.getItem('school') === 'suzhoudaxue') {
                next();
            } else {
                alert('学校名不对,没有权限');
            }
        } else {
            next();
        }
    }
},
  • 组件内守卫:
<script>
export default {
  name'About',
  beforeRouteEnter (to, from, next) {//通过路由规则,进入该组件被调用
    console.log('beforeRouteEnter', to, from);
    if (to.meta.isAuth) { //判断是否鉴权
      if (localStorage.getItem('school') === 'suzhoudaxue') {
        next();
      } else {
        alert('学校名不对,没有权限');
      }
    } else {
      next();
    }
  },
  beforeRouteLeave (to, from, next) { //通过路由规则,离开该组件被调用
    console.log('beforeRouteLeave', to, from);
    next();
  }
};
</script>

应用示例

  • 示例:

  • 目录结构:

|-- README.md
|-- babel.config.js
|-- package.json
|-- public
|   |-- css
|   |   `-- bootstrap.css
|   |-- favicon.ico
|   `-- index.html
|-- src
|   |-- App.vue
|   |-- assets
|   |   `-- logo.png
|   |-- components
|   |   `-- Banner.vue
|   |-- main.js
|   |-- pages
|   |   |-- About.vue
|   |   |-- Detail.vue
|   |   |-- Home.vue
|   |   |-- Message.vue
|   |   `-- News.vue
|   `-- router
|       `-- index.js
|-- vue.config.js
`-- yarn.lock
  • main.js
import Vue from 'vue';
import App from './App';
import VueRouter from 'vue-router';
import router from './router';
//关闭生产提示
Vue.config.productionTip = false;
//安装VueRouter
Vue.use(VueRouter);

new Vue({
  el'#app',
  renderh => h(App),
  router
});
  • App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
        <div class="page-header">
          <Banner/>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link :to="{name:'about'}" active-class="active" class="list-group-item">About</router-link>
          <router-link active-class="active" class="list-group-item " to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 指定组件对应的呈现位置  -->
            <router-view></router-view>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Banner from './components/Banner';

export default {
  name'App',
  components: {
    Banner
  }
};
</script>
  • router/index.js
// 该文件专门用来创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import News from '../pages/News';
import Message from '../pages/Message';
import Detail from '@/pages/Detail';
//创建并暴露路由器
const router = new VueRouter({
  routes: [
    {
      name'about',
      path'/about',
      component: About,
      meta: {
        isAuthfalse,
        title'关于'
      }
    },
    {
      name'home',
      path'/home',
      component: Home,
      meta: {
        isAuthfalse,
        title'主页'
      },
      children: [
        {
          name'news',
          path'news',
          component: News,
          meta: {
            isAuthtrue,
            title'新闻'
          },
          /*
          beforeEnter (to, from, next) { //独享守卫
            if (to.meta.isAuth) { //判断是否鉴权
              if (localStorage.getItem('school') === 'suzhoudaxue') {
                next();
              } else {
                alert('学校名不对,没有权限');
              }
            } else {
              next();
            }
          }
          */

        },
        {
          name'message',
          path'message',
          component: Message,
          meta: {
            isAuthtrue,
            title'消息'
          },
          children: [
            {
              name'detail',
              path'detail/:id/:title'//使用占位符声明接收params参数
              component: Detail,
              //props的第一种写法,值为对象,该对象中的key和value都会以props的形式传递给Detail组件
              /* props: {
                 a: 1,
                 b: 2
               }*/

              //props的第二种写法,值为布尔值,如果布尔值为true,就会把路由组件收到的所有params参数,以props的形式传递给Detail组件
              // props: true
              //props的第三种写法:值为函数,
              props ($route) {
                return { id: $route.params.id, title: $route.params.title };
              }
              /*props ({ params: { id, title } }) {
                return { id, title };
              }*/

            }
          ]
        },
      ]
    },
  ]
});

//全局前置路由守卫---初始化的时候被调用、每次路由切换之前被调用
/*
  router.beforeEach((to, from, next) => {
    console.log('全局前置路由守卫', to, from);
    if (to.meta.isAuth) { //判断是否鉴权
      if (localStorage.getItem('school') === 'suzhoudaxue') {
        next();
      } else {
        alert('学校名不对,没有权限');
      }
    } else {
      next();
    }
  });
*/


//全局后置路由守卫---初始化的时候被调用、每次路由切换之后被调用
/*
router.afterEach((to, from) => {
  console.log('全局后置路由守卫', to, from);
  document.title = to.meta.title || '后台管理系统';
});
*/


export default router;
  • components/Banner.vue
<template>
  <div>
    <h2>Vue Router Demo</h2>
    <button @click="back">后退</button>
    &nbsp;
    <button @click="forward">前进</button>
  </div>
</template>

<script>
export default {
  name'Banner',
  methods: {
    forward () {
      this.$router.forward();
    },
    back () {
      this.$router.back();
    }
  }
};
</script>

<style scoped>

</style>
  • pages/About.vue
<template>
  <div>我是About的内容</div>
</template>

<script>
export default {
  name'About',
  beforeRouteEnter (to, from, next) {//通过路由规则,进入该组件被调用
    console.log('beforeRouteEnter', to, from);
    if (to.meta.isAuth) { //判断是否鉴权
      if (localStorage.getItem('school') === 'suzhoudaxue') {
        next();
      } else {
        alert('学校名不对,没有权限');
      }
    } else {
      next();
    }
  },
  beforeRouteLeave (to, from, next) { //通过路由规则,离开该组件被调用
    console.log('beforeRouteLeave', to, from);
    next();
  }
};
</script>

<style scoped>

</style>
  • pages/Home.vue
<template>
  <div>
    <h2>Home组件内容</h2>
    <div>
      <ul class="nav nav-tabs">
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/news">News</router-link>
        </li>
        <li>
          <router-link active-class="active" class="list-group-item" to="/home/message">Message</router-link>
        </li>
      </ul>
      <!--  include里面是组件名   -->
      <keep-alive include="News">
        <router-view></router-view>
      </keep-alive>
    </div>
  </div>
</template>

<script>
export default {
  name'Home'
};
</script>

<style scoped>

</style>
  • pages/News.vue
<template>
  <ul>
    <li :style="{opacity}">欢迎学习Vue</li>
    <li>news001 <input type="text"></li>
    <li>news002 <input type="text"></li>
    <li>news003 <input type="text"></li>
  </ul>
</template>

<script>
export default {
  name'News',
  data () {
    return {
      opacity1
    };
  },
  /*
  mounted () {
    this.timer = setInterval(() => {
      console.log('@');
      this.opacity -= 0.01;
      if (this.opacity <= 0) {
        this.opacity = 1;
      }
    }, 16);
  },
  */

  // beforeDestroy () {
  //   clearInterval(this.timer);
  // }
  activated () {
    console.log('路由组件被激活了');
    this.timer = setInterval(() => {
      console.log('@');
      this.opacity -= 0.01;
      if (this.opacity <= 0) {
        this.opacity = 1;
      }
    }, 16);
  },
  deactivated () {
    console.log('路由组件失活了');
    clearInterval(this.timer);
  }
};
</script>

<style scoped>

</style>
  • pages/Message.vue
<template>
  <div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
        <!-- 跳转路由并携带params参数,to的字符串写法 -->
        <!-- <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{ m.title }}</router-link> -->
        <!-- 跳转路由并携带params参数,to的对象写法 -->
        <router-link :to="{
          name:'detail',
          params:{id:m.id,title:m.title}
        }"
>
{{ m.title }}
        </router-link>
        <button @click="pushShow(m)">push查看</button>
        <button @click="replaceShow(m)">replace查看</button>
      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name'Message',
  data () {
    return {
      messageList: [
        {
          id'001'title'消息001'
        },
        {
          id'002'title'消息002'
        },
        {
          id'003'title'消息003'
        },
      ]
    };
  },
  methods: {
    pushShow (m) {
      this.$router.push({
        name'detail',
        params: { id: m.id, title: m.title }
      });
    },
    replaceShow (m) {
      this.$router.replace({
        name'detail',
        params: { id: m.id, title: m.title }
      });
    }
  }
};
</script>

<style scoped>

</style>
  • pages/Detail.vue
<template>
  <ul>
    <li>消息编号:{{ id }}</li>
    <li>消息标题:{{ title }}</li>
  </ul>
</template>

<script>
export default {
  name'Detail',
  mounted () {
    console.log(this);
  },
  props: ['id''title']
};
</script>

<style scoped>

</style>

history模式和hash模式

  • 对于一个url来说,#及其后面的内容就是hash值。

  • hash值不会包含在http请求中,即:hash值不会带给服务器。

  • hash模式:


    • ① 地址中永远带着#号,不美观。

    • ② 如果以后将地址通过第三方手机app分享,如果app校验严格,则地址会被标记为不合法。

    • ③ 兼容性较好。
  • history模式:


    • ① 地址干净,美观。

    • ② 兼容性和hash模式相比略差。

    • ③ 应用部署上线后需要后端人员支持,解决刷新页面服务器端404的问题。

vue UI组件库

Vue UI组件库介绍

移动端常用UI组件库

  • Vant:https://youzan.Github.io/vant/#/zh-CN/

  • Cube UI:https://didi.github.io/cube-ui/#/zh-CN

  • Mint UI:http://mint-ui.github.io/

PC端常用UI组件库

  • Element UI:https://element.eleme.cn/#/zh-CN

  • IView UI:http://v1.iviewui.com/

Element UI的使用

下载

  • 命令:
yarn add element-ui

完整引入

  • 完整引入:
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(ElementUI)
  • 示例:

  • main.js

import Vue from 'vue';
//引入ElementUI组件库
import ElementUI from 'element-ui';
//引入ElementUI全部样式
import 'element-ui/lib/theme-chalk/index.css';
import App from './App';
//关闭Vue的生产提示
Vue.config.productionTip = false;
//应用ElementUI
Vue.use(ElementUI);

new Vue({
  el'#app',
  renderh => h(App),
});

Element UI的使用

  • 示例:

  • 目录结构:

|-- README.md
|-- babel.config.js
|-- package.json
|-- public
|   |-- favicon.ico
|   `-- index.html
|-- src
|   |-- App.vue
|   |-- assets
|   |   `-- logo.png
|   |-- components
|   `-- main.js
|-- vue.config.js
`-- yarn.lock
  • main.js
import Vue from 'vue';
//引入ElementUI组件库
import ElementUI from 'element-ui';
//引入ElementUI全部样式
import 'element-ui/lib/theme-chalk/index.css';
import App from './App';
//关闭Vue的生产提示
Vue.config.productionTip = false;
//应用ElementUI
Vue.use(ElementUI);

new Vue({
  el'#app',
  renderh => h(App),
});
  • App.vue
<template>
  <div>
    <button>原生的按钮</button>
    <el-row>
      <el-button>默认按钮</el-button>
      <el-button type="primary">主要按钮</el-button>
      <el-button type="success">成功按钮</el-button>
      <el-button type="info">信息按钮</el-button>
      <el-button type="warning">警告按钮</el-button>
      <el-button type="danger">危险按钮</el-button>
    </el-row>
    <el-date-picker
        v-model="value1"
        type="date"
        placeholder="选择日期">

    </el-date-picker>
  </div>
</template>

<script>

export default {
  name'App',
  data() {
    return {
      pickerOptions: {
        disabledDate(time) {
          return time.getTime() > Date.now();
        },
        shortcuts: [{
          text'今天',
          onClick(picker) {
            picker.$emit('pick'new Date());
          }
        }, {
          text'昨天',
          onClick(picker) {
            const date = new Date();
            date.setTime(date.getTime() - 3600 * 1000 * 24);
            picker.$emit('pick', date);
          }
        }, {
          text'一周前',
          onClick(picker) {
            const date = new Date();
            date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
            picker.$emit('pick', date);
          }
        }]
      },
      value1'',
    };
  }
};
</script>

按需引入

  • 下载:
yarn add babel-plugin-component --dev
yarn add babel-preset-es2015 --dev
yarn add @babel/preset-env --dev
  • babel.config.js
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset',
    ['@babel/preset-env', { 'modules'false }]
  ],
  plugins: [
    [
      'component',
      {
        'libraryName''element-ui',
        'styleLibraryName''theme-chalk'
      }
    ]
  ]
};
  • main.js
import Vue from 'vue';
//按需引入
import { Button, DatePicker, Row } from 'element-ui';

import App from './App';

//关闭Vue的生产提示
Vue.config.productionTip = false;

Vue.component(Button.name, Button);
Vue.component(Row.name, Row);
Vue.component(DatePicker.name, DatePicker);

new Vue({
  el'#app',
  renderh => h(App),
});
  • 示例:

  • 目录结构:

|-- README.md
|-- babel.config.js
|-- package.json
|-- public
|   |-- favicon.ico
|   `-- index.html
|-- src
|   |-- App.vue
|   |-- assets
|   |   `-- logo.png
|   `-- main.js
|-- vue.config.js
`-- yarn.lock
  • babel.config.js
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset',
    ['@babel/preset-env', { 'modules'false }]
  ],
  plugins: [
    [
      'component',
      {
        'libraryName''element-ui',
        'styleLibraryName''theme-chalk'
      }
    ]
  ]
};
  • main.js
import Vue from 'vue';
//按需引入
import { Button, DatePicker, Row } from 'element-ui';

import App from './App';

//关闭Vue的生产提示
Vue.config.productionTip = false;

Vue.component(Button.name, Button);
Vue.component(Row.name, Row);
Vue.component(DatePicker.name, DatePicker);

new Vue({
  el'#app',
  renderh => h(App),
});
  • App.vue
<template>
  <div>
    <button>原生的按钮</button>
    <el-row>
      <el-button>默认按钮</el-button>
      <el-button type="primary">主要按钮</el-button>
      <el-button type="success">成功按钮</el-button>
      <el-button type="info">信息按钮</el-button>
      <el-button type="warning">警告按钮</el-button>
      <el-button type="danger">危险按钮</el-button>
    </el-row>
    <el-date-picker
        v-model="value1"
        type="date"
        placeholder="选择日期">

    </el-date-picker>
  </div>
</template>

<script>

export default {
  name'App',
  data() {
    return {
      pickerOptions: {
        disabledDate(time) {
          return time.getTime() > Date.now();
        },
        shortcuts: [{
          text'今天',
          onClick(picker) {
            picker.$emit('pick'new Date());
          }
        }, {
          text'昨天',
          onClick(picker) {
            const date = new Date();
            date.setTime(date.getTime() - 3600 * 1000 * 24);
            picker.$emit('pick', date);
          }
        }, {
          text'一周前',
          onClick(picker) {
            const date = new Date();
            date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
            picker.$emit('pick', date);
          }
        }]
      },
      value1'',
    };
  }
};
</script>


原文始发于微信公众号(程序员阿晶):Vue高级部分(二)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/19852.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!