Vue-router原理:5、initComponents方法实现

Vue-router原理:5、initComponents方法实现

initComponents方法,主要作用是用来创建router-linkrouter-view这两个组件的。

下面先在这个方法中创建router-link这个组件。

先来看一下router-link这个组件的基本使用

<router-link to="/users"> 用户管理</router-link>

我们知道,router-link这个组件最终会被渲染成a标签,同时to作为一个属性,其值会作为a标签中的href属性的值。同时还要获取<router-link>这个组件中的文本,作为最终超链接的文本。

 initComponents(Vue) {
    Vue.component("router-link", {
      props: {
        to: String,
      },
      template: '<a :href="to"><slot></slot></a>',
    });
  }

在上面的代码中,我们通过Vue.component来创建router-link这个组件,同时通过props接收to属性传递过来的值,并且对应的类型为字符串。

最终渲染的模板是一个a标签,href属性绑定了to属性的值,同时使用<slot>插槽作为占位符,用具体的文字内容填充该占位符。

现在已经将router-link这个组件创建好了。

下面我们需要对我们写的这些代码进行测试。

要进行测试应该先将createRouteMap方法与initComponents方法都调用一次,那么问题是

在什么时候调用这两个方法呢?

我们可以在VueRoute对象创建成功后,并且将VueRouter对象注册到Vue的实例上的时候,调用这两个方法。

也就是在beforeCreate这个钩子函数中。

当然为了调用这两个方便,在这里我们又定义了init方法,来做了一次封装处理。

  init() {
    this.createRouteMap();
    this.initComponents(_Vue);
  }

init方法的调用如下:

   beforeCreate() {
        //在创建Vue实例的时候
        // 也就是new Vue()的时候,才会有$options这个属性,
        //组件中是没有$options这个属性的。
        if (this.$options.router) {
          _Vue.prototype.$router = this.$options.router;
            //调用init
          this.$options.router.init();
        }
      },

this.$options.router.init();
这句代码的含义:this表示的就是Vue实例,$options表示的就是在创建Vue的实例的时候传递的选项,如下所示:

  const vm = new Vue({
        el: "#app",
        router,
      });

通过上面的代码,我们可以看到,传递过来的选项中是有router.

而这个router是什么呢?

 const router = new VueRouter({}

就是VueRouter这个类的实例。而我们当前自己所模拟的路由,所创建的类就叫做VueRouter(也就是以后在创建路由实例的时候,使用我们自己创建的VueRouter这个类来完成).

init方法就是VueRouter这个类的实例方法。所以可以通过this.$options.router.init()的方式来调用。

下面我们来测试一下。

vue_router_app项目的src目录下面,创建router.js文件,文件定义路由规则.

如下代码所示:

import Vue from "vue";
// import Router from "vue-router";
import Router from "./vuerouter";//注意:这里导入的是自己定义的路由规则
import Login from "./components/Login.vue";
import Home from "./components/Home.vue";
Vue.use(Router);
export default new Router({
  model: "history",
  routes: [
    { path: "/", component: Home },
    { path: "/login", component: Login },
  ],
});

components目录下面分别创建Home.vueLogin.vue.

Home.vue 的代码如下:

<template>
  <router-link to="/login">登录</router-link>
</template>

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

<style></style>

Login.vue的代码如下

<template>
  <div>
    登录页面
  </div>
</template>

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

App.vue组件的内容如下:

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link>
      <router-link to="/login">Login</router-link>
    </div>
    <router-view></router-view>
  </div>
</template>

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

main.js 中完成路由的注册。

import Vue from "vue";
import App from "./App.vue";
//导入router.js
import router from "./router";
Vue.config.productionTip = false;

new Vue({
  router,
  render: (h) => h(App),
}).$mount("#app");

运行上面的代码会出现如下的错误:
在这里插入图片描述
第二个错误是我们还没有创建router-view这个组件,所以才会出现该错误。这里暂时可以先不用考虑。

主要是第一个错误,该错误的含义是,目前我们使用的是运行时版本的Vue, 模板编译器不可用。

你可以使用预编译把模板编译成render函数,或者是使用包含编译版本的Vue.

以上错误说明了Vue的构建版本有两个,分别是“运行时版”和"完整版".

运行时版:不支持template模板,需要打包的时候提前编译。

完整版:包含运行时和编译器,体积比运行时版大10k左右,程序运行的时候把模板转换成render函数。性能低于运行时版本。

使用vue-cli创建的项目默认为运行时版本,而我们创建的VueRouter类中有template模板,所以才会出现第一个错误。

官方文档:https://cn.vuejs.org/v2/guide/installation.html

下面我们看一下解决方案:

在前面我们已经提到过,使用vue-cli 创建的项目是运行时项目,所以没有编译器,如果我们将其修改成完整版,就有编译器,对模板进行编译。

解决的方案:在项目的根目录创建vue.config.js文件,在该文件中添加runtimeCompiler配置项,该配置项表示的是,是否使用包含运行时编译器的Vue构建

版本(完整版)。设置为true后你就可以在Vue组件中使用template选项了,但是这会让你的应用额外增加10kb左右。默认该选项的取值为false.

vue.config.js文件配置如下

module.exports = {
  runtimeCompiler: true,
};

表示使用的是完整版,这时编译器会将template选项转换成render函数。

注意:要想以上配置内容起作用,必须重新启动服务器。

npm run serve
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值