Итак, я хочу передать реквизиты компоненту Vue, но я ожидаю, что эти реквизиты в будущем изменятся изнутри этого компонента, например. когда я обновляю этот компонент Vue изнутри, используя AJAX. Так что они предназначены только для инициализации компонента.

My cars-list Элемент компонента Vue, где я передаю реквизиты с начальными свойствами в single-car:

// cars-list.vue




То, как я это делаю прямо сейчас, это то, что внутри моего компонента single-car я назначаю this.initialProperties моему this.data.propertieson created () обработчик инициализации. И работает, и реактивно.

// single-car.vue




Но моя проблема в том, что я не знаю, правильно ли это делать? Разве это не вызовет у меня неприятностей по дороге? Или есть способ лучше?

Dominik Serafin

Ответов: 5

Ответы (5)

Благодаря этому https://github.com/vuejs/vuejs.org/pull/567 Теперь я знаю ответ.

Способ 1

Передать начальную опору непосредственно в данные. Как пример в обновленных документах:

props: ['initialCounter'],
data: function () {
    return {
        counter: this.initialCounter
    }
}

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

Предупреждение: этот метод не рекомендуется. Это сделает ваши компоненты непредсказуемыми. Если вам нужно установить родительские данные из дочерних компонентов, используйте управление состоянием, например Vuex, или используйте «v-модель».https://vuejs.org/v2/guide/components.html#Using-v-модель-на-компонентах

Способ 2

Если ваша начальная опора является объектом или массивом, и если вы не хотите, чтобы изменения в дочернем состоянии распространялись на родительское состояние, просто используйте, например,Vue.util.extend [1], чтобы сделать копию реквизита вместо того, чтобы указывать его непосредственно на дочерние данные, например:

props: ['initialCounter'],
data: function () {
    return {
        counter: Vue.util.extend({}, this.initialCounter)
    }
}

Метод 3

Вы также можете использовать оператор распространения для клонирования реквизита. Подробнее в ответе Игоря: https://stackoverflow.com/a/51911118/3143704

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

Сноски

[1] Имейте в виду, что это внутренняя утилита Vue, и она может измениться в новых версиях. Возможно, вы захотите использовать другие методы для копирования этой опоры, см. «Как правильно клонировать объект JavaScript?».

Моя скрипка, на которой я ее тестировал: https://jsfiddle.net/sm4kx7p9/3/

В дополнение к ответу @ dominik-serafin:

Если вы передаете объект, вы можете легко клонировать его с помощью оператора распространения (синтаксис ES6):

 props: {
   record: {
     type: Object,
     required: true
   }
 },

data () { // opt. 1
  return {
    recordLocal: {...this.record}
  }
},

computed: { // opt. 2
  recordLocal () {
    return {...this.record}
  }
},

Но самое главное - не забыть использовать опт. 2, если вы передаете вычисленное значение или более асинхронное значение. В противном случае локальное значение не обновится.

Демо:

Vue.component ('card', {
  шаблон: '# app2',
  props: {
    test1: нуль,
    test2: нуль
  },
  data () {// opt. 1
    возвращение {
      test1AsData: {... this.test1}
    }
  },
  вычислено: {// opt. 2
    test2AsComputed () {
      return {... this.test2}
    }
  }
})

новый Vue ({
  el: "# app1",
  данные () {
    возвращение {
      test1: {1: 'не обновлять'},
      test2: {2: 'обновится через 1 секунду'}
    }
  },
  mount () {
    setTimeout (() => {
      this.test1 = {1: 'обновлено!'}
      this.test2 = {2: 'обновлено!'}
    }, 1000)
  }
})


https://jsfiddle.net/nomikos3/eywraw8t/281070/

Второй или третий раз я сталкиваюсь с этой проблемой, возвращаясь к старому проекту vue.

Не знаю, почему это так сложно в vue, но это можно сделать с помощью watch:

export default {

  props: ["username"],

  data () {
    return {
      usernameForLabel: "",
    }
  },

  watch: {
    username: {
      immediate: true,
      handler (newVal, oldVal) {
        this.usernameForLabel = newVal;
      }
    },
  },

Я считаю, что вы делаете это правильно, потому что так указано в документации.

Определите свойство локальных данных, которое использует начальное значение свойства в качестве начального значения

https://vuejs.org/guide/components.html#One-Way-Data-Flow

В качестве другого подхода я использовал наблюдатели в дочернем компоненте.

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

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

Пример:

  data() {
    return {
      properties: {},
    };
  },
  props: {
    initial-properties: {
      type: Object,
      default: {},
    },
  },
  watch: {
    initial-properties: function(newVal) {
      this.properties = {...newVal};
    },
    properties: function(newVal) {
      this.$emit('propertiesUpdated', newVal);
    },
  },

Таким образом, у меня больше контроля и меньше неожиданного поведения. Например, когда свойства, передаваемые родительским элементом, являются асинхронными, они могут быть недоступны во время создания или подключения жизненного цикла. Таким образом, вы можете использовать вычисляемое свойство, как упомянул @ Igor-Parra, или посмотреть опору, а затем испустить ее.

2022 WebDevInsider