VueJS: Access parent prop in child when the child is visited directly (using vue-router) without a centralized store (vuex or eventBus)

♀尐吖头ヾ 提交于 2019-12-11 18:25:58

问题


In this codesandbox demo, the parent home component has a child addItem component. Parent's passes array (as prop) to the child and so the child is able to add item to the parent's list i.e. the normal way of passing data from parent -> child i.e. via props :fruitsArr="fruits".

Main.js

import Vue from "vue";
import VueRouter from "vue-router";
import App from "./App.vue";
import Home from "./components/Home.vue";
import addItem from "./components/addItem.vue";

Vue.use(VueRouter);

var router = new VueRouter({
  mode: "history",
  routes: [
    { path: "", component: Home, name: "Home" },
    {
      path: "/addItem",
      component: addItem,
      name: "Add Item"
    }
  ]
});

Vue.config.productionTip = false;

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

App.vue

<template>
  <div id="app">
    <app-header></app-header>
    <br>
    <router-view></router-view>
  </div>
</template>

<script>
import appHeader from "./components/common/appHeader";

export default {
  name: "App",
  components: {
    appHeader
  }
};
</script>

appHeader.vue

<template>
  <ul class="nav nav-pills">
    <router-link tag="li" to="/" active-class="active" exact>
      <a>Home</a>
    </router-link>
    <router-link tag="li" to="/addItem" active-class="active">
      <a>Add Item</a>
    </router-link>
  </ul>
</template>

Home.vue

<template>
  <div>
    <addItem :fruitsArr="fruits"/>
    <h3>Fruits List</h3>
    <ul>
      <li v-for="(fruit, idx) in fruits" :key="idx">{{fruit}}</li>
    </ul>
  </div>
</template>

<script>
import addItem from "./addItem";

export default {
  name: "App",
  data() {
    return {
      fruits: ["Apple", "Mango", "Orange", "PineApple"]
    };
  },
  components: {
    addItem
  }
};
</script>

addItem.vue

<template>
  <div class="input-wrapper">
    Enter Fruit Name:
    <input type="text" v-model="fruitItem">
    <button @click="addFruit">Add Fruit</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      fruitItem: ""
    };
  },
  props: ["fruitsArr"],
  methods: {
    addFruit() {
      this.fruitsArr.push(this.fruitItem);
    }
  },
};
</script>

The problem is when the child is visited directly using router-link (vue-router) then parent's prop :fruitsArr="fruits" is not available.

Can anybuddy tell me, how to or the correct way to pass parent's prop to the child when the current route is the child, such that child is able to add item to the parent's list. I'd prefer a solution WITHOUT using VueX or any other centralized store such as eventBus.

Thanks


回答1:


There are a couple of solutions.

Provide/Inject

You can use provide/inject to send data down the child hierarchy. This is the recommended way to share data from parent to non-immediate child when the communication is only needed on a single parent-child branch, and you do not want to go with Vuex.

https://vuejs.org/v2/api/#provide-inject

Meta Field

You can store items in the route's meta fields and initialize it in a navigation guard. Then it is available in all components.

https://router.vuejs.org/guide/advanced/navigation-guards.html

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'bar',
          component: Bar,
          // a meta field
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})

With that said, the Vue way is to emit events up and receive properties down, so try to work with that architecture if your use-case allows.




回答2:


Steven Spungin`s answer is good. But you shall take into account that provide/inject data is not reactive.

That being said - you need to make some sort of centralized "source of truth". If you don't want to use Vuex - simpliest solution is to declare one more Vue instance and store your global data there. It would be reactive.

const myStore = new Vue({
  data:{
    fruits: ["Apple", "Mango", "Orange", "PineApple"]
  }
})
export myStore;

and in your component

import {myStore} from 'somewhere';

//to use prop in your template - proxy it using computed prop
....
computed:{
  fruits(){
    return myStore.fruits;
  }
}
....


来源:https://stackoverflow.com/questions/56155690/vuejs-access-parent-prop-in-child-when-the-child-is-visited-directly-using-vue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!