Vue.js - Rendre les fonctions d'assistance disponibles globalement pour les composants à un seul fichier

100

J'ai un projet Vue 2 qui a de nombreux (50+) composants mono-fichier . J'utilise Vue-Router pour le routage et Vuex pour l'état.

Il existe un fichier, appelé helpers.js , qui contient un ensemble de fonctions générales, telles que la mise en majuscule de la première lettre d'une chaîne. Ce fichier ressemble à ceci:

export default {
    capitalizeFirstLetter(str) {
        return str.charAt(0).toUpperCase() + str.slice(1);
    }
}

Mon fichier main.js initialise l'application:

import Vue from 'vue'
import VueResource from "vue-resource"
import store from "./store"
import Router from "./router"
import App from "./components/App.vue"

Vue.use(VueResource)

const app = new Vue({
    router: Router,
    store,
    template: '<app></app>',
    components: { App }
}).$mount('#app')

Mon fichier App.vue contient le modèle:

<template>
    <navbar></navbar>
    <div class="container">
        <router-view></router-view>
    </div>
</template>

<script>
export default {
    data() {
        return {
            //stuff
        }
    }
}
</script>

J'ai alors un tas de composants à fichier unique, que Vue-Router gère pour naviguer à l'intérieur de la <router-view>balise dans le modèle App.vue.

Maintenant, disons que j'ai besoin d'utiliser la capitalizeFirstLetter()fonction dans un composant défini dans SomeComponent.vue . Pour ce faire, je dois d'abord l'importer:

<template>Some Component</template>

<script>
import {capitalizeFirstLetter} from '../helpers.js'
export default {
    data() {
        return {
            myString = "test"
        }
    },
    created() {
         var newString = this.capitalizeFirstLetter(this.myString)
    }
}
</script>

Cela devient rapidement un problème car je finis par importer la fonction dans de nombreux composants différents, sinon dans tous. Cela semble répétitif et rend également le projet plus difficile à maintenir. Par exemple, si je veux renommer helpers.js, ou les fonctions qu'il contient, je dois ensuite accéder à chaque composant qui l'importe et modifier l'instruction d'importation.

Pour faire court: comment rendre les fonctions de helpers.js globalement disponibles afin de pouvoir les appeler dans n'importe quel composant sans avoir à les importer au préalable, puis à les ajouter thisau nom de la fonction? Je veux essentiellement pouvoir faire ceci:

<script>
export default {
    data() {
        return {
            myString = "test"
        }
    },
    created() {
         var newString = capitalizeFirstLetter(this.myString)
    }
}
</script>
Ege Ersoz
la source
Vous pourriez utiliser un mixin global, mais vous devrez utiliser this.
Bert
2
Avez-vous envisagé d'exposer vos helpers en tant que filtres afin qu'ils puissent être utilisés directement dans vos modèles sans avoir besoin de les importer? C'est la stratégie que je prends et ça marche bien jusqu'à présent.
David Weldon

Réponses:

154

à l'intérieur de n'importe quel composant sans avoir à les importer d'abord, puis ajoutez-le au nom de la fonction

Ce que vous avez décrit est mixin .

Vue.mixin({
  methods: {
    capitalizeFirstLetter: str => str.charAt(0).toUpperCase() + str.slice(1)
  }
})

C'est un mixin global. avec cela TOUS vos composants auront une capitalizeFirstLetterméthode, vous pouvez donc appeler this.capitalizeFirstLetter(...)des méthodes de composant ou vous pouvez l'appeler directement comme capitalizeFirstLetter(...)dans le modèle de composant.

Exemple de travail: http://codepen.io/CodinCat/pen/LWRVGQ?editors=1010

Voir la documentation ici: https://vuejs.org/v2/guide/mixins.html

