【问题标题】:Vuejs: Passing SAVE function into CRUD componentVuejs:将 SAVE 函数传递给 CRUD 组件
【发布时间】:2020-02-13 22:45:41
【问题描述】:

我正在努力寻找一个需要在 vuejs 中进行高级父子通信的适当解决方案。可以有许多不同的父组件,它们具有如何保存数据的逻辑。另一方面,只有一个子组件具有元素列表和创建新元素的表单,但它不知道如何保存数据。

问题是:除了删除this.$refs.child 链接之外,还有其他方法(更好的方法)可以拥有相同的功能。例如,我想知道是否可以将一个函数(SaveParent1(...)SaveParent2(...))传递给子组件。但问题是该函数包含一些在子上下文中不可用的父变量,并且这些变量可以在运行时更改。

只是一些澄清:

  1. 现实生活中的SaveParent1SaveParent2方法返回 承诺(axios)。
  2. child-component 就像使用的 CRUD 其他任何地方。

目前通讯看起来像这样:CHILD -event->PARENT -ref->CHILD。

下面是例子:

<div id="app">
  <h2>&#128512;Advanced Parent-Child Communication:</h2>
  <parent-component1 param1="ABC"></parent-component1>
  <parent-component2 param2="XYZ"></parent-component2>
</div>
Vue.component('parent-component1', {
  props: { param1: { type: String, required: true } },
  methods: {
    onChildSubmit(p) {
        // Here will be some logic to save the param. Many different parents might have different logic and all of them use the same child component. So child-component contains list, form and validation message but does not know how to save the param to the database.
      var error = SaveParent1({ form: { p: p, param1: this.param1 } });
      if (error)
        this.$refs.child.paramFailed(error);
      else
        this.$refs.child.paramAdded(p);
    }
  },
  template: `<div class="parent"><p>Here is parent ONE:</p><child-component ref="child" @submit="onChildSubmit"></child-component></div>`
});

Vue.component('parent-component2', {
  props: { param2: { type: String, required: true } },
  methods: {
    onChildSubmit(p) {
        // Here is a different logic to save the param. In prictice it is gonna be different requests to the server.
      var error = SaveParent2({ form: { p: p, param2: this.param2 } });
      if (error)
        this.$refs.child.paramFailed(error);
      else
        this.$refs.child.paramAdded(p);
    }
  },
  template: `<div class="parent"><p>Here is parent TWO:</p><child-component ref="child" @submit="onChildSubmit"></child-component></div>`
});

Vue.component('child-component', {
  data() {
    return {
      currentParam: "",
      allParams: [],
      errorMessage: ""
    }
  },
  methods: {
    submit() {
        this.errorMessage = "";
        this.$emit('submit', this.currentParam);
    },
    paramAdded(p) {
        this.currentParam = "";
        this.allParams.push(p);
    },
    paramFailed(msg) {
        this.errorMessage = msg;
    }
  },
  template: `<div><ol><li v-for="p in allParams">{{p}}</li></ol><label>Add Param: <input v-model="currentParam"></label><button @click="submit" :disabled="!currentParam">Submit</button><p class="error">{{errorMessage}}</p></div>`
});

function SaveParent1(data) {
  // Axios API to save data. Bellow is a simulation.
  if (Math.random() > 0.5)
    return null;
  else
    return 'Parent1: You are not lucky today';
}

function SaveParent2(data) {
  // Axios API to save data. Bellow is a simulation.
  if (Math.random() > 0.5)
    return null;
  else
    return 'Parent2: You are not lucky today';
}

new Vue({
  el: "#app"
});

还有一个现场演示:https://jsfiddle.net/FairKing/novdmcxp/

【问题讨论】:

    标签: javascript vue.js parent-child crud


    【解决方案1】:

    在架构上,我建议使用完全从组件层次结构中抽象出来的服务,并且您可以在每个组件中注入和使用该服务。使用这种组件层次结构和架构,很容易遇到这些问题。从组件中抽象出尽可能多的功能和业务逻辑是很重要的。我认为这些现代框架中的组件只是类固醇上的 HTML 模板,它们最多应该充当控制器,使它们尽可能地愚蠢和薄,这样你就不会遇到这些情况。我不知道vue.js,所以我不能给你技术解决方案,但希望这个指示对你有帮助

    【讨论】:

    • 感谢您的回答。我理解你的观点,你提到的服务实际上是SaveParent1SaveParent2,它们可能包含如何验证和持久化数据的整个逻辑。由于简化,它们是本地的。
    • 将它们作为类或实用程序函数放在单独的文件中,然后将它们导入组件中...使用 Web 组件架构,您将获胜
    【解决方案2】:

    我想我找到了解决办法。所以没有两种方式的交流。我可以只传递一个方法,孩子会在不与父母沟通的情况下做所有事情。我很高兴我将其标记为答案。感谢大家的帮助。

    请告诉我你们的想法。

    下面是我的解决方案:

    <div id="app">
      <h2>&#128512;Advanced Parent-Child Communication:</h2>
      <parent-component1 param1="ABC"></parent-component1>
      <parent-component2 param2="XYZ"></parent-component2>
    </div>
    
    Vue.component('parent-component1', {
        props: { param1: { type: String, required: true } },
      computed: {
        saveFunc() {
            return function(p) { SaveParent1({ form: { p: p, param1: this.param1 } }); }.bind(this);
        }
      },
      template: `<div class="parent"><p>Here is parent ONE:</p><child-component :saveFunc="saveFunc"></child-component></div>`
    });
    
    Vue.component('parent-component2', {
        props: { param2: { type: String, required: true } },
      computed: {
        saveFunc() {
            return function(p) { SaveParent2({ form: { p: p, param2: this.param2 } }); }.bind(this);
        }
      },
      template: `<div class="parent"><p>Here is parent TWO:</p><child-component :saveFunc="saveFunc"></child-component></div>`
    });
    
    Vue.component('child-component', {
        props: { 
        saveFunc: { type: Function, required: true }, // This is gonna be a Promise in real life.
      },
      data() {
        return {
          currentParam: "",
          allParams: [],
          errorMessage: ""
        }
      },
      methods: {
        submit() {
            this.errorMessage = "";
          var error = this.saveFunc(this.currentParam);
          if (error)
            this.paramFailed(error);
          else
            this.paramAdded(this.currentParam);
        },
        paramAdded(p) {
            this.currentParam = "";
            this.allParams.push(p);
        },
        paramFailed(msg) {
            this.errorMessage = msg;
        }
      },
      template: `<div><ol><li v-for="p in allParams">{{p}}</li></ol><label>Add Param: <input v-model="currentParam"></label><button @click="submit" :disabled="!currentParam">Submit</button><p class="error">{{errorMessage}}</p></div>`
    });
    
    function SaveParent1(data) {
        console.log(data);
        // Axios API to save data
        if (Math.random() > 0.5)
        return null;
      else
        return 'Parent1: You are not lucky today';
    }
    
    function SaveParent2(data) {
        console.log(data);
        // Axios API to save data
        if (Math.random() > 0.5)
        return null;
      else
        return 'Parent2: You are not lucky today';
    }
    
    new Vue({
      el: "#app"
    });
    

    演示链接:https://jsfiddle.net/FairKing/novdmcxp/126/

    【讨论】:

      猜你喜欢
      • 2019-11-08
      • 2016-03-27
      • 1970-01-01
      • 2018-09-12
      • 2017-08-13
      • 2019-09-15
      • 2020-05-22
      • 1970-01-01
      相关资源
      最近更新 更多