v-model
在原生上实现v-model效果
1 | <input type="number" :value="msg" @input="(e) => { msg = parseInt(e.target.value) }" /> |
事件第一个参数是事件对象
Vue3.4以前 在组件上实现v-model效果
- 自定义事件
- 事件名为
update:value
- 事件名为
App.vue
1 | <Comp :value="msg" @update:value="val => msg = val"></Comp> |
Comp.vue
1 | <input :value="props.value" @input="emits('update:value', $event.target.value)"></input> |
Vue3.4 defineModel
帮助我们封装组件
- 可以同步
- 一个组件可以同时使用多个v-model
- 宏指令
- 用于setup语法糖里
- 编译时
App.vue
1 | <Computer v-model:first-num="val1" v-model:second-num="val2"></Computer> |
Computer.vue
1 | <script setup> |
自定义指令手写v-mode
Question
- 为什么不能用
binding.value
- 因为binding.value
是值而不是引用 ,不能实现 view—>model 层的流动
- 因为binding.value
- 为什么要用
toRef(binding.instance, binding.arg)
- 首先不能
binding.instance[binding.arg]
它会被解包成值类型 - 所以创建一个ref, 它与 外部传进来的ref 保持同步
- 首先不能
- 为什么要
defineExpose({msg})
- setup语法糖要手动暴露自身内部变量
defineExpose
暴露出去的变量才会挂载到binding.instance
即这个组件实例上
已解决
- 双向绑定
- 同时使用多个v-oh-model
依然无法解决的问题
- 写法不同 必须要加args,但是value可以省略。 写成:v-oh-model:msg
- defineExpose
<script setup>
下必须要手动暴露
1 | <script setup lang='ts'> |
总结
根据这次体验,我感觉自动解包有时候真是副作用。
或许这就是Vue的设计模式,但是也确实限制了程序员的发挥。
如果这里能直接拿到msg变量的引用,哪还需要这么麻烦