Итак, я хочу передать реквизиты компоненту Vue, но я ожидаю, что эти реквизиты в будущем изменятся изнутри этого компонента, например, когда я обновляю этот компонент Vue изнутри с помощью AJAX. Так что они предназначены только для инициализации компонента.
cars-list
Элемент моего компонента Vue, в котором я передаю реквизиты с начальными свойствами single-car
:
// cars-list.vue
<script>
export default {
data: function() {
return {
cars: [
{
color: 'red',
maxSpeed: 200,
},
{
color: 'blue',
maxSpeed: 195,
},
]
}
},
}
</script>
<template>
<div>
<template v-for="car in cars">
<single-car :initial-properties="car"></single-car>
</template>
</div>
</template>
Как я сделать это прямо сейчас это , что в моем single-car
компоненте я задаю this.initialProperties
мой this.data.properties
на created()
инициализации крючок. И работает, и реагирует.
// single-car.vue
<script>
export default {
data: function() {
return {
properties: {},
}
},
created: function(){
this.data.properties = this.initialProperties;
},
}
</script>
<template>
<div>Car is in {{properties.color}} and has a max speed of {{properties.maxSpeed}}</div>
</template>
Но моя проблема в том, что я не знаю, правильно ли это делать? Разве это не вызовет у меня неприятностей по дороге? Или есть способ лучше?
javascript
vue.js
vuejs2
Доминик Серафин
источник
источник
data
будетtwo-way
связан, но вы не можете перейтиdata
к компонентам, вы проходитеprops
, но вы не можете изменить принятыйprops
ни преобразоватьprops
вdata
. И что? Я понял одну вещь: вы должны передаватьprops
и запускать события. То есть, если компонент хочет изменитьprops
полученное, он должен вызвать событие и быть «повторно обработанным». Но тогда у вас остаетсяone-way
привязка точно такая же, как у React, и я не вижу в ней пользыdata
. Довольно запутанно.Ответы:
Благодаря этому 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-model-on-Components
Способ 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/
источник
{ ok: 1, notOk: { meh: 2 } }
если установлено на внутренние данные с помощью любого из предыдущих методов клонирования, все равно изменит опоруnotOk.meh
initial
чтобы иметь возможность использовать их в моем компе. Было бы намного чище, если бы мы могли просто передать свойство, вызываемоеdata
любой компом, и заставить его автоматически распространять локализованные данные внутри без всего этогоinitialPropName
безумия.prop --> comp.data
использования Vue-Stash для всех данных (или Vuex тоже подойдет). Но теперь я просто перенаправляю свои данные сwindow
объекта, как я делал это до того, как «современные» JS-фреймворки навязали мне свое мнение. Возникает вопрос: в чем вообще смысл свойства comp.data?В дополнение к ответу @ dominik-serafin:
Если вы передаете объект, вы можете легко клонировать его с помощью оператора распространения (синтаксис ES6):
props: { record: { type: Object, required: true } }, data () { // opt. 1 return { recordLocal: {...this.record} } }, computed: { // opt. 2 recordLocal () { return {...this.record} } },
Но самое главное - не забыть использовать opt. 2, если вы передаете вычисленное значение или более асинхронное значение. В противном случае локальное значение не будет обновляться.
Демо:
Vue.component('card', { template: '#app2', props: { test1: null, test2: null }, data () { // opt. 1 return { test1AsData: {...this.test1} } }, computed: { // opt. 2 test2AsComputed () { return {...this.test2} } } }) new Vue({ el: "#app1", data () { return { test1: {1: 'will not update'}, test2: {2: 'will update after 1 second'} } }, mounted () { setTimeout(() => { this.test1 = {1: 'updated!'} this.test2 = {2: 'updated!'} }, 1000) } })
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> <div id="app1"> <card :test1="test1" :test2="test2"></card> </div> <template id="app2"> <div> test1 as data: {{test1AsData}} <hr /> test2 as computed: {{test2AsComputed}} </div> </template>
https://jsfiddle.net/nomikos3/eywraw8t/281070/
источник
recordLocal: [...this.record]
(в моем случае запись представляет собой массив) у меня не сработало - после загрузки и проверки компонента vue, онrecord
содержит элементы иrecordLocal
был пустым массивом.computed
Я считаю, что вы делаете это правильно, потому что это то, что указано в документации.
https://vuejs.org/guide/components.html#One-Way-Data-Flow
источник
window
объекта.