在Vuejs中跨不同组件共享数据

时间:2016-03-15 16:37:25

标签: model components vue.js

鉴于下面的迷你Vuejs应用程序。

当我单击其中一个增量/减量按钮时,“计数器”组件中的值会更新,但“字母”中的值不会更新。
关于如何在这两个组件之间共享相同数据以便它们自动更新的任何想法?

var counter = Vue.extend({
    props: ['start'],
    template: '#counter',
    data: function() {
      return {
        value: this.start
      }
    },
    methods: {
      increment: function() {
        this.value++
      },
      decrement: function() {
        this.value--
      }
    }
  });

  var alphabet = Vue.extend({
    props: ['value'],
    template: '#alphabet',
    data: function() {
      return {
        value: 0
      }
    }
  });

  new Vue({
    el: '#app',
    data: {
      val: 5
    },
    components: {
      counter: counter,
      alphabet: alphabet
    }
  });
<script id="counter" type="text/template">
  <button @click="increment">+</button> {{ value }}
  <button @click="decrement">-</button>
</script>
<script id="alphabet" type="text/template"> {{ value }} </script>
<div id="app">
  <counter :start="val"></counter>
  <alphabet :value="val"></alphabet>
</div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.17/vue.js"></script>

4 个答案:

答案 0 :(得分:5)

您设置方式有2个问题。这是有效的:https://jsfiddle.net/j9hua7c8/

第一个问题出现在counter组件中,您创建了一个名为value的新变量,其值为this.start。这取了start的值并将其分配给value,但由于value是一个新变量,因此它不再与start同步。更新版本:

var counter = Vue.extend({
  props: ['value'],
  template: '#counter',
  methods: {
    increment: function() {this.value++},
    decrement: function() {this.value--}
  }
});

第二件事是,为了让子变量同步双向,你需要在绑定上使用.sync修饰符。默认情况下,它们只是单向绑定。更新:

<counter :value.sync="val"></counter>

如果对您的用例更好,您还可以使用$dispatch$broadcast在父组件和子组件之间进行通信。

答案 1 :(得分:2)

你有两个选择。

1手动同步您的值

incrementdecrement个函数中添加此句

this.$parent.val = this.value;

并使您的字母值等于父val

computed: {
    value: function() {
        return this.$parent.val;
    }
  }

导致this fiddle

2使用vuex保持数据的全局状态

使用vuex,您store可以为所有组件state使用int a=1; switch(a) { case 1: printf("Case A"); break; default: printf("Default Case"); } 。此状态将是被动的,因此当您更改其值时,将更新每个组件。这可能对你的用例来说太过分了,但绝对是一个要记住的选择

答案 2 :(得分:1)

如前所述,您可以使用vuex。但是,您 不能使用vuex。 Vuex仅仅有助于强制执行如何使用全局状态的约定,并试图使得做错事情变得困难。

然而,只要稍加自律,您就可以轻松自己动手。只需创建全局对象并将其传递给数据函数中的所有组件。

答案 3 :(得分:0)

我花了很长时间才得出结论,我需要 VueX 来让组件相互交谈。因此,我建议所有人,现在就开始学习 VueX ,以免浪费时间。您的同事将欣赏代码标准,并会认可 VueX 为首选方法。我承认,我今天通读了 VueX 网站文档的每一页,但我仍然缺少有效的示例。但是,我确实早先找到了VueX Module Decorators页,当我过渡到 Typescript 时,我将按照自己喜欢的Vue Class ComponentVue Property Decorator包的方式自行实现此操作>使用Vue。

