Является ли мутация свойства реквизита с v-моделью плохой практикой? - PullRequest
0 голосов
/ 09 января 2019

Документы vue.js довольно строги, утверждая, что мутирование реквизита внутри компонента - плохая практика. Также описаны два случая, в которых у разработчика может возникнуть желание нарушить это правило:

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

Поскольку я начал с vue.js, у меня возникло искушение обновить свойство props с помощью v-model. Заходя в Интернет, я нашел несколько обсуждений, которые включали обходные пути или использование vuex.

Мой вопрос таков: обновляет ли свойство реквизита с помощью v-model OK или плохо, потому что оно изменяет родительское состояние. Имо, я хочу изменить родительское состояние, рассмотрим этот пример

Компонент Crud, который загружает определенный компонент формы:

<template>
    <awesome-form @formSubmit="onFormSubmit" :entity="entity"></awesome-form>
</template>

<script>
import AwesomeForm from 'SomeForm'
export default {
  data () {
    return {
      entity: {}
    }
  },
  components: {
    AwesomeForm
  },
  methods: {
    onFormSubmit () {
      axios.post('/backend', this.entity)
    }
  }
}
</script>

Конкретный компонент формы:

<template>
    <form @submit.prevent="submit">
        <input type="text" name="username" v-model="entity.username" />
        ...
    </form>
</template>
<script>
  export default {
    props: {
      entity: {
        type: Object
      }
    },
    methods: {
      submit () {
        this.$emit('formSubmit')
      }
    }
  }
</script>

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

Это действительно плохо и каковы альтернативы?

  • Наличие событий для каждого обновления и отдельного свойства (супер избыточный)
  • Всегда используйте vuex ... (правда?)

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Обновляет ли свойство реквизита с помощью v-модели OK или BAD, потому что оно изменяет родительское состояние

Определенно, это плохо, потому что реквизиты форм передаются как props на родительском уровне верхнего уровня. Таким образом, вы должны увидеть предупреждение от Vue, когда вы попытаетесь изменить значение в child даже с v-model.

Так что, когда я вижу какой-то компонент формы, я ожидаю, что он требует некоторого значения, как v-model, потому что форма предназначена для редактирования чего-либо. Это пример идеи динамической формы, основанной на v-model:

Vue.component('awesome-form', {
  props: ['value'],
  template: `#awesome-form-template`,
  methods: {
    update(key, val) {
      // we should create new object on each change
      let updatedCopy = Object.assign({}, this.value, { [key]: val });
      this.$emit('input', updatedCopy)
    }
  },
  watch: {
    value(val) {
      console.log('value updated: ' + JSON.stringify(val))
    }
  }
})

var vm = new Vue({
  el: '#app',
  data: {
    form: {
      text1: '123',
      text2: '345'
    }
  },
  methods: {
      submit() {
         console.log('submitted!');
      }
  }
})
<script src="https://unpkg.com/vue"></script>


<div id="app">
  <awesome-form @form-submit="submit" v-model="form"></awesome-form>
</div>


<script type="text/x-template" id='awesome-form-template'>
  <form @submit.prevent="$emit('form-submit')">
	    <div v-for="(val, key) in value" :key="key">
          <input 
          type="text" 
          :value="value[key]" 
          @input="update(key, $event.target.value)"
          :name="key">
      </div>
      <button type='submit'>Submit</button>
   </form>
</script>

Наличие событий для каждого обновления и отдельного свойства (супер избыточный)

Но если вам нужно будет добавить некоторую логику проверки, специфичную для каждого входа, вам придется определять событие для каждого обновления или что-то в этом роде.

Вы также можете проверить решение на основе модификатора sync из комментариев к вопросу (@BoussadjraBrahim) с помощью пользовательского миксина jsfiddle , в вашем случае оно может быть более гибким.

0 голосов
/ 09 января 2019

Я вижу, что в вашем случае лучше всего использовать модификатор .sync, как указано в official docs:

// ignore the following two lines, they just disable warnings in "Run code snippet"
Vue.config.devtools = false;
Vue.config.productionTip = false;

Vue.component('awesome-form', {
  props: ['entity'],
  template: `
  <div>
  <form @submit.prevent="submit">
    <input type="text" class="form-control" name="username" v-model="entity.username">
    <input type="email" class="form-control" name="email" v-model="entity.email">
    <input type="submit" class="btn btn-primary" value="submit"/>
    </form>
  </div>`,

  methods: {
    submit() {
      this.$emit('form-submit')
    }
  }
})


new Vue({
  el: "#app",
  data() {
    return {
      entity: {
        username: '',
        email: ''
      }
    }
  },

  methods: {
    onFormSubmit() {
      console.log(this.entity)
    }
  }
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">

<div id="app">
  <awesome-form @form-submit="onFormSubmit" :entity.sync="entity"></awesome-form>
  <p> {{entity}}</p>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...