Как использовать функцию, которая возвращает значение внутри шаблона? Vuex, Vue

#javascript #vue.js #vuex

#javascript #vue.js #vuex

Вопрос:

Я использую шаблон для получения данных из файла json, я использую «v-for» для печати всех данных, например:

 template: /*html*/
    ` 
    <div class="col-lg-8">
        <template v-for="item of actividades">
            <ul>
                <li>{{ item.date }}</li>
            <ul>
        </template>
    </div>
    `,
 

Но мне нужно использовать функции, year() для изменения этой информации и возврата и результата, например:

    template: /*html*/
    ` 
    <div class="col-lg-8">
        <template v-for="item of actividades">
            <ul>
                <li>{{ year(item.date) }}</li>
            <ul>
        </template>
    </div>
    `,
 

Значение {{ item.date }} выводит «2021-01-20», но я надеюсь напечатать «2021», используя функцию {{ year(item.date) }}

Код функции year() с использованием javascript:

 year(date){
            return String(date).substr(0, 4);
        }
 

Я пытался использовать этот код, но не работает, появляется эта ошибка:
это изображение показывает ошибку

Это мой код javascript:

 //VueEx
const store = new Vuex.Store({
    state: {
        actividades: [],
        programas: [],
        year: ""
    },
    mutations: {
        llamarJsonMutation(state, llamarJsonAction){
            state.actividades = llamarJsonAction.Nueva_estructura_proveedor;
            state.programas = llamarJsonAction.BD_programas;
        },
        yearFunction(state, date){
            state.year = String(date).substr(8, 2);
            return state.year;
        }
    },
    actions: {
        llamarJson: async function({ commit }){
            const data = await fetch('calendario-2021-prueba.json');
            const dataJson = await data.json();
            commit('llamarJsonMutation', dataJson);
        }
    }
});

//Vue
new Vue({
    el: '#caja-vue',
    store: store,
    created() {
        this.$store.dispatch('llamarJson');
      }
});
 

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

1. Как это не «работает»? Каков ожидаемый результат? Что на самом деле произошло?

2. Появляется ошибка цикла.

3. Какое сообщение об ошибке?

4. Ваша первая часть вопроса о компоненте, который зацикливает данные и нуждается в year функции, ваша вторая часть о хранилище vuex, но вы не показываете, как эти два взаимодействуют. Действительно сложно понять вашу проблему.

5. Я не уверен, что это позволяет использовать функцию внутри {{}} . В любом случае, я думаю, вы могли бы иметь дело с данными в функции llamarJsonMutation до того, как она была назначена actividades .

Ответ №1:

Внутри шаблона вы можете использовать функции, определенные как methods или computed . Технически вы также можете использовать data для передачи функции в шаблон, но я бы не рекомендовал это. Не то чтобы это не сработало, но Vue делает все, что объявлено в data reactive, и нет смысла делать функцию (которая в основном является константой) реактивной. Итак, в вашем случае:

 new Vue({
  el: '#app',
  data: () => ({
    actividades: [
      { date: '2021-01-20' },
      { date: '2020-01-20' },
      { date: '2019-01-20' },
      { date: '2018-01-20' },
      { date: '2017-01-20' }
    ]
  }),
  methods: {
    year(date) { return date.substring(0, 4); }
  }
}) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <ul>
      <li v-for="(item, key) in actividades" :key="key">
        {{ year(item.date) }}
      </li>
  </ul>
</div> 

Если по какой-то причине вы хотите передать year как computed :

 computed: {
  year() { return date => date.substring(0, 4); }
}
 

Но это запутанная конструкция (функция получения, возвращающая функцию внутренней стрелки), и эта сложность не служит никакой цели. Я бы рекомендовал вам использовать a method в вашем случае, так как он самый простой (легко читаемый / понятный).


Если вы импортируете year функцию из другого файла:

 import { year } from '../helpers'; // random example, replace with your import

// inside component's methods:

methods: {
  year, // this provides `year` imported function to the template, as `year`
        // it is equivalent to `year: year,`
  // other methods here
}
 

Примечания:

  • нет смысла перебирать <template> теги, которые содержат <ul> ‘s. Вы можете поместить v-for непосредственно в <ul> и потерять <template> (вы должны использовать только тогда, когда <template> хотите применить некоторую логику, то есть: a v-if — к куче элементов, фактически не оборачивая их в оболочку DOM; другой вариант использования — когда вы хотите, чтобы его дочерние элементы были прямыми потомкамиего родительского элемента: для <ul> / <li> или <tbody> / <tr> отношений, где у вас не может быть промежуточных оболочек между ними). В вашем случае размещение v-for на <ul> дает точно такой же результат с меньшим количеством кода.
  • вы всегда должны key использовать свои v-for : <ul v-for="(item, key) in actividades" :key="key"> . Ключи помогают Vue поддерживать состояние элементов списка, отслеживать анимации и корректно обновлять их

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

1. ваше объяснение потрясающее, большое вам спасибо.

Ответ №2:

Я вижу, вы пытаетесь работать с хранилищем Vuex. И использование мутации внутри синтаксиса шаблона.

Не уверен, можем ли мы вызвать мутацию напрямую через HTML, как вы делаете. В прошлом, когда я пытался вызвать мутацию, я бы либо:

 Vue.component('followers', {
  template: '<div>Followers: {{ computedFollowers }} {{printSampleLog()}}</div>',
  data() {
    return { followers: 0 }
  },
  created () {
    this.$store.dispatch('getFollowers').then(res => {
        this.followers = res.data.followers
    })
  },
  computed: {
    computedFollowers: function () {
        return this.followers
    }
  },
  methods:{
  printSampleLog(){
  this.$store.dispatch('sampleAction').then(res => {
        this.followers = res.data.followers
    })
  }
  }
});

const store = new Vuex.Store({
  actions: {
    getFollowers() {
      return new Promise((resolve, reject) => {
        axios.get('https://api.github.com/users/octocat')
          .then(response => resolve(response))
          .catch(err => reject(error))
      });
    },
    sampleAction(context){
    context.commit('sampleMutation');
    }
  },
  mutations: {
  sampleMutation(){
    console.log("sample mutation")
  }
  }
})

const app = new Vue({
    store,
  el: '#app'
}) 
 <script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<div id="app">
  <followers></followers>
</div> 

  • Иначе создайте метод без действия в вашем компоненте Vue, непосредственно фиксирующий мутацию, используя this.$store.commit()

PS: Рекомендовал бы сначала создать действие вокруг мутации, поскольку это гораздо более чистый подход.

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

1. @luis, дайте мне знать, правильно ли я понял ваш вопрос.

2. Совершенно безопасно вызывать mutation s или action s из любого места. Единственная разница в том, что action s являются async (и возвращают обещание — у них есть .then() ) и mutation s синхронны.