【问题标题】:Binding Vue component data to external state将 Vue 组件数据绑定到外部状态
【发布时间】:2017-09-18 10:32:20
【问题描述】:

我有一个 Vue 组件,需要在多个地方嵌入到大型遗留(不是 Vue)系统中。 该组件发出一些 AJAX 请求并根据一组数据库记录 ID 显示信息,它通常在页面加载时接收到这些信息。该数组由服务器直接嵌入到页面模板中,并作为 props 传递给组件,如下所示:

let config = {
  records: {{ template_code_outputting_array }},
  ...otherConfigOptions
}

let app = new Vue({
  el: '#app',
  store,
  render: h => h(ComponentName, {
    props: config
  })
})

我的问题是,在需要嵌入的其中一个屏幕上,用户可以使用搜索和添加类型的 AJAX 界面动态选择数据库记录(而不是在页面加载时预先设置) ,所以我需要使组件与用户的选择保持同步,以便在必要时重新渲染它。

我有一个可行的解决方案,但远非理想;目前,每次用户对其选择进行一些更改时,我都会直接在组件上调用一个方法,传递新的选择,以便组件可以更新自己的内部副本:

app.$children[0].recordsChanged(newSelection)

但显然这不是反应式的,而且感觉有点 hacky。我觉得我不应该直接寻址组件,而我调用的函数仅供外部使用;组件内部没有任何东西使用它。

我尝试将 data 中的值绑定到全局变量(这同样不理想,但我没有太多选择),然后添加一个 watch 方法在更改时触发重新渲染。显然,标量值不起作用,因为它们是按值而不是引用,但是将它们包装在一个对象中似乎也不起作用。它们很好地绑定并采用提供的初始值,但更新对象(直接改变其值或用新值替换对象)似乎不会触发 watch 方法或任何反应。

是否有任何最佳做法可以做到这一点,或者我目前的方法是我所希望的最好的方法吗?

【问题讨论】:

  • 为什么不使用 vue 事件总线?喜欢var bus = new Vue({})。然后你可以在任何你想要的地方做bus.$emit("someEvent", {new: data}),并在你的组件中做bus.$on("someEvent", doSomething)。确保将总线变量分配给窗口
  • @Afik​​Deri 这实际上帮了很多忙,谢谢。我已经能够导出一个包装了 emit 的函数,因此对外部代码进行任何更改的人都不需要任何 Vue 知识。如果我可以让它完全反应并完全避免函数调用,那还是很好的,但我开始认为没有更清洁的方法可以做到这一点。

标签: javascript ajax vue.js vuejs2 vue-component


【解决方案1】:

事件总线(如 AfikDeri 在 cmets 中所建议的)是一个很好的解决方案。它提供了一个简单的界面。

也可以对数据进行反应性化处理,with some caveats。用于初始化数据项的 Object 本身将变为反应式。如果改变了你的数组do so in the approved ways,你应该会在你的 Vue 中看到这些变化。

let stuff = [2, 3, 5];

const v = new Vue({
  el: '#app',
  data: {
    reactiveStuff: stuff
  },
  components: {
    myComponent: {
      props: ['arr'],
      template: '<div><div v-for="item in arr">{{item}}</div></div>'
    }
  }
});

setTimeout(() => {
  stuff.push(7);
}, 1200);
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<my-component id="app" :arr="reactiveStuff">
</my-component>

【讨论】:

  • Roy,我如何替换/设置/修改 ` stuff` 数组的值之一?我的意思是如何覆盖这个stuff[2] = 123 保持反应性?
  • @webprogrammer 你需要使用set or splice 以便 Vue 注意到数组元素的变化。
  • Roy, ​​stackoverflow.com/questions/60727977/… - 我在这里提出了关于这个的问题。我想我需要传递 vue 实例才能在额外的脚本中使用它。我可以使用Vue.set() 而不是传递 vue 实例吗?你能给我一些意见吗?谢谢!
  • @webprogrammer 是的,你可以使用Vue.set
猜你喜欢
  • 1970-01-01
  • 2017-03-31
  • 2019-11-13
  • 1970-01-01
  • 2019-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多