Vuejs: передача функции SAVE в компонент CRUD - PullRequest
0 голосов
/ 14 февраля 2020

Я борюсь с правильным решением, которое требует расширенного общения между родителями и детьми в vuejs. Может быть много разных родительских компонентов, у которых есть логика c как сохранять данные. С другой стороны, будет только один дочерний компонент, у которого есть список элементов и форма для создания новых элементов, но он не знает, как сохранить данные.

Вопрос : Есть ли другой способ (лучший подход), чтобы иметь такую ​​же функциональность, кроме как избавиться от this.$refs.child ссылок. Например, мне интересно, могу ли я просто передать функцию (SaveParent1(...) или SaveParent2(...)) дочернему компоненту. Но проблема в том, что функция содержит некоторые родительские переменные, которые не будут доступны в дочернем контексте, и эти переменные могут быть изменены во время выполнения.

Несколько пояснений:

  1. Методы SaveParent1 и SaveParent2 в реальной жизни возвращают Promise (топор ios).
  2. child-component похож на CRUD, который используется повсюду.

На данный момент сообщение выглядит так: РЕБЕНОК -event-> РОДИТЕЛЬ -ref-> РЕБЕНОК *

Ниже приведен пример сильфона:

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

Ответы [ 2 ]

1 голос
/ 14 февраля 2020

Архитектурно я рекомендую иметь сервис, который полностью абстрагируется от иерархии компонентов и который вы можете внедрять и использовать в каждом из компонентов. С этим типом иерархии компонентов и архитектуры легко столкнуться с этими проблемами. Важно абстрагировать как можно больше функциональности и бизнес-логики c от компонентов. Я думаю о компонентах в этих современных средах просто как о HTML шаблонах на стероидах, которые в большинстве случаев должны действовать как контроллеры, сохраняя их настолько тупыми и настолько тонкими, насколько это возможно, чтобы вы не столкнулись с этими ситуациями. Я не знаю vue.js, поэтому я не могу дать вам техническое решение, но надеюсь, что это указание поможет

0 голосов
/ 16 февраля 2020

Я думаю, что нашел решение. Так что нет двух способов общения. Я могу просто передать метод, и ребенок все сделает, не общаясь с родителем. Я счастлив, что отмечаю это как ответ. Спасибо всем за вашу помощь.

Дайте мне знать, пожалуйста, что вы думаете, ребята.

Мое решение - мое решение:

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

...