我有这样的Vue结构:
App
|--{ data: { scrollInfo {...} } }
|
|--Component1
| |--{ data: { sidebarWidth: 500 }
|
|--Component2
| |--{ data: { overlayItemWidth: 389 }
|
|--Component3
...
...
在我的每个组件中,我都有一些元素,这些元素的变量应在滚动和调整大小时更改(例如sidebarWidth
或overlayItemWidth
)。我发现这个post here展示了这种为滚动和调整大小添加侦听器的方式。
我已将其添加到主实例中,如下所示:
data: {
scrollInfo: {
scrollFromTop: 0,
viewportHeight: 0,
viewportWidth: 0,
pageHeight: 0
}
},
created() {
window.addEventListener( 'scroll', this.calculateScroll );
window.addEventListener( 'resize', this.calculateViewport );
window.addEventListener( 'resize', this.calculatePageScrollSpecs );
this.calculateViewport();
this.calculateScroll();
this.calculatePageScrollSpecs();
},
destroyed() {
window.removeEventListener( 'scroll', this.calculateScroll );
window.removeEventListener( 'resize', this.calculateViewport );
window.removeEventListener( 'resize', this.calculatePageScrollSpecs );
}
我不会显示方法的内容(calculateScroll
,calculateViewport
,...),因为它与该问题无关。
现在...在我的组件中,我有一些变量应该在滚动和调整大小时进行更改和重新评估。但是,每当我有一个这样的变量时,当前我都会在created
和destroyed
中添加这些相同的侦听器,然后将相同的事件侦听器添加到给定的组件中,然后根据新的变量进行计算。方法在那里。看起来又长又笨拙。
有没有办法让我在每个组件中都拥有这些window.AddEventListener
,而在我的根实例中只有那些?
...我在想,如果我的主要实例中有一系列“需要在滚动或调整大小时重新计算的东西”,但我不确定是否这样会很混乱,因为组件的变量实际上并不会保留在组件中,而是用this.$root.sidebarWidth
进行引用。这也将使我的主要实例变得庞大。
有什么建议吗?
答案 0 :(得分:1)
很高兴为您找到了一个解决方案,但对于可能想要更舒适/更通用的解决方案的未来访客:几个月前,我遇到了同样的问题,并在npm上放置了一个Vue mixin,它确实可以做到这一点-一次处理全局数据-终身,而不是每个安装的组件一次。
它称为Reactivator,这是您如何使用它为window.resize
创建全局处理程序的方法:
// viewport-width.js
export default {
// Reactivator uses `getInitialState` to fetch the
// initial value before any listener was attached.
getInitialState() {
return window.innerWidth
},
// Reactivator calls `listen` when the first component using
// it is created and executes the returned cleanup callback
// when it's the last component using it is destroyed.
listen(set) {
const resizeHandler = () => set(window.innerWidth)
window.addEventListener('resize', resizeHandler)
return () => window.removeEventListener('resize', resizeHandler)
}
}
// component.js
import reactivator from 'vue-reactivator'
import viewportWidth from './viewport-width.js'
export default {
mixins: [
// `viewportWidth` will now be a reactive property in this component!
reactivator({ viewportWidth })
]
}
也就是说,观察视口大小是一种常见的情况,我将其(以及其他有用的东西,例如滚动位置或鼠标位置)放入了额外的常见Reactivator实现包中。您可以在vue-browser-state
的npm上找到它。
答案 1 :(得分:0)
您应该制作一个自定义组件,该组件可以接受更改内容并执行所有需要的操作(例如添加和删除事件侦听器)作为道具。
答案 2 :(得分:0)
好吧...根本没有答案,所以我自己潜入其中。这是我能想到的最好的。我希望它可以帮助有需要的其他人。
我在使用extends
(source)或mixins
(source)之间感到痛苦。
经过一番研究,我最终使用了mixins(this video达到了我想要达到的目标以及如何解决它的目的)。如果您想使Mixin成为全局组件,请在4:11左右开始观看此视频。我不是在下面写的说明中这样做。
请注意,我将webpack与laravel-mix结合使用,并编写了以下解决方案。它用于WordPress安装中。
披露
这是不计其数的不同答案和文章的混合。这将永远归功于正确的所有者和来源,所以我什至不愿意尝试。抱歉。
./mixins/scrollAndResize.js
)。export const scrollAndResizeMixin = {
created() {
console.log( 'scrollAndResizes loaded' );
this.calcScroll();
this.calcPageAndViewport();
},
data: function() {
return {
scrollFromTop: 0,
viewportHeight: 0,
viewportWidth: 0,
pageHeight: 0
}
},
methods: {
calcScroll: function (){
let doc = document.documentElement;
this.scrollFromTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
// DEBUG (uncomment and scroll, to check if it works)
// console.log( (window.pageYOffset || doc.scrollTop) );
// console.log( (doc.clientTop || 0) );
},
calcPageAndViewport: function(){
// Viewport info
this.viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
this.viewportWidth = Math.min(document.documentElement.clientWidth, window.innerWidth || 0);
// Page length
var body = document.body;
var html = document.documentElement;
this.pageHeight = Math.max(
body.scrollHeight,
body.offsetHeight,
html.clientHeight,
html.scrollHeight,
html.offsetHeight
);
},
}
};
./app.js
)。// Vue
import Vue from 'vue';
// Mixins
import { scrollAndResizeMixin } from './mixins/scrollAndResize';
// The Application
const app = new Vue({
mixins: [
scrollAndResizeMixin
],
computed: {
mobile: function() {
return this.viewportWidth < 992; // This uses the mixin
}
},
created() {
window.addEventListener( 'scroll', this.calcScroll );
window.addEventListener( 'resize', this.calcPageAndViewport );
},
destroyed() {
window.removeEventListener( 'scroll', this.calcScroll );
window.removeEventListener( 'resize', this.calcPageAndViewport );
}
});
<template>
<div>
<p v-if="viewportWidth > 992">
Desktop
</p>
<p v-else>
Mobile
</p>
</div>
</template>
<script>
import { scrollAndResizeMixin } from '../mixins/scrollAndResize';
export default {
mounted() {
},
mixins: [
scrollAndResizeMixin
],
created() {
window.addEventListener('scroll', this.calcScroll);
window.addEventListener('resize', this.calcPageAndViewport);
},
destroyed() {
window.removeEventListener('scroll', this.calcScroll);
window.removeEventListener('resize', this.calcPageAndViewport);
}
}
</script>