手写vue-router
1、编写路由类 my-router.js
let Vue;
class MyRouter{
constructor($options){
// $options为 { routes = [ { path: '/', '路由': Index, name: '首页' }] }
this.$options = $options
// 定义响应式的属性current
const initial = window.location.hash.slice(1) || '/'
Vue.util.defineReactive(this, 'current', initial)
// 监听hashchange事件
window.addEventListener('hashchange', this.onHashChange.bind(this))
// 路由表:缓存path和route映射关系
this.routeMap = {}
// 每个路由地址都对应自己的route
this.$options.routes.forEach(route => {
// '/': { path: '/', '路由': Index, name: '首页' }
this.routeMap[route.path] = route
});
}
onHashChange() {
// 当前hash去掉#
this.current = window.location.hash.slice(1)
}
}
// 定义插件
MyRouter.install = function(vue){
// 保存vue供上面响应式设置
Vue = vue
vue.mixin({
// 每个实例都会调用beforeCreate
beforeCreate(){
// 判断,拿到main.js中new vue()传递的router对象
if(this.$options.router){
vue.prototype.$router = this.$options.router
}
}
})
// 全局组件注册
Vue.component('router-link', {
props: {
to: {
type: String,
required: true
}
},
// runtime-only不带编译器,预编译,打包的时候编译。这里不能用template
// render函数只要用到响应式数据就会被依赖收集起来,等待重新调用
render(h){
return h(
'a',
{ attrs: { href: `#${this.to}` }, style: { display:'inline-block',padding:'0 10px' } },
[this.$slots.default]
)
}
})
// current发生改变render函数重新渲染,实现了组件切换
Vue.component('router-view', {
render(h) {
// 从router对象中拿到当前路由和路由表
// 如果当前路由有children,即路由有router-view,
// router-view会从current匹配当前路由,当前路由又是原来那个路由,无限循环
// 比如:/about有router-view,about要渲染router-view,后面router-view又要渲染about
const { routeMap, current } = this.$router
// 拿到当前路由对应的组件
const component = routeMap[current].component;
return h(component);
}
})
}
export default MyRouter2、router/index.js引入路由,传递路由数组
import MyRouter from './my-router'
import vue from 'vue'
import About from '@/components/about'
import Index from '@/components/index'
vue.use(MyRouter)
const routes = [
{
path: '/',
component : Index,
name: '首页'
},
{
path: '/about',
component: About,
name: '关于'
}
]
const router = new MyRouter({ routes })
export default routermain.js挂载路由实例

使用自定义路由
1、编写组件app.vue

2、index.vue
<template>
<div>index</div>
</template>
<script>
</script>
<style>
</style>3、about.vue
<template>
<div>
<div>about</div>
</div>
</template>
<script>
</script>
<style>
</style>效果

about路由加入children
- 正如上面所提到的如果当前路由有children,即路由有router-view,router-view会从current匹配当前路由,当前路由又是原来那个路由,无限循环
- 比如:/about有router-view,about要渲染router-view,后面router-view
info组件和上面about组件一样简单用div显示:info

更新my-router.js
let Vue;
class MyRouter{
constructor($options){
// $options为 { routes = [ { path: '/', '路由': Index, name: '首页' }] }
this.$options = $options
// 初始化当前页面hash
this.current = window.location.hash.slice(1) || '/'
// 定义响应式的属性matched,所有使用到matched的页面都会收集依赖,matched更新,页面更新
Vue.util.defineReactive(this, 'matched', [])
this.match()
// 监听hashchange事件
window.addEventListener('hashchange', this.onHashChange.bind(this))
}
onHashChange() {
// 当前hash去掉#
this.current = window.location.hash.slice(1)
// 页面跳转重新获取匹配路由数组
this.matched = []
this.match()
}
match(routes){
routes = routes || this.$options.routes
// 递归遍历
for(const route of routes){
if(route.path === '/' && this.current === '/'){
this.matched.push(route)
return
}
// /about/info
if(route.path !== '/' && this.current.indexOf(route.path) !== -1){
this.matched.push(route)
if(route.children){
this.match(route.children)
}
return
}
}
}
}
// 定义插件
MyRouter.install = function(vue){
// 保存vue供上面响应式设置
Vue = vue
vue.mixin({
// 每个实例都会调用beforeCreate
beforeCreate(){
// 判断,拿到main.js中new vue()传递的router对象
if(this.$options.router){
vue.prototype.$router = this.$options.router
}
}
})
// 全局组件注册
Vue.component('router-link', {
props: {
to: {
type: String,
required: true
}
},
// runtime-only不带编译器,预编译,打包的时候编译。这里不能用template
// render函数只要用到响应式数据就会被依赖收集起来,等待重新调用
render(h){
return h(
'a',
{ attrs: { href: `#${this.to}` }, style: { display:'inline-block',padding:'0 10px' } },
[this.$slots.default]
)
}
})
// current发生改变render函数重新渲染,实现了组件切换
Vue.component('router-view', {
render(h) {
// 当前是个router-view
this.$vnode.data.routerView = true
// 标记当前router-view深度
let depth = 0;
let parent = this.$parent
while(parent){
const vnodeData = parent.$vnode && parent.$vnode.data
if(vnodeData){
if(vnodeData.routerView){
// 说明当前parent是一个router-view
// 有多少父router-view,自己深度+多少
depth++
}
}
parent = parent.$parent
}
// 获取path对应的component
let component = null;
const route = this.$router.matched[depth]
if(route){
component = route.component
}
return h(component)
}
})
}
export default MyRouter测试没毛病了

Ценники на вывоз мусора сейчас космос, любые лайфхаки по экономии в тему.
1xbet onlayn kazino platforması ilə vaxtınızı daha səmərəli və maraqlı keçirin. Saytın canlı kazino bölməsi istifadəçilərə fərqli bir dünya təklif edir. Burada canlı dilerli kazino oyunlarının hər bir növünü sınaqdan keçirə bilərsiniz. Krupyelərin peşəkarlığı oyunun dinamikasını və marağını artırır. Müntəzəm olaraq yenilənən oyun siyahısı cansıxıcılığa yol vermir. Hesabınızı artırmaq üçün onlarla fərqli və etibarlı üsul mövcuddur. Qazanılan pullar cəmi bir neçə dəqiqə ərzində şəxsi hesabınıza köçürülür. Aktiv fəaliyyətinizə görə fərdi bonuslar və hədiyyələr qazana bilərsiniz. Dəstək xidməti həm çat, həm də e-poçt vasitəsilə kömək göstərir. 1xbet ailəsinə qoşulun və böyük uduşlar üçün ilk addımı atın. onlayn kazino
我一直梦想, 看到你们相册那样的地方。真棒。
我喜欢, 这里分享真实经验。你的项目 就是 属于这里的。请继续。
我热爱这样的想法, 去那么多国家。真的很鼓舞。
能感受到热爱。继续保持 感受。
我关注这样的资源, 写得很实在。你的网站 就是 属于这里的。加油。
1
1
1