简体   繁体   中英

Create class instance and inject it dynamically

My project is using Nuxt, and I would like to implement dynamic injection of my services. It means I just add a class to my specific folder, and the class will be automatically injected into the context.

For instance, these are my classes placed in nuxtApp/service :

// /service/foo.service.js
export class FooService {
  constructor (context) {
    this.context = context
  }
  
  functionFoo (param) {
    console.log(`FooService.functionFoo: ${param}`)
  }
}

// /service/bar.service.js
export class BarService {
  constructor (context) {
    this.context = context
  }
  
  functionBar (param) {
    console.log(`BarService.functionBar: ${param}`)
  }
}

And this is how my plugin currently looks like, but I would like to automate it:

// /plugins/service-loader.js
import { FooService } from '../service/foo.service'
import { BarService } from '../service/bar.service'

export default ({ app }, inject) => {
  const fooService = new FooService(app)
  inject('fooService', fooService)

  const barService = new BarService(app)
  inject('barService', barService)
}

Is it possible to create automatically loading of services placed in the /service folder, and then inject their instance into the context?

You could use a Nuxt module to provide plugins for ~/service/*.service.js . The module would scan the service/ directory, and call addPlugin() for each .service.js file:

// ~/modules/service-loader.js
import path from 'path'
import glob from 'glob'

export default function serviceLoader() {
  glob(path.resolve(__dirname, '../service/**/*.service.js'), { follow: true }, (err, files) => {
    if (err) throw err

    for (const file of files) {
      const exportedMembers = Object.keys(require(file))
      if (!exportedMembers.length) return

      const className = exportedMembers[0]
      this.addPlugin({
        src: path.resolve(__dirname, './service-template.js'),
        fileName: path.basename(file),
        options: {
          className,
          propName: className.slice(0,1).toLowerCase() + className.substring(1),
          moduleName: file,
        }
      })
    }
  })
}
// ~/modules/service-template.js
import { <%= options.className %> } from '<%= options.moduleName %>'

export default ({ app }, inject) => {
  const <%= options.propName %> = new <%= options.className %> (app)
  inject('<%= options.propName %>', <%= options.propName %>)
}

Install this module under the modules array in your Nuxt config:

// nuxt.config.js
export default {
  modules: [
    '~/modules/service-loader'
  ],
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM