Javascript 基于Electron vue的Electron app中Vuex突变的奇怪行为
我正在尝试用Vue和Electron构建一个简单的任务管理应用程序。我的设置基于与Vuex商店的连接。 用户可以通过模式向列表中添加新项目(并编辑现有项目)。模态将信息发送到存储操作,然后该操作调用一个变异来更新存储并将一个新项推送到列表项数组 这是设置:Javascript 基于Electron vue的Electron app中Vuex突变的奇怪行为,javascript,vue.js,vuejs2,electron,vuex,Javascript,Vue.js,Vuejs2,Electron,Vuex,我正在尝试用Vue和Electron构建一个简单的任务管理应用程序。我的设置基于与Vuex商店的连接。 用户可以通过模式向列表中添加新项目(并编辑现有项目)。模态将信息发送到存储操作,然后该操作调用一个变异来更新存储并将一个新项推送到列表项数组 这是设置:LayerItem是LayerMap的子级。数据从父级LayerMap组件中的存储中接收,然后通过道具提供给子级 重新创建问题:通过层组件中的showEditItemDialog创建新项目。在SAVE\u LAYER\u项目中mutation将
LayerItem
是LayerMap
的子级。数据从父级LayerMap
组件中的存储中接收,然后通过道具提供给子级
重新创建问题:通过层
组件中的showEditItemDialog
创建新项目。在SAVE\u LAYER\u项目中
mutation将创建一个新ID并分配给该新项目。之后,新项目将被推送到层.items
数组。UI将被更新,并且创建的项目可见<代码>项目。文本显示正确。但是,item.id
是不同的。我在变异中加入了一个console.log
。记录的id与此处{{item.id}
组件的UI中显示的id不匹配。因此,在创建新项目后尝试编辑/更新新项目时,变异将创建新项目,而不是更新现有项目,因为在存储阵列中找不到模式接收的ID
我知道有很多代码,我试着删除尽可能多的不必要的代码。在下面的示例中,我创建了一个新项目“test”,您可以看到存储的ID与UI中显示的ID不匹配
终端日志的屏幕截图
来自DevTools控制台的屏幕截图
Vue DevTools商店的屏幕截图
用户界面截图
LayerMap.vue
// 'layers' is a computed property and gets data from the store
<draggable
v-model="layers"
v-bind="getDragOptions"
>
<Layer v-for="(layer, index) in layers" :key="index" :layer="layer"></Layer>
</draggable>
<DetailsModal></DetailsModal>
// Inside computed
computed: {
layers() {
return this.$store.getters.allLayers
}
}
以前从未开发过Electron应用程序,所以我花了一些时间进行了深入研究,但我想我做到了!:) 每个electron应用程序至少有两个进程-主进程(负责打开浏览器窗口)和渲染器(Vue应用程序运行的地方)。如果在代码中使用
console.log
,则从主进程调用的输出显示-console.log
仅显示在终端窗口中(用于在开发模式下启动应用程序),从渲染器进程调用的console.log
仅显示在开发工具中
但是你的基因突变记录在这两种情况下都会出现!这意味着代码必须同时在两个进程中运行,对吗?但是怎么做呢
看起来,模板有一个选项(设置项目时必须打开)可以使用,特别是createSharedMutations
插件。它可以用于在主进程和所有渲染器进程之间共享相同的Vuex存储(从技术上讲,每个进程都有自己的存储,但状态是同步的)。它的工作原理如下:
id
a)被序列化为JSON(),并传递给每个渲染器进程以执行相同的变异(因此保持所有存储同步)。在这里,您的变异将第二次执行(第二次屏幕截图,其中包含来自DevTools的日志)项已分配了id
(A),但它不在项列表中,因此您的代码将分配新的id
(B)并将其推送到集合中id
B显示在屏幕上id
B的项,而该项不在其项集合中。因此,它会分配新的id
(C覆盖B)所以,在渲染器进程中执行的变异会再次看到不在集合中的id为C的项……以此类推
解决方案显然是在存储配置中禁用
createSharedMutations
插件(应该在/renderer/store/index.js
)。如果您确实需要跨主进程/渲染器进程同步存储,您需要重写您的变体…太多代码:)…您正在谈论您的图层项目组件
显示错误的id
(顺便问一下,文本如何?),但是项目
通过道具传递给组件。因此,使用组件(并传递项目)的代码会更有趣(可能您的组件显示的是完全不同的项目?@MichalLevý感谢您的回复。我试图更新我的问题,删除不必要的代码并包含父组件。你知道出了什么问题吗?还不知道<代码>{this.item.text}在LayerItem.vue
中是真实的?第一步。确认存储中id
的值-它是原始(记录的)id
还是id
如LayerItem.vue
组件所示?再次使用Vue开发工具…@MichalLevý,感谢您的帮助!非常感谢!是,this.item.text
显示了正确的值(我更新了原始问题中的文本)。使用Vue开发工具,商店显示的是来自LayerItem.Vue
的值,而不是商店记录的值。哇,非常感谢您为此付出了这么多努力!读完这篇文章后,我做了一些研究并检查了vuex商店的设置。我同时删除了createPersistedState()
和createSharedMutations()
插件,并将这一行添加到main.js
:window.localStorage.clear()
。现在我
// 'layer' gets passed from parent as prop
<span primary-focus @click="showEditItemDialog">Add Item</span>
<draggable v-model="items" v-bind="dragOptions" class="items">
<LayerItem v-for="item in items" :item="item" :layer="layer" :key="item.id"></LayerItem>
</draggable>
// 'items' is a computed property
items: {
get() {
return this.layer.items
}
}
// Function to handle 'Add Item' click and send event which will be handled by DetailsModal.vue
methods: {
showEditItemDialog() {
let payload = {
layer: this.layer,
item: {
id: '',
text: ''
}
}
this.$bus.$emit('item-editing', payload)
}
}
// Layer Item Component
<div class="layer-item" @click.prevent="startEditing">
<div class="item-body">
<p>{{ this.item.text }}</p>
<p>{{ item.id }}</p>
</div>
</div>
// Event will be sent on click with layer item details as parameter
methods: {
startEditing() {
let payload = {
layer: this.layer,
item: {
id: this.item.id,
text: this.item.text
}
}
this.$bus.$emit('item-editing', payload)
}
}
}
// 'editLayerForm' contains layer item id and text
<p>{{editLayerForm.id}}</p>
<div class="bx--form-item">
<input
type="text"
v-model="editLayerForm.text"
/>
</div>
// Inside <script>, event is received and handled, 'editLayerForm' will be updated with payload information
mounted() {
this.$bus.$on('item-editing', this.handleModalOpen)
},
methods: {
handleModalOpen(payload) {
this.layer = payload.layer
this.editLayerForm.id = payload.item.id
this.editLayerForm.text = payload.item.text
this.visible = true
console.log('editing', payload)
},
handleModalSave() {
let payload = {
layerId: this.layer.id,
item: {
id: this.editLayerForm.id,
text: this.editLayerForm.text
}
}
console.log('save', payload)
this.$store.dispatch('saveLayerItem', payload)
}
}
const actions = {
saveLayerItem: ({ commit }, payload) => {
console.log('action item id', payload.item.id)
commit('SAVE_LAYER_ITEM', payload)
}
}
const mutations = {
SAVE_LAYER_ITEM: (state, payload) => {
let layer = state.map.layers.find(l => l.id === payload.layerId)
let itemIdx = layer.items.findIndex(item => item.id === payload.item.id)
console.log('mutation item id', payload.item.id)
if (itemIdx > -1) {
// For existing item
console.log('update item', payload.item)
Vue.set(layer.items, itemIdx, payload.item)
} else {
// For new item
payload.item.id = guid()
console.log('save new item', payload.item)
layer.items.push(payload.item)
}
}
}