简体   繁体   中英

Vue.js Dynamic Component - Template not showing components data

I'm trying to build a quiz-game with VueJs and up until now everything worked out smoothly, but now that I'm started using dynamic components I'm running into issues with displaying the data.

I have a start component (Start View) that I want to be replaced by the actual Quiz component ("In Progress") when the user clicks on the start button. This works smoothly. But then, in the second components template, the data referenced with {{ self.foo }} does not show up anymore, without any error message.

The way I implemented is the following:

startComponent:

startComponent = {
    template: '#start-component',
    data: function () {
        return {
            QuizStore: QuizStore.data
        }
    },
    methods: {
        startQuiz: function () {
                this.QuizStore.currentComponent = 'quiz-component';
            }
        }
    }
};

And the template:

<script type="x-template" id="start-component">
    <div>
        <button v-on:click="startQuiz()">
            <span>Start Quiz</span>
        </button>
    </div>
</script>

Note: I'm using x-templates since it somehow makes the most sense with the rest of the application being Python/Flask. But everything is wrapped in {% raw %} so the brackets are not the issue.

Quiz Component:

quizComponent = {
    template: '#quiz-component',
    data: function () {
        return {
            QuizStore: QuizStore.data,
            question: 'foo',
    }
};

And the template:

<script type="x-template" id="quiz-component">
    <div>
        <p>{{ self.question }}</p>
    </div>
</script>

And as you might have seen I'm using a QuizStore that stores all the states.

The store:

const QuizStore = {
    data: {
        currentComponent: 'start-component',
    }
};

In the main .html I'm implementing the dynamic component as follows:

<div id="app">
    <component :is="QuizStore.currentComponent"></component>
</div>

So what works:

  • The Start screen with the button shows up.
  • When I click on the Start Button, the quizComponent shows up as expected.

What does not work:

  • The {{ self.question }} data in the QuizComponent template does not show up. And it does not throw an error message.
  • it also does not work with {{ question }}.

What I don't understand:

  • If I first render the quizComponent with setting QuizStore.currentComponent = 'startComponent' , the data shows up neatly.
  • If I switch back to <quiz-component></quiz-component> (rather than the dynamic components), it works as well.
  • So it seems to be the issue that this. does not refer to currently active dynamic component - so I guess here is the mistake? But then again I don't understand why there is no error message...

I can't figure out what the issue is here - anyone?

You may have some issues with your parent component not knowing about its child components, and your construct for QuizStore has a data layer that you don't account for when you set currentComponent .

 const startComponent = { template: '#start-component', data: function() { return { QuizStore: QuizStore.data } }, methods: { startQuiz: function() { this.QuizStore.currentComponent = 'quiz-component'; } } }; const QuizStore = { data: { currentComponent: 'start-component', } }; new Vue({ el: '#app', data: { QuizStore }, components: { quizComponent: { template: '#quiz-component', data: function() { return { QuizStore: QuizStore.data, question: 'foo' } } }, startComponent } }); 
 <script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script> <script type="x-template" id="start-component"> <div> <button v-on:click="startQuiz()"> <span>Start Quiz</span> </button> </div> </script> <script type="x-template" id="quiz-component"> <div> <p>{{ question }}</p> </div> </script> <div id="app"> <component :is="QuizStore.data.currentComponent"></component> </div> 

The following worked in the end:

I just wrapped <component :is="QuizStore.currentComponent"></component> in a parent component ("index-component") instead of putting it directly in the main html file:

<div id="app">
    <index-component></index-component>
</div>

And within the index-component:

<script type="x-template" id="index-component">
    <div>
        <component :is="QuizStore.currentComponent"></component>
    </div>
</script>

Maybe this would have been the right way all along, or maybe not, but it works now :) Thanks a lot Roy for your help!

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