前端路由原理与使用

时间:2022-02-19 01:23:20

1.前端路由原理

通过window.onhashchange事件监听路由链接(也就是锚点链接)改变地址栏hash值的变化而改变动态组件is属性在data数据源里面的值。

通俗的说当我们点击锚点链接会改变地址栏hash值,则window.onhashchange会监听到这个值的变化,从而改变对动态组件is属性绑定的值进行更改从而切换不同的组件

<template>
  <div id="app2">
    <h3>App根组件(基于前端路由切换动态组件)</h3>
    //锚点链接改变地址栏hash值
    <a href="#home2">首页</a>
    <a href="#main2">内容区</a>
    <a href="#bottom2">底部</a>
    //动态组件,is属性默认呈现home2组件
    <component :is="comName"></component>
  </div>
</template>

<script>
//导入需要的组件
import Home2 from "./components/Home2.vue";
import Main2 from "./components/Main2.vue";
import Bottom2 from "./components/Bottom2.vue";
export default {
  data() {
    return {
      comName: "Home2",
    };
  },
  components: {
    Home2,
    Main2,
    Bottom2,
  },
  // 通过created生命周期函数监听地址栏hash值变化
  created() {
    window.onhashchange = () => {
      //通过地址栏对应的hash值展现对应的组件
      switch (location.hash) {
        case "#home2":
          this.comName = "Home2";
          break;
        case "#main2":
          this.comName = "Main2";
          break;
        case "#bottom2":
          this.comName = "Bottom2";
          break;
      }
    };
  },
};
</script>

<style scoped>
#app2 {
  min-height: 600px;
  border: 1px solid #ccc;
  margin: auto;
}
a {
  display: inline-block;
  min-width: 30px;
  min-height: 20px;
  margin: 0 10px;
  text-align: center;
  text-decoration: none;
  color: skyblue;
}
</style>

2.前端路由使用

1.下载vue-router(vue-router是vue官方为我们提供的前端路由解决方案,我们只需要指定路由链接即可)

npm i vue-router -S

2.在src->router->index.js下创建路由模块并指定路由链接

//src->router->index.js

//导入vue与vue-router
import Vue from 'vue'
import VueRouter from 'vue-router'
//导入需要的组件
import Home from '../components/Home.vue'
import Main from '../components/Main.vue'
import Bottom from '../components/Bottom.vue'
//将vue-router插件挂载到Vue上
Vue.use(VueRouter)
//创建vue-router实例
const router = new VueRouter({
  //routes是一个数组,里面存放路由链接与组件的对应关系
  routes: [
    //path表示hash值,component表示对应的组件
    { path: '/home', component: Home },
    { path: '/main', component: Main },
    { path: '/bottom', component: Bottom },
    //路由重定向
    { path: '/', component: Home },
    //默认路由(作用与路由重定向相同)
    { path: '', component: Home }
  ]
})
//暴露vue-router实例
export default router

3.在main.js导入并挂载路由模块

//--->main.js

import Vue from 'vue'
import App from './App.vue'
// 导入路由模块
import router from './router/index.js'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  // 挂载路由模块 router:router实例对象
  router:router
}).$mount('#app')

4.在根组件中放入 <router-link to='home'></router-link>(相当于原理中的a链接,但是相对于a链接不需要代#号)与<router-view></router-view>占位符标签(相当于原理中的component)

//--->App.vue

<template>
  <div id="app">
    <h3>vue-router</h3>
    <hr />
    <router-link to="/home">首页</router-link>
    <router-link to="/main">内容</router-link>
    <router-link to="/bottom">底部</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
export default {};
</script>

<style scoped>
#app {
  min-height: 600px;
  border: 1px solid #ccc;
}
</style>

 3.嵌套路由

续写上一个例子,在main组件中增加电影与游戏组件

//--->Main.vue
<template>
  <div id="main">
    <h3>内容</h3>
    <!-- 路由链接 -->
    <router-link to="/main/mov">电影</router-link>
    <router-link to="/main/tig">游戏</router-link>
    <!-- 占位符 -->
    <router-view></router-view>
  </div>
</template>

<script>
export default {};
</script>

<style scoped>
#main {
  min-height: 300px;
  background-color: pink;
}
</style>

在index.js增加路由链接

//--->index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../components/Home.vue'
import Main from '../components/Main.vue'
import Bottom from '../components/Bottom.vue'
import Mov from '../components/Mov.vue'
import Tig from '../components/Tig.vue'

Vue.use(VueRouter)
const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    {
      path: '/main',
      component: Main,
      //在父组件对应的路由链接增加children属性进行路由嵌套
      children: [
        //子组件路由链接,不要加/ 例如/mov
        { path: 'mov', component: Mov },
        { path: 'tig', component: Tig },
        //默认路由
        { path: '', component: Mov }
        //路由重定向
        // { path: '/main', redirect: '/main/mov' }
      ]
    },
    { path: '/bottom', component: Bottom },
    // { path: '/', redirect: '/home' },
    { path: '', component: Home },
  ]
})
export default router

4.动态路由

他算是前端路由的一个优化,不仅可以提高路由规则的复用,还可以提高组件的复用,就好比之前的五个路由对应五个组件,动态路由只需要一条路由规则和一个组件就可以完成,即在一个组件内完成不同内容的展现

续写上一个例子,在Mov组件中增加两条路由链接,但是他们都对应一个Movs组件

//--->Mov.vue
<template>
  <div id="mov">
    <h3>电影</h3>
    <router-link to="/main/mov/1s">熊出没</router-link>
    <router-link to="/main/mov/2s">喜羊羊与灰太狼</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
export default {};
</script>

<style scoped>
#mov {
  min-height: 200px;
  background-color: gray;
  margin: 10px;
}
</style>


//--->index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../components/Home.vue'
import Main from '../components/Main.vue'
import Bottom from '../components/Bottom.vue'
import Mov from '../components/Mov.vue'
import Tig from '../components/Tig.vue'
import Movs from '../components/Movs.vue'
Vue.use(VueRouter)
const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    {
      path: '/main',
      component: Main,
      //在父组件对应的路由链接增加children属性进行路由嵌套
      children: [
        //子组件路由链接,不要加/ 例如/mov
        {
          path: 'mov',
          component: Mov,
          children: [
            {
              //使用英文的(:)来定义路由的参数项
              path: ':id',
              component: Movs,
              //开启props传参,就可以在对应的组件中拿到这个参数项
              props: true
            },
          ]
        },
        { path: 'tig', component: Tig },
        //默认路由
        { path: '', component: Mov }
        //路由重定向
        // { path: '/main', redirect: '/main/mov' }
      ]
    },
    { path: '/bottom', component: Bottom },
    // { path: '/', redirect: '/home' },
    { path: '', component: Home },
  ]
})
export default router

接下来就可以在对应的组件中拿到这个传过来的参数项

<template>
  <div id="movs">
    //1.通过this.$route.params.id获取不同链接后面的参数项(:id)
    <p>电影{{ this.$route.params.id }}--{{ id }}</p>
    <button @click="show">打印</button>
  </div>
</template>

<script>
export default {
  //2.为路由规则添加props:true就可以在组件中访问自定义属性props获取这个参数项
  props: ["id"],
  methods: {
    show() {
      console.log(this);
      // console.log(this.id);
    },
  },
};
</script>

<style scoped>
#movs {
  min-height: 100px;
  background-color: yellow;
  border: 1px solid black;
  margin: 10px;
}
</style>