计算属性中的window.scrollY在页面重新加载时为0,在热重新加载时工作正常

时间:2019-04-24 15:29:19

标签: javascript vue.js

<div id="component-navbar" :class="hasBackground">
computed: {
  hasBackground() {
    if (window.scrollY > 0) {
      return 'has-background'
    }
  }
}

我有一个导航栏,如果页面滚动大于0,我想添加背景。问题是hasBackground

  1. 不会随着滚动变化而重新计算
  2. 页面刷新window.scrollY始终为零,即使页面已滚动
  3. 仅当我对文件进行更改时,才可以使用热重装。

我该怎么做?

2 个答案:

答案 0 :(得分:1)

无法在vue中正确观察window对象。您可以在此处了解有关Vue反应性的更多信息:https://vuejs.org/v2/guide/reactivity.html

我认为可能会在vue数据中代理window对象,但是我相信这实际上为现有属性名称的getter / setter方法创建了一个新对象,这意味着您通过执行操作创建的新数据这不会对原始window对象的更改产生反应,因此,唯一真正的选择是不幸的是监视事件。

答案 1 :(得分:1)

正如@obermillerk所说:

  

无法在vue中正确观察到window对象。

因此,您有2个选择:

  1. 初始化组件时,请阅读window.scrollY
  2. 添加window.addEventListener('scroll', ..., { passive: true })

初始化组件时,请阅读window.scrollY

Vue.component('component-navbar', {
  computed: {
    hasBackground () {
      console.log('window.scrollY', window.scrollY)
      if (window.scrollY > 0) {
        return 'has-background'
      }
    }
  },
  template: '<nav :class="hasBackground"></nav>'
})

const app = new Vue({
  el: '#app'
})
#app {
  min-height: 110vh;
}
nav {
  min-height: 50vh;
}
nav.has-background {
  background: linear-gradient(red, orange);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<article id="app">
  <component-navbar></component-navbar>
</article>

添加window.addEventListener('scroll', ..., { passive: true })

Vue.component('component-navbar', {
  data () {
    return {
      isScrolled: false
    }
  },

  computed: {
    hasBackground () {
      if (this.isScrolled) {
        return 'has-background'
      }
    }
  },

  template: '<nav :class="hasBackground"></nav>',

  mounted () {
    window.addEventListener('scroll', this.setIsScrolled, { passive: true })
    this.setIsScrolled()
  },

  destroyed () {
    window.removeEventListener('scroll', this.setIsScrolled, { passive: true })
  },

  methods: {
    setIsScrolled () {
      this.isScrolled = window.scrollY > 0
    }
  },
})

const app = new Vue({
  el: '#app'
})
#app {
  min-height: 110vh;
}
nav {
  min-height: 50vh;
}
nav.has-background {
  background-image: linear-gradient(red, orange);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<article id="app">
  <component-navbar></component-navbar>
</article>