Vue强制关闭标签

时间:2017-11-08 12:21:22

标签: vue.js vuejs2

我正在从几百行的json中构建一个动态表单。每个json对象都有一个映射到输入/日期/标题等的类型:

{ name: "input1", label: "input1 ", placeholder: "Enter text", value: "", type: "text"},
{ name: "input2", label: "input2", placeholder: "Enter text", value: "", type: "text"},
{ name: "title", label: "Title", placeholder: "", value: "", type: "title"},
{ name: "input3", label: "input3", placeholder: "Enter date", value: "", type: "date"},
{ name: "input4", label: "input4", placeholder: "Enter text", value: "", type: "text"},


<template v-for="item in data">

    <template v-if="item.type === 'text'">
      <label>{{item.label}}</label>
      <input type="text" v-model="item.value" :placeholder="item.placeholder" />
    </template>

    <template v-if="item.type === 'date'">
      <label>{{item.label}}</label>
      <input type="date" v-model="item.value" :placeholder="item.placeholder" />
    </template>

    <template v-if="item.type === 'title'">
      <h1>{{item.label}}</h1>
    </template>

</template>

我想在div中将部分组合在一起进行样式设计。所以我试过了:

{ name: "input1", label: "input1 ", placeholder: "Enter text", value: "", type: "text"},
{ name: "input2", label: "input2", placeholder: "Enter text", value: "", type: "text"},
{ name: "openDiv", label: "", placeholder: "", value: "", type: "openDiv"},
{ name: "title", label: "Title", placeholder: "", value: "", type: "title"},
{ name: "input3", label: "input3", placeholder: "Enter date", value: "", type: "date"},
{ name: "input4", label: "input4", placeholder: "Enter text", value: "", type: "text"},
{ name: "closeDiv", label: "", placeholder: "", value: "", type: "closediv"},

<template v-for="item in data">

    <template v-if="item.type === 'text'">
      <label>{{item.label}}</label>
      <input type="text" v-model="item.value" :placeholder="item.placeholder" />
    </template>

    <template v-if="item.type === 'date'">
      <label>{{item.label}}</label>
      <input type="date" v-model="item.value" :placeholder="item.placeholder" />
    </template>

    <template v-if="item.type === 'title'">
      <h1>{{item.label}}</h1>
    </template>

    <template v-if="item.type === 'openDiv'">
      <div class="mydiv">
    </template>

    <template v-if="item.type === 'closediv'">
      </div>
    </template>

</template>

Vue没有编译,因为我的Div缺少结束标记。我怎么能这样做?我试过v-html但这也是强制关闭标签。

1 个答案:

答案 0 :(得分:1)

您可以做的是将数据转换为计算属性,并在该计算属性内部,基本上将数组作为另一个数组中的数组。然后在模板内部循环外部数组,然后有条件地遍历第一个数组。

虽然这听起来令人困惑,但事实并非如此。

  1. 在我们的组件中,我们制作了一个新的计算部分
  2. 在此计算部分中,我们添加一个新方法,让我们称之为“formattedData”
  3. 在本节中,我们需要创建一个用于存储结果的变量。
  4. 由于我们需要知道我们是否在div块内,我们需要一个额外的变量来跟踪它。
  5. 然后我们遍历所有传入的数据,
  6. 如果我们看到type: "closediv",那么我们用新的替换临时变量,表示打开的块上下文
  7. 如果我们看到type: "opendiv",那么我们用新的替换临时变量,表示打开的块上下文
  8. 如果还有其他内容,并且我们的tmp数组的大小为0,则表示需要将其添加到生成的数组中。
  9. 循环后,我们会返回结果。
  10. 我们现在将数据转换为最终形式,并准备显示它。在我们的<template>部分中,我们添加了第一个循环
  11. 在此循环中,有一个if语句,可以是<div>广告
  12. 然后我们开始下一个循环,这个循环打印出项目本身。
  13. 上述逻辑的示例:(使用“script-template”而不是真正的<template>标记,因为StackOverflow Snippet逻辑

    // bootstrap the demo
    new Vue({
      el: '#demo',
      template: '#example',
      data: {
        information: [
    { name: "input1", label: "input1 ", placeholder: "Enter text", value: "", type: "text"},
    { name: "input2", label: "input2", placeholder: "Enter text", value: "", type: "text"},
    { name: "openDiv", label: "", placeholder: "", value: "", type: "openDiv"},
    { name: "title", label: "Title", placeholder: "", value: "", type: "title"},
    { name: "input3", label: "input3", placeholder: "Enter date", value: "", type: "date"},
    { name: "input4", label: "input4", placeholder: "Enter text", value: "", type: "text"},
    { name: "closeDiv", label: "", placeholder: "", value: "", type: "closediv"},
        ],
      },
      computed: {
        formattedData() {
          const results = [];
          let tmpObject = {
            wrapped: false,
            values: [],
          };
          for(let i = 0; i < this.information.length; i++) {
            if(this.information[i].type === 'openDiv') {
              tmpObject = {
                wrapped: true,
                values: [],
              };
              continue;
            }
            if(this.information[i].type === 'closediv') {
              // TODO Is the capitalization of `closediv` intentional?
              tmpObject = {
                wrapped: false,
                values: [],
              };
              continue;
            }
            if(tmpObject.values.length === 0) {
              results.push(tmpObject);
            }
            tmpObject.values.push(this.information[i]);
          }
          return results;
        }
      },
      methods: {},
    });
    div.testDiv {
    border: red solid 2px;
    }
    <script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
    <script type="text/x-template" id="example">
      <div>
        <template v-for="data in formattedData">
    
          <div v-if="data.wrapped" class="testDiv">
            <template v-for="item in data.values">
              <template v-if="item.type === 'text'">
                <label>{{item.label}}</label>
                <input type="text" v-model="item.value" :placeholder="item.placeholder" />
              </template>
    
              <template v-if="item.type === 'date'">
                <label>{{item.label}}</label>
                <input type="date" v-model="item.value" :placeholder="item.placeholder" />
              </template>
    
              <template v-if="item.type === 'title'">
                <h1>{{item.label}}</h1>
              </template>
            </template>
          </div>
          <template v-else>
            <template v-for="item in data.values">
              <template v-if="item.type === 'text'">
                <label>{{item.label}}</label>
                <input type="text" v-model="item.value" :placeholder="item.placeholder" />
              </template>
    
              <template v-if="item.type === 'date'">
                <label>{{item.label}}</label>
                <input type="date" v-model="item.value" :placeholder="item.placeholder" />
              </template>
    
              <template v-if="item.type === 'title'">
                <h1>{{item.label}}</h1>
              </template>
            </template>
          </template>
        </template>
        <hr>
        <pre>{{ this.formattedData }}</pre>
      </div>
    </script>
    
    
    
    <div id="demo"></div>