Vue.js - globalne udostępnianie funkcji pomocniczych dla komponentów jednoplikowych

105

Mam projekt Vue 2, który ma wiele (50+) jednoplikowych komponentów . Używam Vue-Router do routingu i Vuex do stanu.

Istnieje plik o nazwie helpers.js , który zawiera kilka funkcji ogólnego przeznaczenia, takich jak wielkie litery w pierwszej literze ciągu. Ten plik wygląda następująco:

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

Mój plik main.js inicjuje aplikację:

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')

Plik My App.vue zawiera szablon:

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

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

Mam wtedy kilka komponentów jednoplikowych, które Vue-Router obsługuje przechodzenie do wewnątrz <router-view> jednoplikowych tagu w szablonie App.vue.

Powiedzmy teraz, że muszę użyć capitalizeFirstLetter()funkcji wewnątrz komponentu zdefiniowanego w SomeComponent.vue . Aby to zrobić, najpierw muszę go zaimportować:

<template>Some Component</template>

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

Szybko staje się to problemem, ponieważ w końcu importuję funkcję do wielu różnych komponentów, jeśli nie do wszystkich. Wydaje się to powtarzalne, a także utrudnia utrzymanie projektu. Na przykład, jeśli chcę zmienić nazwę helpers.js lub znajdujących się w nim funkcji, muszę przejść do każdego komponentu, który go importuje, i zmodyfikować instrukcję import.

Krótko mówiąc: jak sprawić, by funkcje zawarte w helper.js były globalnie dostępne, aby móc je wywoływać w dowolnym komponencie bez konieczności ich wcześniejszego importowania, a następnie dodawania thisdo nazwy funkcji? Zasadniczo chcę móc to zrobić:

<script>
export default {
    data() {
        return {
            myString = "test"
        }
    },
    created() {
         var newString = capitalizeFirstLetter(this.myString)
    }
}
</script>
Ege Ersoz
źródło
Możesz użyć globalnego miksu, ale musiałbyś użyć this.
Bert
2
Czy rozważałeś ujawnienie swoich pomocników jako filtrów, aby można było ich używać bezpośrednio w szablonach bez konieczności ich importowania? To strategia, którą obieram i jak na razie działa dobrze.
David Weldon,

Odpowiedzi:

160

wewnątrz dowolnego komponentu bez konieczności ich wcześniejszego importowania, a następnie dołączania tego do nazwy funkcji

To, co opisałeś, to mixin .

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

To jest mieszanka globalna. z tym WSZYSTKIE twoje komponenty będą miały capitalizeFirstLettermetodę, więc możesz wywołać this.capitalizeFirstLetter(...)z metod komponentów lub możesz wywołać ją bezpośrednio jakocapitalizeFirstLetter(...) w szablonie komponentów.

Przykład pracy: http://codepen.io/CodinCat/pen/LWRVGQ?editors=1010

Zobacz dokumentację tutaj: https://vuejs.org/v2/guide/mixins.html

CodinCat
źródło
Niezłe! Dzięki!
Alexey Shabramov
20
Byłoby miło mieć więcej szczegółów w tej odpowiedzi, na przykład jak przechowywać funkcję mixin w jej własnym dedykowanym pliku i jak zaimportować ją do main.js?
Alexis.Rolland
Jak mogę korzystać capitalizeFirstLetterz const vm = new Vue()instancji? Ponieważ vm.capitalizeFirstLetternie działa.
Marcelo Rodovalho
Czy wszystkie komponenty będą odwoływać się do capitalizeFirstLetterfunkcji w miksie, czy też będą miały swoją własną kopię? Szukam miejsca do przechowywania funkcji, która powinna być dostępna dla każdego komponentu, ale poza tym być z nimi niezwiązana (pobieranie danych z serwera do przechowywania w pamięci vuex)
Daniel F
Dzięki ! Działa dobrze w komponentach, ale nie w „store.js”. Mam miksera, który dostosowuje "console.log": "log: str => console.log ('% c' + str + '', 'background: #aaa; color: #fff; padding: 5px; border- promień: 5px ') ”. Jak mogę go używać w store.js?
bArraxas
66

W przeciwnym razie możesz spróbować sprawić, aby twoi pomocnicy działali jako wtyczka:

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

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

Vue.use(plugin)

Podczas helper.jseksportowania funkcji w ten sposób:

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 };

lub

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

Powinieneś wtedy móc ich używać w dowolnym miejscu komponentów, używając:

this.$helpers.capitalizeFirstLetter()

lub w dowolnym miejscu aplikacji przy użyciu:

Vue.helpers.capitalizeFirstLetter()

Możesz dowiedzieć się więcej na ten temat w dokumentacji: https://vuejs.org/v2/guide/plugins.html

Hammerbot
źródło
Proszę wymienić zawartość helpers.vue
Marius
Czy możesz podać przykład dostępu do sklepu Vue? ten. $ store działa w komponentach, ale nie w miksie.
Marius
1
Treść helpers.js jest w pytaniu
Hammerbot
Hej, wypróbowałem twoją metodę, ale dlaczego nie mogę uzyskać dostępu do Vue.helpers? to. $ helpers jest dostępne. Muszę uzyskać dostęp z zewnętrznego komponentu. Każdy może mi pomóc, byłby wdzięczny. Dzięki
Rifqi
11

Utwórz nową składankę:

„src / mixins / generalMixin.js”

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

Następnie zaimportuj go do pliku main.js, na przykład:

import '@/mixins/generalMixin'

Od teraz będziesz mógł używać tej funkcji jak this.capitalizeFirstLetter(str)w skrypcie komponentu lub bez niegothis szablonu.

Musisz użyć, thisponieważ wymieszałeś metodę z główną instancją Vue. Jeśli istnieją sposoby na usunięcie this, prawdopodobnie będzie to wiązało się z czymś niekonwencjonalnym, przynajmniej jest to udokumentowany sposób udostępniania funkcji, który będzie łatwy do zrozumienia dla przyszłych programistów Vue w Twoim projekcie.

wykopać
źródło
1

Korzystanie z pakietu Webpack v4

Utwórz osobny plik dla czytelności (po prostu wrzuciłem mój do folderu wtyczek). Przedruk z odpowiedzi @CodinCat i @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')
      }
    }
  })

Następnie zaimportuj do pliku main.js lub app.js

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

STOSOWANIE:

Zadzwoń this.sampleFunction()lubthis.capitalizeFirstLetter()

DAVID AJAYI
źródło
1

Użyj filtru globalnego, jeśli dotyczy on tylko sposobu formatowania danych podczas renderowania. To jest pierwszy przykład w dokumentacji :

{{ message | capitalize }}
Vue.filter('capitalize', function (value) {
  if (!value) return ''
  value = value.toString()
  return value.charAt(0).toUpperCase() + value.slice(1)
})
ellisdod
źródło
0

Świetne pytanie. W moich badaniach stwierdziłem, że vue-inject radzi sobie z tym najlepiej. Mam wiele bibliotek funkcji (usług) oddzielonych od standardowych metod obsługi logiki komponentów vue. Mój wybór polega na tym, aby metody składowe były delegatorami wywołującymi funkcje usług.

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

user3525949
źródło
-5

Zaimportuj go do pliku main.js, tak jak „store”, a będziesz mieć do niego dostęp we wszystkich komponentach.

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
źródło
11
czy potrafisz uzupełnić odpowiedź, pokazując, jak go wykorzystać w komponencie?
JeanValjean