汪图南
  • RAG

    • RAG
  • 快速入门
  • 高级技巧
前端面试之道
  • 打包工具

    • Webpack
    • Rollup
  • TypeScript

    • TypeScript基础
    • TypeScript类型挑战
  • CSS预编译器

    • SASS
  • 自动化测试

    • Vue应用测试
  • Vue2.0源码分析
  • Vue3.0源码分析
  • 数据结构和算法(基础)
  • LeetCode(刷题)
  • JavaScript书籍

    • 你不知道的JavaScript(上)
    • 你不知道的JavaScript(中下)
    • JavaScript数据结构和算法
    • JavaScript设计模式与开发实践
    • 深入理解ES6
  • Git书籍

    • 精通Git
Github
  • RAG

    • RAG
  • 快速入门
  • 高级技巧
前端面试之道
  • 打包工具

    • Webpack
    • Rollup
  • TypeScript

    • TypeScript基础
    • TypeScript类型挑战
  • CSS预编译器

    • SASS
  • 自动化测试

    • Vue应用测试
  • Vue2.0源码分析
  • Vue3.0源码分析
  • 数据结构和算法(基础)
  • LeetCode(刷题)
  • JavaScript书籍

    • 你不知道的JavaScript(上)
    • 你不知道的JavaScript(中下)
    • JavaScript数据结构和算法
    • JavaScript设计模式与开发实践
    • 深入理解ES6
  • Git书籍

    • 精通Git
Github
  • 介绍

    • 介绍和参考
  • 源码目录设计和架构设计

    • 设计
  • Rollup构建版本

    • Rollup基础知识
    • Vue中的Rollup构建
  • 从入口到构造函数整体流程

    • 整体流程
    • initGlobalAPI流程
    • initMixin流程
    • stateMixin流程
    • eventsMixin流程
    • lifecycleMixin流程
    • renderMixin流程
  • 响应式原理

    • 介绍
    • 前置核心概念
    • props处理
    • methods处理
    • data处理
    • computed处理
    • watch处理
    • 深入响应式原理
    • 依赖收集
    • 派发更新
    • nextTick实现原理
    • 变化侦测注意事项
    • 变化侦测API实现
  • 虚拟DOM和VNode

    • 虚拟DOM
    • VNode介绍
    • Diff算法
  • 组件化

    • 介绍
    • $mount方法
    • render和renderProxy
    • createElement
    • createComponent
    • 合并策略
    • update和patch
    • 组件生命周期
    • 组件注册
  • 编译原理

    • 介绍
    • compileToFunctions
    • parse模板解析
    • optimize优化
    • codegen代码生成
  • 扩展

    • 扩展
    • directive指令
    • filter过滤器
    • event事件处理
    • v-model
    • 插槽
    • Keep-Alive
    • Transition
    • Transition-Group
    • Vue.use插件机制
  • Vue-Router

    • 介绍
    • 路由安装
    • matcher介绍
    • 路由切换
    • 内置组件
    • 路由hooks钩子函数
  • Vuex

    • 介绍
    • Vuex安装
    • Vuex初始化
    • Vuex辅助API
    • Store实例API

methods处理

在分析完props相关逻辑后,我们接下来分析与methods相关的逻辑,这部分相比于props要简单得多。

export function initState (vm: Component) {
  // 省略代码
  const opts = vm.$options
  if (opts.methods) initMethods(vm, opts.methods)
}

在initState()方法中,调用了initMethods()并传入了当前实例vm和我们撰写的methods。接下来,我们看一下initMethods方法具体的实现:

function initMethods (vm: Component, methods: Object) {
  const props = vm.$options.props
  for (const key in methods) {
    if (process.env.NODE_ENV !== 'production') {
      if (typeof methods[key] !== 'function') {
        warn(
          `Method "${key}" has type "${typeof methods[key]}" in the component definition. ` +
          `Did you reference the function correctly?`,
          vm
        )
      }
      if (props && hasOwn(props, key)) {
        warn(
          `Method "${key}" has already been defined as a prop.`,
          vm
        )
      }
      if ((key in vm) && isReserved(key)) {
        warn(
          `Method "${key}" conflicts with an existing Vue instance method. ` +
          `Avoid defining component methods that start with _ or $.`
        )
      }
    }
    vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm)
  }
}

在以上代码中可以看到,initMethods()方法实现中最重要的一段代码就是:

// 空函数
function noop () {}

vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm)

它首先判断了我们定义的methods是不是function类型,如果不是则赋值为一个noop空函数,如果是则把这个方法进行bind绑定,其中传入的vm为当前实例。这样做的目的是为了把methods方法中的this指向当前实例,使得我们能在methods方法中通过this.xxx的形式,很方便的访问到props、data以及computed等与实例相关的属性或方法。

在开发环境下,它还做了如下几种判断:

  • 必须为function类型。
// 抛出错误:Method sayHello has type null in the component definition. 
//          Did you reference the function correctly?
export default {
  methods: {
    sayHello: null
  }
}
  • 命名不能和props冲突。
// 抛出错误:Method name has already been defined as a prop.
export default {
  props: ['name']
  methods: {
    name () {
      console.log('name')
    }
  }
}
  • 命名不能和已有的实例方法冲突。
// 抛出错误:Method $set conflicts with an existing Vue instance method. 
//          Avoid defining component methods that start with _ or $.
export default {
  methods: {
    $set () {
      console.log('$set')
    }
  }
}

在分析完以上initMethods流程后,我们能得到如下流程图:

最后更新时间: 2025/5/6 15:36
贡献者: wangtunan
Prev
props处理
Next
data处理