Vue组件中的方法this固定指向当前组件Vm
原因:源码中对methods方法进行了遍历bind(fn),固定了this为当前实例

示例代码


var fatherVm = {
    template: '<children-vm :testFnFn="testFn"/>',
    component: {
        childrenVm // var定义的话可以这样写
    },
    data() {
        return {
            info: 'fatherVm'
        }
    },
    methods: {
        testFn() {
            console.log("testFn -> testFn", this.info)
        }
    }
}

var childrenVm = {
    template: '<div></div>',
    props: ['testFn'],
    data() {
        return {
            info: 'childrenVm'
        }
    },
    created() {
        this.testFn()
        this.testFn.call({ info: 'custom' })
        /**
    * 输出为
    * "testFn -> testFn fatherVm"
    * "testFn -> testFn fatherVm"
    * thsi指向一直为 fatherVm
    */
    }
}

MDN function bind >

源码

vue 2.6源码
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 $.`
        )
      }
    }
    // 装饰者闭包模式,返回的是一个新的function,内部还有执行fn,所以外部fn call时的this改变影响不到内层fn的this
    vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm)
  }
}

export const bind = Function.prototype.bind
  ? nativeBind
  : polyfillBind
/* istanbul ignore next */
function polyfillBind (fn: Function, ctx: Object): Function {
  function boundFn (a) {
    const l = arguments.length
    return l
      ? l > 1
        ? fn.apply(ctx, arguments)
        : fn.call(ctx, a)
      : fn.call(ctx)
  }

  boundFn._length = fn.length
  return boundFn
}

function nativeBind (fn: Function, ctx: Object): Function {
  return fn.bind(ctx)
}

装饰者闭包模式,返回的是一个新的function,闭包了内部执行function的this为当前实例vm
call,apply是改变不了指向的

Logo

前往低代码交流专区

更多推荐