在 Vuejs 中跨不同组件共享数据
Share data across different components in Vuejs
鉴于下面的迷你 Vuejs 应用程序。
当我单击其中一个 increment/decrement 按钮时,"counter" 组件中的值会更新,但 "alphabet" 中的值不会。
关于如何在这两个组件之间共享相同数据以便它们自动更新的任何想法?
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>
你有两个选择。
1 手动同步您的值
在你的 increment
和 decrement
函数中添加这句话
this.$parent.val = this.value;
并使您的字母表值等于父值
computed: {
value: function() {
return this.$parent.val;
}
}
导致 this fiddle
2 使用 vuex 保持数据的全局状态
使用 vuex
,您可以 store
一个通用的 state
用于所有组件。此状态将是反应性的,因此当您更改其值时将为每个组件更新。这对于您的用例来说可能有点矫枉过正,但绝对是一个需要牢记的选择
您的设置方式存在 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 and $broadcast 在父组件和子组件之间进行通信,如果这更适合您的用例。
如前所述,您可以使用vuex。但是,您 没有 使用 vuex。 Vuex 只是帮助强制执行如何使用全局状态的约定,并试图让做错事变得困难。
但是,只要稍加自律,您就可以轻松做到。只需创建全局对象并将其传递给数据函数中的所有组件。
当我使用 Vue 过渡到 Typescript 时,我花了很长时间才得出我需要 VueX to have components talk to one another. So I am recommending to everyone, start learning VueX now so you do not waste time. Your co-workers will appreciate the code standards, and will recognize VueX as the preferred approach. I will admit, I read through every page of the VueX website documentation today, and I was still for lack of a working example. However, I did find the VueX Module Decorators page earlier, and I will be implementing this myself as I did enjoy, Vue Class Component, and Vue Property Decorator 包的结论。
我最初在JavaScript中使用了Vue组件代码如this.$children
或this.$parent.$children
循环遍历 components 以获取 component data 并在其他 components 上调用 methods 设置页面 声明 我需要的方式。我会说这是一种 肮脏的 方法,但如果你需要快速的东西,它就可以工作。我说它是 dirty,因为所有 Vue Components 都有一个 isolated 作用域。我创建的 方法 是为了从 外部 组件 访问数据来自 组件本身 或来自 组件的模板 来自 VueJS 立场。然而,JavaScript 允许我摆脱我正在做的事情,因为我知道 DOM 的结构。如果你对你所看到的一切都不走运,并且你已经在一个项目上工作了几天,并且非常需要一些东西;这是我所指的一个工作示例:(肮脏的方法)[https://jsfiddle.net/OhRyanOh/s5b21hym/].
如果您使用 Dirty Approach
,例如冲浪 this.$children
或 this.$parent.$children
;请稍后重构您的应用程序并切换到 VueX
。我使用这个 unit-test-driver
组件来填写表单元素 "for me",这样我就可以更快地构建应用程序,同时进行测试。我正在从 Word/Excel 复制和粘贴数据,需要动态添加新的表单组件,然后用数据填充这些组件,并生成一个 pretty XML
到剪贴板。第一次学习Vue组件,写Dirty Approach
代码的时候犯了很多错误。达到能够测试的程度变得非常麻烦,而且我从另一个文档复制和粘贴的方式太多了,这就是为什么我创建了 unit-test-driver
组件来加快我的开发速度。从那时起,我将所有这些转换为基于 Vue CLI 的项目到 TypeScript,由于 this.$refs
,unit-test-driver
实现失败,this.$props
,以及 Vue 的 独立组件作用域。我希望我刚刚知道从 VueX 开始,并且在编写所有这些内容时,希望我能节省其他人的宝贵时间。
在将我的应用程序转换为 TypeScript 之后,我意识到 this.$parent
或 this.$children
成员与 type saftey
的关系不是很好,所以我的应用程序被破坏了,我无法轻易地从 DOM Elements 转换为 TypeScript
组件。我不喜欢在 TypeScript
中的任何地方使用类型 <any>
,因为这会像 <string | null | undefined>
一样引入 union types
,并且依赖代码将负责额外的 undefined/null 检查 type safety
然后你开始失去价值保证。以下是相关链接:Basic Types (check for --strictNullChecks
), Douglous Crockford Vid, Null and Undefined.
我需要为组件通信寻找另一种方式。我尝试使用 this.$refs
代替,因为这是访问 DOM Elements 的最佳做法,然后无法调用在 child 组件上运行...甚至在 mounted(): Promise<void>
中的 this.$nextTick(...)
之后。我也尝试了 this.$props
方法,但是对于在 组件 之间共享数据无效,但更多的是通过绑定数据将数据交给 children在属性中,在 组件模板 标签中。我也走上了 Dodo 的道路,更新了我自己的 TypeScript Vue 组件 并传递了自实例化组件的数组,只是为了了解当使用 v-for
遍历数组时,Vue 有自己的游戏计划,并且还为每一行实例化了自己的 components在数组中也是如此。我创建和链接的 self-referenced 组件 不包含与 DOM 组件 相同的数据,因为 Vue 没有使用 我的组件数组中的项目 self-instantiated,不管我自己将它们的数组和值赋给 this.$refs
,以及两者之间的每一个组合。如果您正在为自己需要在 DOM 中显示的组件使用新的运算符,这是一个糟糕的设计选择。我应该能够通过 Isolated Scopes 和 Shared Global Component State 通过 VueX[=126= 完成我所做的一切] 反而。求助于this.$props
将初始化值传递给child组件,否则使用VueX作为共享组件州.
在弄清楚 VueX 是什么之前,我的最后一种方法是 global bus 方法,这对于由于 开发时间 和 复杂性 ,应用程序更大。这个概念也记录在 VueJS Component Edge Cases 页面上,标题为 Accessing the Root Instanc,然后用后续点说明:"This can be convenient for demos or very small apps with a handful of components. However, the pattern does not scale well to medium or large-scale applications, so we strongly recommend using Vuex to manage state in most cases."
无论如何,我现在要自己弄清楚 VueX 以供自己实施。也许我可以稍后使用更好的 VueJs/TypeScript 示例对其进行编辑。我暂时没有,现在可能会有。我的犹豫是没有干净的 TypeScript VueX 示例,当我第一次看的时候,我并没有马上知道我的场景用法,所以我像躲避瘟疫一样避开它。 .. 直到我对为什么我的 组件 上有未定义的函数完全感到困惑,我试图在 [=42] 之后通过 this.$refs
获取数据=] 哈哈 Mount/NextTick。是的,我绝对需要 VueX,尤其是 TypeScript。
鉴于下面的迷你 Vuejs 应用程序。
当我单击其中一个 increment/decrement 按钮时,"counter" 组件中的值会更新,但 "alphabet" 中的值不会。
关于如何在这两个组件之间共享相同数据以便它们自动更新的任何想法?
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>
你有两个选择。
1 手动同步您的值
在你的 increment
和 decrement
函数中添加这句话
this.$parent.val = this.value;
并使您的字母表值等于父值
computed: {
value: function() {
return this.$parent.val;
}
}
导致 this fiddle
2 使用 vuex 保持数据的全局状态
使用 vuex
,您可以 store
一个通用的 state
用于所有组件。此状态将是反应性的,因此当您更改其值时将为每个组件更新。这对于您的用例来说可能有点矫枉过正,但绝对是一个需要牢记的选择
您的设置方式存在 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 and $broadcast 在父组件和子组件之间进行通信,如果这更适合您的用例。
如前所述,您可以使用vuex。但是,您 没有 使用 vuex。 Vuex 只是帮助强制执行如何使用全局状态的约定,并试图让做错事变得困难。
但是,只要稍加自律,您就可以轻松做到。只需创建全局对象并将其传递给数据函数中的所有组件。
当我使用 Vue 过渡到 Typescript 时,我花了很长时间才得出我需要 VueX to have components talk to one another. So I am recommending to everyone, start learning VueX now so you do not waste time. Your co-workers will appreciate the code standards, and will recognize VueX as the preferred approach. I will admit, I read through every page of the VueX website documentation today, and I was still for lack of a working example. However, I did find the VueX Module Decorators page earlier, and I will be implementing this myself as I did enjoy, Vue Class Component, and Vue Property Decorator 包的结论。
我最初在JavaScript中使用了Vue组件代码如this.$children
或this.$parent.$children
循环遍历 components 以获取 component data 并在其他 components 上调用 methods 设置页面 声明 我需要的方式。我会说这是一种 肮脏的 方法,但如果你需要快速的东西,它就可以工作。我说它是 dirty,因为所有 Vue Components 都有一个 isolated 作用域。我创建的 方法 是为了从 外部 组件 访问数据来自 组件本身 或来自 组件的模板 来自 VueJS 立场。然而,JavaScript 允许我摆脱我正在做的事情,因为我知道 DOM 的结构。如果你对你所看到的一切都不走运,并且你已经在一个项目上工作了几天,并且非常需要一些东西;这是我所指的一个工作示例:(肮脏的方法)[https://jsfiddle.net/OhRyanOh/s5b21hym/].
如果您使用 Dirty Approach
,例如冲浪 this.$children
或 this.$parent.$children
;请稍后重构您的应用程序并切换到 VueX
。我使用这个 unit-test-driver
组件来填写表单元素 "for me",这样我就可以更快地构建应用程序,同时进行测试。我正在从 Word/Excel 复制和粘贴数据,需要动态添加新的表单组件,然后用数据填充这些组件,并生成一个 pretty XML
到剪贴板。第一次学习Vue组件,写Dirty Approach
代码的时候犯了很多错误。达到能够测试的程度变得非常麻烦,而且我从另一个文档复制和粘贴的方式太多了,这就是为什么我创建了 unit-test-driver
组件来加快我的开发速度。从那时起,我将所有这些转换为基于 Vue CLI 的项目到 TypeScript,由于 this.$refs
,unit-test-driver
实现失败,this.$props
,以及 Vue 的 独立组件作用域。我希望我刚刚知道从 VueX 开始,并且在编写所有这些内容时,希望我能节省其他人的宝贵时间。
在将我的应用程序转换为 TypeScript 之后,我意识到 this.$parent
或 this.$children
成员与 type saftey
的关系不是很好,所以我的应用程序被破坏了,我无法轻易地从 DOM Elements 转换为 TypeScript
组件。我不喜欢在 TypeScript
中的任何地方使用类型 <any>
,因为这会像 <string | null | undefined>
一样引入 union types
,并且依赖代码将负责额外的 undefined/null 检查 type safety
然后你开始失去价值保证。以下是相关链接:Basic Types (check for --strictNullChecks
), Douglous Crockford Vid, Null and Undefined.
我需要为组件通信寻找另一种方式。我尝试使用 this.$refs
代替,因为这是访问 DOM Elements 的最佳做法,然后无法调用在 child 组件上运行...甚至在 mounted(): Promise<void>
中的 this.$nextTick(...)
之后。我也尝试了 this.$props
方法,但是对于在 组件 之间共享数据无效,但更多的是通过绑定数据将数据交给 children在属性中,在 组件模板 标签中。我也走上了 Dodo 的道路,更新了我自己的 TypeScript Vue 组件 并传递了自实例化组件的数组,只是为了了解当使用 v-for
遍历数组时,Vue 有自己的游戏计划,并且还为每一行实例化了自己的 components在数组中也是如此。我创建和链接的 self-referenced 组件 不包含与 DOM 组件 相同的数据,因为 Vue 没有使用 我的组件数组中的项目 self-instantiated,不管我自己将它们的数组和值赋给 this.$refs
,以及两者之间的每一个组合。如果您正在为自己需要在 DOM 中显示的组件使用新的运算符,这是一个糟糕的设计选择。我应该能够通过 Isolated Scopes 和 Shared Global Component State 通过 VueX[=126= 完成我所做的一切] 反而。求助于this.$props
将初始化值传递给child组件,否则使用VueX作为共享组件州.
在弄清楚 VueX 是什么之前,我的最后一种方法是 global bus 方法,这对于由于 开发时间 和 复杂性 ,应用程序更大。这个概念也记录在 VueJS Component Edge Cases 页面上,标题为 Accessing the Root Instanc,然后用后续点说明:"This can be convenient for demos or very small apps with a handful of components. However, the pattern does not scale well to medium or large-scale applications, so we strongly recommend using Vuex to manage state in most cases."
无论如何,我现在要自己弄清楚 VueX 以供自己实施。也许我可以稍后使用更好的 VueJs/TypeScript 示例对其进行编辑。我暂时没有,现在可能会有。我的犹豫是没有干净的 TypeScript VueX 示例,当我第一次看的时候,我并没有马上知道我的场景用法,所以我像躲避瘟疫一样避开它。 .. 直到我对为什么我的 组件 上有未定义的函数完全感到困惑,我试图在 [=42] 之后通过 this.$refs
获取数据=] 哈哈 Mount/NextTick。是的,我绝对需要 VueX,尤其是 TypeScript。