Vue.js 仅初始化自定义组件一次并将其用作多个视图的基础
Vue.js initialize custom component only once and use it as base for multiple views
我基于MapBox创建了一个vue组件,它在花钱之前在初始化方面受到限制,这完全没问题。但是为了他们和我自己,我想减少我的地图组件的重新初始化。
这就是为什么我想是否可以定义一次组件,传入一些属性,然后通过 vuex 处理状态。
现在,我必须像这样导入我的组件并添加数据:
<Map
:sources="geoData.sources"
:layers="geoData.layers"
:mapOptions="mapOptions"
:componentOptions="{ drawingEnabled: toggleMapDrawing, activeLayers: activeMapLayers, activeMarkerGroups: [] }"
@loaded="onMapLoaded" @selectedMarkers="onSelectedObjects"/>
正在监视 componentOptions
,因此组件相应地更改其状态。
到目前为止,我的 ideas/approaches 如下:
- 我考虑过将上面的代码片段添加到根 vue 文件中,但这无济于事,因为我想将地图组件动态而不是静态地放置在页面内容的其余部分之前。
- 将呈现的 vue 组件传递到变量中并稍后附加它会有点太老套了,如果可能的话。
- 使用插槽,但根据我在文档中看到的内容,不可能像这样在子组件中使用来自父组件的插槽组件。
- 我想到的最好的主意是定义实际的 MapBox 变量(我想它会触发 API 进行初始化),然后使用商店或其他东西将其全局保存。但是因为这会立即将组件附加到将在选项中指定的 DOM 元素,所以我也必须以某种方式存储它。
地图的初始化发生在组件的挂载钩子中,如下所示:
const baseOptions = {
accessToken: process.env.MAPBOX_TOKEN,
container: 'map',
style: process.env.MAPBOX_STYLE_URL,
minZoom: 10,
maxZoom: 20,
zoom: 13,
bearing: 150,
pitch: 50
}
this.map = new mapboxgl.Map(Object.assign(baseOptions, this.mapOptions))
if (!this.map) { throw new Error('Could not create map. Make sure the token is valid.') }
我可能是错的,也许有更好的方法,或者整个想法可能是垃圾,但希望不是。另请注意,我没有使用 vue-mapbox 模块,因为它不再被维护。
感谢任何想法和提示:)
您可以使用<KeepAlive>,一个在 Vue2 (docs) and Vue3 (docs) 中可用的 built-in 组件.
基本上它确保了一个组件标记为 keep-alive 只会是 mounted
一次。所以在你的情况下,你可以把地图放在任何你想放的地方,地图只会在它的 mounted
挂钩中初始化一次。
如果您需要利用地图“聚焦”或“激活”的那一刻,那么您可以利用 activated
和 deactivated
挂钩。
为什么不能使用 KeepAlive。
有一个明显的逻辑限制。只要父组件处于活动状态并已挂载,正在 kept-alive 的组件的子组件将保持活动状态。但是,如果 keep-alive 组件的父组件被卸载,那么所有 子组件也将被卸载,即使它们一直保持活动状态 。这一切都很明显,但我只是想指出来。
解决方案
因此,在您的用例中,您希望组件(<Map>
组件)在首次初始化后成为全局 kept-alive。我建议您缓存地图元素本身并将其存储在商店中。然后在每个<Map>
组件onBeforeMount
(CompositionAPI)或beforeMount
(OptionsAPI)hook上,手动检查元素是否被缓存,如果是则插入存储中的缓存地图,否则初始化地图。
我基于MapBox创建了一个vue组件,它在花钱之前在初始化方面受到限制,这完全没问题。但是为了他们和我自己,我想减少我的地图组件的重新初始化。 这就是为什么我想是否可以定义一次组件,传入一些属性,然后通过 vuex 处理状态。
现在,我必须像这样导入我的组件并添加数据:
<Map
:sources="geoData.sources"
:layers="geoData.layers"
:mapOptions="mapOptions"
:componentOptions="{ drawingEnabled: toggleMapDrawing, activeLayers: activeMapLayers, activeMarkerGroups: [] }"
@loaded="onMapLoaded" @selectedMarkers="onSelectedObjects"/>
正在监视 componentOptions
,因此组件相应地更改其状态。
到目前为止,我的 ideas/approaches 如下:
- 我考虑过将上面的代码片段添加到根 vue 文件中,但这无济于事,因为我想将地图组件动态而不是静态地放置在页面内容的其余部分之前。
- 将呈现的 vue 组件传递到变量中并稍后附加它会有点太老套了,如果可能的话。
- 使用插槽,但根据我在文档中看到的内容,不可能像这样在子组件中使用来自父组件的插槽组件。
- 我想到的最好的主意是定义实际的 MapBox 变量(我想它会触发 API 进行初始化),然后使用商店或其他东西将其全局保存。但是因为这会立即将组件附加到将在选项中指定的 DOM 元素,所以我也必须以某种方式存储它。
地图的初始化发生在组件的挂载钩子中,如下所示:
const baseOptions = {
accessToken: process.env.MAPBOX_TOKEN,
container: 'map',
style: process.env.MAPBOX_STYLE_URL,
minZoom: 10,
maxZoom: 20,
zoom: 13,
bearing: 150,
pitch: 50
}
this.map = new mapboxgl.Map(Object.assign(baseOptions, this.mapOptions))
if (!this.map) { throw new Error('Could not create map. Make sure the token is valid.') }
我可能是错的,也许有更好的方法,或者整个想法可能是垃圾,但希望不是。另请注意,我没有使用 vue-mapbox 模块,因为它不再被维护。
感谢任何想法和提示:)
您可以使用<KeepAlive>,一个在 Vue2 (docs) and Vue3 (docs) 中可用的 built-in 组件.
基本上它确保了一个组件标记为 keep-alive 只会是 mounted
一次。所以在你的情况下,你可以把地图放在任何你想放的地方,地图只会在它的 mounted
挂钩中初始化一次。
如果您需要利用地图“聚焦”或“激活”的那一刻,那么您可以利用 activated
和 deactivated
挂钩。
为什么不能使用 KeepAlive。
有一个明显的逻辑限制。只要父组件处于活动状态并已挂载,正在 kept-alive 的组件的子组件将保持活动状态。但是,如果 keep-alive 组件的父组件被卸载,那么所有 子组件也将被卸载,即使它们一直保持活动状态 。这一切都很明显,但我只是想指出来。
解决方案
因此,在您的用例中,您希望组件(<Map>
组件)在首次初始化后成为全局 kept-alive。我建议您缓存地图元素本身并将其存储在商店中。然后在每个<Map>
组件onBeforeMount
(CompositionAPI)或beforeMount
(OptionsAPI)hook上,手动检查元素是否被缓存,如果是则插入存储中的缓存地图,否则初始化地图。