【问题标题】:Vue2 - how to recreate component?Vue2 - 如何重新创建组件?
【发布时间】:2018-09-21 12:30:40
【问题描述】:

如何在单击按钮后重新创建整个组件。

假设我在组件“UserPanel”中,并且有一个名为“Refresh”的按钮。 当我单击该按钮时,我想销毁组件并从头开始创建它。我不会使用“vm.$forceUpdate()”之类的选项,因为它对我的情况没有帮助。

有什么办法吗?

我的应用代码:

App.vue:

<template>
    <div id="main-cont">
        <NavBar></NavBar>
        <router-view></router-view>
    </div>
</template>

<script>

import NavBar from './components/TopBar/NavBar';
import {mapActions,mapGetters} from 'vuex';
import axios from 'axios';

    export default {
        name: 'App',
        components: {
            NavBar,
        },
        computed:{
            ...mapGetters(['isLoggedIn'])
        },
        methods:{
            ...mapActions(['loadLanguage','setToken','setUserLogged','loadUserProfile'])
        },
        created(){
            this.loadLanguage();
            this.setToken();
            let userLoggedIn = document.head.querySelector('meta[name="logged"]').content;
            if(userLoggedIn){
                this.setUserLogged();
                this.loadUserProfile();
            }

        }

    }

</script>

<style scoped>
    #main-cont{
        height: 100%;
    }
</style>

main.js:

import Vue from 'vue';
import VueRouter from 'vue-router';
import VueCookie from 'vue-cookie';
import store from './store';
import App from './App';


//Components
import Main from './components/main/Main';
import UserRegister from './components/user/UserRegister';
import ResetPassword from './components/user/ResetPassword';
import UserEdit from './components/user/UserEdit';
import UserView from './components/user/UserView.vue';
import GameMain from './components/game/GameMain';
import GamesList from './components/main/GameList';
import Hall from './components/main/Hall';
import Language from './components/main/Language';
import GameCreate from './components/game/GameCreate';

//Plugins
import langPlugin from './langPlugin';
import VTooltip from 'v-tooltip';

Vue.use(VueRouter);
Vue.use(VueCookie);
Vue.use(langPlugin);

export const router = new VueRouter({
    mode: 'history',
    routes: [
        {path: '/', component: Main},
        {path: '/user-register', component: UserRegister},
        {path: '/user-edit', component: UserEdit},
        {path: '/password-reset', component: ResetPassword},
        {path: '/user', component: UserView},
        {path: '/game', component: GameMain},
        {path: '/game-create', component: GameCreate},
        {path: '/games-list', component: GamesList},
        {path: '/hall-of-fame', component: Hall},
        {path: '/language', component: Language},

    ]
});

new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app');

要重新加载的组件。 游戏创建:

<Template>
    <div>
        <button @click="reloadThisComponent"></button>
    </div>
</Template>
<script>
    export default{
        name: 'GameCreate',
        methods:{
            reloadThisComponent(){

            }
        }
    }
</script>

谢谢。

