代码之家  ›  专栏  ›  技术社区  ›  Svinjica

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

  •  1
  • Svinjica  · 技术社区  · 6 年前

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

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

    <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文件分开。

    例子: 从“something”导入{something}

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

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

    如何使用计算的导入值提交返回结果容器

    1 回复  |  直到 6 年前
        1
  •  3
  •   Michael Giovanni Pumo    6 年前

    如果希望组件相互通信或共享数据,则需要 emit 从一个组件到父组件并通过道具向下传递的事件,或使用某种状态管理模型(如Vuex),其中每个组件都可以监听存储。

    看看这个代码沙盒: https://codesandbox.io/s/8144oy7xy2

    应用程序.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() 通过了整个比赛 向上的 ).

    当这场火灾发生时, App 正在侦听更改,该更改将触发更新名称数据属性的方法。

    因为 name 是一个反应性数据属性,作为 ChildOutput 组件,屏幕将重新呈现并用写入的文本进行更新。

    也不是 儿童输入 也不是 儿童产出 互相了解。是父进程监听传递给它的事件,然后传递新的道具。

    这种工作方式很好,也很容易理解,但我强烈建议您查看Vuex,因为当您超越琐碎的任务时,这种方法可能会变得混乱和复杂。