Vue.js - глобальная доступность вспомогательных функций для однофайловых компонентов

105

У меня есть проект Vue 2, в котором много (50+) однофайловых компонентов . Я использую Vue-Router для маршрутизации и Vuex для состояния.

Существует файл helpers.js , который содержит набор функций общего назначения, таких как использование заглавной буквы в строке. Этот файл выглядит так:

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

Мой файл main.js инициализирует приложение:

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

Мой файл App.vue содержит шаблон:

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

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

Затем у меня есть набор <router-view>однофайловых компонентов, которые Vue-Router обрабатывает, перемещаясь внутри тега в шаблоне App.vue.

Теперь предположим, что мне нужно использовать capitalizeFirstLetter()функцию внутри компонента, определенного в SomeComponent.vue . Для этого мне сначала нужно импортировать его:

<template>Some Component</template>

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

Это быстро становится проблемой, потому что я импортирую функцию во множество различных компонентов, если не во все из них. Это кажется повторяющимся, а также затрудняет поддержку проекта. Например, если я хочу переименовать helpers.js или функции внутри него, мне нужно перейти к каждому компоненту, который его импортирует, и изменить оператор импорта.

Короче говоря: как сделать функции внутри helpers.js глобально доступными, чтобы я мог вызывать их внутри любого компонента без необходимости сначала импортировать их, а затем добавлять thisк имени функции? Я в принципе хочу уметь это делать:

<script>
export default {
    data() {
        return {
            myString = "test"
        }
    },
    created() {
         var newString = capitalizeFirstLetter(this.myString)
    }
}
</script>
Эге Эрсоз
источник
Вы можете использовать глобальный миксин, но вам придется использовать this.
Берт
2
Рассматривали ли вы возможность использования помощников в качестве фильтров, чтобы их можно было использовать непосредственно в ваших шаблонах без необходимости их импорта? Я придерживаюсь этой стратегии, и пока она работает хорошо.
Дэвид Уэлдон

Ответы:

160

внутри любого компонента без необходимости сначала импортировать их, а затем добавлять это к имени функции

Вы описали миксин .

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

Это глобальный миксин. при этом ВСЕ ваши компоненты будут иметь capitalizeFirstLetterметод, поэтому вы можете вызывать их this.capitalizeFirstLetter(...)из методов компонента или напрямую, как capitalizeFirstLetter(...)в шаблоне компонента.

Рабочий пример: http://codepen.io/CodinCat/pen/LWRVGQ?editors=1010

См. Документацию здесь: https://vuejs.org/v2/guide/mixins.html

CodinCat
источник
Хороший! Благодарность!
Алексей Шабрамов
20
Было бы неплохо получить более подробную информацию в этом ответе, например, как вы храните функцию микширования в отдельном файле и как импортировать ее в main.js?
Alexis.Rolland
Как я могу использовать capitalizeFirstLetterиз const vm = new Vue()экземпляра? Потому vm.capitalizeFirstLetterчто не работает.
Марсело Родовальо
Все ли компоненты будут ссылаться на capitalizeFirstLetterфункцию в миксине или у них будет ее собственная копия? Я ищу место для хранения функции, которая должна быть доступна для каждого компонента, но в остальном не связана с ними (получение данных с сервера для хранения в хранилище vuex)
Daniel F
Благодарность ! Он хорошо работает в компонентах, но не в store.js. У меня есть миксин, который настраивает "console.log": "log: str => console.log ('% c' + str + '', 'background: #aaa; color: #fff; padding: 5px; border- радиус: 5 пикселей ') ". Как я могу использовать его в store.js, пожалуйста?
bArraxas,
66

В противном случае вы можете попытаться заставить своих помощников работать с плагином:

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

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

Vue.use(plugin)

В вашем helper.jsэкспорте ваши функции следующим образом:

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

или

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

Затем вы сможете использовать их в любом месте своих компонентов, используя:

this.$helpers.capitalizeFirstLetter()

или в любом месте вашего приложения, используя:

Vue.helpers.capitalizeFirstLetter()

Подробнее об этом можно узнать в документации: https://vuejs.org/v2/guide/plugins.html.

Хаммербот
источник
Пожалуйста, перечислите содержимое helpers.vue
Мариус
Не могли бы вы включить пример того, как получить доступ к магазину Vue? this. $ store работает в компонентах, но не в миксине.
Мариус
1
Под вопросом содержание helpers.js
Hammerbot
Эй, я попробовал ваш метод, но почему я не могу получить доступ к Vue.helpers? this. $ helpers доступен. Мне нужен доступ из внешнего компонента. Любой, кто может мне помочь, будет признателен. Спасибо
Рифки
11

Создайте новый миксин:

"src / mixins / generalMixin.js"

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

Затем импортируйте его в свой main.js, например:

import '@/mixins/generalMixin'

С этого момента вы сможете использовать эту функцию как this.capitalizeFirstLetter(str)в сценарии компонента, так и без него thisв шаблоне.

Вы должны использовать, thisпотому что вы смешали метод с основным экземпляром Vue. Если есть способы удалить thisэто, вероятно, будет связано что-то нетрадиционное, это, по крайней мере, документированный способ совместного использования функций, который будет легко понять любым будущим разработчикам Vue для вашего проекта.

выкопать
источник
1

Использование Webpack v4

Создайте отдельный файл для удобства чтения (просто закинул мой в папку плагинов). Воспроизведено из ответов @CodinCat и @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')
      }
    }
  })

Затем импортируйте в файл main.js или app.js

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

ПРИМЕНЕНИЕ:

Звоните this.sampleFunction()илиthis.capitalizeFirstLetter()

ДЭВИД АДЖАИ
источник
1

Используйте глобальный фильтр, если он касается только того, как данные форматируются при визуализации. Это первый пример в документации :

{{ message | capitalize }}
Vue.filter('capitalize', function (value) {
  if (!value) return ''
  value = value.toString()
  return value.charAt(0).toUpperCase() + value.slice(1)
})
эллисдод
источник
0

Отличный вопрос. В своем исследовании я обнаружил, что vue-inject может справиться с этим наилучшим образом. У меня есть много библиотек функций (служб), которые хранятся отдельно от стандартных методов обработки логики компонентов vue. Я предпочитаю, чтобы методы компонентов были просто делегаторами, вызывающими служебные функции.

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

user3525949
источник
-5

Импортируйте его в файл main.js точно так же, как store, и вы сможете получить к нему доступ во всех компонентах.

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
источник
11
Можете ли вы заполнить ответ, показывающий, как использовать его в компоненте?
JeanValjean