Lesson 16-Vue3 Core Function Source Code Analysis

Directive System Source Code

Directive Registration and Parsing

Directive Registration Process:

// Global directive registration
app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

// Core logic in source code
function registerDirective(app, name, directive) {
  app._context.directives[name] = directive
}

// Local directive registration
const componentDirectives = {
  'custom': {
    beforeMount(el, binding) {
      // ...
    }
  }
}

Directive Parsing Process:

  1. Identify directive syntax during template compilation
  2. Create directive node descriptor object
  3. Associate directive with component instance

Directive Binding and Update Process

Directive Lifecycle Execution Order:

beforeMount → mounted → beforeUpdate → updated → beforeUnmount → unmounted

Key Source Code Implementation Points:

// Core directive binding logic
function mountDirective(vnode, directive) {
  const { instance, value, oldValue } = vnode
  const { beforeMount, mounted } = directive
  
  if (beforeMount) {
    callWithAsyncErrorHandling(beforeMount, instance, ErrorCodes.DIRECTIVE_HOOK, [el, binding])
  }
  
  if (mounted) {
    callWithAsyncErrorHandling(mounted, instance, ErrorCodes.DIRECTIVE_HOOK, [el, binding])
  }
}

// Directive update logic
function updateDirective(vnode, oldVNode) {
  const { instance, value, oldValue } = vnode
  const { beforeUpdate, updated } = directive
  
  if (beforeUpdate) {
    callWithAsyncErrorHandling(beforeUpdate, instance, ErrorCodes.DIRECTIVE_HOOK, [el, binding])
  }
  
  // Execute update operations...
  
  if (updated) {
    callWithAsyncErrorHandling(updated, instance, ErrorCodes.DIRECTIVE_HOOK, [el, binding])
  }
}

Custom Directive Internal Implementation

Complete Custom Directive Example:

const vDebounce = {
  mounted(el, binding) {
    const { value: fn, arg: delay = 300 } = binding
    let timeout
    el.addEventListener('input', () => {
      clearTimeout(timeout)
      timeout = setTimeout(() => fn(), delay)
    })
  },
  unmounted(el) {
    el.removeEventListener('input')
  }
}

// Source-level implementation principle
function createDirective() {
  return {
    beforeMount: (el, binding) => { /* Initialization logic */ },
    mounted: (el, binding) => { /* First mount logic */ },
    beforeUpdate: (el, binding) => { /* Pre-update logic */ },
    updated: (el, binding) => { /* Post-update logic */ },
    beforeUnmount: (el, binding) => { /* Pre-unmount cleanup */ },
    unmounted: (el, binding) => { /* Complete unmount logic */ }
  }
}

Directive Performance Optimization

Optimization Strategies:

  1. Directive Merging: Consolidate multiple calls to the same directive
  2. Lazy Execution: Delay non-critical directive execution
  3. Caching Mechanism: Cache directive computation results

Performance Optimization Example:

const vMemo = {
  mounted(el, binding) {
    const { value, arg: key } = binding
    if (!el._memoCache) el._memoCache = new Map()
    if (el._memoCache.has(key) && el._memoCache.get(key) === value) return
    el._memoCache.set(key, value)
    // Execute actual directive logic...
  },
  updated(el, binding) {
    // Similar caching check logic as mounted
  }
}

Directive Security and Compatibility

Security Measures:

  1. DOM Operation Sanitization: Automatically filter dangerous attributes
  2. Event Handler Validation: Verify event listener legitimacy
  3. XSS Protection: Automatically escape dynamic content

Compatibility Handling Example:

const vIntersection = {
  mounted(el, binding) {
    if ('IntersectionObserver' in window) {
      // Modern browser implementation
    } else {
      // Fallback: Scroll event polling
      const fallback = () => {
        const rect = el.getBoundingClientRect()
        if (rect.top < window.innerHeight) {
          binding.value()
          window.removeEventListener('scroll', fallback)
        }
      }
      window.addEventListener('scroll', fallback)
    }
  }
}

Event System Source Code

Event Binding Internal Implementation

v-on Directive Source Code Process:

  1. Parse event syntax during template compilation
  2. Create wrapper function for event listener
  3. Bind event during component mounting

Simplified Implementation:

function processEvent(el, event, modifiers, handler) {
  const wrappedHandler = (e) => {
    // Handle modifier logic
    if (modifiers.stop) e.stopPropagation()
    if (modifiers.prevent) e.preventDefault()
    
    // Execute original handler
    handler.call(this, e)
  }
  
  el.addEventListener(event, wrappedHandler)
}

Event Modifier Handling Logic

Common Modifier Implementations:

const modifierHandlers = {
  stop(e) { e.stopPropagation() },
  prevent(e) { e.preventDefault() },
  self(e) { return e.target === e.currentTarget },
  once(fn) {
    let called = false
    return function(...args) {
      if (!called) {
        called = true
        fn.apply(this, args)
      }
    }
  }
}

// Handle modifier combinations
function applyModifiers(handler, modifiers) {
  return modifiers.reduce((fn, modifier) => {
    return modifierHandlers[modifier]
      ? modifierHandlers[modifier](fn)
      : fn
  }, handler)
}

