Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vue] watch的属性用箭头函数定义结果会怎么样? #476

Open
haizhilin2013 opened this issue Jun 22, 2019 · 5 comments
Open
Labels
vue vue

Comments

@haizhilin2013
Copy link
Collaborator

[vue] watch的属性用箭头函数定义结果会怎么样?

@haizhilin2013 haizhilin2013 added the vue vue label Jun 22, 2019
@yin-pathfinder
Copy link

this为undefined

@lovelmh13
Copy link

this是undefined,要更改的属性会报TypeError错误, Cannot read property 'xxx' of undefined

@shanyanwt
Copy link

因为箭头函数默绑定父级作用域的上下文,所以不会绑定vue实例,所以 this 是undefind

@xindiyang
Copy link

不应该使用箭头函数来定义 watcher 函数 (例如 searchQuery: newValue => this.updateAutocomplete(newValue))。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.updateAutocomplete 将是 undefined。

@hyj443
Copy link

hyj443 commented Oct 19, 2021

下面从源码角度分析一下:

我们配置的watch选项,所写的处理函数会创建watcher实例,把处理函数挂载给watcher,方法名叫cb。

下面这个run方法是watcher的原型方法,被观测的目标发生变化时,即你watch的属性变化时,它会通知它的dep中所有的watcher,执行update,然后立即执行下面这个run,重新计算你watch的属性的值,再次进行依赖收集,如果求出的新值和旧值不一样了,那么会执行cb,如下所示

 run() { 
    if (!this.active) return 
    var value = this.get(); 
    if (value !== this.value || isObject(value) || this.deep) {
      var oldValue = this.value;  // oldValue保存旧值
      this.value = value;            // this.value更新为新值
      if (this.user) { 
        // 如果当前watcher是开发者定义的,即通过watch选项或$watch创建的watcher的cb是开发者编写的
        // 则行为不可预知,所以执行cb回调时try...catch一下,发生错误能给开发者一个友好的提示
        try { // 开发者编写的回调接收到被观察目标的新值和旧值
          this.cb.call(this.vm, value, oldValue)
        } catch (e) {
          handleError(e, this.vm, `callback for watcher "${this.expression}"`)
        }
      } else { // 不是用户创建的watcher,即渲染函数的watcher或计算属性的watcher
        this.cb.call(this.vm, value, oldValue) // 直接执行回调
      }
    }
  };

那么问题来了,如果cb不是箭头函数,那么它.call执行,执行时的this是能指定vm实例的

源码就是这么做,才把配置的函数中的this指向了vm实例

但如果是箭头函数,情况就不一样了,看下面例子。

function athis(){
    console.log(this === obj)
}
const bthis =()=>{
    console.log(this === obj)
}
athis.call(obj) // true
bthis.call(obj) // false

可见,你是无法将箭头函数执行中的this改绑定的,它只能从上级上下文去取this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
vue vue
Projects
None yet
Development

No branches or pull requests

6 participants