子组件修改实例, 控制v-if 失效的问题




// 父组件创建的实例
const SelectMenuData = new SelectMenu()

父组件子组件
<oneVue      v-if='SelectMenuData.show'        />

// 实例代码
class SelectMenu {
    show: Ref<boolean>
    constructor() {
        this.show = ref(false)
    }
    click() { // 点击显示
        if (this.show.value)  return this.show.value = false // 如果已经显示则关闭
        this.show.value = true
        document.addEventListener('mousedown', this.closeMenu)
    }
   // 这里会出问题,调用时,有时会报错,
    closeMenu() {
        console.log('this.show.value:', this.show) // 这里this.show.value: 为什么会有时是undefined
        this.show.value = false
        document.removeEventListener('mousedown', this.closeMenu)
    }
}

上述错误解决了, 还是没用啊
,v-if='SelectMenuData.show'   不生效, 
closeMenu() 方法改了this.show.value 
SelectMenuData.show 这个值改false了, 此组件还是显示

参考GPT和自己的思路:

问题的根本在于在 closeMenu 方法中的 this 关键字。在这个方法中,this 指向的是 document 对象,而不是 SelectMenu 实例对象。因此,this.show.value 会报错,因为 document 对象上并没有 show 属性。

解决这个问题的简单方法是,将 closeMenu 方法的 this 绑定到 SelectMenu 实例上,可以使用 bind 方法或箭头函数实现:

  1. 使用 bind
class SelectMenu {
    // ...
    constructor() {
        // ...
        this.closeMenu = this.closeMenu.bind(this)
    }
   // ...
}
  1. 使用箭头函数
class SelectMenu {
    // ...
    constructor() {
        // ...
        this.closeMenu = () => {
            console.log('this.show.value:', this.show) 
            this.show.value = false
            document.removeEventListener('mousedown', this.closeMenu)
        }
    }
   // ...
}

使用这两种方法可以确保 closeMenu 方法中的 this 绑定到正确的对象上,并且能够正确修改 show 属性。

参考GPT和自己的思路:

问题的原因是在closeMenu()方法中的this指向发生了变化,不再是SelectMenu的实例,而是事件监听器中的this,因此无法正确地访问到show.value属性。解决方法是在constructor()方法中将closeMenu()方法绑定到当前实例上,即将document.addEventListener('mousedown', this.closeMenu)改为document.addEventListener('mousedown', this.closeMenu.bind(this)),这样在调用closeMenu()方法时,this就会指向当前的SelectMenu实例,不会出现show.valueundefined的问题了。

v-if 对应的判断逻辑是否正确呢

document.addEventListener('mousedown', this.closeMenu.bind(this))

该回答引用GPTᴼᴾᴱᴺᴬᴵ
在closeMenu方法中,this的指向会发生变化,导致this.show有时会变成undefined。可以在构造函数中使用箭头函数将this绑定到实例上,或者使用bind方法将this绑定到closeMenu方法上。
·
解决方法1:在构造函数中使用箭头函数绑定this

class SelectMenu {
    show: Ref<boolean>
    constructor() {
        this.show = ref(false)
        this.closeMenu = this.closeMenu.bind(this) // 绑定this
    }
    click() { // 点击显示
        if (this.show.value)  return this.show.value = false // 如果已经显示则关闭
        this.show.value = true
        document.addEventListener('mousedown', this.closeMenu)
    }
    closeMenu() {
        console.log('this.show.value:', this.show)
        this.show.value = false
        document.removeEventListener('mousedown', this.closeMenu)
    }
}


解决方法2:使用bind绑定this

class SelectMenu {
    show: Ref<boolean>
    constructor() {
        this.show = ref(false)
        this.closeMenu = this.closeMenu.bind(this) // 绑定this
    }
    click() { // 点击显示
        if (this.show.value)  return this.show.value = false // 如果已经显示则关闭
        this.show.value = true
        document.addEventListener('mousedown', this.closeMenu)
    }
    closeMenu() {
        console.log('this.show.value:', this.show)
        this.show.value = false
        document.removeEventListener('mousedown', this.closeMenu)
    }
}