Watchers 是否与 Vue 中的全局 Mixins 一起工作?

Ben*_*rey 2 javascript vue.js

我已经搜索了 Vue 文档,除非我是盲人,否则我看不到任何声明不能在子组件上使用观察者到父组件,或者在我的情况下,全局混合属性。但是,由于某种原因,我无法让我的工作...

我有一个全局 mixin,用于锁定/解锁窗口滚动。很简单,我试图bodyLocked从子组件监听全局 mixin 上布尔属性的更改。

出于某种原因,观察者确实在页面加载时触发,但在那之后,它似乎没有监听变化。

这是我的 mixin(它在全球范围内与 一起使用Vue.mixin()):

export default {

    data() {
        return {
            bodyLocked: false
        }
    },

    methods: {

        /**
         * Lock the DOM body to disable scrolling.
         *
         * @return void
         */
        _lockBody() {
            this.bodyLocked = true;
            document.documentElement.classList.add('no-scroll');
        },

        /**
         * Unlock the DOM body to enable scrolling.
         *
         * @return void
         */
        _unlockBody() {
            this.bodyLocked = false;
            document.documentElement.classList.remove('no-scroll');
        }

    }

};
Run Code Online (Sandbox Code Playgroud)

这是一个示例子组件:

export default {

    watch: {

        bodyLocked: function(locked) {

            console.log('locked: ' + locked);

        }

    }

}
Run Code Online (Sandbox Code Playgroud)

ski*_*tle 5

当您使用全局 mixin 时,组件不会共享相同的bodyLocked数据实例。因此,在一个组件中更改它不会在其他组件中更改它。每个组件都有自己的bodyLocked价值。

另一种方法是在 Vue 原型上共享一个对象,而不是使用全局 mixin。这样的对象将在所有组件实例之间共享。它还可以在组件内提供更清晰的命名空间,并且应该比全局混合具有更低的性能影响。

const locker = Vue.observable({
  locked: false,
  
  lock () {
    locker.locked = true;
    document.documentElement.classList.add('no-scroll');  
  },
  
  unlock () {
    locker.locked = false;
    document.documentElement.classList.remove('no-scroll');
  }
});

Vue.prototype.$bodyLocker = locker;

new Vue({
  el: '#app',
  
  watch: {
    '$bodyLocker.locked' (locked) {
      console.log('watcher fired: ' + locked);
    }
  }
});
Run Code Online (Sandbox Code Playgroud)
.no-scroll {
  background-color: #f00;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id="app">
  <button @click="$bodyLocker.lock">Lock</button>
  <button @click="$bodyLocker.unlock">Unlock</button>
</div>
Run Code Online (Sandbox Code Playgroud)