如何获得父Vue组件和子Vue组件使用同一数据对象?

时间:2018-10-09 07:13:29

标签: vue.js vuejs2 vue-component

我有一个Guestbook组件,我将其分为SignView组件。 我想通过或什至更好地与我的主要访客留言簿组件和子级View组件共享条目数据,但是我不知道如何实现此目的。

我有以下代码:

/src/components/Guestbook.vue

<template>
<div>
    <h1>Guestbook</h1>

    <SignGuestbook />
    <ViewGuestbook :entries="v_entries" />
    <ViewGuestbook :p_entries="v_entries" />
    <!-- Error: '[Vue warn]: Property or method "store" is not defined on the instance but referenced during render.' -->
    <!-- <ViewGuestbook :entries="store" /> -->
    <!--   <ViewGuestbook :p_entries="store" /> -->
    <!-- Error: '[Vue warn]: Property or method "$store" is not defined on the instance but referenced during render.' -->
    <!-- <ViewGuestbook :entries="$store" /> -->
    <!-- <ViewGuestbook :p_entries="$store" /> -->
</div>
</template>

<script>
import SignGuestbook from './SignGuestbook.vue'
import ViewGuestbook from './ViewGuestbook.vue'
import Vue from 'vue'
import Vuex from 'vuex'
import guestbook from './guestbook.js'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    entries: [
      { id: 1, name: 'stored 1', comment: 'comment' },
      { id: 2, name: 'stored 2', comment: 'comment' }
    ]
  },
  getters: {
    entries: entries => {
      return entries
    }
  },
  mutations: {
    refreshList (state) {
      state.s_entries = guestbook.getItems()
    }
  }
})

export default {
  name: 'Guestbook',
  components: {
    SignGuestbook,
    ViewGuestbook
  },
  props: ['v_entries'],
  data () {
    return { comment: '', name: '', entries: ['test'] }
  },
  methods: {
    refreshList: async function () {
      this.entries = await guestbook.getItems()
      store.commit('refreshList')
      // this.$store = await guestbook.getItems()
      console.log('regular entries:', this.entries)
      console.log('stored entries:', this.store.getters.entries)
    }
  },
  async created () {
    await guestbook.authoriseAndConnect()
    await guestbook.createMutableData()
    await this.refreshList()
  }
}
</script>

/src/components/ViewGuestbook.vue

<template>
  <div>

    get entries attempt #1<br>
    <div v-for="entry in entries">
      an entry<br>
    </div>
    <br>
    get entries attempt #2<br>
    {{ entries }}
    <br>
    <!-- Error: '[Vue warn]: Property or method "$store" is not defined on the instance but referenced during render.' -->
    <!-- stored entries<br>
    {{ this.$store }}
    <br>-->
    <br>

    </div>
  </div>
</template>

<script>

export default {
  name: 'ViewGuestbook',
  props: ['p_entries'],
  data () {
    return { entries: [
      { id: 1, name: 'child 1', comment: 'comment' },
      { id: 2, name: 'child 2', comment: 'comment' }
    ]}
  },
  async created () {
    this.entries = this.p_entries
  }
}

</script>

/src/components/guestbook.js

let app
let md

async function authoriseAndConnect () {
  const opts = {
    forceUseMock: true
  }
  let appInfo = {
    name: 'SAFE Guestbook Application',
    id: 'net.maidsafe.tutorials.web-app',
    version: '0.1.0',
    vendor: 'MaidSafe.net Ltd.'
  }
  app = await window.safe.initialiseApp(appInfo, null, opts)
  console.log('Authorising SAFE application...')
  try {
    const authReqUri = await app.auth.genAuthUri()
    console.log('Generated authentication URI...', authReqUri)
    const authUri = await window.safe.authorise(authReqUri)
    console.log('SAFE application authorised...')
    await app.auth.loginFromUri(authUri)
  } catch (err) {
    console.warn('Application authorisation was rejected', err)
  }
  console.log('Application connected to the network')
}

