zoukankan      html  css  js  c++  java
  • vue-router 运行机制 及 底层原理

    1.测试页面

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Document</title>
    	<style>
    		.router-link-active{color: red;}
    	</style>
    </head>
    <body>
    	<!--
    		路由:异步加载
    	-->
    	<!--VueJs核心库-->
    	<script src="vue.js"></script>
    	<!--Router-->
    	<script src="vue-router.js"></script>
    
    	<div id="app">
    		<h1>Hello App</h1>
    		<!--router-link被渲染成a标签,为什么直接用a标签而用router-link?-->
    		<router-link to="/index">Go to Index</router-link>
    		<router-link to="/subpage">Go to SubPage</router-link>
    		<!--渲染位置-->
    		<router-view></router-view>
    	</div>
    
    	<script>
    		//VueJS的router-link,在没有使用之前,不会对任何Tag(标签)起到任何作用
    		//const和var一样都是声明变量的,ES6语法,const(声明常量)
    		//两套模板 
    		const Foo = {template:'<div>Index</div>'}
    		const Bar = {template:'<div>SubPage</div>'}
    
    		const routes = [ // 配置
    			//{路由名称:名字和路径,模板:模板的变量}
    			{path:'/index',component:Foo},
    			{path:'/subpage',component:Bar}
    		]
    
    		const router = new VueRouter({ // 得到VueRouter的实例
    			routes
    		});
    
    		// new Vue({
    		// 	el:"#app", // 指定渲染位置
    		// 	data:{ // 数据
    		// 		message:'Hello App'
    		// 	}
    		// });
    
    		const app = new Vue({ //在一个地方传入的是一个对象,需要一对大括号
    			router
    		}).$mount('#app'); //指定位置
    	</script>
    </body>
    </html>

    index2.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Document</title>
    	<style>
    		.router-link-active{color: red;}
    	</style>
    </head>
    <body>
    	<div id="app">
    		<div>
    			<router-link to="/user/foo">/user/foo</router-link>
    		</div>
    		<div>
    			<router-link to="/user/bar">/user/bar</router-link>
    		</div>
    		<div>
    			<router-view></router-view>
    		</div>
    	</div>
    
    	<!--VueJs核心库-->
    	<script src="vue.js"></script>
    	<!--Router-->
    	<script src="vue-router.js"></script>
    	
    	<!--配置动态路由-->
    	<script>
    		const User = {
    			template:`<div>User:{{$route.params.id}}</div>`
    		}
    
    		const router = new VueRouter({
    			routes:[
    				{path:'/user/:id',component:User}
    			]
    		});
    
    		const app = new Vue({router}).$mount('#app');
    	</script>
    </body>
    </html>

    2.函数封装

    index3.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Document</title>
    	<style>
    		.router-link-active{color: red;}
    	</style>
    </head>
    <body>
    	<a href="#/index?index=1">异步加载首页</a>
    	<a href="#/list?list=1">异步加载列表</a>
    	<a href="#/detail?detail=1">异步加载详情</a>
    	<a href="#/detail2?detail2=1">异步加载详情2</a>
    
    	<div id="content">
    		默认
    	</div>
    	
    	<script src="myroute.js"></script>
    	<script>
    		// window.addEventListener('hashchange',function() { // 监听URL的改变
    		// 	console.log("Hello");
    		// });
    
    		spaRouters.init();
    
    		/*
    		1.开发都是异步的
    		*/
    
    		spaRouters.map("/index",function(transition){
    			spaRouters.asyncFun("index.js",transition)
    		})
    
    		spaRouters.map("/list",function(transition){
    			spaRouters.asyncFun("list.js",transition)
    		})
    	</script>
    </body>
    </html>

    index.js

    SPA_RESOLVE_INIT = function (transition) {
    	document.getElementById("content").innerHTML = "当前是渲染的页面";
    }

    list.js

    SPA_RESOLVE_INIT = function (transition) {
    	document.getElementById("content").innerHTML = "当前是渲染的页面";
    }

    myroute.js

    (function() { // 匿名函数,让代码处于局部
    	// 通过监听,改变页面的显示
    	function spaRouters() {
    		this.routers = {}; // 保存注册所有路由,也可以理解为缓存
    	}
    
    	var util = { // 声明公共类
    		getParamsUrl:function(){ // 获取路由的路径和参数
    			var hasDetail = location.hash.split("?");
    			var hasName = hasDetail[0].split("#")[1]; // 得到路由地址
    			var params = hasDetail[1]?hasDetail[1].split("&"):[]; // 得到参数
    			var query = {};
    
    			for (var i = 0; i < params.length; i++) {
    				var item = params[i].split("=");
    				query[item[0]] = item[1];
    			}
    
    			return {
    				path:hasName,
    				query:query
    			}; // 返回一个路由名称
    		}
    	}
    
    	// 一块业务
    	spaRouters.prototype = {
    		init:function(){
    			var self = this;
    			window.addEventListener('hashchange',function() { // 监听URL的改变
    				// 只是知道发生了改变,并不知道路径,需要路由处理
    				self.urlChange();
    			});
    
    			window.addEventListener('load',function() { // 监听URL的改变
    				// 只是知道发生了改变,并不知道路径,需要路由处理
    				self.urlChange();
    			});
    		},
    		refresh:function(currentHash){ // 加载
    			var self = this;
    			if (self.beforeFun) {
    				self.beforeFun({
    					to:{
    						path:currentHash.path,
    						query:currentHash.query
    					},
    					next:function(){
    						self.routers[currentHash.path].callback.call(self,currentHash);
    					}
    				})
    			}else{
    				self.routers[currentHash.path].callback.call(self,currentHash);
    			}
    		},
    		// URL 路由处理
    		urlChange:function(){
    			var currentHash = util.getParamsUrl();
    			if(this.routers[currentHash.path]){
    				this.refresh(currentHash); 
    			}
    		},
    		// 仅仅作为注册路由
    		map:function(path,callback){
    			// 清除空格
    			path = path.replace(/s*/g,""); // 过滤空格
    			if(callback && Object.prototype.toString.call(callback) === "[object Function]"){
    				this.routers[path] = {
    					callback:callback,
    					fn:null // 缓存异步文件状态
    				}
    			}else{
    				console.trace("注册"+path+"需要注册回调信息");
    			}
    		},
    		asyncFun:function(file,transition){
    			var self = this;
    			if(self.routers[transition.path].fn){
    				self.afterFun && self.afterFun(transition)
    				self.routers[transition.path].fn(transition)
    			}else{
    				console.log("开始异步下载js文件"+file);
    				var _body = document.getElementsByTagName("body")[0];
    				var scriptEle = document.createElement("script");
    				scriptEle.type = 'text/javascript';
    				scriptEle.src = file;
    				scriptEle.async = true;
    				SPA_RESOLVE_INIT = null;
    				scriptEle.onload = function(){ // 加载文件之后
    					console.log("下载"+file+"完成");
    					self.afterFun && self.afterFun(transition)
    					self.routers[transition.path].fn = SPA_RESOLVE_INIT;
    					self.routers[transition.path].fn(transition)
    				}
    				_body.appendChild(scriptEle);
    			}
    		}
    	}
    
    	window.spaRouters = new spaRouters(); // 注册到全局
    })();
    

    .

  • 相关阅读:
    java.lang.ExceptionInInitializerError异常分析
    项目中碰到的ExceptionInInitializerError异常
    获取全局上下文(getApplicationContext)_创建Shared Preference工具类_实现自动登录
    IntelliJ Idea 常用快捷键列表
    Qt 创建圆角、无边框、有阴影、可拖动的窗口 good
    去掉 Windows 中控件的虚线框(当当 element == QStyle::PE_FrameFocusRect 时,直接返回,不绘制虚线框)
    Qt 显示 GIF
    C++ 查看预处理后的源文件(查看真实代码)
    数据库访问工具 DBUtl(公孙二狗)
    Tornado
  • 原文地址:https://www.cnblogs.com/crazycode2/p/7208509.html
Copyright © 2011-2022 走看看