停止Vue.js中依赖输入的多个方法递归调用

时间:2019-03-04 17:59:00

标签: javascript vue.js

亲爱的人们,在堆栈溢出时,

我正在努力使用vue.js来控制一组输入。我想要一个(在下面的示例中为“商店”)来控制其他选项。但是我也希望触发相同的更新事件,而不管发生了什么更改。我的问题是,当我更改主选项时(再次在下面的“商店”中),我不知道其他输入是否会更改,因此我不知道我是否必须调用更新函数,或者在其他选项更改时是否间接执行此操作。结果是我可能有两个我绝对不希望的更新调用。我花了一些时间编写我要尝试的样式化版本,您可以在控制台日志中看到,当“国家”或“性别”未设置为“全部”并且您更改“商店”时,将会有两个更新火。

因此,我想知道是否有人可以通过优雅的方式来解决这种依赖性,而无需多次更新调用。由于我将使用很多类似的东西,因此我愿意更改整个设置,所以我对Vue很陌生。

<html>
  <head>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  </head>
  <body>
    <div id ='app'>
      <div>
        <div style='list-style-type: none' v-for="input in inputs">
          <p><b>{{ input.name }}</b></p>
          <select v-model="input.value">
             <option v-for="option in input.options" :value="option.id" >{{ option.name }}</option>
           </select>
        </div>
      </div>
     </div>

    </div>
    <script>
      let vueApp = new Vue ({
        el: '#app',
        data: {
          inputs: [
            {name: 'shop', value: 'all', options: [{id: 'all', name: 'All shops'}, {id: 1, name: 'Shop 1'}, {id: 2, name: 'Shop 2'}, {id: 3, name: 'Shop 3'}]},
            {name: 'country', value: 'all', options: [{id: 'all', name: 'All countries'}, {id: 1, name: 'Country 1'}, {id: 2, name: 'Country 2'}, {id: 3, name: 'Country 3'}]},
            {name: 'gender', value: 'all', options: [{id: 'all', name: 'All genders'}, {id: 1, name: 'Gender 1'}, {id: 2, name: 'Gender 2'}, {id: 3, name: 'Gender 3'}]}
          ]
        },
        computed: {
          shop() {return this.inputs.filter(d => d.name === 'shop')[0].value;},
          nonShop() {return this.inputs.filter(d => d.name !== 'shop').map(d => d.value)}
        },
        watch: {
          shop() {
             $.when((async function() {
                setTimeout(
                  () => {
                    let newCountries = [];
                    for (let i = 1; i < 4; i++) {
                      let rand = Math.floor(Math.random() * 100);
                      newCountries.push({id: rand, name: 'Country: ' + rand});
                      let countryObject = vueApp.inputs.filter(d => d.name === 'country')[0];
                      countryObject.options = [{id: 'all', name: 'All countries'}, ...newCountries];
                      countryObject.value = 'all';
                    }                   
                  }
                , 200);
             })(),
             (async function() {
                setTimeout(
                  () => {
                    let newGenders = [];
                    for (let i = 1; i < 4; i++) {
                      let rand = Math.floor(Math.random() * 100);
                      newGenders.push({id: rand, name: 'Gender: ' + rand});
                      let genderObject = vueApp.inputs.filter(d => d.name === 'gender')[0];
                      genderObject.options = [{id: 'all', name: 'All genders'}, ...newGenders];
                      genderObject.value = 'all';
                    }                   
                  }
                , 100);          
             })()).done(() => this.update());
          },
          nonShop() {this.update()}
        },
        methods: {
          update() {console.log('updating');}
        }
      });
    </script>
  </body>
</html>

1 个答案:

答案 0 :(得分:0)

与其在观察者中为updateshop调用nonShop,而是向change添加selects事件处理程序以调用{{1} }改为:

update

这样,只要用户更改输入值,而不是Vue更新输入值时,就会调用<select v-model="input.value" @change="update">...</select> 方法。

这是一个完整的工作示例:

update
Vue.config.devtools = false;
Vue.config.productionTip = false;

