【问题标题】:Vue.js - 使辅助函数对单文件组件全局可用
【发布时间】:2017-07-25 13:56:59
【问题描述】:

我有一个 Vue 2 项目,其中有很多 (50+) 个single-file components。我用 Vue-Router 做路由,用 Vuex 做状态。

有一个名为 helpers.js 的文件,其中包含一堆通用函数,例如将字符串的第一个字母大写。该文件如下所示:

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

我的 ma​​in.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>

然后我有一堆单文件组件,Vue-Router 处理导航到 App.vue 模板中的 &lt;router-view&gt; 标记内。

现在假设我需要在 SomeComponent.vue 中定义的组件内使用capitalizeFirstLetter() 函数。为此,我首先需要导入它:

<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 中的函数全局可用,以便我可以在 any 组件中调用它们而无需必须先导入它们,然后在函数名称前面加上this?我基本上希望能够做到这一点:

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

【问题讨论】:

  • 你可以使用全局 mixin,但你必须使用 this
  • 您是否考虑过将您的助手公开为filters,以便它们可以直接在您的模板中使用而无需导入它们?这就是我正在采取的策略,到目前为止效果很好。

标签: vue.js vuejs2 vue-component vuex vue-router


【解决方案1】:

在任何组件中,无需先导入它们,然后将其添加到函数名称之前

你描述的是mixin

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

【讨论】:

  • 如果能在此答案中提供更多详细信息,例如如何将 mixin 函数存储在其自己的专用文件中以及如何将其导入 main.js 中,那就太好了?
  • 我如何在const vm = new Vue() 实例中使用capitalizeFirstLetter?因为vm.capitalizeFirstLetter 不起作用。
  • 所有组件会在 mixin 中引用 capitalizeFirstLetter 函数还是拥有自己的副本?我正在寻找一个存储功能的地方,该功能应该可供每个组件访问,但与它们无关(从服务器获取数据以存储在 vuex 存储中)
  • 谢谢!它在组件中运行良好,但在“store.js”中运行良好。我有一个自定义“console.log”的mixin:“log:str => console.log('%c' + str + '', 'background:#aaa; color:#fff; padding: 5px;border-半径:5px')”。请问如何在 store.js 中使用它?
  • 谁不明白怎么调用:需要在你的main.js中添加Vue.mixin,而不是.vue文件;)
【解决方案2】:

否则,您可以尝试使您的助手功能成为插件:

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

【讨论】:

  • 嘿,我试过你的方法,但为什么我似乎无法访问 Vue.helpers ? this.$helpers 是可访问的。我需要从外部组件访问。任何人都可以帮助我将不胜感激。谢谢
【解决方案3】:

创建一个新的mixin:

“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。即:

<template>
    <div>{{ capitalizeFirstLetter('hello') }}</div>
</template>

您必须使用this,因为您在主 Vue 实例中混入了一个方法。如果有删除this 的方法,它可能会涉及一些非常规的东西,这至少是documented way 的共享功能,对于您项目的任何未来Vue 开发人员来说都很容易理解。

【讨论】:

    【解决方案4】:

    使用 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()

    【讨论】:

      【解决方案5】:

      如果只关注渲染时数据的格式,请使用全局过滤器。这是docs中的第一个例子:

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

      【讨论】:

        【解决方案6】:

        很好的问题。在我的研究中,我发现 vue-inject 可以以最好的方式处理这个问题。我有许多与标准 vue 组件逻辑处理方法分开的函数库(服务)。我的选择是让组件方法只是调用服务函数的委托者。

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

        【讨论】:

          【解决方案7】:

          像'store'一样在main.js文件中导入,就可以在所有组件中访问了。

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

          【讨论】:

            猜你喜欢
            • 2016-03-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-01
            • 2011-06-24
            • 2020-08-14
            相关资源
            最近更新 更多