Vue 3 composition API and access to Vue instance

前端 未结 2 1864
夕颜
夕颜 2021-01-17 13:27

In main.js I have something like this:

import { myUtilFunc} from \'./helpers\';
Object.defineProperty(Vue.prototype, \'$myUtilFunc\', { value: m         


        
相关标签:
2条回答
  • 2021-01-17 13:45

    While Dan's answer is correct, I would like to provide an alternative mentioned in the comments to the accepted answer. There are pros and cons to each, so, you need to choose based on your needs.

    To understand why the code below works, it is important to remember, that provided properties are transitive in the tree of components. I.e. inject('foo') will look for 'foo' in every parent going up the hierarchy all the way to the app; there is no need to declare anything in the middle wrappers.

    So, we can write something like this, where globalDateFormatter() is just an example function we want to use in any component down the tree:

    main.js

    import { createApp } from 'vue'
    import App from './App.vue'
    
    const globalDateFormatter = (date) => {
        return '[' + date.toLocaleString() + ']'
    }
    
    const app = createApp(App)
    app.provide('globalDateFormatter', globalDateFormatter) // <-- define here
    app.mount('#app')
    

    And then, in some DeepDownComponent.vue:

    <template>
      <p> {{ fmt(new Date()) }} </p>
    </template>
    
    <script>
    import { inject } from 'vue'
    export default {
        setup(){
            const fmt = inject('globalDateFormatter', x => x.toString()) 
            //           ^-- use here, optional 2nd parameter is the default
            return {fmt}
        }
    }
    </script>
    

    Obviously, you can directly import and use provide and inject with the following signatures

    provide<T>(key: InjectionKey<T> | string, value: T): void
    

    and

    inject<T>(key: InjectionKey<T> | string, defaultValue: T): T
    

    anywhere in your code, doesn't have to be app.provide()

    You can also provide values, even the global store, like this, just don't forget to use ref() or reactive() as needed.

    In short, whenever you would prefer dependency injection, provide/inject are your friends.

    0 讨论(0)
  • 2021-01-17 13:55

    Use provide/inject

    Provide

    const app = createApp(App);
    app.provide('someVarName', someVar);  // `Provide` a variable to all components here
    

    Inject:

    // In *any* component
    const { inject } = Vue;
    ...
    setup() {
      const someVar = inject('someVarName');   // injecting variable in setup
    }
    

    Note that you don't have to provide from the app root, but can also provide from any component to only its sub-components:

    // In *any* component
    setup() {
      ...
    },
    provide() {
      return {
        someVarName: someVar
      }
    }
    

    Original answer

    [Edit: While my original answer below is still useful for context properties, it's no longer recommended to use context.root, which is no longer mentioned in the guide and may soon be deprecated.]

    In Vue 3, setup has an optional second argument for context. You can access the Vue instance through context.root instead of this:

    setup(props, context) {
      context.root.$myUtilFunc  // same as `this.$myUtilFunc` in Vue 2
    }
    

    Things you can access through context:

    context.attrs
    context.slots
    context.parent
    context.root
    context.emit
    
    0 讨论(0)
提交回复
热议问题