VueJS:在没有集中存储(vuex 或 eventBus)的情况下直接访问子项(使用 vue-router)时访问子项中的父道具

Posted

技术标签:

【中文标题】VueJS:在没有集中存储(vuex 或 eventBus)的情况下直接访问子项(使用 vue-router)时访问子项中的父道具【英文标题】:VueJS: Access parent prop in child when the child is visited directly (using vue-router) without a centralized store (vuex or eventBus) 【发布时间】:2019-10-02 23:20:27 【问题描述】:

在这个codesandbox demo 中,父home 组件有一个子addItem 组件。父母将数组(作为道具)传递给孩子,因此孩子能够将项目添加到父母的列表中,即从父母->孩子传递数据的正常方式,即通过道具: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>

问题是当直接使用router-link(vue-router)访问孩子时,父母的道具:fruitsArr="fruits"不可用。

谁能告诉我,当当前路线是孩子时,如何或正确的方式将父母的道具传递给孩子,以便孩子能够将项目添加到父母的列表中。我更喜欢不使用 VueX 或任何其他集中式存储(例如 eventBus)的解决方案。

谢谢

【问题讨论】:

【参考方案1】:

有几个解决方案。

提供/注入

您可以使用提供/注入将数据向下发送到子层次结构。当只需要在单个parent-child branch 上进行通信并且您不想使用Vuex 时,这是从parent to non-immediate child 共享数据的推荐方式。

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

元字段

您可以将项目存储在路由的元字段中,并在导航守卫中对其进行初始化。然后它在所有组件中都可用。

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 
        
      ]
    
  ]
)

话虽如此,Vue 的方式是 emit events upreceive properties down,所以如果您的用例允许,请尝试使用该架构。

【讨论】:

【参考方案2】:

Steven Spungin 的回答很好。但是你应该考虑到提供/注入数据不是被动的。

话虽如此 - 你需要建立某种集中的“真相来源”。 如果您不想使用 Vuex - 最简单的解决方案是再声明一个 Vue 实例并将您的全局数据存储在那里。 这将是反应性的。

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

在你的组件中

import myStore from 'somewhere';

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

....

【讨论】:

以上是关于VueJS:在没有集中存储(vuex 或 eventBus)的情况下直接访问子项(使用 vue-router)时访问子项中的父道具的主要内容,如果未能解决你的问题,请参考以下文章

VueJS Vuex - 解决状态变化的承诺?

VueJs 3 - Vuex:未捕获的类型错误:存储不是函数

来自 sessionStorage 的对象在 vuejs / vuex 中没有反应

Vuex/Vuejs:在 vuex 存储中访问 localStorage

vuex

VueJS vuex