let vueApp = new Vue ({
  el: '#app',
  data() {
    return {
      inputs: [{
        name: 'shop', 
        value: 'all', 
        options: [
          {id: 'all', name: 'All shops'}, 
          {id: 1, name: 'Shop 1'}, 
          {id: 2, name: 'Shop 2'}, 
          {id: 3, name: 'Shop 3'}
        ]
      }, {
        name: 'country', 
        value: 'all', 
        options: [
          {id: 'all', name: 'All countries'}, 
          {id: 1, name: 'Country 1'}, 
          {id: 2, name: 'Country 2'}, 
          {id: 3, name: 'Country 3'}
        ]
      }, {
        name: 'gender', 
        value: 'all', 
        options: [
          {id: 'all', name: 'All genders'}, 
          {id: 1, name: 'Gender 1'}, 
          {id: 2, name: 'Gender 2'}, 
          {id: 3, name: 'Gender 3'}
        ]
      }]
    };
  },
  computed: {
    shop() {
      return this.inputs.filter(d => d.name === 'shop')[0].value;
    }
  },
  watch: {
    shop() {
      $.when((async function() {
        setTimeout(() => {
          let newCountries = [];
          for (let i = 1; i < 4; i++) {
            let rand = Math.floor(Math.random() * 100);
            newCountries.push({id: rand, name: 'Country: ' + rand});
            let countryObject = vueApp.inputs.filter(d => d.name === 'country')[0];
            countryObject.options = [{id: 'all', name: 'All countries'}, ...newCountries];
            countryObject.value = 'all';
          }					
        }, 200);
      })(), (async function() {
        setTimeout(() => {
          let newGenders = [];
          for (let i = 1; i < 4; i++) {
            let rand = Math.floor(Math.random() * 100);
            newGenders.push({id: rand, name: 'Gender: ' + rand});
            let genderObject = vueApp.inputs.filter(d => d.name === 'gender')[0];
            genderObject.options = [{id: 'all', name: 'All genders'}, ...newGenders];
            genderObject.value = 'all';
          }					
        }, 100);			 
      })());
    },
  },
  methods: {
    update() {
      console.log('updating');
    }
  }
});


如果在调用<script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div id='app'> <div style='list-style-type: none' v-for="input in inputs"> <p><b>{{ input.name }}</b></p> <select v-model="input.value" @change="update"> <option v-for="option in input.options" :value="option.id" >{{ option.name }}</option> </select> </div> </div>方法之前需要更改countrygender的值,请添加一个单独的方法作为update事件的处理程序以设置新的changecountry值,然后在完成后调用gender方法。

以下是示例:

update
Vue.config.devtools = false;
Vue.config.productionTip = false;

let vueApp = new Vue ({
  el: '#app',
  data() {
    return {
      inputs: [{
        name: 'shop', 
        value: 'all', 
        options: [
          {id: 'all', name: 'All shops'}, 
          {id: 1, name: 'Shop 1'}, 
          {id: 2, name: 'Shop 2'}, 
          {id: 3, name: 'Shop 3'}
        ]
      }, {
        name: 'country', 
        value: 'all', 
        options: [
          {id: 'all', name: 'All countries'}, 
          {id: 1, name: 'Country 1'}, 
          {id: 2, name: 'Country 2'}, 
          {id: 3, name: 'Country 3'}
        ]
      }, {
        name: 'gender', 
        value: 'all', 
        options: [
          {id: 'all', name: 'All genders'}, 
          {id: 1, name: 'Gender 1'}, 
          {id: 2, name: 'Gender 2'}, 
          {id: 3, name: 'Gender 3'}
        ]
      }]
    };
  },
  computed: {
    shop() {
      return this.inputs.filter(d => d.name === 'shop')[0].value;
    }
  },
  methods: {
    onChange(name) {
      if (name === 'shop') {
        $.when((async function() {
          setTimeout(() => {
            let newCountries = [];
            for (let i = 1; i < 4; i++) {
              let rand = Math.floor(Math.random() * 100);
              newCountries.push({id: rand, name: 'Country: ' + rand});
              let countryObject = vueApp.inputs.filter(d => d.name === 'country')[0];
              countryObject.options = [{id: 'all', name: 'All countries'}, ...newCountries];
              countryObject.value = 'all';
            }					
          }, 200);
        })(), (async function() {
          setTimeout(() => {
            let newGenders = [];
            for (let i = 1; i < 4; i++) {
              let rand = Math.floor(Math.random() * 100);
              newGenders.push({id: rand, name: 'Gender: ' + rand});
              let genderObject = vueApp.inputs.filter(d => d.name === 'gender')[0];
              genderObject.options = [{id: 'all', name: 'All genders'}, ...newGenders];
              genderObject.value = 'all';
            }					
          }, 100);			 
        })()).then(this.update);
      } else {
        this.update()
      }
    },
    update() {
      console.log('updating');
    }
  }
});