使用Vue js发布具有多个组件的表单的最佳方法是什么?

时间:2018-08-03 13:10:36

标签: forms webpack vue.js vue-component

在进行Vue狂欢时(最近开始,但是到目前为止,我真的很喜欢学习这个框架),出现了几个问题。其中之一是如何从多个组件发布表单。因此,在我继续前进之前,我想问你您对这种结构方式有何想法,如果我错了,请指出正确的方向。

在这里。 我正在使用ASP.NET CORE 2.1和Vue JS模板(带有webpack)(https://github.com/MarkPieszak/aspnetcore-Vue-starter)进行SPA项目,我的项目由多个容器构成,如下所示: 在我的应用程序根目录中,我注册了多个容器

<template>

  <div id="app" class="container">

    <app-first-container></app-first-container>
    <app-second-container></app-second-container>
    <!--<app-third-container></app-third-container>-->
    <app-calculate-container></app-calculate-container>
    <app-result-container></app-result-container>

  </div>   
</template>

<script>
  // imported templates
  import firstContainer from './first-container'
  import secondContainer from './second-container'
  import calculateContainer from './calculateButton-container'
  //import thirdContainer from './third-container'
  import resultContainer from './result-container'

  export default {
    components: {
      'app-first-container': firstContainer,
      'app-second-container': secondContainer,
     // 'app-third-container': thirdContainer,
      'app-calculate-container': calculateContainer,
      'app-result-container': resultContainer
    }
  } 
</script>

在我的第一个容器中,我的脚本文件包含多个下拉列表和两个输入字段,在这里我从API提取数据,并使用获取的数据填充下拉列表和输入字段。

这样的事情(输入了一些虚拟代码进行演示)

<template>
  <div>
    <h1>Crops table</h1>

    <p>This component demonstrates fetching data from the server. {{dataMessage}}</p>

    <div class="form-row">

      <div class="form-group col-md-6">
        <label  for="exampleFormControlSelect1" class="col-form-label-sm font-weight-bold">1. Some text</label>
        <select class="form-control" id="exampleFormControlSelect1" v-model="pickedCropType" @change="getCropsByType()">
          <option v-for="(cropType, index) in cropTypes" :key="index" :value="cropType.id" :data-imagesrc="cropType.imgPath">{{ cropType.name }}</option>
        </select>
      </div>

      <div class="form-group col-md-6">
        <label for="exampleFormControlSelect2" class="col-form-label-sm font-weight-bold">2. Some text</label>
        <select class="form-control" id="exampleFormControlSelect2">
          <option v-for="(crop, index) in cropSelectList" :key="index" :value="crop.id">{{ crop.name }}</option>
        </select>
      </div>
    </div>

  </div>
</template>

<script>

  import { mapActions, mapState } from 'vuex'

  export default {
    data() {
      return {
        cropTypes: null,
        cropSelectList: null,
        crops: null,
        pickedCropType: null,

      }
    },

    methods: {
      loadPage: async function () {
        try {
          //Get crop types and create a new array with crop types with an added imgPath property
          var cropTypesFinal = [];
          let responseCropTypes = await this.$http.get(`http://localhost:8006/api/someData`);
          responseCropTypes.data.data.forEach(function (element) {

            cropTypesFinal.push(tmpType);
          });


        } catch (err) {
          window.alert(err)
          console.log(err)
        }
      },
      getCropsByType: async function () {
        //Get crops by crop type
        let responseCrops = await this.$http.get(`http://localhost:8006/api/crop/Type/${this.pickedCropType}`);
        var responseCropsData = responseCrops.data.data;
        this.cropSelectList = responseCropsData;
      }
    },

    async created() {
      this.loadPage()
    }
  }
</script>

在我的第二个容器中,我具有不同的下拉菜单和具有不同脚本等的不同输入字段。

所以,我的问题是:

1。)。我在第一个容器中有必填数据表单字段,在第二个容器中有附加数据,我的提交按钮在第三个容器中分开了(app-result-container) 。那么,如果不能的话,这种构造容器的正确且合理的方法是否可以指向正确的方向呢?

2。)在要为该特定容器处理/获取/提交某些数据的每个容器中输入脚本标记是否明智?我应该将scripts标签放在分开的文件中并保持结构整洁,将html文件与js文件分开。

示例: 从“某物”中导入{某物}

export default {
  data () {
    return {
      someData: 'Hello'
    }
  },
  methods: {
    consoleLogData: function (event) {
      Console.log(this.someData)
    }
  }
}

3。)是否可以将输入值从一个容器发送到另一个容器(在我的特殊情况下,是从第一个容器和第二个容器到app-calculate-container(第三个容器))?

如何使用已计算的导入值提交退货结果容器

1 个答案:

答案 0 :(得分:2)

如果您希望组件之间相互通信或共享数据,则需要emit从一个组件到父组件的事件,并通过props传递给它,或者使用某种状态管理模型,例如Vuex,您的每个组件都可以在其中收听商店。

看看下面的代码沙箱:https://codesandbox.io/s/8144oy7xy2

App.vue

<template>
  <div id="app">
    <child-input @input="updateName" />
    <child-output :value="name" />
  </div>
</template>

<script>
import ChildInput from "@/components/ChildInput.vue";
import ChildOutput from "@/components/ChildOutput.vue";

export default {
  name: "App",
  components: {
    ChildInput,
    ChildOutput
  },
  data() {
    return {
      name: ""
    };
  },
  methods: {
    updateName(e) {
      this.name = e.target.value;
    }
  }
};
</script>

ChildInput.vue

<template>
  <input type="text" @input="changeHandler">
</template>

<script>
export default {
  name: "ChildInput",
  methods: {
    changeHandler(e) {
      this.$emit("input", e);
    }
  }
};
</script>

ChildOutput.vue

<template>
  <p>{{ value }}</p>
</template>

<script>
export default {
  name: "ChildOutput",
  props: {
    value: {
      type: String,
      default: ""
    }
  }
};
</script>

发生了什么事?

ChildInput组件是一个文本字段,在其中的每个更改上都会触发一个事件(使用this.$emit()发出并通过整个事件 up 传递)。

在触发此操作时,App在监听更改,从而触发一种更新名称数据属性的方法。

由于name是一种反应性数据属性,并且作为对ChildOutput组件的支持而向下传递,因此屏幕将重新渲染并使用写入的文本进行更新。

ChildInputChildOutput都不认识。是父级侦听传递给它的事件,然后向下传递新的道具。

这种工作方式很好并且易于理解,但我强烈建议您查看Vuex,因为当您完成琐碎的任务时,这种方法可能会变得凌乱和复杂。