1. 犀牛前端部落首页
  2. vue-router

vue-router实现原理(一)创建自定义vue.js router

vue-router实现原理(一)创建自定义vue.js router

也许你已经在项目中使用vue-router一段时间了,但是…你自己写过吗?你知道路由器的基本原理吗?它看起来似乎只是工作,但实际上路由器必须处理几件事。

路由是负责路由的组件。我们可以将路由定义为寻找到多个目的地的路径的动作。这适用于不同的领域。

举个例子:那么你按下5的时候,电梯的路由就会把你带到5楼。

在web开发中,路由的应用有两个主要领域:

  • 后端:路由器调用正确的控制器,匹配url模式。
  • 前端:路由器将相应的组件加载到视图中,匹配url模式。

在本系列中,我们将研究如何使用Vue创建自己的前端路由器。为了理解路由器的机制。

创建一个基础的路由组件

首先创建用于路由的Home和Articles组件。

内容并不重要,因为这仅仅是为了显示路由上的一些东西,像下面这样就足够了:

<!-- Home.vue -->
<template>
  <div>Home</div>
</template>

<!-- Articles.vue -->
<template>
  <div>Articles</div>
</template>

由于vuei .js是一个基于组件的框架,创建路由器的简单方法就是使用组件。

这种方式更通用,因为任何前端开发人员工作过任何基于组件的工具都会理解它。

定义routes(路线)

让我们从创建一个AppRouter.vue文件开始,它将是路由器组件本身,包含路由的定义:

<!-- Router.vue -->
<script>
import HomePage from "./HomePage";
import ArticlesPage from "./ArticlesPage";

const routes = {
  "/": HomePage,
  "/articles": ArticlesPage
};
</script>

我导入了HomePageArticlesPage组件,并创建了route对象,其键是路由路径,值是组件本身。用这种方式访问路由既简单又快速,因为访问对象属性是直接操作,只需执行route[“/”]。

如果你需要更多的自定义,其他方式来定义他们将使用一个对象作为值:

const routes = {
  "/": {
    component: HomePage,
    default: true, //默认路由
    name: "root"
  }
}

也可以使用数组来实现,就像vue-router所做的那样。数组解决方案更灵活,但更复杂,因为你将需要循环通过:

const routes = [
  {
    path: "/"
    component: HomePage
  }
}

// A simple way to get the component is using ES2015 array find method
const route = routes.find(route => route.path === "/");

渲染路由组件

一旦我们设置好了路由,我们需要一种方法来呈现给定条件的组件。vue为我们提供了动态组件,非常适合我们的案例。

通过使用特殊的<component>元素,通过使用is属性作为条件,动态组件允许我们轻松地在组件之间进行热交换:

<template>
  <component :is="routedComponent"></component>
</template>

然后我们需要实现这个条件。由于这个条件会随着路由的不同而改变,所以计算出的属性非常适合这个目的:

export default {
  data() {
    return { current: window.location.pathname };
  },
  computed: {
    routedComponent() {
      return routes[this.current];
    }
  }
};

计算属性是一个为默认路由(不匹配任何路由)返回组件的好地方,这就像使用OR操作符一样简单:

routedComponent() {
  return routes[this.current] || DefaultComponent;
}

最后我们的Router.vue组件是这样的:

<!-- Router.vue -->
<template>
  <component :is="routedComponent"></component>
</template>

<script>
import HomePage from "./HomePage";
import ArticlesPage from "./ArticlesPage";

const routes = {
  "/": HomePage,
  "/articles": ArticlesPage
};

export default {
  data() {
    return { current: window.location.pathname };
  },
  computed: {
    routedComponent() {
      return routes[this.current];
    }
  }
};
</script>

作为一种替代解决方案,render函数(或JSX)非常适合这种情况,因为使用render函数的呈现在默认情况下是动态的。所以你可以重写组件在Router.js文件:

// Router.js
import HomePage from "./HomePage";
import ArticlesPage from "./ArticlesPage";

const routes = {
  "/": HomePage,
  "/articles": ArticlesPage
};

export default {
  data() {
    return { current: window.location.pathname };
  },
  computed: {
    routedComponent() {
      return routes[this.current];
    }
  },
  render(createElement) {
    return createElement(this.routedComponent);
  }
};

使用Router组件

让我们创建一个App.vue组件作为应用程序的根组件。然后导入并注册路由器组件:

<!-- App.vue -->
<template>
  <div>
    <app-router></app-router>
  </div>
</template>

<script>
import AppRouter from "./AppRouter";

export default {
  components: {
    AppRouter
  }
};
</script>

在模板中,我们放置 <app-router> 标签,它将被路由器呈现的组件替换。在脚本部分,路由器被导入并添加到App组件中。

如果你运行应用程序,通过在浏览器的工具栏中编写路由来导航/和/articles,你应该会看到路由器加载相应的组件及其内容。

为了更加方便,让我们在App.vue中添加几个按钮和一个在路由之间导航的方法:

<!-- App.vue -->
<template>
  <div>
    <button @click="goTo('/articles')">Go to Articles</button>
    <button @click="goTo('/')">Go to Home</button>
    <app-router></app-router>
  </div>
</template>

<script>
import AppRouter from "./AppRouter";

export default {
  components: {
    AppRouter
  },
  methods: {
    goTo(route) {
      window.location = route;
    }
  }
};
</script>

原创文章,作者:犀牛前端部落,如若转载,请注明出处:https://www.pipipi.net/3430.html

发表评论

登录后才能评论