Vue js:如何在两个组件中使用 mixin 功能?通过执行错误

Posted

技术标签:

【中文标题】Vue js:如何在两个组件中使用 mixin 功能?通过执行错误【英文标题】:Vue js: How to use mixin function in two components? By execution Error 【发布时间】:2022-01-03 18:20:37 【问题描述】:

我有 2 个组件:父子组件和一个 mixin。我试图在他们两个中使用一个功能。从父组件中的子组件调用 mixin 函数。这个 mixin 函数也改变了父组件的 data var,它在子组件中被 props 引用。

但是,在这行代码中:

this.modals.filter = 'block'; occurs error: TypeError: Cannot set properties of undefined (setting 'filter')

我不明白为什么,因为 modals.filter 已经在 props 中被引用了?

<!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>

【问题讨论】:

this.modals 未定义 在子组件和父组件中同时使用相同的 mixin 很奇怪,你可以从子组件发出按钮点击事件,然后在父组件调用 powerbiFilterModal @Radeanu 你能补充一下它是如何实现的吗?我检查了发出点击,但如何通过使用此类事件触发函数? 【参考方案1】:

解释我的评论

子组件

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】:

powerbiFilterModal()是引用this.modals,如果在父组件中使用是可以的,但是子组件没有这样的数据,所以在子组件中调用mixin会报错。

【讨论】:

以上是关于Vue js:如何在两个组件中使用 mixin 功能?通过执行错误的主要内容,如果未能解决你的问题,请参考以下文章

在 Vue.js 中使用Mixin

Vue Js:在本地使用导入插件 mixin

如何测试 Vue.js mixin 的模板?

Vue.js / Mixins - 有没有办法在 vue 组件之外获取全局 mixin-object?

vue-learning:21 - js - mixins

无法从 Vue.js 中的单个文件组件导入 Mixin