美文网首页
五、Router-View

五、Router-View

作者: zdxhxh | 来源:发表于2020-02-02 21:01 被阅读0次

    router-view 组件

    import { warn } from '../util/warn'
    
    /* router-view组件 */
    export default {
      name: 'RouterView',
      functional: true, // 使组件无状态 (没有 data ) 和无实例 (没有 this 上下文)。他们用一个简单的 render 函数返回虚拟节点使他们更容易渲染。
      props: {
        name: {
          type: String,
          default: 'default'
        }
      },
      render (_, { props, children, parent, data }) {
        /* 标记位,标记是route-view组件 */
        data.routerView = true
    
        // 直接使用父类的构造节点函数$createElement
        // 这样组件渲染时可以使用slots
        const h = parent.$createElement
        /* props的name,默认'default' */
        const name = props.name
        /* option中的VueRouter对象 */
        const route = parent.$route
        /* 在parent上建立一个缓存对象 */
        const cache = parent._routerViewCache || (parent._routerViewCache = {})
    
        /* 记录组件深度 */
        let depth = 0
        /* 标记是否是待用(非alive状态)) */
        let inactive = false
        /* _routerRoot中中存放了根组件的实例,这边循环向上级访问,直到访问到根组件,得到depth深度 */
        while (parent && parent._routerRoot !== parent) {
          if (parent.$vnode && parent.$vnode.data.routerView) {
            depth++
          }
          /* 如果_inactive为true,代表是在keep-alive中且是待用(非alive状态) */
          if (parent._inactive) {
            inactive = true
          }
          parent = parent.$parent
        }
        /* 存放route-view组件的深度 */
        data.routerViewDepth = depth
    
        // render previous view if the tree is inactive and kept-alive
        /* 如果inactive为true说明在keep-alive组件中,直接从缓存中取 */
        if (inactive) {
          return h(cache[name], data, children)
        }
    
        const matched = route.matched[depth]
        // render empty node if no matched route
        /* 如果没有匹配到的路由,则渲染一个空节点 */
        if (!matched) {
          cache[name] = null
          return h()
        }
    
        /* 从成功匹配到的路由中取出组件 */
        const component = cache[name] = matched.components[name]
    
        // attach instance registration hook
        // this will be called in the instance's injected lifecycle hooks
        /* 注册实例的registration钩子,这个函数将在实例被注入的加入到组件的生命钩子(beforeCreate与destroyed)中被调用 */
        data.registerRouteInstance = (vm, val) => {  
          /* 第二个值不存在的时候为注销 */
          // val could be undefined for unregistration
          /* 获取组件实例 */
          const current = matched.instances[name]
          if (
            (val && current !== vm) ||
            (!val && current === vm)
          ) {
            /* 这里有两种情况,一种是val存在,则用val替换当前组件实例,另一种则是val不存在,则直接将val(这个时候其实是一个undefined)赋给instances */
            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 = (_, vnode) => {
          matched.instances[name] = vnode.componentInstance
        }
    
        // resolve props
        let 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
          const attrs = data.attrs = data.attrs || {}
          for (const key in propsToPass) {
            if (!component.props || !(key in component.props)) {
              attrs[key] = propsToPass[key]
              delete propsToPass[key]
            }
          }
        }
    
        return h(component, data, children)
      }
    }
    
    function resolveProps (route, config) {
      switch (typeof config) {
        case 'undefined':
          return
        case 'object':
          return config
        case 'function':
          return config(route)
        case 'boolean':
          return config ? route.params : undefined
        default:
          if (process.env.NODE_ENV !== 'production') {
            warn(
              false,
              `props in "${route.path}" is a ${typeof config}, ` +
              `expecting an object, function or boolean.`
            )
          }
      }
    }
    
    function extend (to, from) {
      for (const key in from) {
        to[key] = from[key]
      }
      return to
    }
    ****
    

    相关文章

      网友评论

          本文标题:五、Router-View

          本文链接:https://www.haomeiwen.com/subject/orfcxhtx.html