Vue-router原理:5、initComponents方法实现
initComponents方法,主要作用是用来创建router-link和router-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.vue与Login.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

156

被折叠的 条评论
为什么被折叠?



