如何在 Vue.js 中创建独立运行的动态行?

How do I create dynamic rows in Vue.js that behave independently?

我有一个创建动态行的 vue 实例。该行有两个 Select 选项: PersonInterests 以及 Add row 按钮。这些 Select 选项是依赖选项:

如果我 select Brian 作为 Person,他的 Interests 在第二个 Select 选项中应该加载 Brian 的兴趣。这很好用:

问题:

这很好用,但是我无法克服的奇怪事情是添加第二行时,第二行删除了 Brian 的兴趣并填充了第二个人的兴趣:

例如,Brian 对 Crossfit 不感兴趣 - 这些是 Candice 的选择。本质上,Brian 的选项没有保留,它们被 Candices 覆盖了 - 所以两行都显示了 Candices 的兴趣。

任何人都可以建议我需要做什么来解决这个问题吗?我创建了一个 Jsfiddle 来说明这个问题:

https://jsfiddle.net/syed263/y9emdLvr/45/

HTML:

<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>JS Bin</title>
  </head>

  <body>
    <div id="app">
      <ul>
        <li v-for="(input, index) in inputs">
          Person:
          <select type="text" v-model="input.one" v-on:change="updateList(input.one)">  
             <option v-for= "options in person._person" v-bind:value ="options">
                {{ options.name }}
             </option>
          </select> Interests:
          <select type="text" v-model="input.two"> 
             <option v-for= "options in activity._activity" v-bind:value ="options">
                {{ options.name }}
             </option>
          </select>
          <button @click="deleteRow(index)">Delete</button>
        </li>
      </ul>

      <button @click="addRow">Add row</button>

    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>

  </body>

</html>

JS: 声明

let _people = {

  _person: [{
      name: 'Adam',
      age: '16',
      ID: '2009121',

    },
    {
      name: 'Brian',
      age: '18',
      ID: '2009122',

    },
    {
      name: 'Candice',
      age: '16',
      ID: '2009120',

    },
  ]
}

let _interests = {

  _activity: [{
    name: '',
    type: '',

  }, ]
}

let person

JS 方法:

const app = new Vue({

  el: '#app',

  data: {
    inputs: [],
    person: _people,
    activity: _interests,
  },

  methods: {
    addRow() {
      this.inputs.push({
        one: '',
        two: ''
      })
    },
    deleteRow(index) {
      this.inputs.splice(index, 1)
    },
    updateList(val) {
      this.activity._activity = [];

      if (val.name == "Adam") {
        this.activity._activity.push({
          name: 'Badminton',
          type: '20'
        }, {
          name: 'Football',
          type: '30'
        })
      } else if (val.name == "Brian") {
        this.activity._activity.push({
          name: 'Basketball',
          type: '90'
        }, {
          name: 'Karate',
          type: '50'
        })
      } else if (val.name == "Candice") {
        this.activity._activity.push({
          name: 'Climbing',
          type: '90'
        }, {
          name: 'Cross Fit',
          type: '100'
        })
      }

    }
  }

})

JSfiddle:https://jsfiddle.net/syed263/y9emdLvr/45/

问题是你使用this.activity._activity(每行使用相同的)来生成<option>
但是在 updateList() 中,每当第一个 select 值发生变化时,无论是哪一行, 它会改变 this.activity._activity.
它会影响所有第二个 select 选项,每一行。
所以你应该对每一行做一些 link activity 的事情。 示例代码如下所示,它可以工作,但并不完美。

let _people = {

  _person: [{
      name: 'Adam',
      age: '16',
      ID: '2009121',

    },
    {
      name: 'Brian',
      age: '18',
      ID: '2009122',

    },
    {
      name: 'Candice',
      age: '16',
      ID: '2009120',

    },
  ]
}

let _interests = {

  _activity: [{
    name: '',
    type: '',

  }, ]
}

let person


const app = new Vue({

  el: '#app',

  data: {
    inputs: [],
    person: _people,
    activity: _interests,
  },

  methods: {
    addRow() {
      this.inputs.push({
        one: '',
        two: '',
        activity: [] // To link activity with each row
      })
    },
    deleteRow(index) {
      this.inputs.splice(index, 1)
    },
    updateList(val, index) {
      this.activity._activity = [];

      if (val.name == "Adam") {
        // only change current row's second option
        this.inputs[index].activity =[{
          name: 'Badminton',
          type: '20'
        }, {
          name: 'Football',
          type: '30'
        }]
      } else if (val.name == "Brian") {
        this.inputs[index].activity =[{
          name: 'Basketball',
          type: '90'
        }, {
          name: 'Karate',
          type: '50'
        }]
      } else if (val.name == "Candice") {
        this.inputs[index].activity =[{
          name: 'Climbing',
          type: '90'
        }, {
          name: 'Cross Fit',
          type: '100'
        }]
      }

    }
  }

})
<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>JS Bin</title>
  </head>

  <body>

    <div id="app">

      <ul>
        <li v-for="(input, index) in inputs">
          Person:
          <select type="text" v-model="input.one" v-on:change="updateList(input.one, index)">  
      <option v-for= "options in person._person" v-bind:value ="options">
      {{ options.name }}
      </option>
    
    </select> Interests:
          <select type="text" v-model="input.two"> 
      <option v-for= "options in input.activity" v-bind:value ="options">
      {{ options.name }}
      </option>
        
     </select>
          <button @click="deleteRow(index)">Delete</button>
        </li>
      </ul>

      <button @click="addRow">Add row</button>

    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>

  </body>

</html>