Jak słuchać zmian "rekwizytów"
W VueJS 2.0 docs nie mogę znaleźć żadnych hooków, które mogłyby słuchać zmian props
.
Czy VueJs ma takie haki jak onPropsUpdated()
Czy podobne?
Update
Jak zasugerował @wostex, próbowałem watch
mojej własności, ale nic się nie zmieniło. Wtedy zdałem sobie sprawę, że mam specjalny przypadek:
<template>
<child :my-prop="myProp"></child>
</template>
<script>
export default {
props: ['myProp']
}
</script>
Przekazuję myProp
, że komponent macierzysty otrzymuje do komponentu child
. Wtedy watch: {myProp: ...}
nie działa.
13 answers
Możesz watch
wykonać kod po zmianie właściwości:
new Vue({
el: '#app',
data: {
text: 'Hello'
},
components: {
'child' : {
template: `<p>{{ myprop }}</p>`,
props: ['myprop'],
watch: {
myprop: function(newVal, oldVal) { // watch it
console.log('Prop changed: ', newVal, ' | was: ', oldVal)
}
}
}
}
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<child :myprop="text"></child>
<button @click="text = 'Another text'">Change text</button>
</div>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-16 08:27:11
Próbowałeś tego ?
watch: {
myProp: {
// the callback will be called immediately after the start of the observation
immediate: true,
handler (val, oldVal) {
// do your stuff
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-04 14:46:24
On,,,,]}
W moim przypadku potrzebowałem rozwiązania, w którym za każdym razem, gdy jakieś rekwizyty się zmienią, musiałem ponownie przeanalizować moje dane. Byłem zmęczony robieniem osobnego watchera dla wszystkich moich rekwizytów, więc użyłem tego: {]}
watch: {
$props: {
handler() {
this.parseData();
},
deep: true,
immediate: true,
},
Kluczowym punktem do usunięcia z tego przykładu jest użycie deep: true
, aby nie tylko oglądał $props, ale także zagnieżdżał wartości, takie jak np. props.myProp
Możesz dowiedzieć się więcej o tej rozszerzonej opcji zegarka tutaj: https://vuejs.org/v2/api/#vm-watch
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-31 20:29:15
Musisz zrozumieć, jaką hierarchię komponentów posiadasz i jak przekazujesz rekwizyty, zdecydowanie twój przypadek jest wyjątkowy i zwykle nie spotykany przez deweloperów.
Komponent nadrzędny-myProp - > komponent podrzędny-myProp - > wnuk Komponent
Jeśli myProp zostanie zmienione w komponencie nadrzędnym, to będzie również odzwierciedlone w komponencie podrzędnym.
I jeśli myProp zostanie zmieniony w komponencie potomnym, to zostanie odzwierciedlone w wnuku komponent też.
Więc jeśli myProp zostanie zmieniony w komponencie nadrzędnym, to będzie odzwierciedlone w komponencie wnuk. (na razie tak dobrze).
Dlatego w hierarchii nie musisz nic robić rekwizyty będą z natury reaktywne.
Teraz mówi się o awansie w hierarchii
Jeśli myProp zostanie zmieniony w komponencie grandChild, to nie będzie odzwierciedlane w komponencie potomnym. Musisz użyć .modyfikator synchronizacji w zdarzeniu child I emit z wnuka komponent.
Jeśli myProp zostanie zmienione w komponencie potomnym, to nie zostanie odzwierciedlone w komponencie nadrzędnym. Musisz użyć .modyfikator synchronizacji w komponencie nadrzędnym i emituje Zdarzenie z komponentu podrzędnego.
Jeśli myProp zostanie zmienione w komponencie grandChild, to nie zostanie odzwierciedlone w komponencie nadrzędnym (oczywiście). Musisz użyć .Synchronizuj modyfikator potomny i emituj Zdarzenie z komponentu wnuk, a następnie obserwuj właściwość w komponencie potomnym i emituj Zdarzenie przy zmianie, która jest nasłuchiwane przez komponent nadrzędny za pomocą .modyfikator synchronizacji.
Zobaczmy jakiś kod, aby uniknąć zamieszania
Rodzic.vue<template>
<div>
<child :myProp.sync="myProp"></child>
<input v-model="myProp"/>
<p>{{myProp}}</p>
</div>
</template>
<script>
import child from './Child.vue'
export default{
data(){
return{
myProp:"hello"
}
},
components:{
child
}
}
</script>
<style scoped>
</style>
Dziecko.vue
<template>
<div> <grand-child :myProp.sync="myProp"></grand-child>
<p>{{myProp}}</p>
</div>
</template>
<script>
import grandChild from './Grandchild.vue'
export default{
components:{
grandChild
},
props:['myProp'],
watch:{
'myProp'(){
this.$emit('update:myProp',this.myProp)
}
}
}
</script>
<style>
</style>
Wnuk.vue
<template>
<div><p>{{myProp}}</p>
<input v-model="myProp" @input="changed"/>
</div>
</template>
<script>
export default{
props:['myProp'],
methods:{
changed(event){
this.$emit('update:myProp',this.myProp)
}
}
}
</script>
<style>
</style>
Ale po tym nie zauważysz krzyczących ostrzeżeń vue mówiących
' unikaj mutacji właściwości bezpośrednio, ponieważ wartość zostanie nadpisana za każdym razem, gdy komponent macierzysty ponownie renderuje.'
Ponownie, jak wspomniałem wcześniej, większość deweloperów nie napotyka tego problemu, bo to anty wzór. Dlatego dostajesz to Ostrzeżenie.
Ale w celu rozwiązania problemu (zgodnie z Twoim projektem). Uważam, że musisz wykonać powyższą pracę (hack, aby być szczerym). Nadal zalecam, abyś przemyślał swój projekt i zrobił mniej podatny na błędy.
Mam nadzieję, że to pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-09 05:07:39
Nie wiem, czy to rozwiązałeś (i jeśli dobrze rozumiem), ale oto mój pomysł:
Jeśli rodzic otrzymuje myProp, a Ty chcesz, aby przeszedł do child I oglądał go w child, to rodzic musi mieć kopię myProp (nie referencję).
Spróbuj tego:
new Vue({
el: '#app',
data: {
text: 'Hello'
},
components: {
'parent': {
props: ['myProp'],
computed: {
myInnerProp() { return myProp.clone(); } //eg. myProp.slice() for array
}
},
'child': {
props: ['myProp'],
watch: {
myProp(val, oldval) { now val will differ from oldval }
}
}
}
}
Oraz w html:
<child :my-prop="myInnerProp"></child>
W takich sytuacjach trzeba być bardzo ostrożnym przy pracy nad złożonymi zbiorami (przechodząc kilka razy)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-28 09:14:13
Do wiązania dwukierunkowego musisz użyć .modyfikator synchronizacji
<child :myprop.sync="text"></child>
I musisz użyć właściwości watch w komponencie potomnym, aby nasłuchać i zaktualizować wszelkie zmiany
props: ['myprop'],
watch: {
myprop: function(newVal, oldVal) { // watch it
console.log('Prop changed: ', newVal, ' | was: ', oldVal)
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-25 02:22:22
Pracuję z obliczoną właściwością typu:
items:{
get(){
return this.resources;
},
set(v){
this.$emit("update:resources", v)
}
},
Zasoby są w tym przypadku własnością:
props: [ 'resources' ]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-25 07:05:16
Dla mnie jest to uprzejme rozwiązanie, aby uzyskać jeden konkretny prop (S) zmiany i stworzyć z nim logikę
Użyłbym właściwości props
i zmiennych computed
do tworzenia logiki po odebraniu zmian
export default {
name: 'getObjectDetail',
filters: {},
components: {},
props: {
objectDetail: { // <--- we could access to this value with this.objectDetail
type: Object,
required: true
}
},
computed: {
_objectDetail: {
let value = false
// ...
// if || do || while -- whatever logic
// insert validation logic with this.objectDetail (prop value)
value = true
// ...
return value
}
}
Możemy więc użyć _objectDetail do renderowania html
<span>
{{ _objectDetail }}
</span>
Lub w jakiejś metodzie:
literallySomeMethod: function() {
if (this._objectDetail) {
....
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-07 21:23:10
Funkcja watch powinna umieścić w komponencie potomnym. Nie rodzicem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-25 02:01:49
Możesz użyć trybu zegarka do wykrywania zmian:
Rób wszystko na poziomie atomowym. Więc najpierw sprawdź, czy sama metoda watch jest wywoływana, czy nie, pocieszając coś wewnątrz. Po ustaleniu, że zegarek jest coraz nazywany, rozbić go z logiki biznesowej.watch: {
myProp: function() {
console.log('Prop changed')
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-30 10:18:24
Używam właściwości props
i zmiennych computed
jeśli muszę utworzyć logikę po odebraniu zmian
export default {
name: 'getObjectDetail',
filters: {},
components: {},
props: {
objectDetail: {
type: Object,
required: true
}
},
computed: {
_objectDetail: {
let value = false
...
if (someValidation)
...
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-07 21:08:01
@JoeSchr ma odpowiedź. Oto inny sposób, aby zrobić, jeśli nie chcesz deep: true
mounted() {
this.yourMethod();
// re-render any time a prop changes
Object.keys(this.$options.props).forEach(key => {
this.$watch(key, this.yourMethod);
});
},
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-01 22:28:16
Jeśli myProp jest obiektem, nie może być zmieniony w Normal. więc zegarek nigdy nie zostanie uruchomiony. powodem, dla którego myProp nie może być zmieniany, jest to, że w większości przypadków wystarczy ustawić kilka klawiszy myProp. sam myProp nadal jest tym jedynym. spróbuj oglądać rekwizyty myProp, jak "myProp.a", powinno zadziałać.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-09 03:47:10