摘要:是響應式的,當瀏覽器路由改變時,的值也會相應的改變的作用是清楚了,但頁面內容的變化是怎么實現的呢下面再介紹下的作用。
先上一段簡單的demo,本文根據此demo進行解析
Vue.use(VueRouter) const router = new VueRouter({ routes: [ { path: "/home", component: {template: "home"}} ] }) new Vue({ "el":"#app", router, template: `` })Basic
vue源碼解析(五)中介紹過,Vue.use(VueRouter)其實主要調用了VueRouter.install(Vue)方法
function install (Vue) { //掛載全局的鉤子函數到Vue,vue對象初始化會調用下面的函數 Vue.mixin({ beforeCreate: function beforeCreate () { if (isDef(this.$options.router)) { // _routerRoot為當前vue對象 this._routerRoot = this; // _router為new Vue傳入的VueRouter對象 this._router = this.$options.router; //調用 VueRouter.protoype.init,后面介紹 this._router.init(this); // 設置響應式的_route,this._router.history.current為當前頁面的路由信息 Vue.util.defineReactive(this, "_route", this._router.history.current); } else { this._routerRoot = (this.$parent && this.$parent._routerRoot) || this; } } }); //全局注冊組件 Vue.component("router-view", View); Vue.component("router-link", Link); } // 全局組件router-view的參數 var View = { name: "router-view", functional: true, props: { name: { type: String, default: "default" } }, render: function render (_, ref){} }
install方法主要是掛載鉤子函數和全局注冊組件,全局注冊的組件router-view的值如下,
再看一下router = new VueRouter的過程
var VueRouter = function VueRouter (options) { this.options = options; //默認使用hash進行前端路由 var mode = options.mode || "hash"; switch (mode) { case "history": this.history = new HTML5History(this, options.base); break case "hash": this.history = new HashHistory(this, options.base, this.fallback); break } } // HashHistory 和 HTML5History都是繼承History var HashHistory = (function (History$$1) { function HashHistory (router, base, fallback) { History$$1.call(this, router, base); } if ( History$$1 ) HashHistory.__proto__ = History$$1; HashHistory.prototype = Object.create( History$$1 && History$$1.prototype ); HashHistory.prototype.constructor = HashHistory; return HashHistory; }(History)); var History = function History (router, base) { // VueRouter實例對象 this.router = router; //base路徑 this.base = normalizeBase(base); //當前路由信息,此時是一個空值 this.current = START; };
new Vue的過程中會觸發掛載的beforeCreate函數,主要是調用了this._router.init(this);
為了更清晰的解析整個流程,假定我們現在訪問的頁面路徑是/home,并且是hash的方式進行路由
VueRouter.prototype.init = function init (app /* Vue component instance */) { var history = this.history; if (history instanceof HTML5History) { history.transitionTo(history.getCurrentLocation()); } else if (history instanceof HashHistory) { var setupHashListener = function () { //監聽瀏覽器地址的變更,并調用transitionTo“跳轉”到新的路由頁面 history.setupListeners(); }; //初始化時調用一次transitionTo,根據當前瀏覽器地址欄里的path(/home)來激活對應的路由 history.transitionTo( // 初始化值為“/home” history.getCurrentLocation(), setupHashListener ); } }; HashHistory.prototype.setupListeners = function setupListeners () { //監聽瀏覽器地址的變更 window.addEventListener(supportsPushState ? "popstate" : "hashchange", function () { //實現頁面內容的變更,getHash()為變更后的hash路徑 this$1.transitionTo(getHash()) } } //將頁面轉換到當前真實的路由 History.prototype.transitionTo = function transitionTo (location, onComplete, onAbort) { var this$1 = this; // 根據location("/home")得到route對象{name: undefined, meta: {…}, path: "/home", hash: "", query: {…},?…} var route = this.router.match(location, this.current); //confirmTransition實現比較復雜,本文不做介紹,主要會執行下面的回調函數 this.confirmTransition(route, function () { //將histoty.current值更新為route this$1.updateRoute(route); //執行onComplete(setupHashListener) onComplete && onComplete(route); //更新瀏覽器url地址 this$1.ensureURL(); } }; function match (){ 遍歷路由配置(本文只有一項配置{ path: "/home", component: {template: "home"}}) for (var i = 0; i < pathList.length; i++) { var path = pathList[i]; var record$1 = pathMap[path]; //判斷當前路徑是否有匹配的路由配置 if (matchRoute(record$1.regex, location.path, location.params)) { return _createRoute(record$1, location, redirectedFrom) } } // no match return _createRoute(null, location) } function createRoute (record){ var route = { name: location.name || (record && record.name), meta: (record && record.meta) || {}, path: location.path || "/", hash: location.hash || "", query: query, params: location.params || {}, fullPath: getFullPath(location, stringifyQuery$$1), //當前路徑匹配的路由配置 matched: record ? formatMatch(record) : [] }; return Object.freeze(route) }
根據上面的代碼邏輯可以分析得出,vue對象初始化時會掛載屬性vm._router(記錄了整個應用的路由配置信息)和vm._route(記錄了當前的路由信息)。vm._route是響應式的,當瀏覽器路由改變時,vm._route的值也會相應的改變
vm._route的作用是清楚了,但頁面內容的變化是怎么實現的呢?下面再介紹下router-view的作用。
Vue源碼解析(四)-components組件介紹過,vue初始化時根據template函數生成render函數,本文render函數會調用vm._c("router-view"),_createElement判斷router-view是注冊過的組件,因此以組件的方式生成vnode,但是router-view生成vnode的過程與Vue源碼解析(四)中的方法又有區別
function _createElement(){ //本例tag=‘router-view’,‘router-view’在components屬性中注冊過,因此以組件的方式生成vnode if (isDef(Ctor = resolveAsset(context.$options, "components", tag))) { //Ctor是router-view的構造函數VueComponent(Vue.component("router-view", View)注冊) vnode = createComponent(Ctor, data, context, children, tag); } } function createComponent (Ctor){ //Ctor 此時已經是構造函數 , 不需要再調用Vue.extend生成 var baseCtor = context.$options._base; if (isObject(Ctor)) { Ctor = baseCtor.extend(Ctor); } // router-view是functional component(見上文圖中view的option的值),與用戶自定義的component的vnode生成方法有區別 if (isTrue(Ctor.options.functional)) { return createFunctionalComponent(Ctor, propsData, data, context, children) } //用戶自定義component的vnode構造方法 var vnode = new VNode( ("vue-component-" + (Ctor.cid) + (name ? ("-" + name) : "")), data, undefined, undefined, undefined, context, { Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children } ); } function createFunctionalComponent (Ctor){ var options = Ctor.options; //主要是調用View.render方法,前文提到過 var vnode = options.render.call(null, renderContext._c, renderContext); return vnode; } var View = { name: "router-view", functional: true, props: { name: { type: String, default: "default" } }, render: function render (_, ref) { //Vue實例化對象vm var parent = ref.parent; // vm._route var route = parent.$route; var depth = 0; //上文提到的createRoute中生成的路由匹配信息 var matched = route.matched[depth]; // _createElement方法 var h = parent.$createElement; // render empty node if no matched route if (!matched) { return h() } // 本文component為{template: "home", _Ctor: {…}, inject: {…}} var component = matched.components[name]; //重新調用_createElement,這次是以常規方式生成vnode,后續vnode將渲染成template中的內容 return h(component, data, children) } };
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90405.html
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:請輸入代碼注意只適用于版本,下面我們是基于講的如何使用實現路由功能。一使用路由在中,需要明確安裝路由功能定義組件,這里使用從其他文件進來定義路由創建實例,然后傳配置創建和掛載根實例。路由記錄就是配置數組中的對象副本還有在數組。 請輸入代碼注意:vue-router 2只適用于Vue2.x版本,下面我們是基于vue2.0講的如何使用vue-router 2實現路由功能。推薦使用npm安裝...
摘要:中文官網英文官網組織發出一個問題之后,不要暫時的離開電腦,如果沒有把握先不要提問。珍惜每一次提問,感恩每一次反饋,每個人工作還是業余之外抽出的時間有限,充分準備好應有的資源之后再發問,有利于問題能夠高效質量地得到解決。 Vue.js資源分享 更多資源請Star:https://github.com/maidishike... 文章轉自:https://github.com/maid...
閱讀 3573·2021-11-15 11:36
閱讀 1067·2021-11-11 16:55
閱讀 701·2021-10-20 13:47
閱讀 2998·2021-09-29 09:35
閱讀 3449·2021-09-08 10:45
閱讀 2556·2019-08-30 15:44
閱讀 853·2019-08-30 11:10
閱讀 1435·2019-08-29 13:43