观察者可以在Vue中使用Global Mixins吗?

时间:2019-07-07 01:21:02

标签: javascript vue.js

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

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

由于某些原因,观察者确实会在页面加载时触发,但此后,它似乎并没有监听更改。

这是我的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');
        }

    }

};

这是一个示例子组件:

export default {

    watch: {

        bodyLocked: function(locked) {

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

        }

    }

}

3 个答案:

答案 0 :(得分:2)

来自Vue's documentation for mixin:

  

Mixin是一种灵活的方式来分发可重复使用的功能,用于   Vue组件。 mixin对象可以包含任何组件选项。什么时候   组件使用混入,混入中的所有选项将被“混合”   进入组件自己的选项。

声明全局混合时,应用程序中的每个Vue组件都将拥有自己的数据locked,并使用2种方法_lockBody_unlockBody来修改自己的locked值。我相信您希望在全局mixin中声明的值在组件之间共享,但事实并非如此。您正在寻找的可能是全局状态管理:https://vuejs.org/v2/guide/state-management.html

答案 1 :(得分:1)

Watchers用于监视同一组件中的计算属性和状态属性。组件基本上是带有闭包的对象,因此您要执行的操作无法正常工作。

答案 2 :(得分:1)

使用全局混合时,组件将不会共享bodyLocked数据的同一实例。因此,在一个组件中进行更改不会在其他组件中进行更改。每个组件都有自己的bodyLocked值。

执行此操作的另一种方法是使用Vue原型上的对象,而不是使用全局mixin。这样的对象将在所有组件实例之间共享。它还可以使组件内的命名空间更清晰,并且对性能的影响应小于全局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);
    }
  }
});
.no-scroll {
  background-color: #f00;
}
<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>