【问题讨论】:

    标签: vuejs2


    【解决方案1】:

    编辑(带有新问题的详细信息):由于您使用的是视图路由器并且您的组件已注册为路由,因此只需将以下内容添加到您的游戏组件中的重建方法中,这应该可以正常工作

    this.$router.go(this.$router.currentRoute)
    

    const router = new VueRouter({
      mode: 'history',
    
    })
    
    new Vue({
    	router,
      el: '#app',
      methods: {
        reload: function() {    
           this.$router.go(this.$router.currentRoute)
        }
      },
      created() {
        console.log("Hey")
      }
    })
    <script src="https://npmcdn.com/vue/dist/vue.js"></script>
    <script src="https://npmcdn.com/vue-router/dist/vue-router.js"></script>
    
    <div id="app">
        <button @click="reload">Reload</button>
      <router-view></router-view>
    </div>

    达到目标的简单方法是在组件的 v-if 中设置一个布尔值。然后切换布尔值的真/假。当 v-if 为 false 时,组件被销毁并在之后被重新实例化。


    要做到这一点,有两种方法。我们想要的是改变父组件的状态,这将说明我们是否打印我们的组件。第一种方法是使用像 VueX 这样的状态管理插件,但这对于我们想要做的事情来说有点太多了。最简单的是,我们必须从您的组件触发一个事件,这将触发父组件的状态更改。

    在下面的例子中,当你点击MyComponent里面的reset按钮时,会发出名为“reset”的自定义事件。在父组件中,我们的 MyComponent 标签上有一个 showMyComponent 布尔值和一个监听器 @reset,当我们的 MyComponent 发出“reset”事件时,它将触发名为“resetMyComponent”的方法。

    这里有一些资源:

    希望现在更清楚

    var MyComponent = Vue.component('my-component', {
    	name : "my-component",
    	template : "#my-component-template",
    	data(){
    		return {
    			interval : null,
    			count : 0
    		}
    	},
    	created() {
    		console.log("MyComponent is created")		
    		this.interval = setInterval(() => {
    			this.count++
    		},1000)		
    	},
    	destroyed() {
    		console.log("MyComponent is destroyed")
    		clearInterval(this.interval)
    	}
    });
    
    
    new Vue({
    	el: "#app",
    	components : {
    		MyComponent
    	},
    	data: {
    		showMyComponent : true
    	},
    	methods : {
    		resetMyComponent() {
    			this.showMyComponent = false;
    			Vue.nextTick(() => {
    				this.showMyComponent = true;
    			});
    		}
    	}
    })
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <div id="app">
    	<my-component v-if="showMyComponent" @reset="resetMyComponent"></my-component>
    </div>
    
    
    <script type="text/x-template" id="my-component-template">
    	<div style="padding: 15px">
    		<p>My component is created since {{count}} seconds</p>		
    		<button @click="$emit('reset')">Reset my component</button>
    	</div>
    </script>

    【讨论】:

    • 您能否提供更多详细信息如何在组件上设置 v-if 并从该组件内部切换它?我是Vue的新手,只有一个月的经验。谢谢。
    • 至少有两种方法可以做到这一点。我要编辑我的答案,等几分钟。
    • 嗯,我现在仍然不知道如何在我的项目中实施您的解决方案。我使用“vue-router”,所以它可能在实现上有所不同。给我几分钟时间用我的代码更新我的问题。谢谢。
    • 好的。我添加了我的代码,所以现在应该一切都清楚了。
    • 我刚刚编辑了我的答案。告诉我它是否有效,或者您是否仍然遇到麻烦:D
    【解决方案2】:

    有多种方法可以重新创建组件。最有效的方法是更改​​组件密钥。我们在这里所做的是我们将提供一个关键属性,以便 Vue 知道特定组件与特定数据耦合或绑定。如果 key 不变,它不会改变组件,但是如果 key 改变,Vue 知道它应该摆脱旧组件并重新创建一个新组件。

    这是一个非常基本的方法:

    <template>
    <component-to-re-render :key="componentKey" />
    </template>
    export default {
      data() {
        return {
          componentKey: 0,
        };
      },
      methods: {
        forceRerender() {
          this.componentKey += 1;
        }
      }
    }
    

    每次调用 forceRerender 时,我们的 prop componentKey 都会改变。当这种情况发生时,Vue 将知道它必须销毁组件并创建一个新组件。你得到的是一个子组件,它将重新初始化自己并“重置”它的状态。这种简单而优雅的方式正在解决我们在 Vue 应用开发中面临的最常见挑战!

    您还可以查看其他可能的方法:https://medium.com/emblatech/ways-to-force-vue-to-re-render-a-component-df866fbacf47

    【讨论】:

      猜你喜欢
      • 2020-12-21
      • 2018-06-27
      • 2018-08-01
      • 2014-12-26
      • 2021-12-10
      • 1970-01-01
      • 1970-01-01
      • 2016-03-18
      • 2015-12-19
      相关资源
      最近更新 更多