我最初使用 JavaScript 中的 Vue组件代码(例如this.$childrenthis.$parent.$children)来遍历组件获取组件数据并在其他 components 上调用方法来设置页面 state 我需要的方式。我会说这是一种“肮脏”的方法,但是如果您需要快速处理,它会起作用。我说这是 dirty ,因为所有 Vue组件都有一个 isolated 范围。我创建的方法是用来从外部组件中访问数据,只能从内部访问组件本身或从 VueJS 角度来看的组件模板。但是,JavaScript使我无法进行自己的工作,因为我知道 DOM 的结构。如果您对所看到的一切都不走运,并且您忙于一个项目,并且迫切需要一些东西;这是我所指的一个有效示例:(肮脏方法)[https://jsfiddle.net/OhRyanOh/s5b21hym/]

如果您使用Dirty Approach,例如浏览this.$childrenthis.$parent.$children;请稍后重构您的应用程序并交换到VueX。我使用这个unit-test-driver组件来填写表单元素“为我” ,这样我可以更快地构建应用程序,并进行测试。我正在从Word / Excel复制和粘贴数据,需要动态添加新的表单组件,然后用数据填充这些组件,并向剪贴板生成pretty XML。编写Dirty Approach代码时,我第一次学习 Vue 组件时遇到了很多错误。能够进行测试变得非常繁琐,而且我从另一个文档中复制和粘贴的内容太多了,这就是为什么我创建unit-test-driver组件来加快开发速度的原因。从那以后,我将所有这些都转换为基于 TypeScript 的基于Vue CLI的项目,并且由于unit-test-driver,{{1} }和 Vue的 隔离的组件范围。我希望我刚开始使用 VueX ,并通过编写所有这些内容,希望可以节省别人的宝贵时间。

将我的应用程序转换为 TypeScript 之后,就是当我意识到this.$refsthis.$props成员对this.$parent的使用不太满意时,所以我的应用程序是损坏,我无法轻松地从 DOM Elements 强制转换为this.$children组件。我不喜欢在type saftey中的任何地方使用类型TypeScript,因为这会像<any>这样引入TypeScript,并且依赖代码将负责对{{1 }},您就开始失去价值担保。这是相关的链接:Basic Types (检查union typesDouglous Crockford VidNull and Undefined

我需要找到另一种组件通信的方法。我尝试使用<string | null | undefined>来代替,因为这是访问 DOM Elements 的最佳实践,然后失去了对子组件上的调用函数的访问权限... type safety中的--strictNullChecks。我也尝试过this.$refs方法,但是不适用于在组件之间共享数据,但是更多的方法是通过在中将属性绑定数据将数据传给子级组件模板标签。我还沿着 Dodo 的路走了,更新了我自己的 TypeScript Vue组件,并传递了自实例化组件的环绕数组,才了解到使用this.$nextTick(...)中, Vue 有其自己的游戏计划,并且还为数组中的每一行实例化了其自己的 components 。我创建并链接的自引用组件 DOM组件所包含的数据不同,因为 Vue 并未使用其中的项目我自己实例化的我的组件数组,无论我自己将它们的数组和值赋给mounted(): Promise<void>以及两者之间的每种组合。如果您对需要在 DOM 中显示的自己的组件使用新的运算符,那么这是一个错误的设计选择。我应该能够通过 VueX 完成隔离范围共享全局组件状态的所有工作。借助this.$props将初始化值传递给子组件,否则将 VueX 用于共享组件状态

在弄清 VueX 是什么之前,我的最后一种方法是 global bus 方法,由于 development的发展,对于大型应用程序来说,这并不理想时间复杂度。此概念还记录在 VueJS Component Edge Cases页上的标题为 Accessing Root Instance (访问根实例)的标题下,然后在其中声明后续点:{{1 }}

无论如何,我现在要自己确定 VueX 的实现方式。也许以后我可以用一个更好的 VueJs / TypeScript 示例对此进行编辑。我暂时没有一个,并且现在可能有一个。我的犹豫是,在我初次查看时,并没有干净的 TypeScript VueX 示例,但我不知道该脚本的用法是什么,所以我像瘟疫一样避免了它……仅为了完全理解为什么我的 components 上没有未定义的函数,我试图在v-for之后this.$refs通过this.$props获取数据}}。是的,我绝对需要 VueX ,尤其是 TypeScript