关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

Vue:router-view组件

发布时间:2020-03-19 00:00:00

router-view是一个 functional 组件,渲染路径匹配到的视图组件。 渲染的组件还可以内嵌自己的 ,根据嵌套路径,渲染嵌套组件

它只有一个名为name的props,这个name还有个默认值,就是default,一般情况下,我们不用传递name,只有在命名视图的情况下,我们需要传递name,命名视图就是在同级展示多个视图,而不是嵌套的展示出来,

router-view组件渲染时是从VueRouter实例._route.matched属性获取需要渲染的组件,也就是我们在vue内部的this.$route.matched上获取的,举个栗子:

    info页

渲染如下:

当路由到info页时,我们在控制台打印app.$route.matched,输出如下:

 writer by:大沙漠 QQ:22969969

 当路由到page页时,我们再在控制台打印app.$route.matched,输出如下:

 可以看到matched中保存所有父子组件信息,索引从0开始,依次是顶层组件、然后是一层层下来的子组件。router-view组件内部render实现时就会读取这个matched属性的,如下:

var View = {
  name: 'RouterView',
  functional: true,                   //函数式组件  props: {
    name: {
      type: String,      default: 'default'}
  },
  render: function render (_, ref) {var props = ref.props;              //获取props  ;例如:{name: "default"}var children = ref.children;        //获取所有子节点var parent = ref.parent;            //父组件的引用var data = ref.data;// used by devtools to display a router-view badgedata.routerView = true;// directly use parent context's createElement() function// so that components rendered by router-view can resolve named slotsvar h = parent.$createElement;                                              //获取父组件的$createElement函数引用  这样组件在执行render时可以用命名插槽var name = props.name;var route = parent.$route;                                                  //当前的路由地址var cache = parent._routerViewCache || (parent._routerViewCache = {});      //获取父组件的_routerViewCache属性,如果没有则初始化为空对象// determine current view depth, also check to see if the tree// has been toggled inactive but kept-alive.var depth = 0;                                      //组件嵌套的层次var inactive = false;                               //是否在keep-alive组件内while (parent && parent._routerRoot !== parent) {      if (parent.$vnode && parent.$vnode.data.routerView) {
        depth++;
      }      if (parent._inactive) {                             //如果parent._inactive存在inactive = true;                                    //则设置inactive为true      }
      parent = parent.$parent;
    } 
    data.routerViewDepth = depth;                       //组件嵌套的层次// render previous view if the tree is inactive and kept-aliveif (inactive) {      return h(cache[name], data, children)
    } var matched = route.matched[depth];                 //从matched属性当中获取当前层次的路由对象,这里保存了需要渲染的组件,这就是上面我们通过app.$route.matched获取的对象// render empty node if no matched routeif (!matched) {
      cache[name] = null;      return h()
    }var component = cache[name] = matched.components[name];     //获取需要渲染的组件// attach instance registration hook// this will be called in the instance's injected lifecycle hooksdata.registerRouteInstance = function (vm, val) {      // val could be undefined for unregistration  var current = matched.instances[name];      if (
        (val && current !== vm) ||(!val && current === vm)
      ) {
        matched.instances[name] = val;
      }
    }// also register instance in prepatch hook// in case the same component instance is reused across different routes;(data.hook || (data.hook = {})).prepatch = function (_, vnode) {
      matched.instances[name] = vnode.componentInstance;
    };// resolve propsvar propsToPass = data.props = resolveProps(route, matched.props && matched.props[name]);if (propsToPass) {      // clone to prevent mutation  propsToPass = data.props = extend({}, propsToPass);      // pass non-declared props as attrs  var attrs = data.attrs = data.attrs || {};      for (var key in propsToPass) {if (!component.props || !(key in component.props)) {
          attrs[key] = propsToPass[key];          delete propsToPass[key];
        }
      }
    }return h(component, data, children)                 //最后渲染该组件  }
}

通过阅读源码,我们得知router-view通过判断当前组件的嵌套层次,然后通过这个层次从route.matches数组中获取当前需要渲染的组件,最后调用全局的$createElement来创建对应的VNode完成渲染的。


/template/Home/Zkeys/PC/Static