Event Bubbling and Capturing Implementation

Event Phase Control:

function addEventListener(el, event, handler, options) {
  const { capture, passive } = options
  el.addEventListener(event, handler, {
    capture,
    passive
  })
}

// Apply in directive processing
function processEvent(el, event, modifiers, handler) {
  const options = {
    capture: modifiers.capture,
    passive: modifiers.passive
  }
  addEventListener(el, event, handler, options)
}

Custom Event Triggering and Listening

Custom Event System:

// Trigger custom event
function emit(instance, eventName, ...args) {
  const events = instance.vnode.props?.[`on${capitalize(eventName)}`]
  if (events) {
    events(...args)
  }
}

// Listen to custom event
function on(component, eventName, callback) {
  component._events = component._events || {}
  component._events[eventName] = component._events[eventName] || []
  component._events[eventName].push(callback)
}

Event System Performance Optimization

Optimization Strategies:

  1. Event Delegation: Handle events at the parent element
  2. Throttling and Debouncing: Control event trigger frequency
  3. Passive Listening: Optimize scroll performance

Event Delegation Example:

function delegateEvents(events) {
  const eventMap = {}
  events.forEach(({ event, selector, handler }) => {
    if (!eventMap[event]) {
      eventMap[event] = []
      document.addEventListener(event, dispatchEvent)
    }
    eventMap[event].push({ selector, handler })
  })
}

function dispatchEvent(e) {
  const handlers = eventMap[e.type]
  handlers.forEach(({ selector, handler }) => {
    if (e.target.matches(selector)) {
      handler(e)
    }
  })
}

State Management Source Code (Vuex)

Vuex Core Modules

Vuex Core Structure:

const store = {
  state: reactive({}),
  _mutations: {},
  _actions: {},
  _getters: {},
  commit(type, payload) {
    this._mutations[type].forEach(fn => fn(payload))
  },
  dispatch(type, payload) {
    return this._actions[type].forEach(fn => fn(payload))
  }
}

Modular Implementation:

function registerModule(store, path, module) {
  const namespace = getNamespace(path)
  module.namespaced = true
  
  // Register state
  store._modulesNamespaceMap[namespace] = module
  
  // Register mutations/actions/getters
  installModule(store, rootState, path, module)
}

Plugins and Helper Functions Implementation

Plugin System:

function use(plugin) {
  plugin(this)
}

// Plugin example
const myPlugin = (store) => {
  store.subscribe((mutation, state) => {
    console.log(mutation.type, mutation.payload)
  })
}

Helper Function Source Code:

function mapState(namespace, states) {
  const res = {}
  normalizeMap(states).forEach(({ key, val }) => {
    res[key] = function mappedState() {
      return typeof val === 'function'
        ? val.call(this, this.$store.state, this.$store.getters)
        : this.$store.state[namespace][val]
    }
  })
  return res
}

State Persistence and Debugging Tools

State Persistence Implementation:

function createPersistedState() {
  return (store) => {
    // Load from storage on initialization
    const savedState = localStorage.getItem('vuex')
    if (savedState) {
      store.replaceState(JSON.parse(savedState))
    }
    
    // Subscribe to mutation changes
    store.subscribe((mutation, state) => {
      localStorage.setItem('vuex', JSON.stringify(state))
    })
  }
}

Debugging Tool Integration:

function devtoolPlugin(store) {
  if (!devtools) return
  
  devtools.on('vuex:travel-to-state', targetState => {
    store.replaceState(targetState)
  })
  
  store.subscribe((mutation, state) => {
    devtools.emit('vuex:mutation', mutation, state)
  })
}

Vuex Modular Design

Dynamic Module Registration:

function registerModule(store, path, rawModule) {
  const namespace = getNamespace(path)
  
  // Create submodule
  const module = {
    _raw: rawModule,
    _children: {},
    state: rawModule.state
  }
  
  // Recursively register submodules
  if (rawModule.modules) {
    forEachValue(rawModule.modules, (child, key) => {
      registerModule(store, path.concat(key), child)
    })
  }
  
  // Install module
  installModule(store, state, path, module)
}

Vuex Performance Optimization

Optimization Strategies:

  1. Strict Mode Control: Disable strict checks in production
  2. Batch Updates: Combine multiple mutations
  3. Lazy Module Loading: Dynamically register modules

Performance Optimization Example:

function enableStrictMode(store) {
  if (process.env.NODE_ENV !== 'production') {
    store._vm.$watch(
      () => store._data,
      () => {
        assert(store._committing, `do not mutate vuex store outside mutation handlers`)
      },
      { deep: true, sync: true }
    )
  }
}

Security Strategies:

  1. Type Checking: Validate mutation/action types
  2. Input Sanitization: Filter user input data
  3. Access Control: Module namespace isolation

By deeply analyzing the source code of Vue 3’s core features, developers can gain a thorough understanding of the framework’s inner workings, enabling better design decisions and targeted optimizations for specific scenarios. This foundational knowledge is critical for building high-performance, maintainable large-scale Vue applications.

Share your love