Vue js:如何在两个组件中使用 mixin 功能?通过执行错误
Vue js: How to use mixin function in two components? By execution Error
我有 2 个组件:parent 和 child 以及一个 mixin。我正在尝试在两者中使用一个功能。从父组件中的子组件调用 mixin 函数。这个 mixin 函数还更改了来自父组件的数据 var,它在 props 中引用了子组件。
但是,在这行代码中:
this.modals.filter = 'block'; occurs error: TypeError: Cannot set properties of undefined (setting 'filter')
我不明白为什么,因为道具中已经引用了 modals.filter?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
</head>
<body>
<div id="example" style="width:100%;height:100%">
<parent></parent>
</div>
</body>
<script>
var myMixin = {
methods: {
powerbiFilterModal: function() {
this.modals.filter = 'block';
if (this.embed.channelName, this.filters.columnName, this.filters.tableName) {
// Some other functions
// ...
console.log(this.embed.channelName, this.filters.columnName, this.filters.tableName);
// Hide modal
this.modals.filter = 'none';
// Clear inputs
this.embed.channelName = '';
this.filters.columnName = '';
this.filters.tableName = '';
}
}
}
};
Vue.component('child', {
mixins: [myMixin],
template: `
<div :style="{ display: filterOverlay }">
<span class="close" style="align-self: flex-end; cursor: pointer;" @click="closeModal">x</span>
<span class="label" style="align-self: center; margin-bottom: 4%">Filter Settings: </span>
<input type="text" placeholder="Define channel name" v-model.trim="channelName">
<input type="text" placeholder="Define filter name" v-model.trim="columnName">
<input type="text" placeholder="Define table to filter" v-model.trim="tableName">
<button @click="powerbiFilterModal">Subscribe & Send</button>
</div>
`,
props: {
filterOverlay: {
type: String,
required: false,
default: 'none'
},
channelName: {
type: String,
required: false
},
columnName: {
type: String,
required: false
},
tableName: {
type: String,
required: false
}
},
methods: {
closeModal: function() {
this.$emit('emitEv', 'none');
}
}
});
Vue.component('parent', {
mixins: [myMixin],
template: `
<div>
<button @click="powerbiFilterModal">Set Filters</button>
<child @emitEv="changeOverlay" v-bind:filter-overlay="modals.filter">Child</child>
</div>
`,
data: function() {
return {
modals: {
filter: 'none'
},
embed: {
channelName: ''
},
filters: {
columnName: '',
tableName: ''
}
}
},
methods: {
changeOverlay: function(value) {
this.modals.filter = value;
}
}
});
new Vue({
el: "#example"
});
</script>
</html>
powerbiFilterModal()
引用了this.modals
,在父组件中使用是可以的,但是子组件没有这样的数据,所以在子组件中调用mixin会报错.
解释我的评论
子组件
Vue.component("child", {
// mixins: [myMixin], remove mixin from child
template: `
<div>
<!-- bla bla bla -->
<button @click="$emit('fire')">Subscribe & Send</button>
</div>
...
`
});
父组件
Vue.component("parent", {
mixins: [myMixin],
template: `
<div>
<button @click="powerbiFilterModal">Set Filters</button>
<!-- HERE we listen for event (fire) from child and call powerbiFilterModal method from mixin -->
<child @fire="powerbiFilterModal" @emitEv="changeOverlay" v-bind:filter-overlay="modals.filter">Child</child>
</div>
`,
data: function () {
return {
modals: {
filter: "none"
},
embed: {
channelName: ""
},
filters: {
columnName: "",
tableName: ""
}
};
},
methods: {
changeOverlay: function (value) {
this.modals.filter = value;
}
}
});
我有 2 个组件:parent 和 child 以及一个 mixin。我正在尝试在两者中使用一个功能。从父组件中的子组件调用 mixin 函数。这个 mixin 函数还更改了来自父组件的数据 var,它在 props 中引用了子组件。
但是,在这行代码中:
this.modals.filter = 'block'; occurs error: TypeError: Cannot set properties of undefined (setting 'filter')
我不明白为什么,因为道具中已经引用了 modals.filter?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
</head>
<body>
<div id="example" style="width:100%;height:100%">
<parent></parent>
</div>
</body>
<script>
var myMixin = {
methods: {
powerbiFilterModal: function() {
this.modals.filter = 'block';
if (this.embed.channelName, this.filters.columnName, this.filters.tableName) {
// Some other functions
// ...
console.log(this.embed.channelName, this.filters.columnName, this.filters.tableName);
// Hide modal
this.modals.filter = 'none';
// Clear inputs
this.embed.channelName = '';
this.filters.columnName = '';
this.filters.tableName = '';
}
}
}
};
Vue.component('child', {
mixins: [myMixin],
template: `
<div :style="{ display: filterOverlay }">
<span class="close" style="align-self: flex-end; cursor: pointer;" @click="closeModal">x</span>
<span class="label" style="align-self: center; margin-bottom: 4%">Filter Settings: </span>
<input type="text" placeholder="Define channel name" v-model.trim="channelName">
<input type="text" placeholder="Define filter name" v-model.trim="columnName">
<input type="text" placeholder="Define table to filter" v-model.trim="tableName">
<button @click="powerbiFilterModal">Subscribe & Send</button>
</div>
`,
props: {
filterOverlay: {
type: String,
required: false,
default: 'none'
},
channelName: {
type: String,
required: false
},
columnName: {
type: String,
required: false
},
tableName: {
type: String,
required: false
}
},
methods: {
closeModal: function() {
this.$emit('emitEv', 'none');
}
}
});
Vue.component('parent', {
mixins: [myMixin],
template: `
<div>
<button @click="powerbiFilterModal">Set Filters</button>
<child @emitEv="changeOverlay" v-bind:filter-overlay="modals.filter">Child</child>
</div>
`,
data: function() {
return {
modals: {
filter: 'none'
},
embed: {
channelName: ''
},
filters: {
columnName: '',
tableName: ''
}
}
},
methods: {
changeOverlay: function(value) {
this.modals.filter = value;
}
}
});
new Vue({
el: "#example"
});
</script>
</html>
powerbiFilterModal()
引用了this.modals
,在父组件中使用是可以的,但是子组件没有这样的数据,所以在子组件中调用mixin会报错.
解释我的评论
子组件
Vue.component("child", {
// mixins: [myMixin], remove mixin from child
template: `
<div>
<!-- bla bla bla -->
<button @click="$emit('fire')">Subscribe & Send</button>
</div>
...
`
});
父组件
Vue.component("parent", {
mixins: [myMixin],
template: `
<div>
<button @click="powerbiFilterModal">Set Filters</button>
<!-- HERE we listen for event (fire) from child and call powerbiFilterModal method from mixin -->
<child @fire="powerbiFilterModal" @emitEv="changeOverlay" v-bind:filter-overlay="modals.filter">Child</child>
</div>
`,
data: function () {
return {
modals: {
filter: "none"
},
embed: {
channelName: ""
},
filters: {
columnName: "",
tableName: ""
}
};
},
methods: {
changeOverlay: function (value) {
this.modals.filter = value;
}
}
});