Vue.JS impossible d'initialiser une propriété

Default
,

Bonjour,

J'ai créé un petit composant autocomplete sur un input, avec une props en dur j'arrive à le charger mais je cherche maintenant à l'initialiser sur le resultat d'un appel ajax.
J'ai procédé comme ça:

import axios from 'axios';

export default {
    name: 'autocomplete',
    props: {
        isAsync: {
            type: Boolean,
            required: false,
            default: false,
        },
    },
    data() {
        return {
            items: [],
            isOpen: false,
            results: [],
            search: '',
            isLoading: false,
            arrowCounter: 0,
        };
    },
    methods: {
        onChange() {
            // Let's warn the parent that a change was made
            this.$emit('input', this);

            // Is the data given by an outside ajax request?
            if (this.isAsync) {
                this.isLoading = true;
            } else {
                // Let's  our flat array
                this.filterResults();
                this.isOpen = true;
            }
        },

        filterResults() {
            // first uncapitalize all the things
            this.results = this.items.filter((item) => {
                return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1;
            });
        },
        setResult(result) {
            this.search = result;
            this.isOpen = false;
        },
        onArrowDown(evt) {
            if (this.arrowCounter < this.results.length) {
                this.arrowCounter = this.arrowCounter + 1;
            }
        },
        onArrowUp() {
            if (this.arrowCounter > 0) {
                this.arrowCounter = this.arrowCounter -1;
            }
        },
        onEnter() {
            this.search = this.results[this.arrowCounter];
            this.isOpen = false;
            this.arrowCounter = -1;
        },
        handleClickOutside(evt) {
            if (!this.$el.contains(evt.target)) {
                this.isOpen = false;
                this.arrowCounter = -1;
            }
        }
    },
    watch: {
        items: function (val, oldValue) {
            // actually compare them
            if (val.length !== oldValue.length) {
                this.results = val;
                this.isLoading = false;
            }
        },
    },
    mounted() {
        document.addEventListener('click', this.handleClickOutside)
        axios.get(`http://jsonplaceholder.typicode.com/posts`)
            .then(function(response){
                for (var i = 0; i < response.data.length; i++) {
                    console.log(this);
                    //this.items.push(response.data[i].title)
                }
            })
    },
    destroyed() {
        document.removeEventListener('click', this.handleClickOutside)
    }
};

mais le console.log(this); me retourne un undefined. comment initialiser et mettre à jour cette propriété ?

1 Réponse

7314
,

Salut, ce n'est pas un problème de VueJS mais de scope en JS. Lorsque tu définies une nouvelle fonction avec function() {}, tu crées un nouveau scope. Il faut donc binder ton scope avec le scope global. Pour cela tu as deux solutions:

1) utiliser Function.prototype.bind() https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Function/bind. Valide ES5.

axios.get(`http://jsonplaceholder.typicode.com/posts`)
  .then(function(response){
    for (var i = 0; i < response.data.length; i++) {
      console.log(this);
      //this.items.push(response.data[i].title)
    }
}.bind(this))

2) Utiliser une arrow function https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions, qui garde le scope parent. Attention, c'est une nouveauté de ES6, si tu vises des anciens navigateurs, il faudra utiliser un compilateur pour compiler le code en ES5.

axios.get(`http://jsonplaceholder.typicode.com/posts`)
  .then((response) => {
    for (var i = 0; i < response.data.length; i++) {
      console.log(this);
      //this.items.push(response.data[i].title)
    }
})

Je t'invite à lire ceci : https://hackernoon.com/understanding-javascript-the-this-keyword-4de325d77f68