如何在 Vue.js 中的两个组件之间共享一个方法?

Posted

技术标签:

【中文标题】如何在 Vue.js 中的两个组件之间共享一个方法?【英文标题】:How to share a method between two components in Vue.js? 【发布时间】:2018-12-26 19:17:13 【问题描述】:

我有一个 Ag-Grid,它具有某些操作按钮和从 MongoDB 数据库填充的动态数据。我的 MasterData.Vue 文件上有一个刷新网格的方法。我的网格记录中的每个操作按钮都执行更新/删除操作。当我点击这些按钮时,我在另一个 Modal.Vue 文件中设计了一个自定义的弹出模式组件。我想在 Modal.Vue 中调用 RefreshGrid() 方法。我尝试使用道具来共享数据,但同样的事情在方法上不起作用。

MasterData.Vue 脚本

<script>
import  AgGridVue  from 'ag-grid-vue';
import  mapGetters  from 'vuex';
import gridEditButtons from '@/components/GridEditButton';
import MasterModal from '@/components/MasterModal';
export default 
  name: 'masterData',
  data () 
    return 
      addBtnClick: false,
      delBtnClick: false,
      editVisible: false,
      selected: 'Business Area',
      dropdown_tables: [
        'Business Area',
        'Council',
        'Sub Area',
        'Type',
        'Work Flow Stage'
      ],
      gridOptions: 
        domLayout: 'autoHeight',
        enableColumnResize: true,
        rowDragManaged: true,
        animateRows: true,
        context: 
          vm: null
        
      
    ;
  ,
  components: 
    'ty-master-modal': MasterModal,
    'ag-grid-vue': AgGridVue,
    gridEditButtons
  ,
  methods: 
  // Filter Grid Contents based on Dropdown selection
    RefreshGrid: function () 
      let cName;
      if (this.selected === 'Business Area') 
        cName = 'businessarea';
       else if (this.selected === 'Council') 
      cName = 'council';
       else if (this.selected === 'Type') 
        cName = 'typemaster';
       else if (this.selected === 'Work Flow Stage') 
        cName = 'workflowstage';
      
      let obj = 
        vm: this,
        collectionName: cName,
        action: 'masterData/setMasterData',
        mutation: 'setMasterData'
      ;
      this.$store.dispatch(obj.action, obj);
    
;
</script>

Modal.Vue 脚本

<script>
import mapGetters from 'vuex';

export default 
  name: 'MasterModal',
  props: 
    readOnly: Boolean,
    entryData: Object,
    addBtnClick: Boolean,
    delBtnClick: Boolean,
    editVisible: Boolean,
    selectedTable: String
  ,
  data () 
    return 
      fieldAlert: false,
      isReadOnly: false,
      dialog: false,
      dialogDelete: false,
      valid: false,
      visible: false,
      disable: false
    ;
  ,
  computed: 
    ...mapGetters('masterData', 
      entryState: 'entryState',
      // entryData: 'entryData',
      columns: 'columns',
      selectedRowId: 'selectedRowId'
    )
  ,
  watch: 
    addBtnClick: function (newValue, oldValue) 
      this.setDialog(!this.dialog);
    ,
    editVisible: function (newValue, oldValue) 
      this.setVisible(!this.visible);
    ,
    delBtnClick: function (newValue, oldValue) 
      this.setDialogDelete(!this.dialogDelete);
    
  ,
  methods: 
    setDialog (bValue) 
      this.dialog = bValue;
    ,
    setDialogDelete (bValue) 
      this.dialogDelete = bValue;
    ,
 
;
</script>

【问题讨论】:

您已经在使用 vuex,因此将调度放在一个组件中并在另一个组件中计算,这就足够了(除了在有多个实例时传递一个键或 id)。您能否澄清一下您的意思:在 Modal.Vue 中调用 RefreshGrid() 方法该方法在该组件中不存在 我想从 Modal.Vue 调用 RefreshGrid() 方法 【参考方案1】:

有几种方法可以实现这一点。

一种是使用emit

MasterModal.vue 组件中运行 this.$emit('refreshGrid') 在父 MasterData.Vue 组件中使用 &lt;ty-master-modal @refreshGrid="RefreshGrid" ...&gt;

如果你有一个直接的父子关系,这可能是最好的选择

另一种方法是将函数作为道具传递给子组件。

&lt;ty-master-modal :onRefreshGrid="RefreshGrid" ...&gt;

MasterModal.vue中添加一个prop onRefreshGrid,就可以调用函数了。

使用 vuex 的另一种方法是在 MasterData.Vue 中添加一个监视并监视 vuex 存储中的一个变量,即。 actionInvoker。当actionInvoker 改变时,动作执行。要更改该值,请将其设置为 0 并在其间递增或切换,或设置为随机值。优点是您可以从任何地方调用它。

这个(和之前的)解决方案的问题在于,您的功能与不应该存在的视图/组件相关联。我会推荐第三种解决方案,即将功能推送到 vuex 操作中,然后您可以从任何地方调用它。这需要您将 selected 变量也存储在 vuex 中,并且如果您想要拥有 Modal 和 Master 组件的多个实例,单个存储将禁止这样做(除非您添加对多个实例的支持)。

【讨论】:

所以,我正在使用 onRefreshGrid 一种“对象”类型的道具。我是否需要添加监视来调用 onRefreshGrid()?并以任何方法调用 this.onRefreshGrid()? 为什么不使用 emit/on event @NikulVyas,你可以定义prop property=function,比如props: 'onRefreshGrid ': type: Function, default: ()=&gt; @NikulVyas 如果您将函数作为道具传递(或使用发射),则不需要手表。仅当您希望函数在变量更改值时触发(即使用 vuex)时,手表才有用

以上是关于如何在 Vue.js 中的两个组件之间共享一个方法?的主要内容,如果未能解决你的问题,请参考以下文章

在所有 Vue.js 组件之间共享数据

如何在 Monorepo 中的 VueJS 项目之间共享组件

Vue JS 2. 如何防止在两个父级之间导航时重新加载相同的嵌套组件?

从 Vue.js 中的另一个组件调用方法

Vue JS 3:如何将数据从一个组件传递到另一个组件?

什么是vuex?他有什么作用?如何改变store中的状态(state)?