关于 v-model 学习二
在 [上一篇 v-model] 的学习过程中,
我们知道了,一般在两种场景下,我们会使用到 v-model.
- 使用在 input 表单元素上.
- 使用在组件上.
但是使用在 input 元素上和使用在组件上在某种程度上来说,还是有很大的区别的.
在 v-mode 使用在 input 元素上时, v-model 帮我们做了两件事情.
<input type='text' v-model="data" />
- 将 data 的值使用 :value 属性绑定的形式绑定到了 input 元素的 value 属性上.
- 在父组件内,监听 input 元素的 @input 事件,并同步更新 data.
在组件上使用 v-model 时
<test-comp v-model="data"></test-comp>
- 将 data 以 props 的形式传递到子组件内.
- 父组件将默认监听子组件发布出来的 input 事件.并同步更新子组件传递回来的数据,以更新 v-model 对应的值.
很大的区别在于:
由于子组件,是一个组件,我 v-model 能做的事情,仅仅只是默认传个 props.value 给你,以及在我父组件内部默认监听你子组件内部不知道是谁发布的 input 事件.
但是在子组件中,或者说在子组件中,可能有很多 input 元素需要用到这个 v-model 传递过来的值.
比如 里面有 2 个 input(一个用户名,一个密码),一个 checkbox 等等等.
那么父组件通过 props 传递过来的数据给谁用的?(用户名,密码,还是 checkbox?)
监听谁的事件?((用户名和密码框都是 input ,checkbox 则是 change)
所以,在组件上使用 v-model,我们需要在被接受 v-model 的子组件内进行更细致的配置.
因为默认在使用 v-model 往子组件传递数据时,父组件只负责传递 :value="data" & 在自己内部监听子组件发布出来的 input 事件.
如何配置 v-model 传递的 props 名字以及父组件监听的事件呢?
为什么要会 v-model的 prop 和 event 配置呢?
prop 呢 ? 不就是把数据以 :value 的方式传递进去吗?而且应该是给 input 元素使用不是吗?
event 呢? 默认是父组件监听 input 事件. 这有什么不好吗? 传给输入框使用,本身就应该监听 input 事件呀?为什么要改默认监听的事件呢?
道理也很简单:
在表单元素中,咱们用到的最多的可能就是 input 文本框输入.
对于输入框(比如 text textarea) 来说,:value 默认传进去正好好.
- value 就是它们需要显示的内容.
- input 正好也是它们的 value 在改变时触发的事件...(虽然也要子组件自己监听 dom 再 $emit 一次).
关键在于,input 表单元素,不只有输入框,还有 checkbox select 等.
首先 ,它们的 value 和 input 一样,不是给用户看的(虽然都是往后台提交的)
并且, 它们作为 input 元素来说,自己状态变动也不是 input,而是 change.
所以, 如果一直使用 组件的 v-model 的默认配置(value & input)显然是不合适的.
比如,我有一个组件,内部是一个 <select></select>
.
所以,默认的 props.value 和 input 事件就不合适.
因为 value 不需要我传,内部的 <select></select>
本身就定义了 options . 而 options 里包含了 value.
input 事件也不合适, 因为 <select></select>
事件是 change.
于是,我们需要在包含了 <select></select>
组件的内部重新定义 v-model 的两个默认配置.
const TestComp = {
model: {
prop: 'getDataFromParentByVModel', // 将默认的 value props 改成 getDataFromParentByVModel
event: 'change' // 让父组件默认监听 change 事件.
},
props: ['getDataFromParentByVModel']
}
- model.prop = 'getDataFromParentByVModel' 修改默认的 v-model 传递的属性绑定是 :value
- event = 'change' 让提供了 v-model 的父组件默认的监听子组件发布出去的 change 事件.
- props: ['getDataFromParentByVModel'] v-model 传递过来的是 getDataFromParentByVModel,在子组件内部还是得定义一下对应的 props (就想默认定义 props:['value']) 一样.
然后在子组件的内部:
let ChildComp = {
template: `
<div>
//....other html and components
<select :value="getDataFromParentByVModel" @change="hanlderSelectChange">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
</div>
`,
method: {
hanlderSelectChange (e) {
// 在这就要触发 change 事件了.
this.$emit('change',e.target.value)
}
}
}
查看效果:
image.png image.png image.png两边修改可以互相影响(这也就是 v-model 的作用所在).
其实传统的像什么父子组件间传值.
- 父向子 使用 props .
- 子向父 使用 $emit ..
但是上述两种常规做法,都是单向的.
组件上使用 v-model 也可以作为一个非常好用的父和子之间相[互传递数]据的一种方式.(双向的.)