Давайте посмотрим на ваш пример.Я добавил наблюдатели для значения свойства bar
для родительского и дочернего компонентов и операторов console.log
, чтобы отметить различные моменты при передаче данных между двумя компонентами:
const EVENT_UPDATE_BAR = "update:bar";
Vue.component("foo", {
props:["bar"],
computed:{
_bar:{
get:function(){
console.log('_bar getter is called')
return this.bar;
},
set:function(value){
console.log('_bar setter is called')
this.$emit(EVENT_UPDATE_BAR, value);
}
}
},
methods:{
handler_button_click:function(){
console.log('handler_button_click is called')
this._bar = 5;
console.log('this._bar is accessed with value: ', this._bar);
this.$nextTick(() => {
console.log('next tick handler is called')
})
console.log('handler_button_click finishes')
}
},
watch: {
bar() {
console.log('child bar watcher is called')
}
}
});
new Vue({
el:"#app",
data:{
bar:1
},
watch: {
bar() {
console.log('parent bar watcher is called')
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
<foo inline-template v-bind:bar.sync="bar">
<div>
<button v-on:click="handler_button_click">Set to 5</button>
</div>
</foo>
<span>bar: {{bar}}</span>
</div>
Вы заметите, что сначала запускается handler_button_click
, а затем методы get
и set
для вычисленного _bar
.Но два наблюдателя для bar
не срабатывают до тех пор, пока не завершится функция handler_button_click
.Это указывает на то, что значение, передаваемое дочерним вызовом $emit
, не обрабатывается родительским компонентом до тех пор, пока не завершится выполнение функции handler_button_click
.
Единственный способ, которым Vue обеспечивает ожидание синхронизации свойств родителя и потомка в функции handler_button_click
, - это вызов $nextTick
, как вы описали.Функция $nextTick
будет ожидать выполнения своего обработчика, пока DOM не закончит обновление.Поскольку DOM не завершит рендеринг, пока все изменения данных в родительском и дочернем компонентах не будут разрешены, вы можете быть уверены, что все будет синхронизировано на этом этапе.
Все это говорит,кажется, что вы просто хотите, чтобы дочернее свойство _bar
обновлялось сразу после его установки, и вам не обязательно, чтобы значение обновлялось в родительской области сразу.
В этом случае вы могли бы использовать наблюдатели вместо вычисленных методов получения и установки.Таким образом, поскольку свойство потомка не вычисляется, оно будет обновлено немедленно, а свойство родителя будет обновлено после следующего тика.
Вот пример:
const EVENT_UPDATE_BAR = "update:bar";
Vue.component("foo", {
props: ["bar"],
data() {
return {
value: this.bar,
};
},
methods: {
handler_button_click() {
this.value = 5;
alert("bar: " + this.value);
}
},
watch: {
value(val) {
this.$emit(EVENT_UPDATE_BAR, val);
},
bar(val) {
this.value = val;
}
}
});
new Vue({
el: "#app",
data() {
return {
bar: 1
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
<foo inline-template v-bind:bar.sync="bar">
<div>
<button v-on:click="handler_button_click">Set to 5</button>
</div>
</foo>
<span>bar: {{bar}}</span>
</div>
Обратите внимание, что я изменил имя свойства _bar
на value
, поскольку свойства с добавлением подчеркивания не могут быть просмотрены как они не передаются на экземпляр Vue .