Свойство ‘commit’ не существует

#typescript #vue.js #vuex

#typescript #vue.js #vuex

Вопрос:

Когда я использую Vuex в JavaScript, он работает хорошо, но после того, как я хочу изменить его на 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, и это файл хранилища Vue в разделе path ./src/store/modules/todolist.vue .

Комментарии:

1. Вы используете простой vue SPA или что-то с nuxt? Покажите весь ваш файл, пожалуйста

2. @DarioRega привет? Я добавляю весь файл, который предназначен для приложения vue SPA.

3. Ну, извините, но я не знаю electron, и я не большой знаток typescript, не могу помочь, извините

Ответ №1:

Проблема в том, что вы никогда не должны совершать мутацию внутри другой мутации в vuex. Мутация должна вносить только немедленные изменения в состояние, и это разработано таким образом, чтобы лучше хронологически отслеживать атомарные изменения состояния.

Если вы хотите обернуть логику вокруг вызовов мутаций, вам следует вместо этого использовать действие. Действия получают контекстный объект с методом ‘commit’ внутри.

Итак, в вашем простом примере вы могли бы выполнить действие, которое безопасно фиксирует ‘methodA’, а затем ‘methodB’.

 const actions = {
  actionOne ({commit}): none {
    commit('methodA')
    commit('methodB')
  },
}
 

Если у вас есть какая-либо дополнительная логика (например. условно фиксируя ту или иную мутацию), вы можете поместить его туда внутри своего действия.