CodinCat
la source
Joli! Merci!
Alexey Shabramov
20
Ce serait bien d'avoir plus de détails dans cette réponse, comme comment stocker la fonction mixin dans son propre fichier dédié et comment l'importer dans main.js?
Alexis.Rolland
Comment puis-je utiliser à capitalizeFirstLetterpartir d'une const vm = new Vue()instance? Parce que vm.capitalizeFirstLetterça ne marche pas.
Marcelo Rodovalho
Tous les composants feront-ils référence à la capitalizeFirstLetterfonction dans le mixin ou en auront-ils leur propre copie? Je recherche un endroit pour stocker une fonction qui devrait être accessible à tous les composants, mais sans aucun rapport avec eux (récupérer les données d'un serveur pour les stocker dans un stockage vuex)
Daniel F
Merci ! Cela fonctionne bien dans les composants mais pas dans "store.js". J'ai un mixin qui personnalise le "console.log": "log: str => console.log ('% c' + str + '', 'background: #aaa; color: #fff; padding: 5px; border- rayon: 5px ') ". Comment puis-je l'utiliser dans store.js s'il vous plaît?
bArraxas
66

Sinon, vous pouvez essayer de faire fonctionner vos helpers avec un plugin:

import Vue from 'vue'
import helpers from './helpers'

const plugin = {
  install () {
    Vue.helpers = helpers
    Vue.prototype.$helpers = helpers
  }
}

Vue.use(plugin)

Dans votre helper.jsexportation de vos fonctions, de cette façon:

const capFirstLetter = (val) => val.charAt(0).toUpperCase() + val.slice(1);
const img2xUrl = (val) => `${val.replace(/(\.[\w\d_-]+)$/i, '@2x$1')} 2x`;

export default { capFirstLetter, img2xUrl };

ou

export default { 
  capFirstLetter(val) {
    return val.charAt(0).toUpperCase() + val.slice(1);
  },
  img2xUrl(val) {
    return `${val.replace(/(\.[\w\d_-]+)$/i, '@2x$1')} 2x`;
  },
};

Vous devriez alors pouvoir les utiliser n'importe où dans vos composants en utilisant:

this.$helpers.capitalizeFirstLetter()

ou n'importe où dans votre application en utilisant:

Vue.helpers.capitalizeFirstLetter()

Vous pouvez en savoir plus à ce sujet dans la documentation: https://vuejs.org/v2/guide/plugins.html

Hammerbot
la source
Veuillez lister le contenu de helpers.vue
Marius
Pourriez-vous inclure un exemple sur la façon d'accéder au magasin Vue? this. $ store fonctionne dans les composants, mais pas dans un mixin.
Marius
1
Le contenu de helpers.js est dans la question
Hammerbot
9

Créez un nouveau mixin:

"src / mixins / generalMixin.js"

Vue.mixin({
  methods: {
    capitalizeFirstLetter(str) {
        return str.charAt(0).toUpperCase() + str.slice(1);
    }    
  }
})

Puis importez-le dans votre main.js comme:

import '@/mixins/generalMixin'

À partir de maintenant, vous pourrez utiliser la fonction comme this.capitalizeFirstLetter(str)dans votre script de composant ou sans thisdans un modèle.

Vous devez utiliser thisparce que vous avez mélangé une méthode dans l'instance principale de Vue. S'il existe des moyens de le supprimer, thiscela impliquera probablement quelque chose de non conventionnel, c'est au moins une manière documentée de partager des fonctions qui sera facile à comprendre pour tous les futurs développeurs Vue de votre projet.

déterrer
la source
1

Utilisation de Webpack v4

Créez un fichier séparé pour la lisibilité (vient de déposer le mien dans le dossier plugins). Reproduit des réponses @CodinCat et @digout

//resources/js/plugins/mixin.js
import Vue from 'vue'

Vue.mixin({
    methods: {
      capitalizeFirstLetter: str => str.charAt(0).toUpperCase() + str.slice(1),
      sampleFunction(){
        alert('Global Functions')
      }
    }
  })

Puis importez dans votre fichier main.js ou app.js

//app.js
import mixin from './plugins/mixin' 

USAGE:

Appelez this.sampleFunction()outhis.capitalizeFirstLetter()

DAVID AJAYI
la source
1

Utilisez un filtre global s'il ne concerne que la mise en forme des données lors du rendu. Voici le premier exemple de la documentation :

{{ message | capitalize }}
Vue.filter('capitalize', function (value) {
  if (!value) return ''
  value = value.toString()
  return value.charAt(0).toUpperCase() + value.slice(1)
})
Ellisdod
la source
0

Excellente question. Dans mes recherches, j'ai trouvé que vue-inject peut gérer cela de la meilleure façon. J'ai de nombreuses bibliothèques de fonctions (services) séparées des méthodes de gestion de la logique des composants vue standard. Mon choix est que les méthodes des composants soient simplement des délégués qui appellent les fonctions de service.

https://github.com/jackmellis/vue-inject

user3525949
la source
-5

Importez-le dans le fichier main.js comme 'store' et vous pourrez y accéder dans tous les composants.

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store,
  router,
  render: h => h(App)
})
user2090357
la source
11
pouvez-vous compléter la réponse en montrant comment l'utiliser dans un composant?
JeanValjean