0

Motivation:

I have a single file component, say Player, which displays video or show some images. Since it costs huge amount of memory, and it is used in many pages (components under root), I want to instantiate it only once and reuse it in every page depending on it. Also, Player is resized for some pages, so I need it to be dynamically adjustable, which means it should support props. Furthermore, since there are many pages using Player, I hope I can use Provide / Inject feature of Vue to spreading Player everywhere.

Current:

// Player
<template>
    <div>
        ... // display images and video
    </div>
</template>

<script>
export default Vue.extend({
    props: {
        width: {
            type: Number,
            default: 284,
        },
        height: {
            type: Number,
            default: 214,
        },
    },
    data() {
        ... // images and video
    },
    methods: {
        ... // logic related to images and video
    },
})
// An example of `pages`
<template>
    <div>
        <player
            :width="592"
            :height="333"
        />
    ... // some other logic
    </div>
</template>

... // everything else

Expect:

To sum up, Player has these features in my imagination:

  1. Initiated in root component.
  2. The root component Provide Player to every component under it.
  3. Pages under root can pass props to the Injected Player somehow to resize it.

This is just my imagination, any other available solution is welcome.

What I've tried:

  • I tried to initiate Player in memory, but I don't know how to render it.
  • I tried to initiate Player as a dynamic component, but I don't know where to place the slot and how to initiate Player.
  • I tried to understand render function to re-render it, but I don't know how to leverage it in my case.
  • This post seems to be the closest solution, but I am still confused how to implement the concept with limited description in it.
5
  • Kind of sounds like you might want to create a composable. vuejs.org/guide/reusability/… Commented Nov 28, 2022 at 4:28
  • Thanks for the comment. However, as the tip in the link says, it seems that each component instance depending on a composable tends to create a copy of it. This is not what I need. FYI, TIP: "Each component instance calling useMouse() will create its own copies of x and y state so they won't interfere with one another." Commented Nov 29, 2022 at 9:46
  • vuejs.org/guide/scaling-up/… Although here we are using a single reactive object as a store, you can also share reactive state created using other Reactivity APIs such as ref() or computed(), or even return global state from a Composable Commented Nov 29, 2022 at 10:26
  • BTW Mixins are deprecated in vue3 and the docs suggest you use composables to replace them. vuejs.org/api/options-composition.html#mixins In Vue 2, mixins were the primary mechanism for creating reusable chunks of component logic. While mixins continue to be supported in Vue 3, Composition API is now the preferred approach for code reuse between components. Commented Nov 29, 2022 at 10:57
  • Sorry that I did not mention I was building a Vue 2 based project for some reason. So solution to Vue 2 is preferable for me. The Vue 3 solution may help others, though. On the other hands, I tried mixin in the answer below but I am still not able to achieve what I need. I am still confused about how to share a single state of a certain component in different components depending on it, with Vue 2. Commented Nov 30, 2022 at 6:22

1 Answer 1

0

There are two ways to do this-

  1. Globally import the component in the main.js file and use on any page freely. i.e.-
    import Vue from "vue";  
    import Player from "@/components/Player.vue";  
    Vue.component("AppButton", AppButton); 
  1. Create a mixin named playerMixin.js inside the mixins directory.
    Import the Player component inside that mixin and import that mixin in all pages.
    The mixin code should look like this-

playerMixin.js

import Player from "@/components/Player.vue";

export const playerMixin = {
  data() {
    // any data properties related to player functionalities 
  },

  components: {
    Player,
  },

  methods: {
    // any methods related to player functionalities
  }
}

Now, you can use this mixin on any page, like this-

AnyPage.vue

import { playerMixin} from "@/mixins/playerMixin.js";

export default {
  name: "AnyPage",
  mixins: [playerMixin],
}

The main benefit of using mixin is that not only components will be imported once but the common functionality of Player which is the same for every page like passing props, and methods like play, a pause can be written once and can be used by any page.

To understand more about mixin, read this.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer. However, although I can import Player only once, both approaches seem to instantiate Player separately in different pages. More specifically, the first approach seems to just register Player globally once and I still need to instantiate it everytime I need to use it. And the second approach seems to just reuse the code itself by mixin, that does not change the fact that Player should be instantiated in every page. In my experiment, I print log messages in created hook in Player, and both approaches give the same result that the log is printed more than once.
If helps, you can check this answer- stackoverflow.com/questions/71554507/….

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.