Vuex getter при получении по id возвращает саму функцию?
есть стейт
state: {
todos: [
{ id: 1, text: 'Первый текст', done: true },
{ id: 2, text: 'Второй текст', done: false }
],
},
есть геттер
getters: {
GET_TODO: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
когда пытаюсь получить строку по id
mounted () {
this.todo = this.GET_TODO(1)
console.log(this.todo)
},
в консоль выдает эту функцию а не строку с id = 1. Вопрос почему?
Ответы (4 шт):
Я не спец в javascript но похоже что конструкция
GET_TODO: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
Равносильна этой
GET_TODO: function name1(state) {
return function name2(id) {
return state.todos.find(todo => todo.id === id);
}
}
Поэтому вызов this.GET_TODO(1) и возвращает функцию
Вот что говорит официальная документация! Стиль обращения как к методам Можно также передавать аргументы геттерам, возвращая функцию. Это например пригодится, когда необходимо возвращать массив по указанному критерию:
getters: {
// ...
getTodoById: state => id => {
return state.todos.find(todo => todo.id === id);
}
}
store.getters.getTodoById(2); // -> { id: 2, text: '...', done: false }
Обратите внимание, что геттеры, доступ к которым выполняется как к методам, будут запускаться каждый раз при их вызове, а результаты не будут кэшироваться.
Фрагменты вашего кода правильные. Вы не указали как вы подключаете getters в ваш компонент(приложение), но если вы используете вспомогательную функцию mapGetters - значит "проксируете " геттеры хранилища в локальные вычисляемые свойства компонента, все должно работать.
// импортируете mapGetters из vuex
const {
mapGetters
} = Vuex
// используете в computed
...mapGetters(['GET_TODO'])
Если вы не хотите использовать mapGetters, можете использовать синтаксис прямого доступа к геттерам:
$store.getters['GET_TODO'](2)
Рабочий пример:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: 'Первый текст', done: true },
{ id: 2, text: 'Второй текст', done: false }
],
},
getters: {
GET_TODO: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
},
})
const {
mapGetters
} = Vuex
const app = new Vue({
el: '#app',
store,
data() {
return {
todo: null
};
},
computed: {
...mapGetters(['GET_TODO'])
},
mounted () {
this.todo = this.GET_TODO(1)
console.log(this.todo)
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vuex.js"></script>
<div id="app">
{{ todo }}
<hr>
{{ $store.getters['GET_TODO'](2)}}
</div>
Тут вы создаете геттер, который возвращает тоже функцию (state) => (id) => { // тут какая-то логика } (данная конструкция состоит из двух функций, первая вернет сам геттер например в mapGetters, что создаст замыкание аргумента state (кстати тут можно воспользоваться деструктуризацией: ({ todos }) => ...), затем полученную функцию вы можете вызвать с параметром id в своем темплейте/логике компонента):
getters: {
GET_TODO: ({ todos }) => (id) => todos.find((todo) => todo.id === id) || {},
}
То есть далее вам необходимо воспользоваться к примеру mapGetters.
computed: {
// и уже далее вы можете использовать вызов GET_TODO(id)
...mapGetters('GET_TODO'),
},
Тут стоит заметить, что так использовать геттеры нужно аккуратно, потому что вы теряете основное удобство геттера - это кэширование. Вот статья с советами работы с vuex.