Передача данных от дочернего элемента к родительскому родительскому элементу в Vue.js с помощью метода $emit()

#vue.js #parent-child

#vue.js #родитель-потомок

Вопрос:

Я не могу передавать данные от дочернего элемента к родительским маршрутизаторам с vue.js.

Из нескольких исследований, в том числе по переполнению стека, совершенно ясно, что мы должны использовать метод $emit() от дочернего элемента. Я поиграл с документацией, stackoverflow и некоторыми руководствами YouTube, но все еще кое-что упускаю и делаю неправильно.

Ниже приведена панель меню моего маршрутизатора.vue

 <template>
    <div id="app" class="container-fluid">
         <div @clicked="onClickChild">
            <p>login is set to {{ loggedin }}</p>
            <p>Route query login {{ this.$route.query.loggedin }}</p>
        </div>
        <div v-if="!loggedin">
            <nav>
                <!--<router-link class="btn btn-primary" to="/">Customers</router-link>-->
                <router-link class="btn btn-primary" to= "/menubar/login">Login</router-link>
                <router-link class="btn btn-primary" to="/menubar/register">Register</router-link>
            </nav>
        </div>
        <div v-else>
            <nav>
                <!--<router-link class="btn btn-primary" to="/">Customers</router-link>-->
                <button class="btn btn-primary" v-on:click="logout()">Logout</button>
                <router-link class="btn btn-primary" to="/edit">Edit</router-link>
            </nav>
        </div>

        <br/>
        <router-view/>
    </div>
</template>

<script>
    export default {
        name: "menubar",
        data(){
            return{
                loggedin:false,
            }
        },
        created() {
            if(this.$route.query.loggedin){
                this.loggedin = this.$route.query.loggedin;
            }
        },
        methods: {
            logout(){
                this.loggedin = false;
            },
            onClickChild (value) {
                this.loggedin = value;
                console.log(value) // someValue
            }
        }
    }
</script>
  

И его дочерний Login.vue

 <template>
    <div class="submitform">
        <div class="form-group">
            <label for="username">Username</label>
            <input type="text" class="form-control" id="username" required v-model="user.username" name="username">
        </div>

        <div class="form-group">
            <label for="password">Password</label>
            <input type="password" class="form-control" id="password" required v-model="user.password" name="password">
        </div>

        <button v-on:click="logUser()" class="btn btn-success">Connect</button>
</template>

<script>
    import router from '../../router'

    export default {
        name: "login",
        data(){
            return{
                user: {
                    id: 0,
                    username: "",
                    password: ""
                },
            }
        },
        methods:{
            logUser(){
                var loggedin = true;
                this.$emit('clicked', loggedin);
                router.push({ name: "menubar" });
            }
        }
    }
</script>
  

мой router.js

 {
        path: "/menubar",
        name: "menubar",
        component: Menubar,
        children: [
            {
                path: "login",
                name: "login",
                component: Login,
            },
            {
                path: "register",
                name: "register",
                component: Register,
            }
        ]
    }
  

консоль.в журнале должно быть напечатано true или false, чтобы отслеживать мои параметры ‘loggedin’
Вместо этого, понятия не имею, связано ли это, у меня есть это:
[HMR] Ожидает сигнала обновления от WDS…

который выдает в моем браузере Mozilla (то же самое в Chrome):

Адрес не был понят Firefox не знает, как открыть этот адрес, потому что один из следующих > протоколов (view-source, webpack) не связан ни с какой программой или не разрешен в этом контексте. Возможно, вам потребуется установить другое программное обеспечение, чтобы открыть этот адрес.»

Заранее спасибо за вашу помощь.

Ответ №1:

В вашем случае компонент, прослушивающий событие, не является дочерним компонентом:

 <div @clicked="onClickChild">[...]</div>
  

Здесь дочерним элементом является div, однако, если вы хотите иметь возможность прослушивать emit
сигнал от дочернего компонента, прослушиватель должен быть связан с этим конкретным дочерним компонентом. В этом случае что-то вроде:

 <Login @clicked="onClickChild">[...]</Login>
  

Однако, если вы хотите передать данные от дочернего элемента к родительскому узлу в маршрутизаторе
вы можете определить вид маршрутизатора и перехватить событие следующим образом:

 <router-view @clicked="onClickChild" />
  

Ответ №2:

Из вашего кода похоже, что ваш дочерний компонент правильно передает событие родительскому. Что касается ошибки, которую вы получаете в браузере, это, скорее всего, опечатка или неверный URL, как вы и делаете:

         path: "/menubar",
        name: "menubar",
        component: Menubar,
        children: [
            {
                path: "/menubar/login",
  

Который создаст путь, подобный /menubar/menubar/login, который выглядит неправильно. https://router.vuejs.org/guide/essentials/nested-routes.html

Комментарии:

1. Хороший момент, я изменил дочерние элементы на path: «login». Это чище, однако это не меняет поведение: я все еще могу перемещаться взад и вперед от дочернего элемента к родительскому, и никакие параметры не передаются