目录插件编写的基本方法需求分析我们先看看Vue-router的使用步骤由此我们看看vue-router内部做了什么?实现思路首先我们看看如何将$router挂载到组件上如何实现那
推荐大家先看看官方给出的插件使用和开发方法
https://vuejs.bootCSS.com/guide/plugins.html
1.use
Vue.use(VueRouter)
注意⚠️:
Vue.use()
主要是调用插件内部的install方法,并将Vue实例作为参数传入
2.new 一个router实例
const router = new VueRouter({
// 实例化router传入的参数
mode: 'history',
base: process.env.BASE_URL,
routes
})
3.new Vue() ,把实例放在vue的配置项里面
new Vue({
router, // 注意router的实例也往里传
render: h => h(App)
}).$mount('#app')
4.使用路由组件<router-view/>
、<router-link></router-link>
或者在组件中使用this.$router
将$router挂载到全局上实现并声明了两个组件:<router-view/>
、<router-link></router-link>
let Vue; // 保存vue的构造函数,避免打包将其打进去
VueRouter.install = function (_Vue) {
Vue = _Vue;
console.log("options", Vue.$options);
Vue.mixin({
beforeCreate() {
console.log("inner", this);
console.log(" this.$options.router", this.$options.router);
if (this.$options.router) {
Vue.prototype.$router = this.$options.router;
}
},
});
console.log("end");
};
可以看到:
1、第一次执行的时候,即在Vue.use(Router)时,还没有实例化vue(因为Vue.use()
发生在 new Vue()
之前),所以Vue.$option本身是拿不到的(ps: option就是new Vue()
时传入的参数,router也往里面传),此时既然拿不到router的实例,所以不能直接在install方法里面挂载;
2、我们可以在use的时候做一个全局混入,在合适的时间点,获取到Vue根实例配置项中的router实例, 执行挂载。紧接着在new Vue()根实例创建的时候,因为注入了router实例,所以再执行全局混入(mixin)中的生命周期时,这个时候根实例的配置项this.$options
已经包含了router实例,可以此时把router挂载到Vue的原型上。之后所有Vue实例扩展来的VueCompont都可以通过this.$router
访问到这个属性
先看看路由组件如何使用
<div id="app">
<div id="nav">
<!-- a标签控制跳转 -->
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<!-- 路由出口 -->
<router-view />
</div>
由上面可以看出,点击router-link
,就相当于点了a标签,然后a标签的href属性控制页面路由发生了变化;监听路由变化,然后仔router-view里面输出不同的模板;
class VueRouter {
constructor(options) {
// 接受传入的参数
this.$options = options;
const initial = "/";
// 将current变成响应式数据,
//这样在hashchange的回掉中修改curent时,
//用到current的router-view的render函数就会重新渲染
Vue.util.defineReactive(this, "current", initial);
// 监听路由变化
window.addEventListener("hashchange", () => {
// 获取当前url中的hash
this.current = window.location.hash.slice(1);
});
}
}
VueRouter.install = function (_Vue) {
Vue = _Vue;
Vue.component("router-view", {
render(h) {
// 获取当前路由所对应的组件,然后把它渲染出来
const { current, $options } = this.$router;
// 这里要注意 我们传进来的routes是一个路由表,如下图一
// 所以这里我们是找出匹配到当前current路由的项,然后直接渲染组件
const route = $options.routes.find((item) => {
return item.path === current;
});
let component = route ? route.component : null;
return h(component);
},
});
}
再来看看router-view
class VueRouter {
constructor(options) {
// 接受传入的参数
this.$options = options;
const initial = "/";
// 将current变成响应式数据,
//这样在hashchange的回掉中修改curent时,
//用到current的router-view的render函数就会重新渲染
Vue.util.defineReactive(this, "current", initial);
// 监听路由变化
window.addEventListener("hashchange", () => {
// 获取当前url中的hash
this.current = window.location.hash.slice(1);
});
}
}
VueRouter.install = function (_Vue) {
Vue = _Vue;
Vue.component("router-view", {
render(h) {
// 获取当前路由所对应的组件,然后把它渲染出来
const { current, $options } = this.$router;
// 这里要注意 我们传进来的routes是一个路由表,如下图一
// 所以这里我们是找出匹配到当前current路由的项,然后直接渲染组件
const route = $options.routes.find((item) => {
return item.path === current;
});
let component = route ? route.component : null;
return h(component);
},
});
}
图一
// 我们要实现什么
// 1、插件
// 2、两个组件
// 保存vue的构造函数,避免打包将其打进去
let Vue;
class VueRouter {
constructor(options) {
this.$options = options;
const initial = "/";
Vue.util.defineReactive(this, "current", initial);
this.current = "/";
window.addEventListener("hashchange", () => {
// 获取当前url中的hash
this.current = window.location.hash.slice(1);
});
}
}
// 参数1在Vue.use()调用时传进来,
VueRouter.install = function (_Vue) {
Vue = _Vue;
console.log("options", this);
// 全局混入
// 目的:延迟下面的逻辑 到 router创建完毕并且附加到选项上时才执行
Vue.mixin({
// 在每个组件创建实例时都会执行
beforeCreate() {
// this.$options.router ;即new Vue时放进去的router实例
if (this.$options.router) {
Vue.prototype.$router = this.$options.router;
}
},
});
// 注册并且实现两个组件
Vue.component("router-link", {
props: {
to: {
required: true,
},
},
render(h) {
return h(
"a",
{
attrs: { href: "#" + this.to },
},
this.$slots.default
);
},
});
Vue.component("router-view", {
render(h) {
// 获取当前路由所对应的组件,然后把它渲染出来
const { current, $options } = this.$router;
const route = $options.routes.find((item) => {
return item.path === current;
});
let component = route ? route.component : null;
return h(component);
},
});
};
export default VueRouter;
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!
--结束END--
本文标题: 深入了解vue-router原理并实现一个小demo
本文链接: https://lsjlt.com/news/141213.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-12
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0