如何在 Vue.js 中的组件之间共享方法
How can I share a method between components in Vue.js?
看看这个简单的购物车演示:
http://plnkr.co/edit/CHt2iNSRJAJ6OWs7xmiP?p=preview
用户可以选择蔬菜和水果,然后将其添加到购物车数组中。添加水果/蔬菜的函数非常相似,我想将其组合成一个可以在两个组件之间共享的函数。
selectFruit: function(product){
var cart = this.cart
for(p in cart){
if (cart[p]["type"] == "fruit"){
console.log("We already got a fruit!, Let's remove " + cart[p]["name"] + " and add in " + product["name"]);
this.cart.$remove(cart[p])
}
}
console.log("Adding " + product.name + " to cart.");
var productName = product.name
var cartFruit = {name: product.name, type: 'fruit'}
this.cart.push(cartFruit)
}
selectVeggie: function(product){
var cart = this.cart
for(p in cart){
if (cart[p]["type"] == "veggie"){
console.log("We already got a veggie!, Let's remove " + cart[p]["name"] + " and add in " + product["name"]);
this.cart.$remove(cart[p])
}
}
console.log("Adding " + product.name + " to cart.");
var productName = product.name
var cartVeggie = {name: product.name, type: 'veggie'}
this.cart.push(cartVeggie)
}
我怎样才能改变这种方法并在全球范围内使用它?顺便说一句,我正在这个项目中使用 Vue 路由器,感谢您的任何帮助!
我发现这种技术更简单/更令人满意,因为我更喜欢组合而不是继承:
SRC/共享.js
export default {
foo: function() { alert("foo!") }
}
src/yourcomponent.vue
<template>...</template>
<script>
import shared from './shared'
export default {
created() {
this.foo = shared.foo // now you can call this.foo() (in your functions/template)
}
}
</script>
这也将允许你编写与 Vue 无关的测试。
注意:如果你需要 foo 在 Vue-scope 中运行,请将
this.foo = shared.foo
替换为this.foo = shared.foo.bind(this)
选项 1
跨组件共享方法的一种方法是使用 mixin。下面是一个包含selectProduct
方法的cartMixin
:
var cartMixin = {
methods: {
selectProduct: function (product) {
var cart = this.cart
for(p in cart){
if (cart[p]["type"] == product.type){
console.log("We already got a "+ product.type +"!, Let's remove " + cart[p]["name"] + " and add in " + product["name"]);
this.cart.$remove(cart[p])
}
}
console.log("Adding " + product.name + " to cart.");
var productName = product.name
var cartProduct = {name: product.name, type: product.type}
this.cart.push(cartProduct)
}
}
};
您可以在每个组件中引用它,如下所示:
var Vegetable = Vue.extend({
template: '#vegetable',
mixins: [cartMixin],
data: function(){
return sourceOfTruth
}
})
。然后在您的模板中使用它,如下所示:
<li v-for="product in food | showOnly 'fruit'" @click="selectProduct(product)">
{{product.name}}
</li>
这是你的Plunker的一个分支。
选项 2
在考虑了更多之后,您可能会考虑的另一个选项是创建一个基本Product
组件并将其扩展以创建Fruit
和Vegetable
组件。然后,您将通用功能放在基本组件中。
var Product = Vue.extend({
data: function(){
return sourceOfTruth
},
methods: {
selectProduct: function (product) {
var cart = this.cart
for(p in cart){
if (cart[p]["type"] == product.type){
console.log("We already got a "+ product.type +"!, Let's remove " + cart[p]["name"] + " and add in " + product["name"]);
this.cart.$remove(cart[p])
}
}
console.log("Adding " + product.name + " to cart.");
var productName = product.name
var cartProduct = {name: product.name, type: product.type}
this.cart.push(cartProduct)
}
}
})
var Vegetable = Product.extend({
template: '#vegetable',
});
var Fruit = Product.extend({
template: '#fruit',
});
这是这种方法的Plunker。
鉴于您的水果和蔬菜模板非常相似,您也许可以更进一步地利用这个想法,并使用基本组件中的通用模板。
如果您尝试在多个 vue 模板和布局之间或沿多个 vue 模板和布局共享相同的组件逻辑,您可以简单地尝试以下方法:
以前:
A.vue
<template>
<div>
<h1>{{title}}</h1>
<small>{{datetime}}</small>
</div>
</template>
<script>
export default {
props: {
title: String
},
data() {
return {
datetime: new Date()
}
}
}
</script>
B.vue
<template>
<div>
<h3>{{title}}</h3>
<h6>{{datetime}}</h6>
</div>
</template>
<script>
export default {
props: {
title: String
},
data() {
return {
datetime: new Date()
}
}
}
</script>
后:
A.vue
<template>
<div>
<h1>{{title}}</h1>
<small>{{datetime}}</small>
</div>
</template>
<script>
import shared from "./shared.js";
export default Object.assign({}, shared);
</script>
B.vue
<template>
<div>
<h3>{{title}}</h3>
<h6>{{datetime}}</h6>
</div>
</template>
<script>
import shared from "./shared.js";
export default Object.assign({}, shared);
</script>
共享.js
export default {
props: {
title: String
},
data() {
return {
datetime: new Date()
}
}
}
您可以将该方法放在根 Vue 实例中,然后在选择蔬菜或选择水果时从子实例调度事件。 事件在其父组件上查找处理程序,如果找不到事件处理程序,则它们将继续沿链向上移动,直到找到为止。 因此,在您的根实例上:
events: {
'choose-fruit':function(fruit){
//handle the choosing of fruit
}
}
然后在子实例上:
selectFruit: function(product){
this.$dispatch('choose-fruit', product);
}
在 Vue 3 中,你可以使用 Composables 来重用代码
js/Composables/Capitalize.js
export function useCapitalized(name) {
const capitalizedFirst = name[0].toUpperCase();
const rest = name.slice(1);
return capitalizedFirst + rest;
}
js/Components/YourComponent.vue
<template>...</template>
<script>
import { useCapitalized } from '@/Composables/Capitalize.js'; // by convention, composable function names start with "use"
export default {
props: {
statusName: String,
},
data() {
return {
content: "",
}
},
created() {
this.content = useCapitalized(this.statusName)
}
}
</script>
Vue 3 关于使用 Composables 在组件之间重用代码的官方文档 这里 选项 API 和这里 Composition API
我只会配置一个混合
export const sharedMethods = {
// Generic funcion
methods: {
axiosGet(route){
return axios.get(route)
.then(response => response.data)
.catch((error)=> {console.log(error)})
},
axiosPost(route, postObj, resolveCallback, rejectCallback){
axios.post(route, postObj)
.then(resolveCallback)
.catch(rejectCallback);
},
}
然后在组件中使用 mixin,像调用组件本身的功能一样调用其函数,就好像这些函数是您要导入 mixin 的组件的一部分一样:
把它放在组件上:mixins: [sharedMethods],
在组件内部,我调用 mixin 函数:
this.axiosPost(
'/route',
data,
() => console.log('success'),
() => console.log('fail')
)
这很有用,因为使用 aproach 只是从 js 文件导入函数,正在导入的文件中的函数将采用自己的"this"在函数中使用,这可能会导致一些混淆,而 mixin 将使用它正在导入的组件的"this",就好像它的函数是组件的一部分, 正如我所说。
注意:如果共享文件中有 2 个(或更多)方法.js,则可以使用以下方法从另一个方法调用一个方法:
utils.js:
export default {
method1(){
···
return ...
},
method2(){
val1 = this.method1();
···
return ...
},
}
yourcomponent.vue
<template>...</template>
<script>
import utils from './utils.js';
export default {
created() {
val2 = utils.method2();
}
}
</script>
- 设置两个反应组件之间状态的正确方式
- Ember.js:接受的子组件和父组件之间通信的最佳实践
- Angular 2,在没有直接关系的两个组件之间共享一个对象
- 在 React/Redux 中管理同级组件之间的滚动状态
- 如何更新angular2中组件之间的事件数据
- Aurelia中HTML组件和普通组件之间的区别
- Vuejs中同级组件之间的通信
- 尝试在组件之间传递数据时未定义
- React组件之间共享属性
- Reactjs:如何在组件之间共享 websocket
- 在两个组件之间传输状态
- Reactjs 组件之间的通信
- AngularJS:在组件之间进行通信的最佳实践是什么?
- 如何管理独立反应组件之间的通信
- 响应组件之间的交互
- 两个网络组件之间的绑定:谷歌地图+地理定位
- 如何在 Vue.js 中的组件之间共享方法
- 在 React 组件之间交换事件
- 在两个同级React.js组件之间传递数据
- 在reactjs中没有父子关系的不同组件之间进行通信