programing

Vue + Vuex: 스토어 변경이 없는 경우 스토어별로 입력값이 설정되지 않음

javaba 2022. 7. 28. 23:21
반응형

Vue + Vuex: 스토어 변경이 없는 경우 스토어별로 입력값이 설정되지 않음

<template>
  <input
    @input="formatValue"
    type="text"
    :value="formattedValue"
  />
</template>

<script type="text/javascript">
  import {formatPhoneNumber} from '~/utils/string';

  export default {
    computed: {
      formattedValue: function(){
        return formatPhoneNumber(this.value)
      },
    },
    methods: {
      formatValue(e) {
        this.$emit('input', formatPhoneNumber(e.target.value))
      }
    },
    props: ['value']
  }
</script>

의 경우formatPhoneNumber(value)는 다른 값을 생성합니다.모든 것은 정상적으로 동작합니다만, 일단 최대 길이에 도달하면(이후,formatPhoneNumber('xx xx xx xx xx whatever') == 'xx xx xx xx xx')의 출력값은 현재 스토어 값과 동일합니다.

그 결과 상태가 변이되지 않고 컴포넌트가 재렌더되지 않는다는 점만 제외하면 전혀 문제가 없습니다.formattedValue()는 호출되지 않습니다.

그래서 나는 결국xx xx xx xx xx스토어에 있지만 입력이 표시됩니다.xx xx xx xx xx whatever로컬 입력값이 스토어 입력값과 다르기 때문입니다.

어떻게 하면 이 예상치 못한 행동을 피할 수 있을까요?이동formatPhoneNumber()변이를 막을 수 있기 때문에 내 문제를 해결하지 못할 것이다.formatPhoneNumber()formattedValue()스토어에서 포맷되지 않은 값을 얻을 수 있습니다.이 값도 제가 원하는 값이 아닙니다.

왜 Vue's는input역동적으로valueset는 여전히 로컬 상태를 관리합니까?

원하는 것을 달성하려면 (내 생각에는) 포맷을 다음과 같이 변경할 수 있습니다.값 메서드는

formatValue(e) {
   this.$emit('input', e.target.value = formatPhoneNumber(e.target.value));
}

입력이 형식화된 전화번호 값으로 설정되도록 합니다.어떤 식으로든 입력이 생성하는 내용을 덮어쓰게 되므로 입력 이벤트에서 수행하는 것이 좋습니다.

v-value 대신 v-model을 사용하면 입력 필드에 표시할 내용을 완전히 제어할 수 있습니다.

이 방법으로 입력 값의 형식을 지정한 다음 모델에 다시 설정할 수 있습니다.다음과 같이 됩니다.

<template>
  <input @input="formatValue" type="text" v-model="inputModel">
</template>

<script type="text/javascript">    
export default {
  data() {
    return {
      inputModel: this.value
    };
  },
  methods: {
    formatValue() {
      this.inputModel = formatPhoneNumber(this.inputModel);
      this.$emit("input", this.inputModel);
    }
  },
  props: ["value"]
};
</script>

테스트하기 위해 작성한 작업 예를 다음에 나타냅니다.

가장 쉬운 방법은 부모의 @input 이벤트에 대한 간단한 한 줄 수정이라고 생각합니다.이러한 변경은 업데이트 전에 프로포트의 값을 클리어하는 것입니다.

그래도 하나의 값만 내보내면 되지만, 내보낸 값으로 작업하기 전에 프로펠러를 클리어합니다.


아래에 스니펫을 제공했습니다(스니펫의 다른 점에 주의해 주십시오).

입력 필드 값을 지정하는 대신 v-model을 사용하여 get 및 set 메서드가 있는 계산된 속성에 바인딩하도록 선택했습니다.이를 통해 데이터에 액세스할 때와 데이터를 수정할 때 서로 다른 논리를 사용할 수 있었습니다(많은 상황에서 매우 편리함).

이 논리를 분리함으로써 입력 이벤트 내부에서 설정 방식으로 기능을 이동하여 입력 이벤트를 완전히 제거할 수 있었습니다.

new Vue({
  el: "#app",
  // props: ['valueProp'],  
  data: {
    valueProp: "" //simulate prop data
  },
  
  computed: {    
    // --Value input element is binded to--
    inputValue:{
      get(){ //when getting the value, return the prop
        return this.valueProp;
      },
      set(val){ //when the value is set, emit value
        this.formatValue(val);
      }
    }
  },

  methods: {

    // --Emit the value to the parent--
    formatValue(val) {      
      this.parentFunction(this.formatPhoneNumber(val)); //simulate emitting the value
      // this.$emit('input', formatPhoneNumber(val));
    },

    // --Simulate parent receiving emit event--
    parentFunction(emittedValue){
      console.log("emitted:" + emittedValue);
      this.valueProp = null;         //first clear it (updates the input field)
      this.valueProp = emittedValue; //then assign it the emitted value
    },

    // --Simulate your format method--
    // THIS LOGIC CAN BE IGNORED. It is just a quick implementation of a naive formatter.
    // The "important" thing is it limits the length, to demonstrate exceeding the limit doesn't get reflected in the input field
    formatPhoneNumber(val){
      var phoneSpaces = [2,4,6,8];  //specify space formatting (space locations)
      var maxLength = 10;           //specify the max length
      val = val.replace(/ /g,'');   //remove existing formatting
      if(val.length > maxLength)    //limits the length to the max length
        val = val.substring(0, maxLength);

      // for the number of desired spaces, check each space location (working backwards) ... if value is longer than space location and space location is not a space ... add a space at the location.
      for(var i = phoneSpaces.length-1; i >= 0; i--){
        if(val.length > phoneSpaces[i] && val[phoneSpaces[i]] != " "){
          val = val.substring(0, phoneSpaces[i]) + " " + val.substring(phoneSpaces[i], val.length);
        }
      }
      return val
    }
  
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <input type="text" v-model="inputValue"/>

  <label style="float: right;">
    Prop Value: <span>{{valueProp}}</span>
  </label>

  <br>

  <label >format (xx xx xx xx xx)</label>
</div>

언급URL : https://stackoverflow.com/questions/59263861/vue-vuex-input-value-not-set-by-store-if-no-store-change

반응형