Как я могу преобразовать длинный список 'watch' в функциональный способ в VueJS? - PullRequest
0 голосов
/ 23 декабря 2018

Я новичок в vueJS.У меня есть длинный список наблюдения.Это все то же самое.Но я не знаю, как преобразовать их в функциональный способ.

Они все для добавления запятой в тег ввода и v-модели.Это работает очень хорошо.Но коды выглядят очень глупо, потому что они точно такие же, но не их имя.

new Vue({
  data: {
    tmp_price1: '',
    tmp_price2: '',
    tmp_price3: '',
    tmp_a_price: '',
    tmp_b_price: '',
  },

  watch: {
   tmp_price1: function(newValue) {
     if (newValue != '') {
       const result = newValue.replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, ",");
       Vue.nextTick(() => this.tmp_price1 = result);
     }
   },
   tmp_price2: function(newValue) {
     if (newValue != '') {
       const result = newValue.replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, ",");
       Vue.nextTick(() => this.tmp_price2 = result);
     }
   },

  ....(repeat)

  },

Пожалуйста, помогите мне улучшить эти тупые коды эффективным способом.

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

Просто отобразить отформатированную версию значения можно с помощью простого фильтра:

new Vue({
  el: '#app',
  data: {
    tmp_price1: '123123',
    tmp_price2: '',
    tmp_price3: ''
  },
  filters: {
    myFilter(v) {
      return v.replace(/\D/g, '').replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    }   
  }
});
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <div><input v-model="tmp_price1">{{tmp_price1 | myFilter}}</div>
  <div><input v-model="tmp_price2">{{tmp_price2 | myFilter}}</div>
  <div><input v-model="tmp_price3">{{tmp_price3 | myFilter}}</div>
  
</div>

... но этого недостаточно для полей ввода;Вы не можете просто добавить фильтр к атрибуту v-model.Подкомпонент, как описано в ответ Роя J , вероятно, является лучшим и наиболее пригодным для повторного использования способом справиться с этим, но если вы в порядке с чем-то немного быстрым и грязным (но не с тоже грязно) вы можете просто добавить обработчик изменений к проблеме:

new Vue({
  el: '#app',
  data: {
    tmp_price1: '123123',
    tmp_price2: '',
    tmp_price3: ''
  },
  methods: {
    myFormatter(fieldname) {
      /* replace the user's input with the formatted value.
      
          There's probably some clever way to read the v-model 
          name from the input field instead of passing it to the 
          method as a string, but I'm not going to mess around 
          with that for what is after all a quick-and-dirty technique */
      this[fieldname] = this[fieldname].replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    }
  },
  mounted() {
    // if the initial values aren't always empty, you'll need to run the
    // formatter function on component load as well as on user input:
    ['tmp_price1', 'tmp_price2', 'tmp_price3'].forEach(f => {
      this.myFormatter(f);
    });
  }
});
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <div><input v-model="tmp_price1" @input="myFormatter('tmp_price1')">{{tmp_price1}}</div>
  <div><input v-model="tmp_price2" @input="myFormatter('tmp_price2')">{{tmp_price2}}</div>
  <div><input v-model="tmp_price3" @input="myFormatter('tmp_price3')">{{tmp_price3}}</div>
</div>

(Или, как другой вариант, этот ответ на похожий вопрос использует, по сути, ту же технику, но заключает ее в директиву Vue длясвязывайте события ввода вместо того, чтобы прикреплять обработчики @input.)

Обратите внимание, что в версии «filter» значения v-model остаются исходным пользовательским вводом;фильтр влияет только на отображаемое значение.Во втором примере форматирование применяется к самим v-model значениям ed, поэтому, если вы передадите эти значения в другое место, вы получите отформатированную версию.Оба метода могут быть полезны, в зависимости от обстоятельств.(Или вы можете даже использовать их в комбинации - удалите не-цифры в v-модели, затем добавьте запятые через фильтр только для отображения, например.)

0 голосов
/ 23 декабря 2018

Это может показаться чрезмерным, но я бы, вероятно, сделал компонент для инкапсуляции запутанного поведения.Компонент будет иметь вычисляемую переменную, которая генерирует запятую значение для родителя, чтобы использовать при обновлении.

new Vue({
  el: '#app',
  data: {
    tmp_price1: '',
    tmp_price2: '',
    tmp_price3: '',
    tmp_a_price: '',
    tmp_b_price: '',
  },
  components: {
    commafiedInput: {
      props: ['value'],
      template: '<input v-model="commaValue">',
      computed: {
        commaValue: {
          get() {
            return this.value;
          },
          set(newValue) {
            this.$emit('input', this.addCommas(newValue));
          }
        }
      },
      methods: {
        addCommas(v) {
          return v.replace(/\D/g, '').replace(/\B(?=(\d{3})+(?!\d))/g, ",");
        }
      }
    }
  }
});
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <div> {{tmp_price1}}
    <commafied-input v-model="tmp_price1"></commafied-input>
  </div>
  <commafied-input v-model="tmp_price2"></commafied-input>
  <commafied-input v-model="tmp_price3"></commafied-input>
  <commafied-input v-model="tmp_a_price"></commafied-input>
  <commafied-input v-model="tmp_b_price"></commafied-input>
</div>
...