async function createMutableData () {
  console.log('Creating MutableData with initial dataset...')
  const typeTag = 15000
  md = await app.mutableData.newRandomPublic(typeTag)
  const initialData = {
    'random_key_1': JSON.stringify({
      name: 'parent 1',
      comment: 'comment'
    }),
    'random_key_2': JSON.stringify({
      name: 'parent 2',
      comment: 'comment'
    })
  }
  await md.quickSetup(initialData)
}

async function getItems () {
  const entries = await md.getEntries()
  let entriesList = await entries.listEntries()
  let items = []
  entriesList.forEach((entry) => {
    const value = entry.value
    if (value.buf.length === 0) return
    const parsedValue = JSON.parse(value.buf)
    items.push({ key: entry.key, value: parsedValue, version: value.version })
  })
  return items
}

module.exports = {
  authoriseAndConnect,
  createMutableData,
  getItems
}

index.js

import Vue from 'vue'
import App from './App'
import router from './router'

export default new Vue({
  el: '#root',
  router,
  render: (h) => h(App)
})

// Error: unused variable
// let globalData = new Vue({
//   data: {
//     $store: {}
//   }
// })

// Error: '[Vue warn]: Property or method "$store" is not defined on the instance but referenced during render.'
// Vue.mixin({
//   computed: {
//     $store: {
//       get: function () { return globalData.$data.$store },
//       set: function (newData) { globalData.$data.$store = newData }
//     }
//   }
// })

预期(至少其中之一):

get entries attempt #1
an entry
an entry
get entries attempt #2
[{ id: 1, name: 'stored 1', comment: 'comment' },{ id: 2, name: 'stored 2', comment: 'comment' }]

结果:

get entries attempt #1

get entries attempt #2


get entries attempt #1

get entries attempt #2

3 个答案:

答案 0 :(得分:0)

TL; DR: https://codesandbox.io/s/62wvro7083

我用自己的小数据存储解决了这个问题,这是一种非常简单的方法,但是对我来说足够好,而无需深入研究Vuex。

首先,我在初始化其他任何内容之前在某个地方创建数据存储。

window.globalData = new Vue({
    data: {
        $store: {
            shared: {}
        }
    },
});

此后,我添加了一个全局Mixin,它允许获取数据并将其设置到全局存储中。

Vue.mixin({
    computed: {
        $store: {
            get: function () { return window.globalData.$data.$store },
            set: function (newData) { window.globalData.$data.$store = newData; }
        }
    }
});

然后,每个组件都可以通过this.$store访问数据存储。在一个示例codeandbox中,我有一个“ shared”变量来保存内容,可以随意进行以下操作:

https://codesandbox.io/s/62wvro7083

Edit Vue Template

答案 1 :(得分:0)

在ViewGuestbook.vue中,您必须将属性复制到主数据中。

created()mounted()钩中执行以下操作:

this.entries = this.p_entries; //Just assign
this.entries = JSON.parse(JSON.stringify(this.p_entries)); //Or clone it.

答案 2 :(得分:0)

要共享数据,请使用v-bind将数据对象从父组件绑定到子组件的props对象。

像这样:

/src/components/Guestbook.vue

...
<ViewGuestbook v-bind:entries="d_entries" />
...

export default {
  name: 'Guestbook',
  components: {
    SignGuestbook,
    ViewGuestbook
  },
data () {
  return { d_entries: [] }
},
methods: {
  refreshList: async function () {
    this.d_entries = [
      { id: 1, name: 'placeholder 1', comment: 'comment' },
      { id: 2, name: 'placeholder 2', comment: 'comment' }
    ]
  },
},
async created () {
  this.refreshList()
}
...

/src/components/ViewGuestbook.vue

<template>
  <div>

    entries<br>
    <div v-for="entry in entries">
      {{ entry.name }}<br>
      {{ entry.comment }}<br>
    </div>

  </div>
</template>

<script>

export default {
  name: 'ViewGuestbook',
  props: {
    'entries': Array
  }
}
</script>