理解 v-model、v-bind、$attrs、 $listener 和 .sync 及其在跨组件数据双向绑定上的应用
一、v-model
v-model是v-bind以及v-on配合使用的语法糖。
父组件—>子组件 v-bind 数据绑定(M—>V) ,子组件—>父组件 v-on事件监听(V—>M)。
<input v-model="msg" />
<!-- 相当于:-->
<input :value="msg" @input="msg= $event.target.value" />
二、v-bind
v-bind本质是批量传入prop
<Component v-bind="{a:foo,b:bar}" />
<!-- 相当于:-->
<Component :a=foo :b=bar />
三、 $attrs
父组件传入给子组件的值,只要没有被props指名接收,都会在子组件的 $attrs 中,被props指名接收的,都放入子组件的 $props 里。
四、 $listeners
父组件通过v-on对子组件挂载事件监听,对子组件而言,父组件监听的事件都放在 $listeners 里。
如果子组件对后代组件使用v-on=" $listeners ",相当于对后代组件批量挂载了父组件对自己的事件监听。因此后代组件的emit会触发父组件的事件方法。
五、.sync
实质是更方便地实现数据双向绑定。即数据流向父->子天然实现,子->父只需子组件emit相关事件即可,从而实现双向绑定。
<Component
:foo="val"
@update:foo="payload=>{ val = payload }"
/>
<!-- 相当于 -->
<Component :foo.sync="val" />
// 子组件使用
this.$emit("update:foo", payload);
六、实现跨越三层的双向绑定
<!-- A Component -->
<template>
<BComponent v-model="modalShow"></BComponent>
</template>
<script>
this.modalShow = true // 往下传递状态,直接到C
</script>
<!-- B Component -->
<template>
<CComponent v-bind="$attrs" v-on="$listeners"></CComponent>
</template>
<script>
// 中间组件也可以中途向两边更改状态,一致性需要手动保持
// this.$attrs.value = true
// this.$emit('input', true)
</script>
<!-- C Component -->
<script>
@Props()
value:boolean
handleClose(){
this.$emit('input', false) // 往上emit状态,直接到A
}
</script>
总结:父组件更改了数据,会因为 $atrrs 传递到后代组件。而后代组件 emit 一个 input 事件,会因为 $listeners 冒到父组件处。又因为父组件的 v-model 而自动把新数据赋值到父组件变量上,因此实现了所谓的"双向绑定"。