zoukankan      html  css  js  c++  java
  • vue-router简单实现

    1.构造VueRouter类

    constructor(options) {
    	/* 初始化 */
    	this.mode = options.mode || 'hash';
    	this.routes = options.routes || [];
    	/* 转化为{'/home':Home}的形式 */
    	this.routesMap = this.createMap(this.routes);
    	/* 初始化状态 */
    	this.history = new HistoryRoute();
    	/* 初始化路由设置 */
    	this.init();
    }
    

    2.将routes格式[{path:'/home',component:Home}]转化为{'/home':Home}的形式

    createMap(routes) {
    	return routes.reduce((data, item) => {
    		data[item.path] = item.component;
    		return data;
    	}, {});
    }
    

    3.对hash模式和history模式的路径进行赋值,设置监听函数,用this.history.current保存当前path

    init() {
    	if (this.mode === 'hash') {
    		location.hash ? '' : location.hash = '/';
    		// 加载完成事件监听
    		window.addEventListener('load', () => {
    			this.history.current = location.hash.slice(1);
    		})
    		/* 监听hash改变 */
    		window.addEventListener('hashchange', () => {
    			this.history.current = location.hash.slice(1);
    		})
    	} else {
    		location.pathname ? '' : location.pathname = '/';
    		window.addEventListener('load', () => {
    			this.history.current = location.pathname;
    		})
    		/* 前进后退 */
    		window.addEventListener('popstate', () => {
    			this.history.current = location.pathname;
    		})
    	}
    }
    

    4.实现每个子组件this.$routerthis.$route的功能
    (1)mixin的内容所有组件适用,并且不会相互干扰
    (2)找到根组件并设置this._root=this,每次实例化子组件时继承父组件的_root属性,然后通过数据劫持的方式获取到VueRouter实例
    (3)对this._router.history设置响应式,路径改变视图更新

    VueRouter.install = (Vue, opts) => {
    	Vue.mixin({
    		/* 创建实例之前 */
    		beforeCreate() {
    			/* 只有根组件存在router */
    			if (this.$options && this.$options.router) {
    				this._root = this;/* 根组件 */
    				this._router = this.$options.router;/* 路由实例 */
    				/* 监听current */
    				Vue.util.defineReactive(this, 'xxx', this._router.history);
    			} else {
    				this._root = this.$parent._root;/* 传递根组件使每个子组件都可以访问到根组件 */
    			}
    			/* 劫持$router的获取 */
    			Object.defineProperty(this, '$router', {
    				get() {/* 获取根组件,然后取根组件的路由项 */
    					return this._root._router;
    				}
    			})
    			/* 劫持$route的获取 */
    			Object.defineProperty(this, '$route', {
    				get() {//路由状态
    					return this._root._router.history;
    				}
    			})
    		}
    	});
    	//省略...
    }
    

    5.创建router-linkrouter-view
    (1)router-link负责提供触发入口,改变路由状态
    (2)router-view接受响应并放到render函数中进行视图更新

    VueRouter.install = (Vue, opts) => {
    	//省略...
    	Vue.component('router-link', {
    		props: { to: String, tag: String },
    		methods: {
    			handleClick() {//点击router-link
    				let mode = this._self._root._router.mode;//模式
    				if (mode === 'hash') {
    					location.hash = this.to;
    				} else {
    					history.pushState({}, null, this.to);
    				}
    				//改变状态,从而更新router-view更新视图
    				this._self._root._router.history.current = this.to;
    			}
    		},
    		render(h) {
    			let mode = this._self._root._router.mode;
    			let tag = this.tag ? this.tag : 'a';
    			//区别a标签和自定义标签
    			if (tag === 'a') return <a href={mode === 'hash' ? `#${this.to}` : this.to}>{this.$slots.default}</a>;
    			else return <tag onclick={this.handleClick}>{this.$slots.default}</tag>
    		}
    	});
    	Vue.component('router-view', {
    		render(h) {
    			/* current加载前获取,需要在beforCreated中设置成响应式对象*/
    			let current = this._self._root._router.history.current;/* /home */
    			let routesMap = this._self._root._router.routesMap;
    			return h(routesMap[current]);//渲染得到的组件
    		}
    	})
    
    }
    

    源码:https://gitee.com/aeipyuan/vue_router.git

  • 相关阅读:
    SQLServer XML
    批量数据入库
    iBatis --> MyBatis
    一句话,一段文
    一首诗,一阕词
    Web Service
    一天一首现代诗
    一天一首歌
    DB2
    Kafka
  • 原文地址:https://www.cnblogs.com/aeipyuan/p/12726197.html
Copyright © 2011-2022 走看看