typescript - 属性“提交”不存在
问题描述
当我在 JavaScript 中使用 Vuex 时,它运行良好,但在我想将其更改为 TypeScript 之后,它告诉我Property 'commit' does not exist
在 Vuex 的突变中:
const mutations = {
methodA (): none {
this.commit('methodB') // raise error here!!! <- Property 'commit' does not exist on type '...'
},
methodB (): nont {
log.console('hello')
}
}
我该怎么做才能让它发挥作用。
编辑:
还在等……www
编辑:
这是整个文件的一部分,可能对您来说太长(200 行):
import fs from 'fs'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'
import { remote } from 'electron'
// editor_text_C: const state for editor's text
const editor_text_C = {
main: 'Text TODO, enter <kbd>Ctrl+Enter</kbd> to submit:',
sub: title => `Text TODO, enter <kbd>Ctrl+Enter</kbd> for submit for ` +
`${JSON.stringify(title)}, and enter <kbd>Esc</kbd> to ` +
`leave:`
}
interface Bar {
title: string;
time: Date;
OK: boolean;
folding: boolean;
child: Bar[];
}
interface Editor {
text: string;
index: number[];
container?: HTMLElement;
// TODO: ugly type
obj: any;
}
interface State {
bars: Bar[];
editor: Editor;
filePath: string;
}
const state = (): State => ({
bars: [],
editor: {
text: editor_text_C.main,
index: [],
container: undefined,
obj: null
},
filePath: ''
})
// make the bar/bars be normal, be in bars' shape
var normalBar = (bar: any): Bar => {
if (!bar['title']) console.error('Bar require title')
bar['time'] = bar['time'] ? new Date(bar['time']) : new Date()
bar['OK'] = bar['OK'] ? bar['OK'] : false
bar['folding'] = bar['folding'] ? bar['folding'] : false
bar['child'] = normalBars(bar['child'])
return bar
}
var normalBars = (bars: any[]): Bar[] => {
var result = []
if (bars) {
for (var i = 0; i < bars.length; i++) {
if(bars[i])
result.push(normalBar(bars[i]))
}
}
return result
}
// get the bar by index
var barByIndex = (bars: Bar[], index: number[]): Bar => {
var result: any = { child: bars }
for (var i = 0; i < index.length; i++) {
result = result.child[index[i]]
}
return result as Bar
}
// mutations
const mutations = {
init (state: State, { filePath }: { filePath: string; }) {
// init Bars for todo application.
// read `json` file form filePath, then init state.bars with update mutations.
// ------------------------------------------------------------------------
state.filePath = filePath
fs.readFile(state.filePath, (err, data) => {
if (err) {
this.update(state, {
bars: normalBars([
{title: '1. Click on my text to set my state (OK/Todo)'},
{title: ['2. Want to set a new Todo? Edit at below editor, then press',
' `Ctrl+Enter`'].join('')},
{title: ['3. A Useless Todo bar? move on me and you can find a bin ',
'icon, then click on the my delete bin icon'].join('')}
])
})
return
}
state.bars = normalBars(JSON.parse(data.toString()))
})
// init the Editor
// ------------------------------------------------------------------------
state.editor.container = document.createElement('div')
state.editor.container.style.height = '5em'
state.editor.obj = monaco.editor.create(state.editor.container, {
value: '',
language: 'markdown',
folding: true,
foldingStrategy: 'indentation',
automaticLayout: true,
overviewRulerBorder: false,
scrollBeyondLastLine: false,
minimap: {
enabled: false
}
})
// Set the command for edit to enter the message
state.editor.obj.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {
this.commit('todolist/submit', { message: state.editor.obj.getValue() })
state.editor.obj.setValue('')
})
// Set the command for enter the message for root
state.editor.obj.addCommand(monaco.KeyCode.Escape, () => {
this.commit('todolist/addBar', { index: undefined })
})
},
// update Bars and save
// set the state.bars' value to `bars`, then write it to filePath
update (state: State, { bars }: { bars: Bar[]; }) {
state.bars = bars
fs.writeFile(state.filePath, JSON.stringify(state.bars), (err) => {
if (err) {
console.error(`Cannot write to ${state.filePath}!`)
}
})
},
// kill bar by index
killBar (state: State, { index }: { index: number[] }) {
// reset the editor's index
this.commit('todolist/addBar', { index: undefined })
var index_ = index.slice()
if (index.length != 1) {
var i = index_.pop()
var aim = barByIndex(state.bars, index_)
remote.clipboard.writeText(aim.child[i].title)
aim.child.splice(i, 1)
this.commit('todolist/update', { bars: state.bars })
} else {
remote.clipboard.writeText(state.bars[index[0]].title)
state.bars.splice(index[0], 1)
this.commit('todolist/update', { bars: state.bars })
}
},
// change the bay's OK state by index
changeState (state: State, { index }: { index: number[] }) {
var aim = barByIndex(state.bars, index)
aim.OK = !aim.OK
this.commit('todolist/update', { bars: state.bars })
},
// add Bar for todo list:
// - if index == undef, add bar to the root
// - else, add bar for bars[index[0]][index[1]]...
addBar (state: State, { index }: { index: number[] }) {
state.editor.index = index
if (state.editor.index != undefined) {
var aim = barByIndex(state.bars, state.editor.index)
state.editor.text = editor_text_C.sub(aim.title)
} else {
state.editor.text = editor_text_C.main
}
// focus on the editor auto
state.editor.obj.focus()
this.commit('todolist/update', { bars: state.bars })
},
// fold Bar for todo list
foldBar (state: State, { index }: { index: number[]; }) {
var aim = barByIndex(state.bars, index)
aim.folding = !aim.folding
this.commit('todolist/update', { bars: state.bars })
},
// submit by message and index, and then update it:
// - if index == undef, add bar to the root
// - else, add bar for bars[index]
submit (state: State, { message }: { message: string; }) {
if (state.editor.index != undefined) {
var aim = barByIndex(state.bars, state.editor.index)
aim.child.unshift(normalBar({title: message}))
this.commit('todolist/update', { bars: state.bars })
} else {
state.bars.unshift(normalBar({title: message}))
this.commit('todolist/update', { bars: state.bars })
}
}
}
const getters = {
state: (state: State) => (index: number[]) => {
var aim = barByIndex(state.bars, index)
if (aim.child.length != 0) {
return aim.folding ? 'folding' : 'unfolding'
} else {
return aim.OK ? 'OK' : 'not OK'
}
},
folding: (state: State) => (index: number[]) => {
return barByIndex(state.bars, index).folding
},
havechildren: (state: State) => (index: number[]) => {
return barByIndex(state.bars, index).child.length != 0
},
OK: (state: State, getters: any) => (index: number[]) => {
var aim = barByIndex(state.bars, index)
if (getters['havechildren'](index)) {
var flag = true
for (var i = 0; i < aim.child.length; i ++) {
if (!getters['OK'](index.concat(i))) {
flag = false
}
}
return flag
} else {
return aim.OK
}
}
}
export default {
namespaced: true,
state,
mutations,
getters
}
以下是一些可能有帮助或没有帮助的信息:它是用 构建的electron
,我将把它制作成 typescript 文件,它是 path 下的一个 Vue 存储文件./src/store/modules/todolist.vue
。
解决方案
问题是你永远不应该从 vuex 的另一个突变内部提交一个突变。突变只应立即更改状态,这样设计是为了更好地按时间顺序跟踪状态的原子更改。
如果您想围绕对突变的调用包装逻辑,您应该使用一个操作。动作接收一个带有“提交”方法的上下文对象。
因此,在您的简单示例中,您可以执行一个操作,即先提交“methodA”,然后提交“methodB”。
const actions = {
actionOne ({commit}): none {
commit('methodA')
commit('methodB')
},
}
如果您有任何其他逻辑(即有条件地提交一个或另一个突变),您可以将其放在您的操作中。
推荐阅读
- javascript - JS 在 PHP 可以发送电子邮件之前删除表单数据
- selenium-chromedriver - selenium-chromedriver:是否可以访问浏览器 Inspector-Network 页面中的所有内容?
- javascript - 当出现新单元格时,如何使表格单元格保持在其原始位置?
- apache-camel - 通过 Camel 中的组件绑定的外部服务(类似于 Mule 绑定接口)
- javascript - 如何获取仅包含 Javascript 中附加值的键的数组?
- html - 基于背景的不同图像的 CSS 动画
- java - 如何防止Spring执行变量替换
- pandas - 为什么 Google 搜索将 Pandas 文档页面标记为不安全?
- swift - Xcode Swift MacOS App,将文件拖放到 NSTextField
- c++ - 由于普通字符签名,哪些工具可以诊断 C++ 可移植性问题?